From b33706f990bff175d7c8b0a8600238e2d4a07221 Mon Sep 17 00:00:00 2001 From: leo Date: Fri, 21 Jul 2000 15:29:37 +0000 Subject: new Object class to be used as the base for the Piece, Camera and Light classes git-svn-id: http://svn.leocad.org/trunk@93 c7d43263-9d01-0410-8a33-9dba5d9f93d6 --- common/object.cpp | 221 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ common/object.h | 154 +++++++++++++++++++++++++++++++++++++ 2 files changed, 375 insertions(+) create mode 100755 common/object.cpp create mode 100755 common/object.h diff --git a/common/object.cpp b/common/object.cpp new file mode 100755 index 0000000..2d75341 --- /dev/null +++ b/common/object.cpp @@ -0,0 +1,221 @@ +// Base class for all drawable objects +// + +#include +#include +#include "object.h" +#include "matrix.h" +#include "vector.h" + +// ============================================================================= +// Static functions + +// Returns in (A,B,C,D) the coefficientes of the plane with the three +// succesive (in counterclockwise order) vertices p1,p2,p3. +static void GetPolyCoeffs (float x1, float y1, float z1, float x2, float y2, float z2, + float x3, float y3, float z3, float *A, float *B, float *C, float *D) +{ + *A = ((y1-y2)*(z3-z2)) - ((z1-z2)*(y3-y2)); + *B = ((z1-z2)*(x3-x2)) - ((x1-x2)*(z3-z2)); + *C = ((x1-x2)*(y3-y2)) - ((y1-y2)*(x3-x2)); + *D = - ((*A)*x1) - ((*B)*y1) - ((*C)*z1); +} + +// ============================================================================= +// ClickLine structure + +double LC_CLICKLINE::PointDistance (float *point) +{ + Vector op (point[0] - a1, point[1] - b1, point[2] - c1); + Vector d ((float)a2, (float)b2, (float)c2); + float len = d.Length (); + d.Normalize (); + float t = op.Dot (d); + + if (t > 0) + { + if (t >= len) + t = 1; + else + t /= len; + + d.Scale (t*len); + op -= d; + } + + return op.Length (); +} + +// ============================================================================= +// Object class + +Object::Object (LC_OBJECT_TYPE nType) +{ + // m_nState = 0; + // m_strName[0] = '\0'; + m_nObjectType = nType; + + // m_pParent = NULL; + // m_pNext = NULL; + // m_pNextRender = NULL; +} + +Object::~Object () +{ + +} + +// ============================================================================= +// BoundingBox stuff + +// Find the distance from the object to the beginning of the "click line". +double Object::BoundingBoxIntersectDist (LC_CLICKLINE* pLine) const +{ + double x, y, z; + + if (BoundingBoxIntersectionbyLine (pLine->a1, pLine->b1, pLine->c1, pLine->a2, pLine->b2, pLine->c2, &x, &y, &z)) + return (float)sqrt ((pLine->a1-x)*(pLine->a1-x)+(pLine->b1-y)*(pLine->b1-y)+(pLine->c1-z)*(pLine->c1-z)); + + return DBL_MAX; +} + +// Returns TRUE if the specified point is inside the bounding box of this object. +bool Object::BoundingBoxPointInside(double x, double y, double z) const +{ + int i = 0; + while (i < 6 && ((m_fBoxPlanes[0][i]*x + m_fBoxPlanes[1][i]*y + + m_fBoxPlanes[2][i]*z + m_fBoxPlanes[3][i]) <= 0.001)) + i++; + return (i == 6); +} + +// Returns TRUE if the line is intersecting any of the planes of the bounding +// box and if this point is also inside this bounding box. +bool Object::BoundingBoxIntersectionbyLine (double a1, double b1, double c1, double a2, double b2, + double c2, double *x, double *y, double *z) const +{ + double curr_t = DBL_MAX; + double t, t1, t2; + + for (int i = 0; i < 6; i++) + { + t1 = (m_fBoxPlanes[0][i]*a1 + m_fBoxPlanes[1][i]*b1 + m_fBoxPlanes[2][i]*c1 + m_fBoxPlanes[3][i]); + t2 = (m_fBoxPlanes[0][i]*a2 + m_fBoxPlanes[1][i]*b2 + m_fBoxPlanes[2][i]*c2); + + if (t1!=0 && t2!=0) + { + t = -( t1 / t2 ); + if (t>=0) + { + *x=a1+a2*t; + *y=b1+b2*t; + *z=c1+c2*t; + + if (BoundingBoxPointInside(*x,*y,*z)) + if (t < curr_t) + curr_t = t; + } + } + } + + if (curr_t != DBL_MAX) + { + *x=a1+a2*curr_t; + *y=b1+b2*curr_t; + *z=c1+c2*curr_t; + return true; + } + else + return false; +} + +// For pieces +void Object::BoundingBoxCalculate (Matrix *mat, float Dimensions[6]) +{ + // BASE TOP + // 1------3 .------4 ^ X + // | | | | | + // | | | | | Y + // 0------. 2------5 .---> + + float pts[18] = { + Dimensions[0], Dimensions[1], Dimensions[5], + Dimensions[3], Dimensions[1], Dimensions[5], + Dimensions[0], Dimensions[1], Dimensions[2], + Dimensions[3], Dimensions[4], Dimensions[5], + Dimensions[3], Dimensions[4], Dimensions[2], + Dimensions[0], Dimensions[4], Dimensions[2] }; + + mat->TransformPoints(pts, 6); + + GetPolyCoeffs (pts[3], pts[4], pts[5], pts[0], pts[1], pts[2], pts[6], pts[7], pts[8], + &m_fBoxPlanes[0][0], &m_fBoxPlanes[1][0], &m_fBoxPlanes[2][0], &m_fBoxPlanes[3][0]); //1,0,2 + GetPolyCoeffs (pts[9], pts[10],pts[11], pts[12],pts[13],pts[14], pts[15],pts[16],pts[17], + &m_fBoxPlanes[0][1], &m_fBoxPlanes[1][1], &m_fBoxPlanes[2][1], &m_fBoxPlanes[3][1]); //3,4,5 + GetPolyCoeffs (pts[15],pts[16],pts[17], pts[6], pts[7], pts[8], pts[0], pts[1], pts[2], + &m_fBoxPlanes[0][2], &m_fBoxPlanes[1][2], &m_fBoxPlanes[2][2], &m_fBoxPlanes[3][2]); //5,2,0 + GetPolyCoeffs (pts[12],pts[13],pts[14], pts[9], pts[10],pts[11], pts[3], pts[4], pts[5], + &m_fBoxPlanes[0][3], &m_fBoxPlanes[1][3], &m_fBoxPlanes[2][3], &m_fBoxPlanes[3][3]); //4,3,1 + GetPolyCoeffs (pts[6], pts[7], pts[8], pts[15],pts[16],pts[17], pts[12],pts[13],pts[14], + &m_fBoxPlanes[0][4], &m_fBoxPlanes[1][4], &m_fBoxPlanes[2][4], &m_fBoxPlanes[3][4]); //2,5,4 + GetPolyCoeffs (pts[0], pts[1], pts[2], pts[3], pts[4], pts[5], pts[9], pts[10],pts[11], + &m_fBoxPlanes[0][5], &m_fBoxPlanes[1][5], &m_fBoxPlanes[2][5], &m_fBoxPlanes[3][5]); //0,1,3 +} + +// Cameras +void Object::BoundingBoxCalculate (Matrix *mat) +{ + float normals[6][3] = { + { 1,0,0 }, { 0,1,0 }, { 0,0,1 }, + { -1,0,0 }, { 0,-1,0 }, { 0,0,-1 } }; + float x,y,z,dist; + + if (IsCamera ()) + dist = 0.3f; + else + dist = 0.2f; + + mat->GetTranslation(&x,&y,&z); + mat->SetTranslation(0,0,0); + mat->TransformPoints(&normals[0][0], 6); + + for (int i = 0; i < 6; i++) + { + m_fBoxPlanes[0][i] = normals[i][0]; + m_fBoxPlanes[1][i] = normals[i][1]; + m_fBoxPlanes[2][i] = normals[i][2]; + + float pt[3]; + pt[0] = dist*normals[i][0] + x; + pt[1] = dist*normals[i][1] + y; + pt[2] = dist*normals[i][2] + z; + + m_fBoxPlanes[3][i] = -(pt[0]*normals[i][0]+pt[1]*normals[i][1]+pt[2]*normals[i][2]); + } +} + +// Light +void Object::BoundingBoxCalculate (float pos[3]) +{ + float pts[18] = { + 0.3f+pos[0], 0.3f+pos[1], -0.3f+pos[2], + -0.3f+pos[0], 0.3f+pos[1], -0.3f+pos[2], + 0.3f+pos[0], 0.3f+pos[1], 0.3f+pos[2], + -0.3f+pos[0], -0.3f+pos[1], -0.3f+pos[2], + -0.3f+pos[0], -0.3f+pos[1], 0.3f+pos[2], + 0.3f+pos[0], -0.3f+pos[1], 0.3f+pos[2] }; + + GetPolyCoeffs (pts[3], pts[4], pts[5], pts[0], pts[1], pts[2], pts[6], pts[7], pts[8], + &m_fBoxPlanes[0][0], &m_fBoxPlanes[1][0], &m_fBoxPlanes[2][0], &m_fBoxPlanes[3][0]); //1,0,2 + GetPolyCoeffs (pts[9], pts[10],pts[11], pts[12],pts[13],pts[14], pts[15],pts[16],pts[17], + &m_fBoxPlanes[0][1], &m_fBoxPlanes[1][1], &m_fBoxPlanes[2][1], &m_fBoxPlanes[3][1]); //3,4,5 + GetPolyCoeffs (pts[15],pts[16],pts[17], pts[6], pts[7], pts[8], pts[0], pts[1], pts[2], + &m_fBoxPlanes[0][2], &m_fBoxPlanes[1][2], &m_fBoxPlanes[2][2], &m_fBoxPlanes[3][2]); //5,2,0 + GetPolyCoeffs (pts[12],pts[13],pts[14], pts[9], pts[10],pts[11], pts[3], pts[4], pts[5], + &m_fBoxPlanes[0][3], &m_fBoxPlanes[1][3], &m_fBoxPlanes[2][3], &m_fBoxPlanes[3][3]); //4,3,1 + GetPolyCoeffs (pts[6], pts[7], pts[8], pts[15],pts[16],pts[17], pts[12],pts[13],pts[14], + &m_fBoxPlanes[0][4], &m_fBoxPlanes[1][4], &m_fBoxPlanes[2][4], &m_fBoxPlanes[3][4]); //2,5,4 + GetPolyCoeffs (pts[0], pts[1], pts[2], pts[3], pts[4], pts[5], pts[9], pts[10],pts[11], + &m_fBoxPlanes[0][5], &m_fBoxPlanes[1][5], &m_fBoxPlanes[2][5], &m_fBoxPlanes[3][5]); //0,1,3 +} + diff --git a/common/object.h b/common/object.h new file mode 100755 index 0000000..495ee90 --- /dev/null +++ b/common/object.h @@ -0,0 +1,154 @@ +#ifndef _OBJECT_H_ +#define _OBJECT_H_ + +class File; +class Matrix; +class Object; +/* +#define LC_OBJECT_NAME_LEN 80 +#define LC_OBJECT_HIDDEN 0x01 +#define LC_OBJECT_SELECTED 0x02 +#define LC_OBJECT_FOCUSED 0x04 +*/ +typedef enum +{ + LC_OBJECT_PIECE, + LC_OBJECT_CAMERA, + LC_OBJECT_CAMERA_TARGET, + LC_OBJECT_LIGHT, + LC_OBJECT_LIGHT_TARGET, + // LC_OBJECT_GROUP, + // LC_OBJECT_GROUP_PIVOT, + // LC_OBJECT_CURVE +} LC_OBJECT_TYPE; + +// rendering parameters +typedef struct +{ + bool lighting; + bool stipple; + bool edges; + float fLineWidth; + + unsigned char lastcolor; + bool transparent; +} LC_RENDER_INFO; + +// Callback "closure" struct, used to make the necessary parameters known to +// the callback function. +typedef struct LC_CLICKLINE +{ + double a1, b1, c1; + double a2, b2, c2; + double mindist; + Object *pClosest; + // void *pParam; + + double PointDistance (float *point); + +} LC_CLICKLINE; + +class Object +{ + public: + Object (LC_OBJECT_TYPE nType); + virtual ~Object (); + + + /* + + // These functions must be implemented for each class + virtual void UpdatePosition (unsigned short nTime, bool bAnimation) = 0; + virtual void CompareBoundingBox (float *box) { }; + virtual void Move (unsigned short nTime, bool bAnimation, bool bAddKey, float dx, float dy, float dz) = 0; + virtual void FileSave (File* file) = 0; + virtual void FileLoad (File* file) = 0; + virtual void Render (LC_RENDER_INFO* pInfo) = 0; + + // Query functions + virtual bool IsSelected () const + { return (m_nState & LC_OBJECT_SELECTED) != 0; }; + virtual bool IsFocused () const + { return (m_nState & LC_OBJECT_FOCUSED) != 0; }; + virtual bool IsVisible (unsigned short nTime, bool bAnimation) const + { return (m_nState & LC_OBJECT_HIDDEN) == 0; } + const char* GetName() const + { return m_strName; } + + // State change, most classes will have to replace these functions + virtual void SetSelection (bool bSelect, void *pParam = NULL) + { + if (bSelect) + m_nState |= LC_OBJECT_SELECTED; + else + m_nState &= ~(LC_OBJECT_SELECTED | LC_OBJECT_FOCUSED); + }; + virtual void SetFocus (bool bFocus, void *pParam = NULL) + { + if (bFocus) + m_nState |= (LC_OBJECT_SELECTED | LC_OBJECT_FOCUSED); + else + m_nState &= ~LC_OBJECT_FOCUSED; + }; + virtual void SetVisible (bool bVisible) + { + if (bVisible) + m_nState &= ~LC_OBJECT_HIDDEN; + else + { + m_nState |= LC_OBJECT_HIDDEN; + SetSelection (false, NULL); + } + } + virtual bool SetColor (int nColor) + { return false; }; + + // collision detection + virtual void MinIntersectDist (LC_CLICKLINE* pLine) = 0; + // void BoxMinIntersectDist (LC_CLICKLINE* pLine); + // void SphereMinIntersectDist (LC_CLICKLINE* pLine); + */ + // determine the object type + bool IsPiece () const + { return m_nObjectType == LC_OBJECT_PIECE; } + bool IsCamera () const + { return m_nObjectType == LC_OBJECT_CAMERA; } + bool IsLight () const + { return m_nObjectType == LC_OBJECT_LIGHT; } + /* + bool IsGroup () const + { return m_nObjectType == LC_OBJECT_GROUP; } + bool IsCurve () const + { return m_nObjectType == LC_OBJECT_CURVE; } + */ + LC_OBJECT_TYPE GetType () const + { return m_nObjectType; } + /* + // For linked lists + Object* m_pNext; + Object* m_pNextRender; + Object* m_pParent; + + Object* GetTopAncestor () + { return m_pParent ? m_pParent->GetTopAncestor () : this; } + */ + protected: + // char m_strName[LC_OBJECT_NAME_LEN+1]; + // unsigned char m_nState; + + // Bounding box stuff + double BoundingBoxIntersectDist (LC_CLICKLINE* pLine) const; + void BoundingBoxCalculate (float pos[3]); + void BoundingBoxCalculate (Matrix *mat); + void BoundingBoxCalculate (Matrix *mat, float Dimensions[6]); + + private: + bool BoundingBoxIntersectionbyLine (double a1, double b1, double c1, double a2, double b2, double c2, + double *x, double *y, double *z) const; + bool BoundingBoxPointInside (double x, double y, double z) const; + float m_fBoxPlanes[4][6]; + + LC_OBJECT_TYPE m_nObjectType; +}; + +#endif -- cgit v1.2.3