summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/algebra.cpp235
-rw-r--r--common/algebra.h307
-rw-r--r--common/camera.h4
-rwxr-xr-xcommon/curve.h2
-rw-r--r--common/light.h4
-rwxr-xr-xcommon/object.h26
-rw-r--r--common/piece.cpp203
-rw-r--r--common/piece.h1
-rw-r--r--common/project.cpp403
-rw-r--r--common/project.h1
-rw-r--r--common/typedefs.h12
-rw-r--r--win/LeoCAD.dsp23
-rw-r--r--win/LeoCAD.rc24
-rw-r--r--win/res/toolsbar.bmpbin2398 -> 2518 bytes
-rw-r--r--win/resource.h40
15 files changed, 1019 insertions, 266 deletions
diff --git a/common/algebra.cpp b/common/algebra.cpp
index a34f91d..05a357c 100644
--- a/common/algebra.cpp
+++ b/common/algebra.cpp
@@ -26,10 +26,11 @@ void Matrix44::CreateLookAt(const Point3& Eye, const Point3& Target, const Vecto
y.Normalize();
z.Normalize();
- m_Rows[0] = Float4(x.GetX(), y.GetX(), z.GetX(), 0.0f);
- m_Rows[1] = Float4(x.GetY(), y.GetY(), z.GetY(), 0.0f);
- m_Rows[2] = Float4(x.GetZ(), y.GetZ(), z.GetZ(), 0.0f);
+ m_Rows[0] = Vector4(x.GetX(), y.GetX(), z.GetX(), 0.0f);
+ m_Rows[1] = Vector4(x.GetY(), y.GetY(), z.GetY(), 0.0f);
+ m_Rows[2] = Vector4(x.GetZ(), y.GetZ(), z.GetZ(), 0.0f);
m_Rows[3] = m_Rows[0]*-Eye.GetX() + m_Rows[1]*-Eye.GetY() + m_Rows[2]*-Eye.GetZ();
+ m_Rows[3][3] = 1.0f;
}
void Matrix44::CreatePerspective(float FoVy, float Aspect, float Near, float Far)
@@ -54,21 +55,134 @@ void Matrix44::CreatePerspective(float FoVy, float Aspect, float Near, float Far
c = -(Far + Near) / (Far - Near);
d = -(2.0f * Far * Near) / (Far - Near);
- m_Rows[0] = Float4(x, 0, a, 0);
- m_Rows[1] = Float4(0, y, b, 0);
- m_Rows[2] = Float4(0, 0, c, d);
- m_Rows[3] = Float4(0, 0, -1, 0);
+ m_Rows[0] = Vector4(x, 0, 0, 0);
+ m_Rows[1] = Vector4(0, y, 0, 0);
+ m_Rows[2] = Vector4(a, b, c, -1);
+ m_Rows[3] = Vector4(0, 0, d, 0);
+}
+
+// Inverse code from the GLU library.
+Matrix44 Inverse(const Matrix44& m)
+{
+#define SWAP_ROWS(a, b) { float *_tmp = a; (a)=(b); (b)=_tmp; }
+#define MAT(m,c,r) m.m_Rows[r][c]
+
+ float wtmp[4][8];
+ float m0, m1, m2, m3, s;
+ float *r0, *r1, *r2, *r3;
+
+ r0 = wtmp[0], r1 = wtmp[1], r2 = wtmp[2], r3 = wtmp[3];
+
+ r0[0] = MAT(m,0,0), r0[1] = MAT(m,0,1),
+ r0[2] = MAT(m,0,2), r0[3] = MAT(m,0,3),
+ r0[4] = 1.0, r0[5] = r0[6] = r0[7] = 0.0,
+
+ r1[0] = MAT(m,1,0), r1[1] = MAT(m,1,1),
+ r1[2] = MAT(m,1,2), r1[3] = MAT(m,1,3),
+ r1[5] = 1.0, r1[4] = r1[6] = r1[7] = 0.0,
+
+ r2[0] = MAT(m,2,0), r2[1] = MAT(m,2,1),
+ r2[2] = MAT(m,2,2), r2[3] = MAT(m,2,3),
+ r2[6] = 1.0, r2[4] = r2[5] = r2[7] = 0.0,
+
+ r3[0] = MAT(m,3,0), r3[1] = MAT(m,3,1),
+ r3[2] = MAT(m,3,2), r3[3] = MAT(m,3,3),
+ r3[7] = 1.0, r3[4] = r3[5] = r3[6] = 0.0;
+
+ // choose pivot - or die
+ if (fabs(r3[0])>fabs(r2[0])) SWAP_ROWS(r3, r2);
+ if (fabs(r2[0])>fabs(r1[0])) SWAP_ROWS(r2, r1);
+ if (fabs(r1[0])>fabs(r0[0])) SWAP_ROWS(r1, r0);
+// if (0.0 == r0[0]) return GL_FALSE;
+
+ // eliminate first variable
+ m1 = r1[0]/r0[0]; m2 = r2[0]/r0[0]; m3 = r3[0]/r0[0];
+ s = r0[1]; r1[1] -= m1 * s; r2[1] -= m2 * s; r3[1] -= m3 * s;
+ s = r0[2]; r1[2] -= m1 * s; r2[2] -= m2 * s; r3[2] -= m3 * s;
+ s = r0[3]; r1[3] -= m1 * s; r2[3] -= m2 * s; r3[3] -= m3 * s;
+ s = r0[4];
+ if (s != 0.0) { r1[4] -= m1 * s; r2[4] -= m2 * s; r3[4] -= m3 * s; }
+ s = r0[5];
+ if (s != 0.0) { r1[5] -= m1 * s; r2[5] -= m2 * s; r3[5] -= m3 * s; }
+ s = r0[6];
+ if (s != 0.0) { r1[6] -= m1 * s; r2[6] -= m2 * s; r3[6] -= m3 * s; }
+ s = r0[7];
+ if (s != 0.0) { r1[7] -= m1 * s; r2[7] -= m2 * s; r3[7] -= m3 * s; }
+
+ // choose pivot - or die
+ if (fabs(r3[1])>fabs(r2[1])) SWAP_ROWS(r3, r2);
+ if (fabs(r2[1])>fabs(r1[1])) SWAP_ROWS(r2, r1);
+// if (0.0 == r1[1]) return GL_FALSE;
+
+ // eliminate second variable
+ m2 = r2[1]/r1[1]; m3 = r3[1]/r1[1];
+ r2[2] -= m2 * r1[2]; r3[2] -= m3 * r1[2];
+ r2[3] -= m2 * r1[3]; r3[3] -= m3 * r1[3];
+ s = r1[4]; if (0.0 != s) { r2[4] -= m2 * s; r3[4] -= m3 * s; }
+ s = r1[5]; if (0.0 != s) { r2[5] -= m2 * s; r3[5] -= m3 * s; }
+ s = r1[6]; if (0.0 != s) { r2[6] -= m2 * s; r3[6] -= m3 * s; }
+ s = r1[7]; if (0.0 != s) { r2[7] -= m2 * s; r3[7] -= m3 * s; }
+
+ // choose pivot - or die
+ if (fabs(r3[2])>fabs(r2[2])) SWAP_ROWS(r3, r2);
+// if (0.0 == r2[2]) return GL_FALSE;
+
+ // eliminate third variable
+ m3 = r3[2]/r2[2];
+ r3[3] -= m3 * r2[3], r3[4] -= m3 * r2[4],
+ r3[5] -= m3 * r2[5], r3[6] -= m3 * r2[6],
+ r3[7] -= m3 * r2[7];
+
+ // last check
+// if (0.0 == r3[3]) return GL_FALSE;
+
+ s = 1.0f/r3[3]; // now back substitute row 3
+ r3[4] *= s; r3[5] *= s; r3[6] *= s; r3[7] *= s;
+
+ m2 = r2[3]; // now back substitute row 2
+ s = 1.0f/r2[2];
+ r2[4] = s * (r2[4] - r3[4] * m2), r2[5] = s * (r2[5] - r3[5] * m2),
+ r2[6] = s * (r2[6] - r3[6] * m2), r2[7] = s * (r2[7] - r3[7] * m2);
+ m1 = r1[3];
+ r1[4] -= r3[4] * m1, r1[5] -= r3[5] * m1,
+ r1[6] -= r3[6] * m1, r1[7] -= r3[7] * m1;
+ m0 = r0[3];
+ r0[4] -= r3[4] * m0, r0[5] -= r3[5] * m0,
+ r0[6] -= r3[6] * m0, r0[7] -= r3[7] * m0;
+
+ m1 = r1[2]; // now back substitute row 1
+ s = 1.0f/r1[1];
+ r1[4] = s * (r1[4] - r2[4] * m1), r1[5] = s * (r1[5] - r2[5] * m1),
+ r1[6] = s * (r1[6] - r2[6] * m1), r1[7] = s * (r1[7] - r2[7] * m1);
+ m0 = r0[2];
+ r0[4] -= r2[4] * m0, r0[5] -= r2[5] * m0,
+ r0[6] -= r2[6] * m0, r0[7] -= r2[7] * m0;
+
+ m0 = r0[1]; // now back substitute row 0
+ s = 1.0f/r0[0];
+ r0[4] = s * (r0[4] - r1[4] * m0), r0[5] = s * (r0[5] - r1[5] * m0),
+ r0[6] = s * (r0[6] - r1[6] * m0), r0[7] = s * (r0[7] - r1[7] * m0);
+
+ Matrix44 out(Vector4(r0[4], r1[4], r2[4], r3[4]),
+ Vector4(r0[5], r1[5], r2[5], r3[5]),
+ Vector4(r0[6], r1[6], r2[6], r3[6]),
+ Vector4(r0[7], r1[7], r2[7], r3[7]));
+
+ return out;
+
+#undef MAT
+#undef SWAP_ROWS
}
// ============================================================================
-// Other Functions.
+// Project/Unproject a point.
-// Convert object coordinates to screen coordinates.
+// Convert world coordinates to screen coordinates.
Point3 ProjectPoint(const Point3& Pt, const Matrix44& ModelView, const Matrix44& Projection, const int Viewport[4])
{
- Point3 Tmp;
+ Vector4 Tmp;
- Tmp = Pt * ModelView;
+ Tmp = Vector4(Pt) * ModelView;
Tmp = Tmp * Projection;
// Normalize.
@@ -77,3 +191,102 @@ Point3 ProjectPoint(const Point3& Pt, const Matrix44& ModelView, const Matrix44&
// Screen coordinates.
return Point3(Viewport[0]+(1+Tmp[0])*Viewport[2]/2, Viewport[1]+(1+Tmp[1])*Viewport[3]/2, (1+Tmp[2])/2);
}
+
+// Convert screen coordinates to world coordinates.
+Point3 UnprojectPoint(const Point3& Point, const Matrix44& ModelView, const Matrix44& Projection, const int Viewport[4])
+{
+ Point3 Tmp = Point;
+ UnprojectPoints(&Tmp, 1, ModelView, Projection, Viewport);
+ return Tmp;
+}
+
+void UnprojectPoints(Point3* Points, int NumPoints, const Matrix44& ModelView, const Matrix44& Projection, const int Viewport[4])
+{
+ // Calculate the screen to model transform.
+ Matrix44 Transform = Inverse(ModelView * Projection);
+
+ for (int i = 0; i < NumPoints; i++)
+ {
+ Vector4 Tmp;
+
+ // Convert the point to homogeneous coordinates.
+ Tmp[0] = (Points[i][0] - Viewport[0]) * 2.0f / Viewport[2] - 1.0f;
+ Tmp[1] = (Points[i][1] - Viewport[1]) * 2.0f / Viewport[3] - 1.0f;
+ Tmp[2] = Points[i][2] * 2.0f - 1.0f;
+ Tmp[3] = 1.0f;
+
+ Tmp = Tmp * Transform;
+
+ if (Tmp[3] != 0.0f)
+ Tmp /= Tmp[3];
+
+ Points[i] = Point3(Tmp[0], Tmp[1], Tmp[2]);
+ }
+}
+
+// ============================================================================
+// Geometry functions.
+
+// Sutherland-Hodgman method of clipping a polygon to a plane.
+void PolygonPlaneClip(Point3* InPoints, int NumInPoints, Point3* OutPoints, int* NumOutPoints, const Vector4& Plane)
+{
+ Point3 *s, *p, i;
+
+ *NumOutPoints = 0;
+ s = &InPoints[NumInPoints-1];
+
+ for (int j = 0; j < NumInPoints; j++)
+ {
+ p = &InPoints[j];
+
+ if (Dot3(*p, Plane) + Plane[3] <= 0)
+ {
+ if (Dot3(*s, Plane) + Plane[3] <= 0)
+ {
+ // Both points inside.
+ OutPoints[*NumOutPoints] = *p;
+ *NumOutPoints = *NumOutPoints + 1;
+ }
+ else
+ {
+ // Outside, inside.
+ LinePlaneIntersection(i, *s, *p, Plane);
+
+ OutPoints[*NumOutPoints] = i;
+ *NumOutPoints = *NumOutPoints + 1;
+ OutPoints[*NumOutPoints] = *p;
+ *NumOutPoints = *NumOutPoints + 1;
+ }
+ }
+ else
+ {
+ if (Dot3(*s, Plane) + Plane[3] <= 0)
+ {
+ // Inside, outside.
+ LinePlaneIntersection(i, *s, *p, Plane);
+
+ OutPoints[*NumOutPoints] = i;
+ *NumOutPoints = *NumOutPoints + 1;
+ }
+ }
+
+ s = p;
+ }
+}
+
+// Return the intersction point of a line and a plane, or false if they are parallel.
+bool LinePlaneIntersection(Point3& Intersection, const Point3& Start, const Point3& End, const Vector4& Plane)
+{
+ Vector3 Dir = End - Start;
+
+ float t1 = Dot3(Plane, Start) + Plane[3];
+ float t2 = Dot3(Plane, Dir);
+
+ if (t2 == 0.0f)
+ return false;
+
+ Intersection = Start - (t1 / t2) * Dir;
+
+ return true;
+}
+
diff --git a/common/algebra.h b/common/algebra.h
index 36d5b7b..5d614c1 100644
--- a/common/algebra.h
+++ b/common/algebra.h
@@ -6,38 +6,50 @@
//
// Simple math library and linear algebra functions.
//
-// Everything is based on the Float4 class, so changing that class should be enough
+// Everything is based on the Vector4 class, so changing that class should be enough
// to add support for compiler specific math intrinsics.
//
// Functions that end with 34 mean that they don't care what happens to the 4th
// component, it can either be affected or not.
//
+// Matrices are represented as row-major, so we pre-multiply instead of post-multiplying
+// like you would in a column major notation.
+//
+// OpenGL only expects a matrix to be an array of 16 floats so it doesn't matter what
+// notation we use.
+//
+// v[0] v[1] v[2] v[3] <- x, y, z, w
+//
+// m[0] m[1] m[2] m[3] <- x axis
+// m[4] m[5] m[6] m[7] <- y axis
+// m[8] m[9] m[10] m[11] <- z axis
+// m[12] m[13] m[14] m[15] <- translation
+//
// TODO: Move this define to config.h
#define LC_MATH_FLOAT
//#define LC_MATH_SSE
// Classes defined in this file:
-class Float4;
class Point3;
class Vector3;
+class Vector4;
class Quaternion;
-class Matrix33;
class Matrix44;
// ============================================================================
-// Float4 class (float version).
+// Vector4 class (float version).
#ifdef LC_MATH_FLOAT
-class Float4
+class Vector4
{
public:
// Constructors.
- inline Float4() { }
- inline explicit Float4(const float _x, const float _y, const float _z)
+ inline Vector4() { }
+ inline explicit Vector4(const float _x, const float _y, const float _z)
: x(_x), y(_y), z(_z) { }
- inline explicit Float4(const float _x, const float _y, const float _z, const float _w)
+ inline explicit Vector4(const float _x, const float _y, const float _z, const float _w)
: x(_x), y(_y), z(_z), w(_w) { }
// Get/Set functions.
@@ -50,69 +62,81 @@ public:
inline void SetZ(const float _z) { z = _z; }
inline void SetW(const float _w) { w = _w; }
- template<typename T>
- inline const float operator[](T i) const { return ((const float*)this)[i]; }
+ inline float& operator[](int i) const { return ((float*)this)[i]; }
// Comparison.
- friend inline bool operator==(const Float4& a, const Float4& b)
+ friend inline bool operator==(const Vector4& a, const Vector4& b)
{ return (a.x == b.x) && (a.y == b.y) && (a.z == b.z) && (a.w == b.w); }
- friend inline bool Compare3(const Float4& a, const Float4& b)
+ friend inline bool Compare3(const Vector4& a, const Vector4& b)
{ return (a.x == b.x) && (a.y == b.y) && (a.z == b.z); }
// Math operations for 4 components.
- friend inline Float4 operator+(const Float4& a, const Float4& b)
- { return Float4(a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w); }
+ friend inline Vector4 operator+(const Vector4& a, const Vector4& b)
+ { return Vector4(a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w); }
- friend inline Float4 operator-(const Float4& a, const Float4& b)
- { return Float4(a.x-b.x, a.y-b.y, a.z-b.z, a.w-b.w); }
+ friend inline Vector4 operator-(const Vector4& a, const Vector4& b)
+ { return Vector4(a.x-b.x, a.y-b.y, a.z-b.z, a.w-b.w); }
- friend inline Float4 operator*(const Float4& a, float f)
- { return Float4(a.x*f, a.y*f, a.z*f, a.w*f); }
+ friend inline Vector4 operator*(const Vector4& a, float f)
+ { return Vector4(a.x*f, a.y*f, a.z*f, a.w*f); }
- friend inline Float4 operator*(const Float4& a, const Float4& b)
- { return Float4(a.x*b.x, a.y*b.y, a.z*b.z, a.w*b.w); }
+ friend inline Vector4 operator*(const Vector4& a, const Vector4& b)
+ { return Vector4(a.x*b.x, a.y*b.y, a.z*b.z, a.w*b.w); }
- friend inline Float4 operator/(const Float4& a, float f)
- { return Float4(a.x/f, a.y/f, a.z/f, a.w/f); }
+ friend inline Vector4 operator/(const Vector4& a, float f)
+ { return Vector4(a.x/f, a.y/f, a.z/f, a.w/f); }
- friend inline Float4 operator-(const Float4& a)
- { return Float4(-a.x, -a.y, -a.z, -a.w); }
+ friend inline Vector4 operator/=(Vector4& a, float f)
+ { a = Vector4(a.x/f, a.y/f, a.z/f, a.w/f); return a; }
+
+ friend inline Vector4 operator-(const Vector4& a)
+ { return Vector4(-a.x, -a.y, -a.z, -a.w); }
// Math operations ignoring the 4th component.
- friend inline Float4 Add34(const Float4& a, const Float4& b)
- { return Float4(a.x+b.x, a.y+b.y, a.z+b.z); }
+ friend inline Vector4 Add34(const Vector4& a, const Vector4& b)
+ { return Vector4(a.x+b.x, a.y+b.y, a.z+b.z); }
- friend inline Float4 Subtract34(const Float4& a, const Float4& b)
- { return Float4(a.x-b.x, a.y-b.y, a.z-b.z); }
+ friend inline Vector4 Subtract34(const Vector4& a, const Vector4& b)
+ { return Vector4(a.x-b.x, a.y-b.y, a.z-b.z); }
- friend inline Float4 Multiply34(const Float4& a, float f)
- { return Float4(a.x*f, a.y*f, a.z*f); }
+ friend inline Vector4 Multiply34(const Vector4& a, float f)
+ { return Vector4(a.x*f, a.y*f, a.z*f); }
- friend inline Float4 Multiply34(const Float4& a, const Float4& b)
- { return Float4(a.x*b.x, a.y*b.y, a.z*b.z); }
+ friend inline Vector4 Multiply34(const Vector4& a, const Vector4& b)
+ { return Vector4(a.x*b.x, a.y*b.y, a.z*b.z); }
- friend inline Float4 Divide34(const Float4& a, float f)
- { return Float4(a.x/f, a.y/f, a.z/f); }
+ friend inline Vector4 Divide34(const Vector4& a, float f)
+ { return Vector4(a.x/f, a.y/f, a.z/f); }
- friend inline Float4 Negate34(const Float4& a)
- { return Float4(-a.x, -a.y, -a.z, -a.w); }
+ friend inline Vector4 Negate34(const Vector4& a)
+ { return Vector4(-a.x, -a.y, -a.z, -a.w); }
// Dot product.
- friend inline float Dot3(const Float4& a, const Float4& b)
+ friend inline float Dot3(const Vector4& a, const Vector4& b)
{ return a.x*b.x + a.y*b.y + a.z*b.z; }
+ friend inline float Dot4(const Vector4& a, const Vector4& b)
+ { return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w; }
+
// Cross product.
- friend inline Float4 Cross3(const Float4& a, const Float4& b)
- { return Float4(a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x); }
+ friend inline Vector4 Cross3(const Vector4& a, const Vector4& b)
+ { return Vector4(a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x); }
// Other functions.
inline float Length3() const
{ return sqrtf(Dot3(*this, *this)); }
- inline void Normalize3()
+ inline void Normalize34()
{ *this = *this / Length3(); }
+ inline void Abs34()
+ {
+ if (x < 0.0f) x = -x;
+ if (y < 0.0f) y = -y;
+ if (z < 0.0f) z = -z;
+ }
+
inline void Abs()
{
if (x < 0.0f) x = -x;
@@ -128,23 +152,23 @@ protected:
#endif
// ============================================================================
-// Float4 class (SSE version).
+// Vector4 class (SSE version).
#ifdef LC_MATH_SSE
// If you can't find this file you need to install the VS6 Processor Pack.
#include <xmmintrin.h>
-class __declspec(align(16)) Float4
+class __declspec(align(16)) Vector4
{
public:
// Constructors.
- inline Float4() { }
- inline explicit Float4(const __m128& _xyzw)
+ inline Vector4() { }
+ inline explicit Vector4(const __m128& _xyzw)
: xyzw(_xyzw) { }
- inline explicit Float4(const float _x, const float _y, const float _z)
+ inline explicit Vector4(const float _x, const float _y, const float _z)
: xyzw(_mm_setr_ps(_x, _y, _z, _z)) { }
- inline explicit Float4(const float _x, const float _y, const float _z, const float _w)
+ inline explicit Vector4(const float _x, const float _y, const float _z, const float _w)
: xyzw(_mm_setr_ps(_x, _y, _z, _w)) { }
// Get/Set functions.
@@ -173,59 +197,58 @@ public:
xyzw = _mm_shuffle_ps(xyzw, zzww, _MM_SHUFFLE(2, 0, 1, 0));
}
- template<typename T>
- inline const float operator[](T i) const { return ((const float*)this)[i]; }
+ inline float& operator[](int i) const { return ((const float*)this)[i]; }
// Comparison.
- friend inline bool operator==(const Float4& a, const Float4& b)
+ friend inline bool operator==(const Vector4& a, const Vector4& b)
{ return !_mm_movemask_ps(_mm_cmpneq_ps(a.xyzw, b.xyzw)); }
- friend inline bool Compare3(const Float4& a, const Float4& b)
+ friend inline bool Compare3(const Vector4& a, const Vector4& b)
{ return (_mm_movemask_ps(_mm_cmpeq_ps(a.xyzw, b.xyzw)) & 0x7) == 0x7; }
// Math operations for 4 components.
- friend inline Float4 operator+(const Float4& a, const Float4& b)
- { return Float4(_mm_add_ps(a.xyzw, b.xyzw)); }
+ friend inline Vector4 operator+(const Vector4& a, const Vector4& b)
+ { return Vector4(_mm_add_ps(a.xyzw, b.xyzw)); }
- friend inline Float4 operator-(const Float4& a, const Float4& b)
- { return Float4(_mm_sub_ps(a.xyzw, b.xyzw)); }
+ friend inline Vector4 operator-(const Vector4& a, const Vector4& b)
+ { return Vector4(_mm_sub_ps(a.xyzw, b.xyzw)); }
- friend inline Float4 operator*(const Float4& a, float f)
- { return Float4(_mm_mul_ps(a.xyzw, _mm_load_ps1(&f))); }
+ friend inline Vector4 operator*(const Vector4& a, float f)
+ { return Vector4(_mm_mul_ps(a.xyzw, _mm_load_ps1(&f))); }
- friend inline Float4 operator*(const Float4& a, const Float4& b)
- { return Float4(_mm_mul_ps(a.xyzw, b.xyzw)); }
+ friend inline Vector4 operator*(const Vector4& a, const Vector4& b)
+ { return Vector4(_mm_mul_ps(a.xyzw, b.xyzw)); }
- friend inline Float4 operator/(const Float4& a, float f)
- { return Float4(_mm_div_ps(a.xyzw, _mm_load_ps1(&f))); }
+ friend inline Vector4 operator/(const Vector4& a, float f)
+ { return Vector4(_mm_div_ps(a.xyzw, _mm_load_ps1(&f))); }
- friend inline Float4 operator-(const Float4& a)
+ friend inline Vector4 operator-(const Vector4& a)
{
static const __declspec(align(16)) unsigned int Mask[4] = { 0x80000000, 0x80000000, 0x80000000, 0x80000000 }
- return Float4(_mm_xor_ps(xyzw, *(__m128*)&Mask));
+ return Vector4(_mm_xor_ps(xyzw, *(__m128*)&Mask));
}
// Math operations ignoring the 4th component.
- friend inline Float4 Add34(const Float4& a, const Float4& b)
+ friend inline Vector4 Add34(const Vector4& a, const Vector4& b)
{ return a*b }
- friend inline Float4 Subtract34(const Float4& a, const Float4& b)
+ friend inline Vector4 Subtract34(const Vector4& a, const Vector4& b)
{ return a-b; }
- friend inline Float4 Multiply34(const Float4& a, float f)
+ friend inline Vector4 Multiply34(const Vector4& a, float f)
{ return a*f; }
- friend inline Float4 Multiply34(const Float4& a, const Float4& b)
+ friend inline Vector4 Multiply34(const Vector4& a, const Vector4& b)
{ return a*b; }
- friend inline Float4 Divide34(const Float4& a, float f)
+ friend inline Vector4 Divide34(const Vector4& a, float f)
{ return a/f; }
- friend inline Float4 Negate34(const Float4& a)
+ friend inline Vector4 Negate34(const Vector4& a)
{ return -a; }
// Dot product.
- friend inline float Dot3(const Float4& a, const Float4& b)
+ friend inline float Dot3(const Vector4& a, const Vector4& b)
{
__m128 tmp = _mm_mul_ps(a.xyzw, b.xyzw);
__m128 yz = _mm_add_ss(_mm_shuffle_ps(tmp, tmp, _MM_SHUFFLE(1, 1, 1, 1)), _mm_shuffle_ps(tmp, tmp, _MM_SHUFFLE(2, 2, 2, 2)));
@@ -235,13 +258,13 @@ public:
}
// Cross product.
- friend inline Float4 Cross3(const Float4& a, const Float4& b)
+ friend inline Vector4 Cross3(const Vector4& a, const Vector4& b)
{
// a(yzx)*b(zxy)-a(zxy)*b(yzx)
__m128 r1 = _mm_mul_ps(_mm_shuffle_ps(a.xyzw, a.xyzw, _MM_SHUFFLE(0, 0, 2, 1)), _mm_shuffle_ps(b.xyzw, b.xyzw, _MM_SHUFFLE(0, 1, 0, 2)));
__m128 r2 = _mm_mul_ps(_mm_shuffle_ps(a.xyzw, a.xyzw, _MM_SHUFFLE(0, 1, 0, 2)), _mm_shuffle_ps(b.xyzw, b.xyzw, _MM_SHUFFLE(0, 0, 2, 1)));
- return Float4(_mm_sub_ps(r1, r2));
+ return Vector4(_mm_sub_ps(r1, r2));
}
// Other functions.
@@ -255,7 +278,7 @@ public:
return *(const float*)&tmp;
}
- inline void Normalize3()
+ inline void Normalize34()
{
__m128 tmp = _mm_mul_ps(xyzw, xyzw);
__m128 yz = _mm_add_ss(_mm_shuffle_ps(tmp, tmp, _MM_SHUFFLE(1, 1, 1, 1)), _mm_shuffle_ps(tmp, tmp, _MM_SHUFFLE(2, 2, 2, 2)));
@@ -285,13 +308,13 @@ class Point3
public:
// Constructors.
inline Point3() { }
- inline explicit Point3(const Float4& _v)
+ inline explicit Point3(const Vector4& _v)
: m_Value(_v) { }
inline explicit Point3(const float _x, const float _y, const float _z)
: m_Value(_x, _y, _z) { }
// Get/Set functions.
- inline const Float4& GetValue() const { return m_Value; }
+ inline const Vector4& GetValue() const { return m_Value; }
inline float GetX() const { return m_Value.GetX(); }
inline float GetY() const { return m_Value.GetY(); }
inline float GetZ() const { return m_Value.GetZ(); }
@@ -299,17 +322,15 @@ public:
inline void SetY(const float _y) { m_Value.SetY(_y); }
inline void SetZ(const float _z) { m_Value.SetZ(_z); }
- template<typename T>
- inline const float operator[](T i) const { return m_Value[i]; }
+ inline operator const Vector4() const
+ { return Vector4(m_Value[0], m_Value[1], m_Value[2], 1.0f); }
+
+ inline float& operator[](int i) const { return m_Value[i]; }
// Math operations.
- template<typename T> inline Point3& operator+=(const T& a) { return *this = *this + a; }
- template<typename T> inline Point3& operator-=(const T& a) { return *this = *this - a; }
- template<typename T> inline Point3& operator/=(const T& a) { return *this = *this / a; }
- template<typename T> inline Point3& operator*=(const T& a) { return *this = *this * a; }
protected:
- Float4 m_Value;
+ Vector4 m_Value;
};
@@ -322,13 +343,13 @@ public:
// Constructors.
inline Vector3()
{ }
- inline explicit Vector3(const Float4& _v)
+ inline explicit Vector3(const Vector4& _v)
: m_Value(_v) { }
inline explicit Vector3(const float _x, const float _y, const float _z)
: m_Value(_x, _y, _z) { }
// Get/Set functions.
- inline const Float4& GetValue() const { return m_Value; }
+ inline const Vector4& GetValue() const { return m_Value; }
inline float GetX() const { return m_Value.GetX(); }
inline float GetY() const { return m_Value.GetY(); }
inline float GetZ() const { return m_Value.GetZ(); }
@@ -336,14 +357,17 @@ public:
inline void SetY(const float _y) { m_Value.SetY(_y); }
inline void SetZ(const float _z) { m_Value.SetZ(_z); }
- template<typename T>
- inline const float operator[](T i) const { return m_Value[i]; }
+ inline operator const Vector4() const
+ { return Vector4(m_Value[0], m_Value[1], m_Value[2], 0.0f); }
+
+ inline float& operator[](int i) const { return m_Value[i]; }
// Math operations.
- template<typename T> inline Vector3& operator+=(const T& a) { return *this = *this + a; }
- template<typename T> inline Vector3& operator-=(const T& a) { return *this = *this - a; }
- template<typename T> inline Vector3& operator/=(const T& a) { return *this = *this / a; }
- template<typename T> inline Vector3& operator*=(const T& a) { return *this = *this * a; }
+ friend inline Vector3 operator+=(Vector3& a, const Vector3& b)
+ { a.m_Value = a.m_Value + b.m_Value; return a; }
+
+ friend inline Vector3 operator*=(Vector3& a, float b)
+ { a.m_Value = a.m_Value * b; return a; }
// Other functions.
inline float Length() const
@@ -352,14 +376,14 @@ public:
inline float LengthSquared() const
{ return Dot3(m_Value, m_Value); }
- inline void Normalize()
- { m_Value.Normalize3(); }
+ inline const Vector3& Normalize()
+ { m_Value.Normalize34(); return *this; }
inline void Abs()
- { m_Value.Abs(); }
+ { m_Value.Abs34(); }
protected:
- Float4 m_Value;
+ Vector4 m_Value;
};
@@ -450,7 +474,7 @@ public:
// Constructors.
inline Quaternion()
{ }
- inline explicit Quaternion(const Float4& _v)
+ inline explicit Quaternion(const Vector4& _v)
: m_Value(_v) { }
inline explicit Quaternion(const float _x, const float _y, const float _z, const float _w)
: m_Value(_x, _y, _z, _w) { }
@@ -469,24 +493,24 @@ public:
inline const float operator[](T i) const { return m_Value[i]; }
// Conversions.
- inline void FromAxisAngle(const Float4& AxisAngle)
+ inline void FromAxisAngle(const Vector4& AxisAngle)
{
float s = sinf(AxisAngle[3] / 2.0f);
- m_Value = Float4(AxisAngle[0] * s, AxisAngle[1] * s, AxisAngle[2] * s, cosf(AxisAngle[3] / 2.0f));
+ m_Value = Vector4(AxisAngle[0] * s, AxisAngle[1] * s, AxisAngle[2] * s, cosf(AxisAngle[3] / 2.0f));
}
- inline void ToAxisAngle(Float4& AxisAngle) const
+ inline void ToAxisAngle(Vector4& AxisAngle) const
{
float Len = m_Value[0]*m_Value[0] + m_Value[1]*m_Value[1] + m_Value[2]*m_Value[2];
if (Len > 0.001f)
{
float f = 1.0f / sqrtf(Len);
- AxisAngle = Float4(m_Value[0] * f, m_Value[1] * f, m_Value[2] * f, acosf(m_Value[3]) * 2.0f);
+ AxisAngle = Vector4(m_Value[0] * f, m_Value[1] * f, m_Value[2] * f, acosf(m_Value[3]) * 2.0f);
}
else
{
- AxisAngle = Float4(0, 0, 1, 0);
+ AxisAngle = Vector4(0, 0, 1, 0);
}
}
@@ -526,7 +550,7 @@ public:
}
protected:
- Float4 m_Value;
+ Vector4 m_Value;
};
@@ -588,43 +612,96 @@ protected:
Vector3 m_Rows[3];
};
+// ============================================================================
+// 4x3 Matrix class.
+/*
+class Matrix43
+{
+public:
+ inline Matrix43()
+ { }
+ inline Matrix43(const Vector4& Row0, const Vector4& Row1, const Vector4& Row2, const Vector4& Row3)
+ { m_Rows[0] = Row0; m_Rows[1] = Row1; m_Rows[2] = Row2; m_Rows[3] = Row3; }
+
+ inline void SetTranslation(const Point3& a)
+ { m_Rows[3] = Vector4(a.GetX(), a.GetY(), a.GetZ(), 0.0f); }
+
+ void CreateLookAt(const Point3& Eye, const Point3& Target, const Vector3& Up);
+ void CreatePerspective(float FoVy, float Aspect, float Near, float Far);
+ friend inline Point3 operator*(const Point3& a, const Matrix43& b)
+ { return Point3(b.m_Rows[0]*a.GetX() + b.m_Rows[1]*a.GetY() + b.m_Rows[2]*a.GetZ() + b.m_Rows[3]); }
+
+ friend inline Vector4 operator*(const Vector4& a, const Matrix43& b)
+ { return Point3(b.m_Rows[0]*a.GetX() + b.m_Rows[1]*a.GetY() + b.m_Rows[2]*a.GetZ() + b.m_Rows[3]*a.GetW()); }
+
+protected:
+ Vector4 m_Rows[4];
+};
+*/
// ============================================================================
-// 4x4 Matrix class (actually 4x3).
+// 4x4 Matrix class.
class Matrix44
{
public:
inline Matrix44()
- { }
- inline Matrix44(const Float4& Row0, const Float4& Row1, const Float4& Row2, const Float4& Row3)
- { m_Rows[0] = Row0; m_Rows[1] = Row1; m_Rows[2] = Row2; m_Rows[3] = Row3; }
+ { }
+ inline Matrix44(const Vector4& Row0, const Vector4& Row1, const Vector4& Row2, const Vector4& Row3)
+ { m_Rows[0] = Row0; m_Rows[1] = Row1; m_Rows[2] = Row2; m_Rows[3] = Row3; }
+
+ // Math operations.
+ friend inline Point3 operator*(const Point3& a, const Matrix44& b)
+ { return Point3(b.m_Rows[0]*a.GetX() + b.m_Rows[1]*a.GetY() + b.m_Rows[2]*a.GetZ() + b.m_Rows[3]); }
+
+ friend inline Vector3 operator*(const Vector3& a, const Matrix44& b)
+ { return Vector3(b.m_Rows[0]*a.GetX() + b.m_Rows[1]*a.GetY() + b.m_Rows[2]*a.GetZ()); }
+
+ friend inline Vector4 operator*(const Vector4& a, const Matrix44& b)
+ { return Vector4(b.m_Rows[0]*a.GetX() + b.m_Rows[1]*a.GetY() + b.m_Rows[2]*a.GetZ() + b.m_Rows[3]*a.GetW()); }
+
+ friend inline Matrix44 operator*(const Matrix44& a, const Matrix44& b)
+ {
+ Vector4 Col0(b.m_Rows[0][0], b.m_Rows[1][0], b.m_Rows[2][0], b.m_Rows[3][0]);
+ Vector4 Col1(b.m_Rows[0][1], b.m_Rows[1][1], b.m_Rows[2][1], b.m_Rows[3][1]);
+ Vector4 Col2(b.m_Rows[0][2], b.m_Rows[1][2], b.m_Rows[2][2], b.m_Rows[3][2]);
+ Vector4 Col3(b.m_Rows[0][3], b.m_Rows[1][3], b.m_Rows[2][3], b.m_Rows[3][3]);
+
+ Vector4 Ret0(Dot4(a.m_Rows[0], Col0), Dot4(a.m_Rows[0], Col1), Dot4(a.m_Rows[0], Col2), Dot4(a.m_Rows[0], Col3));
+ Vector4 Ret1(Dot4(a.m_Rows[1], Col0), Dot4(a.m_Rows[1], Col1), Dot4(a.m_Rows[1], Col2), Dot4(a.m_Rows[1], Col3));
+ Vector4 Ret2(Dot4(a.m_Rows[2], Col0), Dot4(a.m_Rows[2], Col1), Dot4(a.m_Rows[2], Col2), Dot4(a.m_Rows[2], Col3));
+ Vector4 Ret3(Dot4(a.m_Rows[3], Col0), Dot4(a.m_Rows[3], Col1), Dot4(a.m_Rows[3], Col2), Dot4(a.m_Rows[3], Col3));
+
+ return Matrix44(Ret0, Ret1, Ret2, Ret3);
+ }
inline void Transpose3()
{
- Float4 a = m_Rows[0], b = m_Rows[1], c = m_Rows[2];
- m_Rows[0] = Float4(a.GetX(), b.GetX(), c.GetX(), a.GetW());
- m_Rows[1] = Float4(a.GetY(), b.GetY(), c.GetY(), b.GetW());
- m_Rows[2] = Float4(a.GetZ(), b.GetZ(), c.GetZ(), c.GetW());
+ Vector4 a = m_Rows[0], b = m_Rows[1], c = m_Rows[2];
+ m_Rows[0] = Vector4(a.GetX(), b.GetX(), c.GetX(), a.GetW());
+ m_Rows[1] = Vector4(a.GetY(), b.GetY(), c.GetY(), b.GetW());
+ m_Rows[2] = Vector4(a.GetZ(), b.GetZ(), c.GetZ(), c.GetW());
}
inline void SetTranslation(const Point3& a)
- { m_Rows[3] = Float4(a.GetX(), a.GetY(), a.GetZ(), 0.0f); }
+ { m_Rows[3] = Vector4(a.GetX(), a.GetY(), a.GetZ(), 1.0f); }
+ friend Matrix44 Inverse(const Matrix44& m);
void CreateLookAt(const Point3& Eye, const Point3& Target, const Vector3& Up);
void CreatePerspective(float FoVy, float Aspect, float Near, float Far);
- friend inline Point3 operator*(const Point3& a, const Matrix44& b)
- { return Point3(b.m_Rows[0]*a.GetX() + b.m_Rows[1]*a.GetY() + b.m_Rows[2]*a.GetZ() + b.m_Rows[3]); }
-
protected:
- Float4 m_Rows[4];
+ Vector4 m_Rows[4];
};
-
// ============================================================================
// Other Functions.
-Point3 ProjectPoint(const Point3& Pt, const Matrix44& ModelView, const Matrix44& Projection, const int Viewport[4]);
+Point3 ProjectPoint(const Point3& Point, const Matrix44& ModelView, const Matrix44& Projection, const int Viewport[4]);
+Point3 UnprojectPoint(const Point3& Point, const Matrix44& ModelView, const Matrix44& Projection, const int Viewport[4]);
+void UnprojectPoints(Point3* Points, int NumPoints, const Matrix44& ModelView, const Matrix44& Projection, const int Viewport[4]);
+
+void PolygonPlaneClip(Point3* InPoints, int NumInPoints, Point3* OutPoints, int* NumOutPoints, const Vector4& Plane);
+bool LinePlaneIntersection(Point3& Intersection, const Point3& Start, const Point3& End, const Vector4& Plane);
#endif
diff --git a/common/camera.h b/common/camera.h
index ac86d3a..840b9f5 100644
--- a/common/camera.h
+++ b/common/camera.h
@@ -40,6 +40,8 @@ public:
public:
void MinIntersectDist (LC_CLICKLINE* pLine);
+ bool IntersectsVolume(const Vector4* Planes, int NumPlanes)
+ { 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)
{
@@ -141,6 +143,8 @@ public:
void FileSave (File& file) const;
void MinIntersectDist (LC_CLICKLINE* pLine);
void Select (bool bSelecting, bool bFocus, bool bMultiple);
+ bool IntersectsVolume(const Vector4* Planes, int NumPlanes)
+ { return false; }
void UpdatePosition(unsigned short nTime, bool bAnimation);
diff --git a/common/curve.h b/common/curve.h
index 874b828..f9a90a6 100755
--- a/common/curve.h
+++ b/common/curve.h
@@ -37,6 +37,8 @@ class CurvePoint : public Object
bool FileLoad (File& file);
void FileSave (File& file) const;
void MinIntersectDist (LC_CLICKLINE* pLine);
+ bool IntersectsVolume(const Vector4* Planes, int NumPlanes)
+ { 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/light.h b/common/light.h
index 1e36b8c..d5d203b 100644
--- a/common/light.h
+++ b/common/light.h
@@ -31,6 +31,8 @@ class LightTarget : public Object
public:
void MinIntersectDist (LC_CLICKLINE* pLine);
+ bool IntersectsVolume(const Vector4* Planes, int NumPlanes)
+ { 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)
{
@@ -90,6 +92,8 @@ public:
void Render (float fLineWidth);
void MinIntersectDist (LC_CLICKLINE* Line);
+ bool IntersectsVolume(const Vector4* Planes, int NumPlanes)
+ { 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 Setup (int index);
diff --git a/common/object.h b/common/object.h
index 291a534..5052bb1 100755
--- a/common/object.h
+++ b/common/object.h
@@ -68,19 +68,23 @@ typedef struct LC_CLICKLINE
class Object
{
- public:
- Object (LC_OBJECT_TYPE nType);
- virtual ~Object ();
+public:
+ Object (LC_OBJECT_TYPE nType);
+ virtual ~Object ();
- public:
- // move the object
- virtual void Move (unsigned short nTime, bool bAnimation, bool bAddKey, float dx, float dy, float dz) = 0;
- // check if the object intersects the ray
- virtual void MinIntersectDist (LC_CLICKLINE* pLine) = 0;
- // bSelecting is the action (add/remove), bFocus means "add focus if selecting"
- // or "remove focus only if deselecting", bMultiple = Ctrl key is down
- virtual void Select (bool bSelecting, bool bFocus, bool bMultiple) = 0;
+public:
+ // Move the object.
+ virtual void Move(unsigned short nTime, bool bAnimation, bool bAddKey, float dx, float dy, float dz) = 0;
+
+ // Check if the object intersects the ray.
+ virtual void MinIntersectDist(LC_CLICKLINE* pLine) = 0;
+
+ // bSelecting is the action (add/remove), bFocus means "add focus if selecting"
+ // or "remove focus only if deselecting", bMultiple = Ctrl key is down
+ 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;
/*
diff --git a/common/piece.cpp b/common/piece.cpp
index 28bdbaf..66ce48b 100644
--- a/common/piece.cpp
+++ b/common/piece.cpp
@@ -12,6 +12,7 @@
#include "piece.h"
#include "group.h"
#include "project.h"
+#include "algebra.h"
#define LC_PIECE_SAVE_VERSION 9 // LeoCAD 0.73
@@ -612,6 +613,208 @@ void Piece::MinIntersectDist(LC_CLICKLINE* pLine)
free(verts);
}
+// Return true if a polygon intersects a set of planes.
+bool PolygonIntersectsPlanes(float* p1, float* p2, float* p3, float* p4, const Vector4* Planes, int NumPlanes)
+{
+ float* Points[4] = { p1, p2, p3, p4 };
+ int Outcodes[4] = { 0, 0, 0, 0 };
+ int NumPoints = (p4 != NULL) ? 4 : 3;
+
+ // First do the Cohen-Sutherland out code test for trivial rejects/accepts.
+ for (int i = 0; i < NumPoints; i++)
+ {
+ Point3 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)
+ Outcodes[i] |= 1 << j;
+ }
+ }
+
+ if (p4 != NULL)
+ {
+ // Polygon completely outside a plane.
+ if ((Outcodes[0] & Outcodes[1] & Outcodes[2] & Outcodes[3]) != 0)
+ return false;
+
+ // If any vertex has an out code of all zeros then we intersect the volume.
+ if (!Outcodes[0] || !Outcodes[1] || !Outcodes[2] || !Outcodes[3])
+ return true;
+ }
+ else
+ {
+ // Polygon completely outside a plane.
+ if ((Outcodes[0] & Outcodes[1] & Outcodes[2]) != 0)
+ return false;
+
+ // If any vertex has an out code of all zeros then we intersect the volume.
+ if (!Outcodes[0] || !Outcodes[1] || !Outcodes[2])
+ return true;
+ }
+
+ // Buffers for clipping the polygon.
+ Point3 ClipPoints[2][8];
+ int NumClipPoints[2];
+ int ClipBuffer = 0;
+
+ NumClipPoints[0] = NumPoints;
+ ClipPoints[0][0] = Point3(p1[0], p1[1], p1[2]);
+ ClipPoints[0][1] = Point3(p2[0], p2[1], p2[2]);
+ ClipPoints[0][2] = Point3(p3[0], p3[1], p3[2]);
+
+ if (NumPoints == 4)
+ ClipPoints[0][3] = Point3(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]);
+ ClipBuffer ^= 1;
+
+ if (!NumClipPoints[ClipBuffer])
+ return false;
+ }
+
+ return true;
+}
+
+bool Piece::IntersectsVolume(const Vector4* Planes, int NumPlanes)
+{
+ // First check the bounding box for quick rejection.
+ Point3 Box[8] =
+ {
+ Point3(m_pPieceInfo->m_fDimensions[0], m_pPieceInfo->m_fDimensions[1], m_pPieceInfo->m_fDimensions[5]),
+ Point3(m_pPieceInfo->m_fDimensions[3], m_pPieceInfo->m_fDimensions[1], m_pPieceInfo->m_fDimensions[5]),
+ Point3(m_pPieceInfo->m_fDimensions[0], m_pPieceInfo->m_fDimensions[1], m_pPieceInfo->m_fDimensions[2]),
+ Point3(m_pPieceInfo->m_fDimensions[3], m_pPieceInfo->m_fDimensions[4], m_pPieceInfo->m_fDimensions[5]),
+ Point3(m_pPieceInfo->m_fDimensions[3], m_pPieceInfo->m_fDimensions[4], m_pPieceInfo->m_fDimensions[2]),
+ Point3(m_pPieceInfo->m_fDimensions[0], m_pPieceInfo->m_fDimensions[4], m_pPieceInfo->m_fDimensions[2]),
+ Point3(m_pPieceInfo->m_fDimensions[0], m_pPieceInfo->m_fDimensions[4], m_pPieceInfo->m_fDimensions[5]),
+ Point3(m_pPieceInfo->m_fDimensions[3], m_pPieceInfo->m_fDimensions[1], m_pPieceInfo->m_fDimensions[2])
+ };
+
+ // TODO: transform the planes to local space instead.
+ Matrix m(m_fRotation, m_fPosition);
+
+ // Start by testing trivial reject/accept cases.
+ int Outcodes[8];
+
+ for (int i = 0; i < 8; i++)
+ {
+ Point3 Point;
+ m.TransformPoint(&Point[0], &Box[i][0]);
+ Outcodes[i] = 0;
+
+ for (int j = 0; j < NumPlanes; j++)
+ {
+ if (Dot3(Point, Planes[j]) + Planes[j][3] > 0)
+ Outcodes[i] |= 1 << j;
+ }
+ }
+
+ int OutcodesOR = 0, OutcodesAND = 0x3f;
+
+ for (i = 0; i < 8; i++)
+ {
+ OutcodesAND &= Outcodes[i];
+ OutcodesOR |= Outcodes[i];
+ }
+
+ // All corners outside the same plane.
+ if (OutcodesAND != 0)
+ return false;
+
+ // All corners inside the volume.
+ if (OutcodesOR == 0)
+ return true;
+
+ // Partial intersection, so check if any triangles are inside.
+ Matrix mat(m_fRotation, m_fPosition);
+ float* verts = (float*)malloc(sizeof(float)*3*m_pPieceInfo->m_nVertexCount);
+ memcpy(verts, m_pPieceInfo->m_fVertexArray, sizeof(float)*3*m_pPieceInfo->m_nVertexCount);
+ mat.TransformPoints(verts, m_pPieceInfo->m_nVertexCount);
+
+ bool ret = false;
+
+ if (m_pPieceInfo->m_nFlags & LC_PIECE_LONGDATA)
+ {
+ unsigned long* info = (unsigned long*)m_pDrawInfo, colors, i;
+ colors = *info;
+ info++;
+
+ while (colors--)
+ {
+ info++;
+
+ for (i = 0; i < *info; i += 4)
+ {
+ if (PolygonIntersectsPlanes(&verts[info[i+1]*3], &verts[info[i+2]*3],
+ &verts[info[i+3]*3], &verts[info[i+4]*3], Planes, NumPlanes))
+ {
+ ret = true;
+ break;
+ }
+ }
+
+ info += *info + 1;
+
+ for (i = 0; i < *info; i += 3)
+ {
+ if (PolygonIntersectsPlanes(&verts[info[i+1]*3], &verts[info[i+2]*3],
+ &verts[info[i+3]*3], NULL, Planes, NumPlanes))
+ {
+ ret = true;
+ break;
+ }
+ }
+
+ info += *info + 1;
+ info += *info + 1;
+ }
+ }
+ else
+ {
+ unsigned short* info = (unsigned short*)m_pDrawInfo, colors, i;
+ colors = *info;
+ info++;
+
+ while (colors--)
+ {
+ info++;
+
+ for (i = 0; i < *info; i += 4)
+ {
+ if (PolygonIntersectsPlanes(&verts[info[i+1]*3], &verts[info[i+2]*3],
+ &verts[info[i+3]*3], &verts[info[i+4]*3], Planes, NumPlanes))
+ {
+ ret = true;
+ break;
+ }
+ }
+
+ info += *info + 1;
+
+ for (i = 0; i < *info; i += 3)
+ {
+ if (PolygonIntersectsPlanes(&verts[info[i+1]*3], &verts[info[i+2]*3],
+ &verts[info[i+3]*3], NULL, Planes, NumPlanes))
+ {
+ ret = true;
+ break;
+ }
+ }
+
+ info += *info + 1;
+ info += *info + 1;
+ }
+ }
+
+ free(verts);
+
+ return ret;
+}
+
void Piece::Move (unsigned short nTime, bool bAnimation, bool bAddKey, float dx, float dy, float dz)
{
m_fPosition[0] += dx;
diff --git a/common/piece.h b/common/piece.h
index d6abfa0..db17f35 100644
--- a/common/piece.h
+++ b/common/piece.h
@@ -34,6 +34,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);
diff --git a/common/project.cpp b/common/project.cpp
index e825406..6de06fe 100644
--- a/common/project.cpp
+++ b/common/project.cpp
@@ -30,6 +30,7 @@
#include "library.h"
#include "texfont.h"
#include "algebra.h"
+#include "debug.h"
// FIXME: temporary function, replace the code !!!
void SystemUpdateFocus (void* p)
@@ -2364,6 +2365,10 @@ void Project::RenderScene(bool bShaded, bool bDrawViewports)
RenderBoxes(true);
}
+#ifdef LC_DEBUG
+ RenderDebugPrimitives();
+#endif
+
// Draw cameras & lights
if (bDrawViewports)
{
@@ -2395,6 +2400,50 @@ void Project::RenderScene(bool bShaded, bool bDrawViewports)
glEnable (GL_LIGHTING);
}
+ // Draw the selection rectangle.
+ if ((m_nCurAction == LC_ACTION_SELECT_REGION) && (m_nTracking == LC_TRACK_LEFT))
+ {
+ int x, y, w, h;
+
+ x = (int)(viewports[m_nViewportMode].dim[m_nActiveViewport][0] * (float)m_nViewX);
+ y = (int)(viewports[m_nViewportMode].dim[m_nActiveViewport][1] * (float)m_nViewY);
+ w = (int)(viewports[m_nViewportMode].dim[m_nActiveViewport][2] * (float)m_nViewX);
+ h = (int)(viewports[m_nViewportMode].dim[m_nActiveViewport][3] * (float)m_nViewY);
+
+ glViewport(x, y, w, h);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, w, 0, h, -1, 1);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef(0.375, 0.375, 0.0);
+
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_LINE_STIPPLE);
+ glLineStipple(5, 0x5555);
+ glColor3f(0, 0, 0);
+
+ float pt1x = (float)(m_nDownX - x);
+ float pt1y = (float)(m_nDownY - y);
+ float pt2x = m_fTrack[0] - x;
+ float pt2y = m_fTrack[1] - y;
+
+ glBegin(GL_LINES);
+ glVertex2f(pt1x, pt1y);
+ glVertex2f(pt2x, pt1y);
+ glVertex2f(pt2x, pt1y);
+ glVertex2f(pt2x, pt2y);
+ glVertex2f(pt2x, pt2y);
+ glVertex2f(pt1x, pt2y);
+ glVertex2f(pt1x, pt2y);
+ glVertex2f(pt1x, pt1y);
+ glEnd();
+
+ glDisable(GL_LINE_STIPPLE);
+ glEnable(GL_DEPTH_TEST);
+ }
+
if (bDrawViewports && m_OverlayActive)
RenderOverlays(vp);
}
@@ -2504,7 +2553,7 @@ void Project::RenderOverlays(int Viewport)
// Draw a disc showing the rotation amount.
if (m_MouseTotalDelta.LengthSquared() != 0.0f && (m_nTracking != LC_TRACK_NONE))
{
- Float4 Rotation;
+ Vector4 Rotation;
float Angle, Step;
switch (m_OverlayMode)
@@ -2512,17 +2561,17 @@ void Project::RenderOverlays(int Viewport)
case LC_OVERLAY_X:
glColor4f(0.8f, 0.0f, 0.0f, 0.3f);
Angle = m_MouseTotalDelta[0];
- Rotation = Float4(0.0f, 0.0f, 0.0f, 0.0f);
+ Rotation = Vector4(0.0f, 0.0f, 0.0f, 0.0f);
break;
case LC_OVERLAY_Y:
glColor4f(0.0f, 0.8f, 0.0f, 0.3f);
Angle = m_MouseTotalDelta[1];
- Rotation = Float4(90.0f, 0.0f, 0.0f, 1.0f);
+ Rotation = Vector4(90.0f, 0.0f, 0.0f, 1.0f);
break;
case LC_OVERLAY_Z:
glColor4f(0.0f, 0.0f, 0.8f, 0.3f);
Angle = m_MouseTotalDelta[2];
- Rotation = Float4(90.0f, 0.0f, -1.0f, 0.0f);
+ Rotation = Vector4(90.0f, 0.0f, -1.0f, 0.0f);
break;
default:
Angle = 0.0f;
@@ -6666,6 +6715,88 @@ void Project::FindObjectFromPoint(int x, int y, LC_CLICKLINE* pLine)
pLight->MinIntersectDist(pLine);
}
+void Project::FindObjectsInBox(float x1, float y1, float x2, float y2, PtrArray<Object>& Objects)
+{
+ int Viewport[4] =
+ {
+ (int)(viewports[m_nViewportMode].dim[m_nActiveViewport][0] * (float)m_nViewX),
+ (int)(viewports[m_nViewportMode].dim[m_nActiveViewport][1] * (float)m_nViewY),
+ (int)(viewports[m_nViewportMode].dim[m_nActiveViewport][2] * (float)m_nViewX),
+ (int)(viewports[m_nViewportMode].dim[m_nActiveViewport][3] * (float)m_nViewY)
+ };
+
+ float Aspect = (float)Viewport[2]/(float)Viewport[3];
+ Camera* Cam = m_pViewCameras[m_nActiveViewport];
+
+ // Build the matrices.
+ Matrix44 ModelView, Projection;
+ ModelView.CreateLookAt(Cam->GetEyePosition(), Cam->GetTargetPosition(), Cam->GetUpVector());
+ Projection.CreatePerspective(Cam->m_fovy, Aspect, Cam->m_zNear, Cam->m_zFar);
+
+ // Find out the top-left and bottom-right corners in screen coordinates.
+ float Left, Top, Bottom, Right;
+
+ if (x1 < x2)
+ {
+ Left = x1;
+ Right = x2;
+ }
+ else
+ {
+ Left = x2;
+ Right = x1;
+ }
+
+ if (y1 > y2)
+ {
+ Top = y1;
+ Bottom = y2;
+ }
+ else
+ {
+ Top = y2;
+ Bottom = y1;
+ }
+
+ // Unproject 6 points to world space.
+ Point3 Corners[6] =
+ {
+ Point3(Left, Top, 0), Point3(Left, Bottom, 0), Point3(Right, Bottom, 0),
+ Point3(Right, Top, 0), Point3(Left, Top, 1), Point3(Right, Bottom, 1)
+ };
+
+ UnprojectPoints(Corners, 6, ModelView, Projection, Viewport);
+
+ // Build the box planes.
+ Vector4 Planes[6];
+
+ Planes[0] = Cross3(Corners[4] - Corners[0], Corners[1] - Corners[0]).Normalize(); // Left
+ Planes[1] = Cross3(Corners[5] - Corners[2], Corners[3] - Corners[2]).Normalize(); // Right
+ Planes[2] = Cross3(Corners[3] - Corners[0], Corners[4] - Corners[0]).Normalize(); // Top
+ Planes[3] = Cross3(Corners[1] - Corners[2], Corners[5] - Corners[2]).Normalize(); // Bottom
+ Planes[4] = Cross3(Corners[1] - Corners[0], Corners[3] - Corners[0]).Normalize(); // Front
+ Planes[5] = Cross3(Corners[1] - Corners[2], Corners[3] - Corners[2]).Normalize(); // Back
+
+ Planes[0][3] = -Dot3(Planes[0], Corners[0]);
+ Planes[1][3] = -Dot3(Planes[1], Corners[5]);
+ Planes[2][3] = -Dot3(Planes[2], Corners[0]);
+ Planes[3][3] = -Dot3(Planes[3], Corners[5]);
+ Planes[4][3] = -Dot3(Planes[4], Corners[0]);
+ Planes[5][3] = -Dot3(Planes[5], Corners[5]);
+
+ // Check if any objects are inside the volume.
+ for (Piece* piece = m_pPieces; piece != NULL; piece = piece->m_pNext)
+ {
+ if (piece->IsVisible(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation))
+ {
+ if (piece->IntersectsVolume(Planes, 6))
+ Objects.Add(piece);
+ }
+ }
+
+ // TODO: lights and cameras.
+}
+
/////////////////////////////////////////////////////////////////////////////
// Mouse handling
@@ -6755,6 +6886,42 @@ bool Project::StopTracking(bool bAccept)
{
switch (m_nCurAction)
{
+ case LC_ACTION_SELECT_REGION:
+ {
+ // Find objects inside the rectangle.
+ PtrArray<Object> Objects;
+ FindObjectsInBox((float)m_nDownX, (float)m_nDownY, m_fTrack[0], m_fTrack[1], Objects);
+
+ // Deselect old pieces.
+ bool Control = Sys_KeyDown(KEY_CONTROL);
+ SelectAndFocusNone(Control);
+
+ // Select new pieces.
+ for (int i = 0; i < Objects.GetSize(); i++)
+ {
+ if (Objects[i]->GetType() == LC_OBJECT_PIECE)
+ {
+ Group* pGroup = ((Piece*)Objects[i])->GetTopGroup();
+ if (pGroup != NULL)
+ {
+ for (Piece* pPiece = m_pPieces; pPiece; pPiece = pPiece->m_pNext)
+ if ((pPiece->IsVisible(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation)) &&
+ (pPiece->GetTopGroup() == pGroup))
+ pPiece->Select (true, false, false);
+ }
+ else
+ Objects[i]->Select(true, false, Control);
+ }
+ else
+ Objects[i]->Select(true, false, Control);
+ }
+
+ // Update screen and UI.
+ UpdateSelection();
+ UpdateAllViews();
+ SystemUpdateFocus(NULL);
+ } break;
+
case LC_ACTION_MOVE:
{
SetModifiedFlag(true);
@@ -6809,10 +6976,13 @@ bool Project::StopTracking(bool bAccept)
}
else if (m_pTrackFile != NULL)
{
- DeleteContents (true);
- FileLoad (m_pTrackFile, true, false);
- delete m_pTrackFile;
- m_pTrackFile = NULL;
+ if (m_nCurAction != LC_ACTION_SELECT_REGION)
+ {
+ DeleteContents (true);
+ FileLoad (m_pTrackFile, true, false);
+ delete m_pTrackFile;
+ m_pTrackFile = NULL;
+ }
}
return true;
@@ -7099,7 +7269,7 @@ void Project::RotateSelectedObjects(const Vector3& Delta)
pPiece->GetRotation(rot);
Quaternion q;
- q.FromAxisAngle(Float4(rot[0], rot[1], rot[2], rot[3] * LC_DTOR));
+ q.FromAxisAngle(Vector4(rot[0], rot[1], rot[2], rot[3] * LC_DTOR));
if (nSel == 1)
{
@@ -7145,7 +7315,7 @@ void Project::RotateSelectedObjects(const Vector3& Delta)
pPiece->ChangeKey(m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, m_bAddKeys, pos, LC_PK_POSITION);
}
- Float4 tmp;
+ Vector4 tmp;
q.ToAxisAngle(tmp);
rot[0] = tmp[0];
rot[1] = tmp[1];
@@ -7533,32 +7703,32 @@ bool Project::OnKeyDown(char nKey, bool bControl, bool bShift)
void Project::OnLeftButtonDown(int x, int y, bool bControl, bool bShift)
{
- GLdouble modelMatrix[16], projMatrix[16], point[3];
- GLint viewport[4];
+ GLdouble modelMatrix[16], projMatrix[16], point[3];
+ GLint viewport[4];
- if (IsDrawing())
- return;
+ if (IsDrawing())
+ return;
- if (m_nTracking != LC_TRACK_NONE)
- if (StopTracking(false))
- return;
+ if (m_nTracking != LC_TRACK_NONE)
+ if (StopTracking(false))
+ return;
- if (SetActiveViewport(x, y))
- return;
+ if (SetActiveViewport(x, y))
+ return;
- m_bTrackCancel = false;
- m_nDownX = x;
- m_nDownY = y;
+ m_bTrackCancel = false;
+ m_nDownX = x;
+ m_nDownY = y;
m_MouseTotalDelta = Vector3(0, 0, 0);
m_MouseSnapLeftover = Vector3(0, 0, 0);
- LoadViewportProjection(m_nActiveViewport);
- glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
- glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
- glGetIntegerv(GL_VIEWPORT, viewport);
+ LoadViewportProjection(m_nActiveViewport);
+ glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
+ glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);
+ glGetIntegerv(GL_VIEWPORT, viewport);
- gluUnProject(x, y, 0.9, modelMatrix, projMatrix, viewport, &point[0], &point[1], &point[2]);
- m_fTrack[0] = (float)point[0]; m_fTrack[1] = (float)point[1]; m_fTrack[2] = (float)point[2];
+ gluUnProject(x, y, 0.9, modelMatrix, projMatrix, viewport, &point[0], &point[1], &point[2]);
+ m_fTrack[0] = (float)point[0]; m_fTrack[1] = (float)point[1]; m_fTrack[2] = (float)point[2];
switch (m_nCurAction)
{
@@ -7575,7 +7745,7 @@ void Project::OnLeftButtonDown(int x, int y, bool bControl, bool bShift)
{
switch (ClickLine.pClosest->GetType ())
{
- case LC_OBJECT_PIECE:
+ case LC_OBJECT_PIECE:
{
Piece* pPiece = (Piece*)ClickLine.pClosest;
Group* pGroup = pPiece->GetTopGroup();
@@ -7592,10 +7762,10 @@ void Project::OnLeftButtonDown(int x, int y, bool bControl, bool bShift)
pPiece->Select (!bFocus, false, false);
} break;
- case LC_OBJECT_CAMERA:
- case LC_OBJECT_CAMERA_TARGET:
- case LC_OBJECT_LIGHT:
- case LC_OBJECT_LIGHT_TARGET:
+ case LC_OBJECT_CAMERA:
+ case LC_OBJECT_CAMERA_TARGET:
+ case LC_OBJECT_LIGHT:
+ case LC_OBJECT_LIGHT_TARGET:
{
SelectAndFocusNone (bControl);
ClickLine.pClosest->Select (true, true, bControl);
@@ -7610,83 +7780,83 @@ void Project::OnLeftButtonDown(int x, int y, bool bControl, bool bShift)
SystemUpdateFocus(ClickLine.pClosest);
}
- if ((m_nCurAction == LC_ACTION_ERASER) && (ClickLine.pClosest != NULL))
- {
- switch (ClickLine.pClosest->GetType ())
- {
- case LC_OBJECT_PIECE:
- {
- Piece* pPiece = (Piece*)ClickLine.pClosest;
- RemovePiece(pPiece);
- delete pPiece;
+ if ((m_nCurAction == LC_ACTION_ERASER) && (ClickLine.pClosest != NULL))
+ {
+ switch (ClickLine.pClosest->GetType ())
+ {
+ case LC_OBJECT_PIECE:
+ {
+ Piece* pPiece = (Piece*)ClickLine.pClosest;
+ RemovePiece(pPiece);
+ delete pPiece;
// CalculateStep();
- RemoveEmptyGroups();
- } break;
+ RemoveEmptyGroups();
+ } break;
- case LC_OBJECT_CAMERA:
- case LC_OBJECT_CAMERA_TARGET:
- {
- Camera* pCamera;
- if (ClickLine.pClosest->GetType () == LC_OBJECT_CAMERA)
- pCamera = (Camera*)ClickLine.pClosest;
- else
- pCamera = ((CameraTarget*)ClickLine.pClosest)->GetParent();
- bool bCanDelete = pCamera->IsUser();
-
- for (int i = 0; i < 4; i++)
- if (pCamera == m_pViewCameras[i])
- bCanDelete = false;
-
- if (bCanDelete)
- {
- Camera* pPrev;
- for (pPrev = m_pCameras; pPrev; pPrev = pPrev->m_pNext)
- if (pPrev->m_pNext == pCamera)
- {
- pPrev->m_pNext = pCamera->m_pNext;
- delete pCamera;
- SystemUpdateCameraMenu(m_pCameras);
- SystemUpdateCurrentCamera(NULL, m_pViewCameras[m_nActiveViewport], m_pCameras);
- break;
- }
- }
- } break;
-
- case LC_OBJECT_LIGHT:
- case LC_OBJECT_LIGHT_TARGET:
- {
-/* pos = m_Lights.Find(pObject->m_pParent);
- m_Lights.RemoveAt(pos);
- delete pObject->m_pParent;
-*/ } break;
- }
+ case LC_OBJECT_CAMERA:
+ case LC_OBJECT_CAMERA_TARGET:
+ {
+ Camera* pCamera;
+ if (ClickLine.pClosest->GetType () == LC_OBJECT_CAMERA)
+ pCamera = (Camera*)ClickLine.pClosest;
+ else
+ pCamera = ((CameraTarget*)ClickLine.pClosest)->GetParent();
+ bool bCanDelete = pCamera->IsUser();
- UpdateSelection();
- UpdateAllViews();
- SetModifiedFlag(true);
- CheckPoint("Deleting");
+ for (int i = 0; i < 4; i++)
+ if (pCamera == m_pViewCameras[i])
+ bCanDelete = false;
+
+ if (bCanDelete)
+ {
+ Camera* pPrev;
+ for (pPrev = m_pCameras; pPrev; pPrev = pPrev->m_pNext)
+ if (pPrev->m_pNext == pCamera)
+ {
+ pPrev->m_pNext = pCamera->m_pNext;
+ delete pCamera;
+ SystemUpdateCameraMenu(m_pCameras);
+ SystemUpdateCurrentCamera(NULL, m_pViewCameras[m_nActiveViewport], m_pCameras);
+ break;
+ }
+ }
+ } break;
+
+ case LC_OBJECT_LIGHT:
+ case LC_OBJECT_LIGHT_TARGET:
+ {
+// pos = m_Lights.Find(pObject->m_pParent);
+// m_Lights.RemoveAt(pos);
+// delete pObject->m_pParent;
+ } break;
+ }
+
+ UpdateSelection();
+ UpdateAllViews();
+ SetModifiedFlag(true);
+ CheckPoint("Deleting");
// AfxGetMainWnd()->PostMessage(WM_LC_UPDATE_INFO, NULL, OT_PIECE);
- }
+ }
- if ((m_nCurAction == LC_ACTION_PAINT) && (ClickLine.pClosest != NULL) &&
- (ClickLine.pClosest->GetType() == LC_OBJECT_PIECE))
- {
- Piece* pPiece = (Piece*)ClickLine.pClosest;
+ if ((m_nCurAction == LC_ACTION_PAINT) && (ClickLine.pClosest != NULL) &&
+ (ClickLine.pClosest->GetType() == LC_OBJECT_PIECE))
+ {
+ Piece* pPiece = (Piece*)ClickLine.pClosest;
- if (pPiece->GetColor() != m_nCurColor)
- {
- bool bTrans = pPiece->IsTransparent();
- pPiece->SetColor(m_nCurColor);
- if (bTrans != pPiece->IsTransparent())
- pPiece->CalculateConnections(m_pConnections, m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, true, true);
-
- SetModifiedFlag(true);
- CheckPoint("Painting");
- SystemUpdateFocus(NULL);
- UpdateAllViews();
- }
- }
- } break;
+ if (pPiece->GetColor() != m_nCurColor)
+ {
+ bool bTrans = pPiece->IsTransparent();
+ pPiece->SetColor(m_nCurColor);
+ if (bTrans != pPiece->IsTransparent())
+ pPiece->CalculateConnections(m_pConnections, m_bAnimation ? m_nCurFrame : m_nCurStep, m_bAnimation, true, true);
+
+ SetModifiedFlag(true);
+ CheckPoint("Painting");
+ SystemUpdateFocus(NULL);
+ UpdateAllViews();
+ }
+ }
+ } break;
case LC_ACTION_INSERT:
case LC_ACTION_LIGHT:
@@ -7840,6 +8010,7 @@ void Project::OnLeftButtonDown(int x, int y, bool bControl, bool bShift)
}
} break;
+ case LC_ACTION_SELECT_REGION:
case LC_ACTION_ZOOM:
case LC_ACTION_ROLL:
case LC_ACTION_PAN:
@@ -8040,6 +8211,26 @@ void Project::OnMouseMove(int x, int y, bool bControl, bool bShift)
switch (m_nCurAction)
{
+ case LC_ACTION_SELECT_REGION:
+ {
+ int ptx = x, pty = y;
+
+ if (ptx >= viewport[0] + viewport[2])
+ ptx = viewport[0] + viewport[2] - 1;
+ else if (ptx <= viewport[0])
+ ptx = viewport[0] + 1;
+
+ if (pty >= viewport[1] + viewport[3])
+ pty = viewport[1] + viewport[3] - 1;
+ else if (pty <= viewport[1])
+ pty = viewport[1] + 1;
+
+ m_fTrack[0] = (float)ptx;
+ m_fTrack[1] = (float)pty;
+
+ UpdateAllViews();
+ } break;
+
case LC_ACTION_INSERT:
// TODO: handle action_insert (draw preview)
break;
@@ -8518,9 +8709,9 @@ void Project::OnMouseMove(int x, int y, bool bControl, bool bShift)
glVertex2i(rx, m_nDownY);
glEnd();
- // SystemSwapBuffers();
+ // SystemSwapBuffers();
} break;
-
+
case LC_ACTION_PAN:
{
if ((m_nDownY == y) && (m_nDownX == x))
diff --git a/common/project.h b/common/project.h
index 3ef90b0..1492b40 100644
--- a/common/project.h
+++ b/common/project.h
@@ -148,6 +148,7 @@ protected:
void RemovePiece(Piece* pPiece);
bool RemoveSelectedObjects();
void FindObjectFromPoint(int x, int y, LC_CLICKLINE* pLine);
+ void FindObjectsInBox(float x1, float y1, float x2, float y2, PtrArray<Object>& Objects);
void SelectAndFocusNone(bool bFocusOnly);
bool GetSelectionCenter(Point3& Center) const;
void CalculateStep();
diff --git a/common/typedefs.h b/common/typedefs.h
index b6e910f..7c03359 100644
--- a/common/typedefs.h
+++ b/common/typedefs.h
@@ -9,7 +9,8 @@ class Piece;
class PieceInfo;
#include "defines.h"
-typedef enum {
+typedef enum
+{
LC_COLOR_CHANGED,
LC_GROUP_CHANGED,
LC_CAPTURE_LOST,
@@ -19,7 +20,8 @@ typedef enum {
LC_LIGHT_MODIFIED
} LC_NOTIFY;
-typedef enum {
+typedef enum
+{
LC_FILE_NEW,
LC_FILE_OPEN,
LC_FILE_MERGE,
@@ -127,8 +129,10 @@ typedef enum {
LC_EDIT_ACTION_ROLL,
} LC_COMMANDS;
-typedef enum {
- LC_ACTION_SELECT = 0,
+typedef enum
+{
+ LC_ACTION_SELECT,
+ LC_ACTION_SELECT_REGION,
LC_ACTION_INSERT,
LC_ACTION_LIGHT,
LC_ACTION_SPOTLIGHT,
diff --git a/win/LeoCAD.dsp b/win/LeoCAD.dsp
index ddf0f5b..c82006a 100644
--- a/win/LeoCAD.dsp
+++ b/win/LeoCAD.dsp
@@ -69,7 +69,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /Yu"stdafx.h" /FD /c
-# ADD CPP /nologo /G6 /MTd /W3 /Gm /Gi /GX /ZI /Od /I "../common" /I "../win" /D "_DEBUG" /D "WIN32" /D "LC_WINDOWS" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /G6 /MTd /W3 /Gm /Gi /GX /ZI /Od /I "../common" /I "../win" /D "_DEBUG" /D "WIN32" /D "LC_WINDOWS" /D "LC_DEBUG" /Yu"stdafx.h" /FD /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
@@ -130,6 +130,10 @@ SOURCE=.\Cadview.cpp
# End Source File
# Begin Source File
+SOURCE=.\categdlg.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\Clrpick.cpp
# End Source File
# Begin Source File
@@ -388,6 +392,10 @@ SOURCE=.\CADView.h
# End Source File
# Begin Source File
+SOURCE=.\categdlg.h
+# End Source File
+# Begin Source File
+
SOURCE=.\Clrpick.h
# End Source File
# Begin Source File
@@ -1152,6 +1160,19 @@ SOURCE=..\common\curve.cpp
# End Source File
# Begin Source File
+SOURCE=..\common\debug.cpp
+
+!IF "$(CFG)" == "LeoCAD - Win32 Release"
+
+!ELSEIF "$(CFG)" == "LeoCAD - Win32 Debug"
+
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
SOURCE=..\Common\file.cpp
# SUBTRACT CPP /YX /Yc /Yu
# End Source File
diff --git a/win/LeoCAD.rc b/win/LeoCAD.rc
index 0958847..6251874 100644
--- a/win/LeoCAD.rc
+++ b/win/LeoCAD.rc
@@ -143,6 +143,7 @@ BEGIN
BUTTON ID_ACTION_CAMERA
SEPARATOR
BUTTON ID_ACTION_SELECT
+ BUTTON ID_ACTION_SELECT_REGION
BUTTON ID_ACTION_MOVE
BUTTON ID_ACTION_ROTATE
BUTTON ID_ACTION_REMOVE
@@ -1424,6 +1425,20 @@ BEGIN
GROUPBOX "Offset",IDC_STATIC,105,7,80,68
END
+IDD_CATEGORY DIALOG DISCARDABLE 0, 0, 205, 67
+STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Category"
+FONT 8, "MS Sans Serif"
+BEGIN
+ LTEXT "Name",IDC_STATIC,7,9,26,8
+ EDITTEXT IDC_CATDLG_NAME,45,7,100,12,ES_AUTOHSCROLL
+ LTEXT "Keywords",IDC_STATIC,7,26,33,8
+ EDITTEXT IDC_CATDLG_KEYWORDS,45,24,100,36,ES_MULTILINE |
+ ES_AUTOVSCROLL
+ DEFPUSHBUTTON "OK",IDOK,157,7,41,14
+ PUSHBUTTON "Cancel",IDCANCEL,157,26,41,14
+END
+
#ifndef _MAC
/////////////////////////////////////////////////////////////////////////////
@@ -1694,6 +1709,14 @@ BEGIN
TOPMARGIN, 7
BOTTOMMARGIN, 75
END
+
+ IDD_CATEGORY, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 198
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 60
+ END
END
#endif // APSTUDIO_INVOKED
@@ -2096,6 +2119,7 @@ STRINGTABLE DISCARDABLE
BEGIN
ID_FILE_IMPORTPIECE "Import a piece from LDraw"
ID_VIEW_NEWVIEW "Creates a new view window"
+ ID_ACTION_SELECT_REGION "Select objects with the mouse\nSelect Region"
END
#endif // English (U.S.) resources
diff --git a/win/res/toolsbar.bmp b/win/res/toolsbar.bmp
index 84ad134..721346d 100644
--- a/win/res/toolsbar.bmp
+++ b/win/res/toolsbar.bmp
Binary files differ
diff --git a/win/resource.h b/win/resource.h
index b5cd772..ebf83ec 100644
--- a/win/resource.h
+++ b/win/resource.h
@@ -137,6 +137,7 @@
#define IDD_LIBRARY_TEXTURES 234
#define IDD_PREFKEYBOARD 235
#define IDD_TRANSFORM 236
+#define IDD_CATEGORY 237
#define IDC_SELDLG_LIST 1000
#define IDC_SELDLG_ALL 1001
#define IDC_SELDLG_NONE 1002
@@ -383,6 +384,7 @@
#define IDC_MF_HANDR 1211
#define IDC_TEROPT_FLAT 1211
#define IDC_TRANSDLG_GY 1211
+#define IDC_CATDLG_KEYWORDS 1211
#define IDC_MF_TOOLL 1212
#define IDC_EDIT2 1212
#define IDC_SCNDLG_SOLID 1212
@@ -444,6 +446,7 @@
#define IDC_MF_SHOERSPIN 1245
#define IDC_TRANSDLG_GX 1245
#define IDC_TRANSDLG_OX 1246
+#define IDC_CATDLG_NAME 1246
#define ID_EDIT_SELECTALL 32772
#define ID_EDIT_SELECTNONE 32773
#define ID_EDIT_SELECTINVERT 32774
@@ -456,21 +459,22 @@
#define ID_VIEW_STEP_CHOOSE 32784
#define ID_VIEW_STEP_INSERT 32785
#define ID_ACTION_SELECT 32788
-#define ID_ACTION_INSERT 32789
-#define ID_ACTION_LIGHT 32790
-#define ID_ACTION_SPOTLIGHT 32791
-#define ID_ACTION_CAMERA 32792
-#define ID_ACTION_MOVE 32793
-#define ID_ACTION_ROTATE 32794
-#define ID_ACTION_REMOVE 32795
-#define ID_ACTION_PAINT 32796
-#define ID_ACTION_ZOOM 32797
-#define ID_ACTION_ZOOM_REGION 32798
-#define ID_ACTION_PAN 32799
-#define ID_ACTION_ROTATE_VIEW 32800
-#define ID_ACTION_ROLL 32801
-#define ID_ACTION_ZOOM_EXTENTS 32802
-#define ID_ZOOM_EXTENTS 32802
+#define ID_ACTION_SELECT_REGION 32789
+#define ID_ACTION_INSERT 32790
+#define ID_ACTION_LIGHT 32791
+#define ID_ACTION_SPOTLIGHT 32792
+#define ID_ACTION_CAMERA 32793
+#define ID_ACTION_MOVE 32794
+#define ID_ACTION_ROTATE 32795
+#define ID_ACTION_REMOVE 32796
+#define ID_ACTION_PAINT 32797
+#define ID_ACTION_ZOOM 32798
+#define ID_ACTION_ZOOM_REGION 32799
+#define ID_ACTION_PAN 32800
+#define ID_ACTION_ROTATE_VIEW 32801
+#define ID_ACTION_ROLL 32802
+#define ID_ACTION_ZOOM_EXTENTS 32803
+#define ID_ZOOM_EXTENTS 32807
#define ID_PIECE_GROUP 32808
#define ID_PIECE_UNGROUP 32809
#define ID_VIEW_PREFERENCES 32810
@@ -677,9 +681,9 @@
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_3D_CONTROLS 1
-#define _APS_NEXT_RESOURCE_VALUE 237
-#define _APS_NEXT_COMMAND_VALUE 33158
-#define _APS_NEXT_CONTROL_VALUE 1246
+#define _APS_NEXT_RESOURCE_VALUE 238
+#define _APS_NEXT_COMMAND_VALUE 33159
+#define _APS_NEXT_CONTROL_VALUE 1247
#define _APS_NEXT_SYMED_VALUE 121
#endif
#endif