mirror of
https://github.com/leozide/leocad
synced 2024-11-17 07:47:55 +01:00
872 lines
20 KiB
C++
Executable file
872 lines
20 KiB
C++
Executable file
// Curve class, used to represent all flexible objects
|
|
//
|
|
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#include "globals.h"
|
|
#include "curve.h"
|
|
#include "opengl.h"
|
|
#include "matrix.h"
|
|
#include "vector.h"
|
|
|
|
#define LC_CURVE_SAVE_VERSION 1 // LeoCAD 0.73
|
|
#define LC_CURVE_POINT_SAVE_VERSION 1 // LeoCAD 0.73
|
|
|
|
GLuint CurvePoint::m_nArrowList = 0;
|
|
GLuint CurvePoint::m_nSphereList = 0;
|
|
|
|
static LC_OBJECT_KEY_INFO curve_point_key_info[LC_CURVE_POINT_KEY_COUNT] =
|
|
{
|
|
{ "Control Point Position", 3, LC_CURVE_POINT_KEY_POSITION },
|
|
{ "Control Point Direction 1", 3, LC_CURVE_POINT_KEY_DIRECTION1 },
|
|
{ "Control Point Direction 2", 3, LC_CURVE_POINT_KEY_DIRECTION2 },
|
|
{ "Control Point Angle", 1, LC_CURVE_POINT_KEY_ANGLE }
|
|
};
|
|
|
|
// =============================================================================
|
|
// CurvePoint class
|
|
|
|
CurvePoint::CurvePoint (Curve *pParent)
|
|
: Object (LC_OBJECT_CURVE_POINT)
|
|
{
|
|
m_pParent = pParent;
|
|
|
|
/*
|
|
FIXME
|
|
strcpy (m_strName, pParent->GetName ());
|
|
m_strName[LC_OBJECT_NAME_LEN-8] = '\0';
|
|
strcat (m_strName, ".Target");
|
|
*/
|
|
|
|
Initialize ();
|
|
}
|
|
|
|
CurvePoint::CurvePoint (Curve *pParent, const float *pos, const float *dir)
|
|
: Object (LC_OBJECT_CURVE_POINT)
|
|
{
|
|
m_pParent = pParent;
|
|
|
|
/*
|
|
FIXME
|
|
strcpy (m_strName, pParent->GetName ());
|
|
m_strName[LC_OBJECT_NAME_LEN-8] = '\0';
|
|
strcat (m_strName, ".Target");
|
|
*/
|
|
|
|
Initialize ();
|
|
|
|
float angle[1] = { 0 };
|
|
|
|
ChangeKey (1, false, true, pos, LC_CURVE_POINT_KEY_POSITION);
|
|
ChangeKey (1, false, true, dir, LC_CURVE_POINT_KEY_DIRECTION1);
|
|
ChangeKey (1, false, true, dir, LC_CURVE_POINT_KEY_DIRECTION2);
|
|
ChangeKey (1, false, true, angle, LC_CURVE_POINT_KEY_ANGLE);
|
|
ChangeKey (1, true, true, pos, LC_CURVE_POINT_KEY_POSITION);
|
|
ChangeKey (1, true, true, dir, LC_CURVE_POINT_KEY_DIRECTION1);
|
|
ChangeKey (1, true, true, dir, LC_CURVE_POINT_KEY_DIRECTION2);
|
|
ChangeKey (1, true, true, angle, LC_CURVE_POINT_KEY_ANGLE);
|
|
|
|
UpdatePosition (1, false);
|
|
}
|
|
|
|
void CurvePoint::Initialize ()
|
|
{
|
|
if (m_nSphereList == 0)
|
|
{
|
|
m_nSphereList = glGenLists (1);
|
|
glNewList (m_nSphereList, GL_COMPILE);
|
|
|
|
float radius = 0.2f;
|
|
int slices = 6, stacks = 6;
|
|
float rho, drho, theta, dtheta;
|
|
float x, y, z;
|
|
int i, j, imin, imax;
|
|
drho = 3.1415926536f/(float)stacks;
|
|
dtheta = 2.0f*3.1415926536f/(float)slices;
|
|
|
|
// draw +Z end as a triangle fan
|
|
glBegin(GL_TRIANGLE_FAN);
|
|
glVertex3f(0.0, 0.0, radius);
|
|
for (j = 0; j <= slices; j++)
|
|
{
|
|
theta = (j == slices) ? 0.0f : j * dtheta;
|
|
x = (float)(-sin(theta) * sin(drho));
|
|
y = (float)(cos(theta) * sin(drho));
|
|
z = (float)(cos(drho));
|
|
glVertex3f(x*radius, y*radius, z*radius);
|
|
}
|
|
glEnd();
|
|
|
|
imin = 1;
|
|
imax = stacks-1;
|
|
|
|
for (i = imin; i < imax; i++)
|
|
{
|
|
rho = i * drho;
|
|
glBegin(GL_QUAD_STRIP);
|
|
for (j = 0; j <= slices; j++)
|
|
{
|
|
theta = (j == slices) ? 0.0f : j * dtheta;
|
|
x = (float)(-sin(theta) * sin(rho));
|
|
y = (float)(cos(theta) * sin(rho));
|
|
z = (float)(cos(rho));
|
|
glVertex3f(x*radius, y*radius, z*radius);
|
|
x = (float)(-sin(theta) * sin(rho+drho));
|
|
y = (float)(cos(theta) * sin(rho+drho));
|
|
z = (float)(cos(rho+drho));
|
|
glVertex3f(x*radius, y*radius, z*radius);
|
|
}
|
|
glEnd();
|
|
}
|
|
|
|
// draw -Z end as a triangle fan
|
|
glBegin(GL_TRIANGLE_FAN);
|
|
glVertex3f(0.0, 0.0, -radius);
|
|
rho = 3.1415926536f - drho;
|
|
for (j = slices; j >= 0; j--)
|
|
{
|
|
theta = (j==slices) ? 0.0f : j * dtheta;
|
|
x = (float)(-sin(theta) * sin(rho));
|
|
y = (float)(cos(theta) * sin(rho));
|
|
z = (float)(cos(rho));
|
|
glVertex3f(x*radius, y*radius, z*radius);
|
|
}
|
|
glEnd();
|
|
glEndList();
|
|
}
|
|
|
|
m_nState = LC_CURVE_POINT_CONTINUOUS;
|
|
|
|
float *values[] = { m_fPos, m_fDir1, m_fDir2, &m_fAngle };
|
|
RegisterKeys (values, curve_point_key_info, LC_CURVE_POINT_KEY_COUNT);
|
|
}
|
|
|
|
CurvePoint::~CurvePoint ()
|
|
{
|
|
}
|
|
|
|
void CurvePoint::MinIntersectDist (LC_CLICKLINE* pLine)
|
|
{
|
|
float dist = (float)BoundingBoxIntersectDist (pLine);
|
|
|
|
if (dist < pLine->mindist)
|
|
{
|
|
pLine->mindist = dist;
|
|
pLine->pClosest = this;
|
|
|
|
m_nLastHit = 1;
|
|
}
|
|
|
|
m_nLastHit = 0;
|
|
// FIXME: check arrows
|
|
}
|
|
|
|
void CurvePoint::UpdatePosition (unsigned short nTime, bool bAnimation)
|
|
{
|
|
CalculateKeys (nTime, bAnimation);
|
|
}
|
|
|
|
bool CurvePoint::FileLoad (File& file)
|
|
{
|
|
// FIXME
|
|
return true;
|
|
}
|
|
|
|
void CurvePoint::FileSave (File& file) const
|
|
{
|
|
// FIXME
|
|
}
|
|
|
|
void CurvePoint::Move (unsigned short nTime, bool bAnimation, bool bAddKey, float dx, float dy, float dz)
|
|
{
|
|
/*
|
|
if (m_nState & LC_CURVE_POINT_ARROW1_FOCUS)
|
|
if (m_nState & LC_CURVE_POINT_ARROW2_FOCUS)
|
|
if (m_nState & LC_CURVE_POINT_CONTINUOUS)
|
|
;
|
|
*/
|
|
}
|
|
|
|
void CurvePoint::Select (bool bSelecting, bool bFocus, bool bMultiple)
|
|
{
|
|
// FIXME: select arrows, use m_nLastHit
|
|
|
|
if (bSelecting == true)
|
|
{
|
|
m_nState |= LC_CURVE_POINT_SELECTED;
|
|
|
|
if (bFocus == true)
|
|
{
|
|
m_nState |= LC_CURVE_POINT_FOCUSED;
|
|
|
|
m_pParent->DeselectOtherPoints (this, bMultiple);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bFocus == true)
|
|
m_nState &= ~(LC_CURVE_POINT_SELECTED|LC_CURVE_POINT_FOCUSED);
|
|
else
|
|
m_nState &= ~(LC_CURVE_POINT_SELECTED);
|
|
}
|
|
}
|
|
|
|
void CurvePoint::Render (LC_RENDER_INFO* pInfo)
|
|
{
|
|
if (m_nState & LC_CURVE_POINT_FOCUSED)
|
|
glColor3ubv (FlatColorArray[LC_COL_FOCUSED]);
|
|
else if (m_nState & LC_CURVE_POINT_SELECTED)
|
|
glColor3ubv (FlatColorArray[LC_COL_SELECTED]);
|
|
else
|
|
glColor3f(0.5f, 0.8f, 0.5f); // FIXME: same as camera color, add to FlatColorArray
|
|
// glColor3ub (0, 0, 0); // FIXME: inverse of background
|
|
// FIXME: add a new color to the array and change the names from LC_COL to LC_COLOR ?
|
|
|
|
glPushMatrix ();
|
|
glTranslatef (m_fPos[0], m_fPos[1], m_fPos[2]);
|
|
glCallList (m_nSphereList);
|
|
|
|
// FIXME: create and use arrow display list
|
|
// if (m_pPoints[i].m_nFlags & LC_CURVE_POINT_FOCUSED)
|
|
{
|
|
glBegin (GL_LINES);
|
|
glVertex3f ( m_fDir1[0]/5, m_fDir1[1]/5, m_fDir1[2]/5);
|
|
glVertex3f (-m_fDir2[0]/5, -m_fDir2[1]/5, -m_fDir2[2]/5);
|
|
glEnd ();
|
|
}
|
|
|
|
glPopMatrix ();
|
|
}
|
|
|
|
// =============================================================================
|
|
// Curve class
|
|
|
|
Curve::Curve ()
|
|
: Object (LC_OBJECT_CURVE)
|
|
{
|
|
Initialize ();
|
|
}
|
|
|
|
Curve::Curve (PieceInfo *pInfo, const float *pos, unsigned char color)
|
|
: Object (LC_OBJECT_CURVE)
|
|
{
|
|
/*
|
|
Initialize ();
|
|
|
|
// FIXME: set the curve type and length based on the PieceInfo
|
|
m_fLength = 5;
|
|
|
|
m_nCurveType = LC_CURVE_TYPE_HOSE;
|
|
m_nColor = color;
|
|
|
|
float dir[3] = { 0, 20, 0 }, pos2[3] = { pos[0] + m_fLength, pos[1], pos[2] };
|
|
|
|
m_fUp0[0] = 0;
|
|
m_fUp0[1] = 0;
|
|
m_fUp0[2] = 1;
|
|
|
|
CurvePoint *pt;
|
|
pt = new CurvePoint (this, pos, dir);
|
|
m_Points.Add (pt);
|
|
|
|
dir[1] = 0;
|
|
dir[2] = -5;
|
|
|
|
pt = new CurvePoint (this, pos2, dir);
|
|
m_Points.Add (pt);
|
|
|
|
pos2[0] += 5;
|
|
dir[2] = 5;
|
|
|
|
pt = new CurvePoint (this, pos2, dir);
|
|
m_Points.Add (pt);
|
|
|
|
UpdatePosition (1, false);
|
|
*/
|
|
}
|
|
|
|
Curve::~Curve ()
|
|
{
|
|
/*
|
|
for (int i = 0; i < m_Points.GetSize (); i++)
|
|
delete m_Points[i];
|
|
glDeleteLists (m_nDisplayList, 1);
|
|
*/
|
|
}
|
|
|
|
void Curve::Initialize ()
|
|
{
|
|
m_nCurveType = (LC_CURVE_TYPE)0;
|
|
m_nState = 0;
|
|
m_nColor = 0;
|
|
m_nDisplayList = glGenLists (1);
|
|
}
|
|
|
|
bool Curve::FileLoad (File& file)
|
|
{
|
|
// FIXME
|
|
return true;
|
|
}
|
|
|
|
void Curve::FileSave (File& file) const
|
|
{
|
|
// FIXME
|
|
}
|
|
|
|
void Curve::MinIntersectDist (LC_CLICKLINE* pLine)
|
|
{
|
|
// FIXME
|
|
}
|
|
|
|
void Curve::UpdatePosition (unsigned short nTime, bool bAnimation)
|
|
{
|
|
for (int i = 0; i < m_Points.GetSize (); i++)
|
|
m_Points[i]->UpdatePosition (nTime, bAnimation);
|
|
|
|
glNewList (m_nDisplayList, GL_COMPILE);
|
|
|
|
switch (m_nCurveType)
|
|
{
|
|
case LC_CURVE_TYPE_HOSE:
|
|
TesselateHose ();
|
|
break;
|
|
}
|
|
|
|
glEndList ();
|
|
}
|
|
|
|
void Curve::Move (unsigned short nTime, bool bAnimation, bool bAddKey, float dx, float dy, float dz)
|
|
{
|
|
for (int i = 0; i < m_Points.GetSize (); i++)
|
|
m_Points[i]->Move (nTime, bAnimation, bAddKey, dx, dy, dz);
|
|
}
|
|
|
|
void Curve::Select (bool bSelecting, bool bFocus, bool bMultiple)
|
|
{
|
|
if (bSelecting == true)
|
|
{
|
|
if (bFocus == true)
|
|
{
|
|
m_nState |= (LC_CURVE_SELECTED|LC_CURVE_FOCUSED);
|
|
|
|
for (int i = 0; i < m_Points.GetSize (); i++)
|
|
m_Points[i]->Select (false, true, bMultiple);
|
|
}
|
|
else
|
|
m_nState |= LC_CURVE_SELECTED;
|
|
}
|
|
else
|
|
{
|
|
if (bFocus == true)
|
|
m_nState &= ~(LC_CURVE_SELECTED|LC_CURVE_FOCUSED);
|
|
else
|
|
m_nState &= ~(LC_CURVE_SELECTED);
|
|
|
|
for (int i = 0; i < m_Points.GetSize (); i++)
|
|
m_Points[i]->Select (false, bFocus, bMultiple);
|
|
}
|
|
}
|
|
|
|
void Curve::DeselectOtherPoints (CurvePoint *pSender, bool bFocusOnly)
|
|
{
|
|
CurvePoint *pt;
|
|
|
|
for (int i = 0; i < m_Points.GetSize (); i++)
|
|
{
|
|
pt = m_Points[i];
|
|
if (pt != pSender)
|
|
pt->Select (false, bFocusOnly, true);
|
|
}
|
|
}
|
|
|
|
/*
|
|
void Curve::TesselateHose ()
|
|
{
|
|
float x, y, z, t, t2, t3, cx[4], cy[4], cz[4];
|
|
const float *p1, *p2, *r1, *r2, *u1, *u2;
|
|
|
|
glEnableClientState (GL_VERTEX_ARRAY);
|
|
|
|
for (unsigned int i = 0; i < m_Points.GetSize () - 1; i++)
|
|
{
|
|
p1 = m_Points[i]->GetPosition ();
|
|
p2 = m_Points[i+1]->GetPosition ();
|
|
r1 = m_Points[i]->GetDirection1 ();
|
|
r2 = m_Points[i+1]->GetDirection2 ();
|
|
u1 = m_Points[i]->GetUpVector ();
|
|
u2 = m_Points[i+1]->GetUpVector ();
|
|
|
|
cx[0] = 2*p1[0] - 2*p2[0] + r1[0] + r2[0];
|
|
cx[1] = -3*p1[0] + 3*p2[0] - 2*r1[0] - r2[0];
|
|
cx[2] = r1[0];
|
|
cx[3] = p1[0];
|
|
|
|
cy[0] = 2*p1[1] - 2*p2[1] + r1[1] + r2[1];
|
|
cy[1] = -3*p1[1] + 3*p2[1] - 2*r1[1] - r2[1];
|
|
cy[2] = r1[1];
|
|
cy[3] = p1[1];
|
|
|
|
cz[0] = 2*p1[2] - 2*p2[2] + r1[2] + r2[2];
|
|
cz[1] = -3*p1[2] + 3*p2[2] - 2*r1[2] - r2[2];
|
|
cz[2] = r1[2];
|
|
cz[3] = p1[2];
|
|
|
|
int steps1 = 16, steps2 = 6, j, k;
|
|
float* verts = (float*)malloc ((steps1+1) * steps2 * 3 * sizeof (float));
|
|
float a, b, c;
|
|
float ux, uy, uz;
|
|
|
|
for (t = 0, j = 0; j <= steps1; j++, t += 1.0f/steps1)
|
|
{
|
|
t2 = t*t;
|
|
t3 = t2*t;
|
|
|
|
// position
|
|
x = cx[0]*t3 + cx[1]*t2 + cx[2]*t + cx[3];
|
|
y = cy[0]*t3 + cy[1]*t2 + cy[2]*t + cy[3];
|
|
z = cz[0]*t3 + cz[1]*t2 + cz[2]*t + cz[3];
|
|
|
|
// tangent
|
|
a = 3*cx[0]*t2 + 2*cx[1]*t + cx[2];
|
|
b = 3*cy[0]*t2 + 2*cy[1]*t + cy[2];
|
|
c = 3*cz[0]*t2 + 2*cz[1]*t + cz[2];
|
|
|
|
// gradient
|
|
ux = 6*cx[0]*t + 2*cx[1];
|
|
uy = 6*cy[0]*t + 2*cy[1];
|
|
uz = 6*cz[0]*t + 2*cz[1];
|
|
|
|
Vector side, front (a, b, c);
|
|
Vector up (ux, uy, uz);
|
|
side.Cross (front, up);
|
|
up.Cross (side, front);
|
|
up.Normalize ();
|
|
front.Normalize ();
|
|
side.Normalize ();
|
|
|
|
float f[16];
|
|
#define M(row,col) f[col*4+row]
|
|
M(0,0) = side[0]; M(0,1) = up[0]; M(0,2) = front[0]; M(0,3) = x;
|
|
M(1,0) = side[1]; M(1,1) = up[1]; M(1,2) = front[1]; M(1,3) = y;
|
|
M(2,0) = side[2]; M(2,1) = up[2]; M(2,2) = front[2]; M(2,3) = z;
|
|
M(3,0) = 0.0; M(3,1) = 0.0; M(3,2) = 0.0; M(3,3) = 1.0;
|
|
#undef M
|
|
|
|
float v[3];
|
|
Matrix m;
|
|
m.FromFloat (f);
|
|
|
|
for (int k = 0; k < steps2; k++)
|
|
{
|
|
float *o = &verts[(j*steps2+k)*3];
|
|
v[0] = cos (2.0 * M_PI * k / steps2) * 0.15f;
|
|
v[1] = sin (2.0 * M_PI * k / steps2) * 0.15f;
|
|
v[2] = 0;
|
|
m.TransformPoint (o, v);
|
|
glVertex3fv (o);
|
|
}
|
|
}
|
|
|
|
GLuint *index = (GLuint*)malloc (2 * (steps2+1) * sizeof (GLuint));
|
|
glVertexPointer (3, GL_FLOAT, 0, verts);
|
|
for (j = 0; j < steps1; j++)
|
|
{
|
|
for (k = 0; k < steps2; k++)
|
|
{
|
|
index[k*2] = j*steps2+k;
|
|
index[k*2+1] = (j+1)*steps2+k;
|
|
}
|
|
index[k*2] = index[0];
|
|
index[k*2+1] = index[1];
|
|
glDrawElements (GL_TRIANGLE_STRIP, 2*(steps2+1), GL_UNSIGNED_INT, index);
|
|
}
|
|
|
|
free (index);
|
|
free (verts);
|
|
}
|
|
}
|
|
*/
|
|
|
|
void Curve::TesselateHose ()
|
|
{
|
|
float x, y, z, t, t2, t3, cx[4], cy[4], cz[4];
|
|
const float *p1, *p2, *r1, *r2;
|
|
|
|
float u[3] = { m_fUp0[0], m_fUp0[1], m_fUp0[2] };
|
|
int steps1 = 16, steps2 = 6, j, k;
|
|
float* verts = (float*)malloc ((steps1+1) * steps2 * 3 * sizeof (float));
|
|
float a, b, c;
|
|
|
|
glEnableClientState (GL_VERTEX_ARRAY);
|
|
glVertexPointer (3, GL_FLOAT, 0, verts);
|
|
|
|
for (int i = 0; i < m_Points.GetSize () - 1; i++)
|
|
{
|
|
float a1, a2, angle_step; // axial rotation
|
|
|
|
p1 = m_Points[i]->GetPosition ();
|
|
p2 = m_Points[i+1]->GetPosition ();
|
|
r1 = m_Points[i]->GetDirection1 ();
|
|
r2 = m_Points[i+1]->GetDirection2 ();
|
|
a1 = m_Points[i]->GetAngle ();
|
|
a2 = m_Points[i+1]->GetAngle ();
|
|
|
|
angle_step = (a2 - a1) / steps1;
|
|
if (fabs (angle_step) < 0.01f)
|
|
angle_step = 0;
|
|
|
|
cx[0] = 2*p1[0] - 2*p2[0] + r1[0] + r2[0];
|
|
cx[1] = -3*p1[0] + 3*p2[0] - 2*r1[0] - r2[0];
|
|
cx[2] = r1[0];
|
|
cx[3] = p1[0];
|
|
|
|
cy[0] = 2*p1[1] - 2*p2[1] + r1[1] + r2[1];
|
|
cy[1] = -3*p1[1] + 3*p2[1] - 2*r1[1] - r2[1];
|
|
cy[2] = r1[1];
|
|
cy[3] = p1[1];
|
|
|
|
cz[0] = 2*p1[2] - 2*p2[2] + r1[2] + r2[2];
|
|
cz[1] = -3*p1[2] + 3*p2[2] - 2*r1[2] - r2[2];
|
|
cz[2] = r1[2];
|
|
cz[3] = p1[2];
|
|
|
|
for (t = 0, j = 0; j <= steps1; j++, t += 1.0f/steps1)
|
|
{
|
|
t2 = t*t;
|
|
t3 = t2*t;
|
|
|
|
// position
|
|
x = cx[0]*t3 + cx[1]*t2 + cx[2]*t + cx[3];
|
|
y = cy[0]*t3 + cy[1]*t2 + cy[2]*t + cy[3];
|
|
z = cz[0]*t3 + cz[1]*t2 + cz[2]*t + cz[3];
|
|
|
|
// tangent
|
|
a = 3*cx[0]*t2 + 2*cx[1]*t + cx[2];
|
|
b = 3*cy[0]*t2 + 2*cy[1]*t + cy[2];
|
|
c = 3*cz[0]*t2 + 2*cz[1]*t + cz[2];
|
|
|
|
Vector side, front (a, b, c);
|
|
Vector up (u);
|
|
side.Cross (front, up);
|
|
up.Cross (side, front);
|
|
up.Normalize ();
|
|
front.Normalize ();
|
|
side.Normalize ();
|
|
|
|
if (angle_step != 0)
|
|
{
|
|
Matrix rot;
|
|
rot.FromAxisAngle (front, angle_step);
|
|
rot.TransformPoint (u, up);
|
|
}
|
|
else
|
|
up.ToFloat (u);
|
|
|
|
float f[16];
|
|
#define M(row,col) f[col*4+row]
|
|
M(0,0) = side[0]; M(0,1) = up[0]; M(0,2) = front[0]; M(0,3) = x;
|
|
M(1,0) = side[1]; M(1,1) = up[1]; M(1,2) = front[1]; M(1,3) = y;
|
|
M(2,0) = side[2]; M(2,1) = up[2]; M(2,2) = front[2]; M(2,3) = z;
|
|
M(3,0) = 0.0; M(3,1) = 0.0; M(3,2) = 0.0; M(3,3) = 1.0;
|
|
#undef M
|
|
|
|
float v[3];
|
|
Matrix m;
|
|
m.FromFloat (f);
|
|
|
|
for (int k = 0; k < steps2; k++)
|
|
{
|
|
float *o = &verts[(j*steps2+k)*3];
|
|
v[0] = (float)(cos (2.0 * M_PI * k / steps2) * 0.15);
|
|
v[1] = (float)(sin (2.0 * M_PI * k / steps2) * 0.15);
|
|
v[2] = 0;
|
|
m.TransformPoint (o, v);
|
|
}
|
|
}
|
|
|
|
GLuint *index = (GLuint*)malloc (2 * (steps2+1) * sizeof (GLuint));
|
|
for (j = 0; j < steps1; j++)
|
|
{
|
|
for (k = 0; k < steps2; k++)
|
|
{
|
|
index[k*2] = j*steps2+k;
|
|
index[k*2+1] = (j+1)*steps2+k;
|
|
}
|
|
index[k*2] = index[0];
|
|
index[k*2+1] = index[1];
|
|
glDrawElements (GL_TRIANGLE_STRIP, 2*(steps2+1), GL_UNSIGNED_INT, index);
|
|
}
|
|
|
|
free (index);
|
|
}
|
|
free (verts);
|
|
}
|
|
|
|
void Curve::Render (LC_RENDER_INFO* pInfo)
|
|
{
|
|
if ((m_nState & LC_CURVE_HIDDEN) != 0)
|
|
return;
|
|
|
|
// FIXME: create a "set color" function in LC_RENDER_INFO
|
|
if (pInfo->lighting)
|
|
glColor4ubv (ColorArray[m_nColor]);
|
|
else
|
|
glColor3ubv (FlatColorArray[m_nColor]);
|
|
|
|
if (m_nColor > 13 && m_nColor < 22) // FIXME: use a #define
|
|
{
|
|
if (!pInfo->transparent)
|
|
{
|
|
pInfo->transparent = true;
|
|
glEnable (GL_BLEND);
|
|
glDepthMask (GL_FALSE);
|
|
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pInfo->transparent)
|
|
{
|
|
pInfo->transparent = false;
|
|
glDepthMask (GL_TRUE);
|
|
glDisable (GL_BLEND);
|
|
}
|
|
}
|
|
|
|
// glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
|
|
glCallList (m_nDisplayList);
|
|
|
|
// if (m_nState & LC_CURVE_SELECTED)
|
|
{
|
|
// turn off transparency to draw the control points
|
|
if (pInfo->transparent)
|
|
{
|
|
pInfo->transparent = false;
|
|
if (pInfo->transparent)
|
|
{
|
|
glDepthMask (GL_TRUE);
|
|
glDisable (GL_BLEND);
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < m_Points.GetSize (); i++)
|
|
m_Points[i]->Render (pInfo);
|
|
}
|
|
|
|
/*
|
|
if (IsSelected ())
|
|
{
|
|
|
|
for (int i = 0; i < m_nNumPoints; i++)
|
|
{
|
|
if (m_pPoints[i].m_nFlags & LC_CURVE_POINT_FOCUSED)
|
|
glColor3ubv (FlatColorArray[LC_COL_FOCUSED]);
|
|
else if (m_pPoints[i].m_nFlags & LC_CURVE_POINT_SELECTED)
|
|
glColor3ubv (FlatColorArray[LC_COL_SELECTED]);
|
|
else
|
|
glColor3f(0.5f, 0.8f, 0.5f); // FIXME: same as camera color, add to FlatColorArray
|
|
// glColor3ub (0, 0, 0); // FIXME: inverse of background
|
|
// FIXME: add a new color to the array and change the names from LC_COL to LC_COLOR ?
|
|
|
|
glPushMatrix ();
|
|
// RenderSegment (m_pPoints[i].m_fPos, m_pPoints[i+1].m_fPos, m_pSegments[i].m_fR1, m_pSegments[i].m_fR2);
|
|
glTranslatef (m_pPoints[i].m_fPos[0], m_pPoints[i].m_fPos[1], m_pPoints[i].m_fPos[2]);
|
|
glCallList (m_nSphereList);
|
|
|
|
if (m_pPoints[i].m_nFlags & LC_CURVE_POINT_FOCUSED)
|
|
{
|
|
glBegin (GL_LINES);
|
|
if (i < m_nNumSegments)
|
|
{
|
|
glVertex3fv (m_pSegments[i].m_fR1);
|
|
glVertex3f (0, 0, 0);
|
|
}
|
|
else if (i > 0)
|
|
{
|
|
glVertex3f (-m_pSegments[i-1].m_fR2[0], -m_pSegments[i-1].m_fR2[1], -m_pSegments[i-1].m_fR2[2]);
|
|
glVertex3f (0, 0, 0);
|
|
}
|
|
glEnd ();
|
|
}
|
|
|
|
glPopMatrix ();
|
|
}
|
|
}
|
|
*/
|
|
|
|
|
|
/*
|
|
if (m_nFlags & LC_CURVE_LOOP)
|
|
{
|
|
i = m_nNumPoints - 1;
|
|
RenderSegment (m_pPoints[0].pos, m_pPoints[i].pos, m_pPoints[0].normal, m_pPoints[i].normal);
|
|
}
|
|
*/
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
#define LC_CURVE_POINT_RADIUS 0.2f
|
|
|
|
// =============================================================================
|
|
// Static functions
|
|
|
|
#include <math.h>
|
|
/*
|
|
// TODO: optimize
|
|
static void RenderSegment (float p1[3], float p2[3], float r1[3], float r2[3])
|
|
{
|
|
float x, y, z, t, t2, t3, cx[4], cy[4], cz[4];
|
|
int i;
|
|
|
|
cx[0] = 2*p1[0] - 2*p2[0] + r1[0] + r2[0];
|
|
cx[1] = -3*p1[0] + 3*p2[0] - 2*r1[0] - r2[0];
|
|
cx[2] = r1[0];
|
|
cx[3] = p1[0];
|
|
|
|
cy[0] = 2*p1[1] - 2*p2[1] + r1[1] + r2[1];
|
|
cy[1] = -3*p1[1] + 3*p2[1] - 2*r1[1] - r2[1];
|
|
cy[2] = r1[1];
|
|
cy[3] = p1[1];
|
|
|
|
cz[0] = 2*p1[2] - 2*p2[2] + r1[2] + r2[2];
|
|
cz[1] = -3*p1[2] + 3*p2[2] - 2*r1[2] - r2[2];
|
|
cz[2] = r1[2];
|
|
cz[3] = p1[2];
|
|
|
|
glColor3f (1,0,0);
|
|
|
|
glBegin (GL_LINE_STRIP);
|
|
glVertex3f (cx[3], cy[3], cz[3]);
|
|
|
|
for (t = 0, i = 0; i < 10; i++)
|
|
{
|
|
t += 0.1f;
|
|
t2 = t*t;
|
|
t3 = t2*t;
|
|
|
|
x = cx[0]*t3 + cx[1]*t2 + cx[2]*t + cx[3];
|
|
y = cy[0]*t3 + cy[1]*t2 + cy[2]*t + cy[3];
|
|
z = cz[0]*t3 + cz[1]*t2 + cz[2]*t + cz[3];
|
|
glVertex3f (x, y, z);
|
|
}
|
|
|
|
glEnd ();
|
|
|
|
|
|
glColor3f (0,0,0);
|
|
|
|
float a, b, c;
|
|
for (t = 0, i = 0; i <= 10; i++, t += 0.1f)
|
|
{
|
|
t2 = t*t;
|
|
t3 = t2*t;
|
|
|
|
x = cx[0]*t3 + cx[1]*t2 + cx[2]*t + cx[3];
|
|
y = cy[0]*t3 + cy[1]*t2 + cy[2]*t + cy[3];
|
|
z = cz[0]*t3 + cz[1]*t2 + cz[2]*t + cz[3];
|
|
|
|
a = 3*cx[0]*t2 + 2*cx[1]*t + cx[2];
|
|
b = 3*cy[0]*t2 + 2*cy[1]*t + cy[2];
|
|
c = 3*cz[0]*t2 + 2*cz[1]*t + cz[2];
|
|
|
|
Vector v1 (0, 0, 1);
|
|
Vector v2 (a, b, c);
|
|
Vector v3;
|
|
v3.Cross (v1, v2);
|
|
a = v1.Angle (v2);
|
|
float v[3];
|
|
v3.ToFloat (v);
|
|
Matrix m;
|
|
m.FromAxisAngle (v, a);
|
|
|
|
glBegin (GL_LINE_LOOP);
|
|
for (int j = 0; j < 16; j++)
|
|
{
|
|
float o[3];
|
|
v[0] = cos (2.0 * M_PI * j / 16) * 0.15f;
|
|
v[1] = sin (2.0 * M_PI * j / 16) * 0.15f;
|
|
v[2] = 0;
|
|
m.TransformPoint (o, v);
|
|
glVertex3f (o[0]+x, o[1]+y, o[2]+z);
|
|
}
|
|
|
|
glEnd ();
|
|
}
|
|
|
|
}
|
|
*/
|
|
|
|
// =============================================================================
|
|
// Curve class
|
|
|
|
void Curve::MinIntersectDist (LC_CLICKLINE* pLine)
|
|
{
|
|
// FIXME: Curve segments and tangent arrows
|
|
|
|
for (int i = 0; i < m_nNumPoints; i++)
|
|
{
|
|
double dist = pLine->PointDistance (m_pPoints[i].m_fPos);
|
|
|
|
if ((dist < pLine->mindist) && (dist < LC_CURVE_POINT_RADIUS))
|
|
{
|
|
pLine->mindist = dist;
|
|
pLine->pClosest = this;
|
|
pLine->pParam = &m_pPoints[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
void Curve::SetSelection (bool bSelect, void *pParam)
|
|
{
|
|
Object::SetSelection (bSelect, pParam);
|
|
|
|
if (pParam != NULL)
|
|
{
|
|
for (int i = 0; i < m_nNumPoints; i++)
|
|
if (&m_pPoints[i] == pParam)
|
|
{
|
|
if (bSelect)
|
|
m_pPoints[i].m_nState |= LC_CURVE_POINT_SELECTED;
|
|
else
|
|
m_pPoints[i].m_nState &= ~(LC_CURVE_POINT_SELECTED | LC_CURVE_POINT_FOCUSED);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < m_nNumPoints; i++)
|
|
if (bSelect)
|
|
m_pPoints[i].m_nState |= LC_CURVE_POINT_SELECTED;
|
|
else
|
|
m_pPoints[i].m_nState &= ~(LC_CURVE_POINT_SELECTED | LC_CURVE_POINT_FOCUSED);
|
|
}
|
|
}
|
|
|
|
void Curve::SetFocus (bool bFocus, void *pParam)
|
|
{
|
|
Object::SetFocus (bFocus, pParam);
|
|
|
|
if (pParam != NULL)
|
|
{
|
|
for (int i = 0; i < m_nNumPoints; i++)
|
|
if (&m_pPoints[i] == pParam)
|
|
{
|
|
if (bFocus)
|
|
m_pPoints[i].m_nState |= (LC_CURVE_POINT_SELECTED | LC_CURVE_POINT_FOCUSED);
|
|
else
|
|
m_pPoints[i].m_nState &= ~LC_CURVE_POINT_FOCUSED;
|
|
}
|
|
else
|
|
{
|
|
m_pPoints[i].m_nState &= ~LC_CURVE_POINT_FOCUSED;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#endif
|