diff --git a/common/camera.h b/common/camera.h index 975f6044..670d5969 100644 --- a/common/camera.h +++ b/common/camera.h @@ -39,7 +39,7 @@ public: public: void MinIntersectDist (LC_CLICKLINE* pLine); - bool IntersectsVolume(const Vector4* Planes, int NumPlanes) + bool IntersectsVolume(const lcVector4 Planes[6]) { return false; } void Select (bool bSelecting, bool bFocus, bool bMultiple); void Move (unsigned short nTime, bool bAnimation, bool bAddKey, float x, float y, float z) @@ -124,7 +124,7 @@ public: void FileSave(lcFile& file) const; void MinIntersectDist (LC_CLICKLINE* pLine); void Select (bool bSelecting, bool bFocus, bool bMultiple); - bool IntersectsVolume(const Vector4* Planes, int NumPlanes) + bool IntersectsVolume(const lcVector4 Planes[6]) { return false; } diff --git a/common/curve.h b/common/curve.h index 027e12bc..991c33ec 100755 --- a/common/curve.h +++ b/common/curve.h @@ -37,8 +37,8 @@ class CurvePoint : public Object bool FileLoad(lcFile& file); void FileSave(lcFile& file) const; void MinIntersectDist (LC_CLICKLINE* pLine); - bool IntersectsVolume(const Vector4* Planes, int NumPlanes) - { return false; } + bool IntersectsVolume(const lcVector4 Planes[6]) + { return false; } void UpdatePosition (unsigned short nTime, bool bAnimation); void Move (unsigned short nTime, bool bAnimation, bool bAddKey, float dx, float dy, float dz); void Render (LC_RENDER_INFO* pInfo); diff --git a/common/lc_math.h b/common/lc_math.h index cac47083..44274297 100644 --- a/common/lc_math.h +++ b/common/lc_math.h @@ -294,6 +294,16 @@ inline float lcDot(const lcVector3& a, const lcVector3& b) return a.x * b.x + a.y * b.y + a.z * b.z; } +inline float lcDot3(const lcVector4& a, const lcVector3& b) +{ + return a.x * b.x + a.y * b.y + a.z * b.z; +} + +inline float lcDot3(const lcVector3& a, const lcVector4& b) +{ + return a.x * b.x + a.y * b.y + a.z * b.z; +} + inline float lcDot(const lcVector4& a, const lcVector4& b) { return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; diff --git a/common/lc_mesh.cpp b/common/lc_mesh.cpp index 6d0b726d..56bc07e9 100644 --- a/common/lc_mesh.cpp +++ b/common/lc_mesh.cpp @@ -216,9 +216,57 @@ bool lcMesh::MinIntersectDist(const lcVector3& Start, const lcVector3& End, floa return MinIntersectDist(Start, End, MinDist, Intersection); } -// Return true if a polygon intersects a set of planes. -static bool PolygonIntersectsPlanes(float* p1, float* p2, float* p3, float* p4, const Vector4* Planes, int NumPlanes) // TODO: move to lc_math +// Sutherland-Hodgman method of clipping a polygon to a plane. +static void lcPolygonPlaneClip(lcVector3* InPoints, int NumInPoints, lcVector3* OutPoints, int* NumOutPoints, const lcVector4& Plane) { + lcVector3 *s, *p, i; + + *NumOutPoints = 0; + s = &InPoints[NumInPoints-1]; + + for (int j = 0; j < NumInPoints; j++) + { + p = &InPoints[j]; + + if (lcDot3(*p, Plane) + Plane[3] <= 0) + { + if (lcDot3(*s, Plane) + Plane[3] <= 0) + { + // Both points inside. + OutPoints[*NumOutPoints] = *p; + *NumOutPoints = *NumOutPoints + 1; + } + else + { + // Outside, inside. + lcLinePlaneIntersection(i, *s, *p, Plane); + + OutPoints[*NumOutPoints] = i; + *NumOutPoints = *NumOutPoints + 1; + OutPoints[*NumOutPoints] = *p; + *NumOutPoints = *NumOutPoints + 1; + } + } + else + { + if (lcDot3(*s, Plane) + Plane[3] <= 0) + { + // Inside, outside. + lcLinePlaneIntersection(i, *s, *p, Plane); + + OutPoints[*NumOutPoints] = i; + *NumOutPoints = *NumOutPoints + 1; + } + } + + s = p; + } +} + +// Return true if a polygon intersects a set of planes. +static bool PolygonIntersectsPlanes(float* p1, float* p2, float* p3, float* p4, const lcVector4 Planes[6]) // TODO: move to lc_math +{ + const int NumPlanes = 6; float* Points[4] = { p1, p2, p3, p4 }; int Outcodes[4] = { 0, 0, 0, 0 }, i; int NumPoints = (p4 != NULL) ? 4 : 3; @@ -226,11 +274,11 @@ static bool PolygonIntersectsPlanes(float* p1, float* p2, float* p3, float* p4, // First do the Cohen-Sutherland out code test for trivial rejects/accepts. for (i = 0; i < NumPoints; i++) { - Vector3 Pt(Points[i][0], Points[i][1], Points[i][2]); + lcVector3 Pt(Points[i][0], Points[i][1], Points[i][2]); for (int j = 0; j < NumPlanes; j++) { - if (Dot3(Pt, Planes[j]) + Planes[j][3] > 0) + if (lcDot3(Pt, Planes[j]) + Planes[j][3] > 0) Outcodes[i] |= 1 << j; } } @@ -257,22 +305,22 @@ static bool PolygonIntersectsPlanes(float* p1, float* p2, float* p3, float* p4, } // Buffers for clipping the polygon. - Vector3 ClipPoints[2][8]; + lcVector3 ClipPoints[2][8]; int NumClipPoints[2]; int ClipBuffer = 0; NumClipPoints[0] = NumPoints; - ClipPoints[0][0] = Vector3(p1[0], p1[1], p1[2]); - ClipPoints[0][1] = Vector3(p2[0], p2[1], p2[2]); - ClipPoints[0][2] = Vector3(p3[0], p3[1], p3[2]); + ClipPoints[0][0] = lcVector3(p1[0], p1[1], p1[2]); + ClipPoints[0][1] = lcVector3(p2[0], p2[1], p2[2]); + ClipPoints[0][2] = lcVector3(p3[0], p3[1], p3[2]); if (NumPoints == 4) - ClipPoints[0][3] = Vector3(p4[0], p4[1], p4[2]); + ClipPoints[0][3] = lcVector3(p4[0], p4[1], p4[2]); // Now clip the polygon against the planes. for (i = 0; i < NumPlanes; i++) { - PolygonPlaneClip(ClipPoints[ClipBuffer], NumClipPoints[ClipBuffer], ClipPoints[ClipBuffer^1], &NumClipPoints[ClipBuffer^1], Planes[i]); + lcPolygonPlaneClip(ClipPoints[ClipBuffer], NumClipPoints[ClipBuffer], ClipPoints[ClipBuffer^1], &NumClipPoints[ClipBuffer^1], Planes[i]); ClipBuffer ^= 1; if (!NumClipPoints[ClipBuffer]) @@ -283,7 +331,7 @@ static bool PolygonIntersectsPlanes(float* p1, float* p2, float* p3, float* p4, } template -bool lcMesh::IntersectsPlanes(const Vector4* Planes, int NumPlanes) +bool lcMesh::IntersectsPlanes(const lcVector4 Planes[6]) { float* Verts = (float*)mVertexBuffer.mData; @@ -297,19 +345,19 @@ bool lcMesh::IntersectsPlanes(const Vector4* Planes, int NumPlanes) IndexType* Indices = (IndexType*)mIndexBuffer.mData + Section->IndexOffset / sizeof(IndexType); for (int Idx = 0; Idx < Section->NumIndices; Idx += 3) - if (PolygonIntersectsPlanes(&Verts[Indices[Idx]*3], &Verts[Indices[Idx+1]*3], &Verts[Indices[Idx+2]*3], NULL, Planes, NumPlanes)) + if (PolygonIntersectsPlanes(&Verts[Indices[Idx]*3], &Verts[Indices[Idx+1]*3], &Verts[Indices[Idx+2]*3], NULL, Planes)) return true; } return false; } -bool lcMesh::IntersectsPlanes(const Vector4* Planes, int NumPlanes) +bool lcMesh::IntersectsPlanes(const lcVector4 Planes[6]) { if (mIndexType == GL_UNSIGNED_SHORT) - return IntersectsPlanes(Planes, NumPlanes); + return IntersectsPlanes(Planes); else - return IntersectsPlanes(Planes, NumPlanes); + return IntersectsPlanes(Planes); } template diff --git a/common/lc_mesh.h b/common/lc_mesh.h index 84ea6aa0..a125d21e 100644 --- a/common/lc_mesh.h +++ b/common/lc_mesh.h @@ -3,7 +3,6 @@ #include #include "opengl.h" -#include "algebra.h" class lcVertexBuffer { @@ -129,8 +128,8 @@ public: bool MinIntersectDist(const lcVector3& Start, const lcVector3& End, float& MinDist, lcVector3& Intersection); template - bool IntersectsPlanes(const Vector4* Planes, int NumPlanes); - bool IntersectsPlanes(const Vector4* Planes, int NumPlanes); + bool IntersectsPlanes(const lcVector4 Planes[6]); + bool IntersectsPlanes(const lcVector4 Planes[6]); void UpdateBuffers() { diff --git a/common/light.h b/common/light.h index 69091a03..61500a52 100644 --- a/common/light.h +++ b/common/light.h @@ -32,7 +32,7 @@ public: public: void MinIntersectDist (LC_CLICKLINE* pLine); - bool IntersectsVolume(const Vector4* Planes, int NumPlanes) + bool IntersectsVolume(const lcVector4 Planes[6]) { return false; } void Select (bool bSelecting, bool bFocus, bool bMultiple); void Move (unsigned short nTime, bool bAnimation, bool bAddKey, float x, float y, float z) @@ -98,7 +98,7 @@ public: void Render (float fLineWidth); void MinIntersectDist (LC_CLICKLINE* Line); - bool IntersectsVolume(const Vector4* Planes, int NumPlanes) + bool IntersectsVolume(const lcVector4 Planes[6]) { return false; } void UpdatePosition (unsigned short nTime, bool bAnimation); void Move (unsigned short nTime, bool bAnimation, bool bAddKey, float dx, float dy, float dz); diff --git a/common/object.h b/common/object.h index 18b08825..c477f914 100755 --- a/common/object.h +++ b/common/object.h @@ -81,7 +81,7 @@ public: virtual void Select(bool bSelecting, bool bFocus, bool bMultiple) = 0; // Check if the object intersects the volume specified by a given set of planes. - virtual bool IntersectsVolume(const class Vector4* Planes, int NumPlanes) = 0; + virtual bool IntersectsVolume(const lcVector4 Planes[6]) = 0; /* diff --git a/common/piece.cpp b/common/piece.cpp index e27830a5..72482299 100644 --- a/common/piece.cpp +++ b/common/piece.cpp @@ -15,7 +15,6 @@ #include "piece.h" #include "group.h" #include "project.h" -#include "algebra.h" #include "lc_application.h" #define LC_PIECE_SAVE_VERSION 11 // LeoCAD 0.77 @@ -412,33 +411,33 @@ void Piece::MinIntersectDist(LC_CLICKLINE* pLine) pLine->pClosest = this; } -bool Piece::IntersectsVolume(const Vector4* Planes, int NumPlanes) +bool Piece::IntersectsVolume(const lcVector4 Planes[6]) { // First check the bounding box for quick rejection. - Vector3 Box[8] = + lcVector3 Box[8] = { - Vector3(mPieceInfo->m_fDimensions[0], mPieceInfo->m_fDimensions[1], mPieceInfo->m_fDimensions[5]), - Vector3(mPieceInfo->m_fDimensions[3], mPieceInfo->m_fDimensions[1], mPieceInfo->m_fDimensions[5]), - Vector3(mPieceInfo->m_fDimensions[0], mPieceInfo->m_fDimensions[1], mPieceInfo->m_fDimensions[2]), - Vector3(mPieceInfo->m_fDimensions[3], mPieceInfo->m_fDimensions[4], mPieceInfo->m_fDimensions[5]), - Vector3(mPieceInfo->m_fDimensions[3], mPieceInfo->m_fDimensions[4], mPieceInfo->m_fDimensions[2]), - Vector3(mPieceInfo->m_fDimensions[0], mPieceInfo->m_fDimensions[4], mPieceInfo->m_fDimensions[2]), - Vector3(mPieceInfo->m_fDimensions[0], mPieceInfo->m_fDimensions[4], mPieceInfo->m_fDimensions[5]), - Vector3(mPieceInfo->m_fDimensions[3], mPieceInfo->m_fDimensions[1], mPieceInfo->m_fDimensions[2]) + lcVector3(mPieceInfo->m_fDimensions[0], mPieceInfo->m_fDimensions[1], mPieceInfo->m_fDimensions[5]), + lcVector3(mPieceInfo->m_fDimensions[3], mPieceInfo->m_fDimensions[1], mPieceInfo->m_fDimensions[5]), + lcVector3(mPieceInfo->m_fDimensions[0], mPieceInfo->m_fDimensions[1], mPieceInfo->m_fDimensions[2]), + lcVector3(mPieceInfo->m_fDimensions[3], mPieceInfo->m_fDimensions[4], mPieceInfo->m_fDimensions[5]), + lcVector3(mPieceInfo->m_fDimensions[3], mPieceInfo->m_fDimensions[4], mPieceInfo->m_fDimensions[2]), + lcVector3(mPieceInfo->m_fDimensions[0], mPieceInfo->m_fDimensions[4], mPieceInfo->m_fDimensions[2]), + lcVector3(mPieceInfo->m_fDimensions[0], mPieceInfo->m_fDimensions[4], mPieceInfo->m_fDimensions[5]), + lcVector3(mPieceInfo->m_fDimensions[3], mPieceInfo->m_fDimensions[1], mPieceInfo->m_fDimensions[2]) }; // Transform the planes to local space. - Matrix44 WorldToLocal; - WorldToLocal.CreateFromAxisAngle(Vector3(mRotation[0], mRotation[1], mRotation[2]), -mRotation[3] * LC_DTOR); - WorldToLocal.SetTranslation(Mul31(Vector3(-mPosition[0], -mPosition[1], -mPosition[2]), WorldToLocal)); + lcMatrix44 WorldToLocal = lcMatrix44FromAxisAngle(lcVector3(mRotation[0], mRotation[1], mRotation[2]), -mRotation[3] * LC_DTOR); + WorldToLocal.SetTranslation(lcMul31(lcVector3(-mPosition[0], -mPosition[1], -mPosition[2]), WorldToLocal)); - Vector4* LocalPlanes = new Vector4[NumPlanes]; + const int NumPlanes = 6; + lcVector4 LocalPlanes[NumPlanes]; int i; for (i = 0; i < NumPlanes; i++) { - LocalPlanes[i] = Mul30(Vector3(Planes[i]), WorldToLocal); - LocalPlanes[i][3] = Planes[i][3] - Dot3(Vector3(WorldToLocal[3]), Vector3(LocalPlanes[i])); + lcVector3 PlaneNormal = lcMul30(lcVector3(Planes[i][0], Planes[i][1], Planes[i][2]), WorldToLocal); + LocalPlanes[i] = lcVector4(PlaneNormal, Planes[i][3] - lcDot3(WorldToLocal[3], PlaneNormal)); } // Start by testing trivial reject/accept cases. @@ -450,7 +449,7 @@ bool Piece::IntersectsVolume(const Vector4* Planes, int NumPlanes) for (int j = 0; j < NumPlanes; j++) { - if (Dot3(Box[i], LocalPlanes[j]) + LocalPlanes[j][3] > 0) + if (lcDot3(Box[i], LocalPlanes[j]) + LocalPlanes[j][3] > 0) Outcodes[i] |= 1 << j; } } @@ -465,22 +464,14 @@ bool Piece::IntersectsVolume(const Vector4* Planes, int NumPlanes) // All corners outside the same plane. if (OutcodesAND != 0) - { - delete[] LocalPlanes; return false; - } // All corners inside the volume. if (OutcodesOR == 0) - { - delete[] LocalPlanes; return true; - } // Partial intersection, so check if any triangles are inside. - bool Hit = mPieceInfo->mMesh->IntersectsPlanes(LocalPlanes, NumPlanes); - - delete[] LocalPlanes; + bool Hit = mPieceInfo->mMesh->IntersectsPlanes(LocalPlanes); return Hit; } diff --git a/common/piece.h b/common/piece.h index 49857431..3a313928 100644 --- a/common/piece.h +++ b/common/piece.h @@ -29,7 +29,7 @@ public: void Select (bool bSelecting, bool bFocus, bool bMultiple); virtual void InsertTime (unsigned short start, bool animation, unsigned short time); virtual void RemoveTime (unsigned short start, bool animation, unsigned short time); - virtual bool IntersectsVolume(const Vector4* Planes, int NumPlanes); + virtual bool IntersectsVolume(const lcVector4 Planes[6]); diff --git a/common/project.cpp b/common/project.cpp index 76978b4a..fe229464 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -6297,7 +6297,7 @@ void Project::FindObjectsInBox(float x1, float y1, float x2, float y2, PtrArray< { if (piece->IsVisible(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation)) { - if (piece->IntersectsVolume((Vector4*)Planes, 6)) + if (piece->IntersectsVolume(Planes)) Objects.Add(piece); } }