diff --git a/constraint.cpp b/constraint.cpp index e0a043b..cef9980 100644 --- a/constraint.cpp +++ b/constraint.cpp @@ -126,6 +126,10 @@ void Constraint::MenuConstrain(int id) { c.type = PT_ON_CIRCLE; c.ptA = gs.point[0]; c.entityA = gs.entity[0]; + } else if(gs.points == 1 && gs.faces == 1 && gs.n == 2) { + c.type = PT_ON_FACE; + c.ptA = gs.point[0]; + c.entityA = gs.face[0]; } else { Error("Bad selection for on point / curve / plane constraint."); return; @@ -547,6 +551,16 @@ void Constraint::Generate(IdList *l) { SS.GetEntity(ptA)->PointGetExprs(), entityA), 0); break; + case PT_ON_FACE: { + // a plane, n dot (p - p0) = 0 + ExprVector p = SS.GetEntity(ptA)->PointGetExprs(); + Entity *f = SS.GetEntity(entityA); + ExprVector p0 = f->FaceGetPointExprs(); + ExprVector n = f->FaceGetNormalExprs(); + AddEq(l, (p.Minus(p0)).Dot(n), 0); + break; + } + case PT_ON_LINE: if(workplane.v == Entity::FREE_IN_3D.v) { Entity *ln = SS.GetEntity(entityA); diff --git a/drawconstraint.cpp b/drawconstraint.cpp index 7a6edbb..da00092 100644 --- a/drawconstraint.cpp +++ b/drawconstraint.cpp @@ -224,11 +224,25 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) { case PT_ON_CIRCLE: case PT_ON_LINE: + case PT_ON_FACE: case PT_IN_PLANE: { - double s = 7/SS.GW.scale; + double s = 8/SS.GW.scale; Vector p = SS.GetEntity(ptA)->PointGetNum(); - Vector r = gr.WithMagnitude(s); - Vector d = gu.WithMagnitude(s); + Vector r, d; + if(type == PT_ON_FACE) { + Vector n = SS.GetEntity(entityA)->FaceGetNormalNum(); + r = n.Normal(0); + d = n.Normal(1); + } else if(type == PT_IN_PLANE) { + Entity *n = SS.GetEntity(entityA)->Normal(); + r = n->NormalU(); + d = n->NormalV(); + } else { + r = gr; + d = gu; + s *= (6.0/8); // draw these a little smaller + } + r = r.WithMagnitude(s); d = d.WithMagnitude(s); LineDrawOrGetDistance(p.Plus (r).Plus (d), p.Plus (r).Minus(d)); LineDrawOrGetDistance(p.Plus (r).Minus(d), p.Minus(r).Minus(d)); LineDrawOrGetDistance(p.Minus(r).Minus(d), p.Minus(r).Plus (d)); diff --git a/dsc.h b/dsc.h index 3782610..412947b 100644 --- a/dsc.h +++ b/dsc.h @@ -16,6 +16,7 @@ public: double w, vx, vy, vz; static Quaternion From(double w, double vx, double vy, double vz); + static Quaternion From(hParam w, hParam vx, hParam vy, hParam vz); static Quaternion From(Vector u, Vector v); Quaternion Plus(Quaternion b); diff --git a/entity.cpp b/entity.cpp index c64e681..0d1a873 100644 --- a/entity.cpp +++ b/entity.cpp @@ -574,6 +574,69 @@ Quaternion Entity::PointGetQuaternion(void) { return q; } +bool Entity::IsFace(void) { + switch(type) { + case FACE_NORMAL_PT: + case FACE_XPROD: + case FACE_N_ROT_TRANS: + return true; + default: + return false; + } +} + +ExprVector Entity::FaceGetNormalExprs(void) { + ExprVector r; + if(type == FACE_NORMAL_PT) { + r = ExprVector::From(numNormal.vx, numNormal.vy, numNormal.vz); + } else if(type == FACE_XPROD) { + ExprVector vc = ExprVector::From(param[0], param[1], param[2]); + ExprVector vn = ExprVector::From(numVector); + r = vc.Cross(vn); + } else if(type == FACE_N_ROT_TRANS) { + // The numerical normal vector gets the rotation + r = ExprVector::From(numNormal.vx, numNormal.vy, numNormal.vz); + ExprQuaternion q = + ExprQuaternion::From(param[3], param[4], param[5], param[6]); + r = q.Rotate(r); + } else oops(); + return r; +} + +Vector Entity::FaceGetNormalNum(void) { + Vector r; + if(type == FACE_NORMAL_PT) { + r = Vector::From(numNormal.vx, numNormal.vy, numNormal.vz); + } else if(type == FACE_XPROD) { + Vector vc = Vector::From(param[0], param[1], param[2]); + r = vc.Cross(numVector); + } else if(type == FACE_N_ROT_TRANS) { + // The numerical normal vector gets the rotation + r = Vector::From(numNormal.vx, numNormal.vy, numNormal.vz); + Quaternion q = Quaternion::From(param[3], param[4], param[5], param[6]); + r = q.Rotate(r); + } else oops(); + return r; +} + +ExprVector Entity::FaceGetPointExprs(void) { + ExprVector r; + if(type == FACE_NORMAL_PT) { + r = SS.GetEntity(point[0])->PointGetExprs(); + } else if(type == FACE_XPROD) { + r = ExprVector::From(numPoint); + } else if(type == FACE_N_ROT_TRANS) { + // The numerical point gets the rotation and translation. + ExprVector trans = ExprVector::From(param[0], param[1], param[2]); + ExprQuaternion q = + ExprQuaternion::From(param[3], param[4], param[5], param[6]); + r = ExprVector::From(numPoint); + r = q.Rotate(r); + r = r.Plus(trans); + } else oops(); + return r; +} + void Entity::LineDrawOrGetDistance(Vector a, Vector b) { if(dogd.drawing) { // glPolygonOffset works only on polys, not lines, so do it myself @@ -890,6 +953,12 @@ void Entity::DrawOrGetDistance(int order) { break; } + case FACE_NORMAL_PT: + case FACE_XPROD: + case FACE_N_ROT_TRANS: + // Do nothing; these are drawn with the triangle mesh + break; + default: oops(); } @@ -933,5 +1002,11 @@ void Entity::CalculateNumerical(void) { if(type == DISTANCE || type == DISTANCE_N_COPY) { actDistance = DistanceGetNum(); } + if(IsFace()) { + ExprVector p = FaceGetPointExprs(); + ExprVector n = FaceGetNormalExprs(); + numPoint = Vector::From( p.x->Eval(), p.y->Eval(), p.z->Eval()); + numNormal = Quaternion::From(0, n.x->Eval(), n.y->Eval(), n.z->Eval()); + } } diff --git a/expr.cpp b/expr.cpp index eed0ac7..1904cb6 100644 --- a/expr.cpp +++ b/expr.cpp @@ -21,6 +21,14 @@ ExprVector ExprVector::From(hParam x, hParam y, hParam z) { return ve; } +ExprVector ExprVector::From(double x, double y, double z) { + ExprVector ve; + ve.x = Expr::From(x); + ve.y = Expr::From(y); + ve.z = Expr::From(z); + return ve; +} + ExprVector ExprVector::Minus(ExprVector b) { ExprVector r; r.x = x->Minus(b.x); @@ -236,6 +244,15 @@ int Expr::Children(void) { } } +int Expr::Nodes(void) { + switch(Children()) { + case 0: return 1; + case 1: return 1 + a->Nodes(); + case 2: return 1 + a->Nodes() + b->Nodes(); + default: oops(); + } +} + Expr *Expr::DeepCopy(void) { Expr *n = AllocExpr(); *n = *this; diff --git a/expr.h b/expr.h index cb8ebf8..1d68e77 100644 --- a/expr.h +++ b/expr.h @@ -92,6 +92,8 @@ public: Expr *DeepCopy(void); // number of child nodes: 0 (e.g. constant), 1 (sqrt), or 2 (+) int Children(void); + // total number of nodes in the tree + int Nodes(void); // Make a copy, with the parameters (usually referenced by hParam) // resolved to pointers to the actual value. This speeds things up @@ -125,6 +127,7 @@ public: static ExprVector From(Expr *x, Expr *y, Expr *z); static ExprVector From(Vector vn); static ExprVector From(hParam x, hParam y, hParam z); + static ExprVector From(double x, double y, double z); ExprVector Plus(ExprVector b); ExprVector Minus(ExprVector b); diff --git a/glhelper.cpp b/glhelper.cpp index b5aa401..1f1a7a3 100644 --- a/glhelper.cpp +++ b/glhelper.cpp @@ -111,7 +111,7 @@ void glxColor4d(double r, double g, double b, double a) if(!ColorLocked) glColor4d(r, g, b, a); } -void glxFillMesh(bool useModelColor, SMesh *m) +void glxFillMesh(int specColor, SMesh *m, DWORD h, DWORD s1, DWORD s2) { glEnable(GL_NORMALIZE); int prevColor = -1; @@ -121,8 +121,19 @@ void glxFillMesh(bool useModelColor, SMesh *m) Vector n = tr->Normal(); glNormal3d(n.x, n.y, n.z); - int color = tr->meta.color; - if(useModelColor && color != prevColor) { + int color; + if((s1 != 0 && tr->meta.face == s1) || + (s2 != 0 && tr->meta.face == s2)) + { + color = RGB(200, 0, 0); + } else if(h != 0 && tr->meta.face == h) { + color = RGB(200, 200, 0); + } else if(specColor < 0) { + color = tr->meta.color; + } else { + color = specColor; + } + if(color != prevColor) { GLfloat mpf[] = { ((color >> 0) & 0xff) / 255.0f, ((color >> 8) & 0xff) / 255.0f, ((color >> 16) & 0xff) / 255.0f, 1.0 }; diff --git a/graphicswin.cpp b/graphicswin.cpp index a65f2aa..2b42023 100644 --- a/graphicswin.cpp +++ b/graphicswin.cpp @@ -745,6 +745,15 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp) { } } + // Faces, from the triangle mesh; these are lowest priority + if(s.constraint.v == 0 && s.entity.v == 0 && (showMesh || showShaded)) { + SMesh *m = &((SS.GetGroup(activeGroup))->mesh); + DWORD v = m->FirstIntersectionWith(mp); + if(v) { + s.entity.v = v; + } + } + if(!s.Equals(&hover)) { hover = s; InvalidateGraphics(); @@ -804,6 +813,11 @@ void GraphicsWindow::GroupSelection(void) { gs.vector[(gs.vectors)++] = s->entity; } + // Faces (which are special, associated/drawn with triangles) + if(e->IsFace()) { + gs.face[(gs.faces)++] = s->entity; + } + // And some aux counts too switch(e->type) { case Entity::WORKPLANE: (gs.workplanes)++; break; diff --git a/mesh.cpp b/mesh.cpp index cdc5cbd..6e0b560 100644 --- a/mesh.cpp +++ b/mesh.cpp @@ -235,6 +235,35 @@ void SMesh::MakeFromDifference(SMesh *a, SMesh *b) { dbp("tris = %d", l.n); } +DWORD SMesh::FirstIntersectionWith(Point2d mp) { + Vector gu = SS.GW.projRight, gv = SS.GW.projUp; + Vector gn = (gu.Cross(gv)).WithMagnitude(1); + + Vector p0 = gu.ScaledBy(mp.x/SS.GW.scale).Plus( + gv.ScaledBy(mp.y/SS.GW.scale)); + p0 = p0.Minus(SS.GW.offset); + + double maxT = -1e12; + DWORD face = 0; + + int i; + for(i = 0; i < l.n; i++) { + STriangle *tr = &(l.elem[i]); + Vector n = tr->Normal(); + if(n.Dot(gn) < LENGTH_EPS) continue; // back-facing or on edge + + if(tr->ContainsPointProjd(gn, p0)) { + // Let our line have the form r(t) = p0 + gn*t + double t = (n.Dot((tr->a).Minus(p0)))/(n.Dot(gn)); + if(t > maxT) { + maxT = t; + face = tr->meta.face; + } + } + } + return face; +} + SBsp2 *SBsp2::Alloc(void) { return (SBsp2 *)AllocTemporary(sizeof(SBsp2)); } SBsp3 *SBsp3::Alloc(void) { return (SBsp3 *)AllocTemporary(sizeof(SBsp3)); } diff --git a/polygon.cpp b/polygon.cpp index e54d771..699b581 100644 --- a/polygon.cpp +++ b/polygon.cpp @@ -6,9 +6,12 @@ Vector STriangle::Normal(void) { } bool STriangle::ContainsPoint(Vector p) { + Vector n = Normal(); + return ContainsPointProjd(n.WithMagnitude(1), p); +} + +bool STriangle::ContainsPointProjd(Vector n, Vector p) { Vector ab = b.Minus(a), bc = c.Minus(b), ca = a.Minus(c); - Vector n = ab.Cross(bc); - n = n.WithMagnitude(1); Vector no_ab = n.Cross(ab); if(no_ab.Dot(p) < no_ab.Dot(a) - LENGTH_EPS) return false; diff --git a/polygon.h b/polygon.h index c29eca5..743c3cd 100644 --- a/polygon.h +++ b/polygon.h @@ -114,6 +114,7 @@ public: static STriangle From(STriMeta meta, Vector a, Vector b, Vector c); Vector Normal(void); bool ContainsPoint(Vector p); + bool ContainsPointProjd(Vector n, Vector p); }; class SBsp2 { @@ -190,6 +191,8 @@ public: void AddAgainstBsp(SMesh *srcm, SBsp3 *bsp3); void MakeFromUnion(SMesh *a, SMesh *b); void MakeFromDifference(SMesh *a, SMesh *b); + + DWORD FirstIntersectionWith(Point2d mp); }; // A linked list of triangles diff --git a/sketch.cpp b/sketch.cpp index 225e42c..6482e32 100644 --- a/sketch.cpp +++ b/sketch.cpp @@ -10,6 +10,8 @@ const hRequest Request::HREQUEST_REFERENCE_XY = { 1 }; const hRequest Request::HREQUEST_REFERENCE_YZ = { 2 }; const hRequest Request::HREQUEST_REFERENCE_ZX = { 3 }; +#define gs (SS.GW.gs) + void Group::AddParam(IdList *param, hParam hp, double v) { Param pa; memset(&pa, 0, sizeof(pa)); @@ -30,7 +32,6 @@ void Group::MenuGroup(int id) { } SS.GW.GroupSelection(); -#define gs (SS.GW.gs) switch(id) { case GraphicsWindow::MNU_GROUP_3D: @@ -214,7 +215,7 @@ void Group::Generate(IdList *entity, break; } - case EXTRUDE: + case EXTRUDE: { AddParam(param, h.param(0), gn.x); AddParam(param, h.param(1), gn.y); AddParam(param, h.param(2), gn.z); @@ -224,10 +225,16 @@ void Group::Generate(IdList *entity, } else if(subtype == TWO_SIDED) { ai = -1; af = 1; } else oops(); + + // Get some arbitrary point in the sketch, that will be used + // as a reference when defining top and bottom faces. + hEntity pt = { 0 }; for(i = 0; i < entity->n; i++) { Entity *e = &(entity->elem[i]); if(e->group.v != opA.v) continue; + if(e->IsPoint()) pt = e->h; + e->CalculateNumerical(); hEntity he = e->h; e = NULL; // As soon as I call CopyEntity, e may become invalid! That @@ -242,7 +249,11 @@ void Group::Generate(IdList *entity, true, false); MakeExtrusionLines(he); } + // Remapped versions of that arbitrary point will be used to + // provide points on the plane faces. + MakeExtrusionTopBottomFaces(pt); break; + } case TRANSLATE: { // The translation vector @@ -386,16 +397,54 @@ hEntity Group::Remap(hEntity in, int copyNumber) { void Group::MakeExtrusionLines(hEntity in) { Entity *ep = SS.GetEntity(in); - if(!(ep->IsPoint())) return; Entity en; - memset(&en, 0, sizeof(en)); - en.point[0] = Remap(ep->h, REMAP_TOP); - en.point[1] = Remap(ep->h, REMAP_BOTTOM); + ZERO(&en); + if(ep->IsPoint()) { + // A point gets extruded to form a line segment + en.point[0] = Remap(ep->h, REMAP_TOP); + en.point[1] = Remap(ep->h, REMAP_BOTTOM); + en.group = h; + en.h = Remap(ep->h, REMAP_PT_TO_LINE); + en.type = Entity::LINE_SEGMENT; + SS.entity.Add(&en); + } else if(ep->type == Entity::LINE_SEGMENT) { + // A line gets extruded to form a plane face; an endpoint of the + // original line is a point in the plane, and the line is in the plane. + Vector a = SS.GetEntity(ep->point[0])->PointGetNum(); + Vector b = SS.GetEntity(ep->point[1])->PointGetNum(); + Vector ab = b.Minus(a); + + en.param[0] = h.param(0); + en.param[1] = h.param(1); + en.param[2] = h.param(2); + en.numPoint = a; + en.numVector = ab; + + en.group = h; + en.h = Remap(ep->h, REMAP_LINE_TO_FACE); + en.type = Entity::FACE_XPROD; + SS.entity.Add(&en); + } +} + +void Group::MakeExtrusionTopBottomFaces(hEntity pt) { + if(pt.v == 0) return; + Group *src = SS.GetGroup(opA); + Vector n = src->poly.normal; + + Entity en; + ZERO(&en); + en.type = Entity::FACE_NORMAL_PT; en.group = h; - en.h = Remap(ep->h, 10); - en.type = Entity::LINE_SEGMENT; - // And then this line segment gets added + + en.numNormal = Quaternion::From(0, n.x, n.y, n.z); + en.point[0] = Remap(pt, REMAP_TOP); + en.h = Remap(Entity::NO_ENTITY, REMAP_TOP); + SS.entity.Add(&en); + + en.point[0] = Remap(pt, REMAP_BOTTOM); + en.h = Remap(Entity::NO_ENTITY, REMAP_BOTTOM); SS.entity.Add(&en); } @@ -498,6 +547,23 @@ void Group::CopyEntity(Entity *ep, int timesApplied, int remap, en.numDistance = ep->actDistance; break; + case Entity::FACE_NORMAL_PT: + case Entity::FACE_XPROD: + case Entity::FACE_N_ROT_TRANS: + if(asTrans || asAxisAngle) return; + + en.type = Entity::FACE_N_ROT_TRANS; + en.param[0] = dx; + en.param[1] = dy; + en.param[2] = dz; + en.param[3] = qw; + en.param[4] = qvx; + en.param[5] = qvy; + en.param[6] = qvz; + en.numPoint = ep->numPoint; + en.numNormal = ep->numNormal; + break; + default: oops(); } @@ -526,8 +592,8 @@ void Group::TagEdgesFromLineSegments(SEdgeList *el) { for(j = 0; j < el->l.n; j++) { SEdge *se = &(el->l.elem[j]); - if((p0.Equals(se->a) && p1.Equals(se->b))) se->tag = 1; - if((p0.Equals(se->b) && p1.Equals(se->a))) se->tag = 1; + if((p0.Equals(se->a) && p1.Equals(se->b))) se->tag = e->h.v; + if((p0.Equals(se->b) && p1.Equals(se->a))) se->tag = e->h.v; } } } @@ -583,6 +649,7 @@ void Group::MakePolygons(void) { STriMeta meta = { 0, color }; // Do the bottom; that has normal pointing opposite from translate + meta.face = Remap(Entity::NO_ENTITY, REMAP_BOTTOM).v; for(i = 0; i < srcm.l.n; i++) { STriangle *st = &(srcm.l.elem[i]); Vector at = (st->a).Plus(tbot), @@ -595,6 +662,7 @@ void Group::MakePolygons(void) { } } // And the top; that has the normal pointing the same dir as translate + meta.face = Remap(Entity::NO_ENTITY, REMAP_TOP).v; for(i = 0; i < srcm.l.n; i++) { STriangle *st = &(srcm.l.elem[i]); Vector at = (st->a).Plus(ttop), @@ -618,6 +686,15 @@ void Group::MakePolygons(void) { SEdge *edge = &(edges.l.elem[i]); Vector abot = (edge->a).Plus(tbot), bbot = (edge->b).Plus(tbot); Vector atop = (edge->a).Plus(ttop), btop = (edge->b).Plus(ttop); + // We tagged the edges that came from line segments; their + // triangles should be associated with that plane face. + if(edge->tag) { + hEntity hl = { edge->tag }; + hEntity hf = Remap(hl, REMAP_LINE_TO_FACE); + meta.face = hf.v; + } else { + meta.face = 0; + } if(flipBottom) { outm.AddTriangle(meta, bbot, abot, atop); outm.AddTriangle(meta, bbot, atop, btop); @@ -641,6 +718,11 @@ void Group::MakePolygons(void) { for(int i = 0; i < impMesh.l.n; i++) { STriangle st = impMesh.l.elem[i]; + + if(st.meta.face != 0) { + hEntity he = { st.meta.face }; + st.meta.face = Remap(he, 0).v; + } st.a = q.Rotate(st.a).Plus(offset); st.b = q.Rotate(st.b).Plus(offset); st.c = q.Rotate(st.c).Plus(offset); @@ -665,21 +747,30 @@ void Group::Draw(void) { // Show this even if the group is not visible. It's already possible // to show or hide just this with the "show solids" flag. - bool useModelColor; + int specColor; if(type != EXTRUDE && type != IMPORTED) { - GLfloat mpf[] = { 0.1f, 0.1f, 0.1f, 1.0 }; - glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mpf); - useModelColor = false; + specColor = RGB(25, 25, 25); // force the color to something dim } else { - useModelColor = true; + specColor = -1; // use the model color } // The back faces are drawn in red; should never seem them, since we // draw closed shells, so that's a debugging aid. GLfloat mpb[] = { 1.0f, 0.1f, 0.1f, 1.0 }; glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, mpb); + // When we fill the mesh, we need to know which triangles are selected + // or hovered, in order to draw them differently. + DWORD mh = 0, ms1 = 0, ms2 = 0; + hEntity he = SS.GW.hover.entity; + if(he.v != 0 && SS.GetEntity(he)->IsFace()) { + mh = he.v; + } + SS.GW.GroupSelection(); + if(gs.faces > 0) ms1 = gs.face[0].v; + if(gs.faces > 1) ms2 = gs.face[1].v; + glEnable(GL_LIGHTING); - if(SS.GW.showShaded) glxFillMesh(useModelColor, &mesh); + if(SS.GW.showShaded) glxFillMesh(specColor, &mesh, mh, ms1, ms2); glDisable(GL_LIGHTING); if(SS.GW.showMesh) glxDebugMesh(&mesh); diff --git a/sketch.h b/sketch.h index 86e2bb1..27a966f 100644 --- a/sketch.h +++ b/sketch.h @@ -148,8 +148,11 @@ public: static const int REMAP_LAST = 1000; static const int REMAP_TOP = 1001; static const int REMAP_BOTTOM = 1002; + static const int REMAP_PT_TO_LINE = 1003; + static const int REMAP_LINE_TO_FACE = 1004; hEntity Remap(hEntity in, int copyNumber); void MakeExtrusionLines(hEntity in); + void MakeExtrusionTopBottomFaces(hEntity pt); void TagEdgesFromLineSegments(SEdgeList *sle); void CopyEntity(Entity *ep, int timesApplied, int remap, hParam dx, hParam dy, hParam dz, @@ -232,9 +235,9 @@ public: static const int DISTANCE = 4000; static const int DISTANCE_N_COPY = 4001; - static const int FACE_N_COPY = 5000; - static const int FACE_N_TRANS = 5001; - static const int FACE_N_XPROD = 5002; + static const int FACE_NORMAL_PT = 5000; + static const int FACE_XPROD = 5001; + static const int FACE_N_ROT_TRANS = 5002; static const int WORKPLANE = 10000; @@ -258,6 +261,8 @@ public: Vector numPoint; Quaternion numNormal; double numDistance; + // and a bit more state that the faces need + Vector numVector; // All points/normals/distances have their numerical value; this is // a convenience, to simplify the import/assembly code, so that the @@ -297,6 +302,11 @@ public: Vector WorkplaneGetOffset(void); Entity *Normal(void); + bool IsFace(void); + ExprVector FaceGetNormalExprs(void); + Vector FaceGetNormalNum(void); + ExprVector FaceGetPointExprs(void); + bool IsPoint(void); // Applies for any of the point types Vector PointGetNum(void); diff --git a/solvespace.h b/solvespace.h index 930ee18..65fc12e 100644 --- a/solvespace.h +++ b/solvespace.h @@ -104,7 +104,7 @@ void glxVertex3v(Vector u); typedef void GLX_CALLBACK glxCallbackFptr(void); void glxTesselatePolygon(GLUtesselator *gt, SPolygon *p); void glxFillPolygon(SPolygon *p); -void glxFillMesh(bool useModelColor, SMesh *m); +void glxFillMesh(int color, SMesh *m, DWORD h, DWORD s1, DWORD s2); void glxDebugPolygon(SPolygon *p); void glxDebugEdgeList(SEdgeList *l); void glxDebugMesh(SMesh *m); diff --git a/util.cpp b/util.cpp index a89482e..801b6c2 100644 --- a/util.cpp +++ b/util.cpp @@ -32,6 +32,15 @@ Quaternion Quaternion::From(double w, double vx, double vy, double vz) { return q; } +Quaternion Quaternion::From(hParam w, hParam vx, hParam vy, hParam vz) { + Quaternion q; + q.w = SS.GetParam(w )->val; + q.vx = SS.GetParam(vx)->val; + q.vy = SS.GetParam(vy)->val; + q.vz = SS.GetParam(vz)->val; + return q; +} + Quaternion Quaternion::From(Vector u, Vector v) { Vector n = u.Cross(v);