void EllipseObject::BuildShape(TimeValue t, BezierShape& ashape) { // Start the validity interval at forever and whittle it down. ivalid = FOREVER; float length; float width; pblock->GetValue(PB_LENGTH, t, length, ivalid); pblock->GetValue(PB_WIDTH, t, width, ivalid); LimitValue( length, MIN_LENGTH, MAX_LENGTH ); LimitValue( width, MIN_WIDTH, MAX_WIDTH ); // Delete the existing shape and create a new spline in it ashape.NewShape(); // Get parameters from SimpleSpline and place them in the BezierShape int steps; BOOL optimize,adaptive; ipblock->GetValue(IPB_STEPS, t, steps, ivalid); ipblock->GetValue(IPB_OPTIMIZE, t, optimize, ivalid); ipblock->GetValue(IPB_ADAPTIVE, t, adaptive, ivalid); ashape.steps = adaptive ? -1 : steps; ashape.optimize = optimize; float radius, xmult, ymult; if(length < width) { radius = width; xmult = 1.0f; ymult = length / width; } else if(width < length) { radius = length; xmult = width / length; ymult = 1.0f; } else { radius = length; xmult = ymult = 1.0f; } MakeCircle(ashape, radius / 2.0f, xmult, ymult); ashape.UpdateSels(); // Make sure it readies the selection set info ashape.InvalidateGeomCache(); }
void DonutObject::BuildShape(TimeValue t, BezierShape& ashape) { // Start the validity interval at forever and whittle it down. ivalid = FOREVER; float radius1; float radius2; pblock->GetValue(PB_RADIUS1, t, radius1, ivalid); if(mPipe) { float thickness; pblock->GetValue(PB_THICKNESS, t, thickness, ivalid); radius2 = radius1-thickness; } else { pblock->GetValue(PB_RADIUS2, t, radius2, ivalid); } LimitValue( radius1, MIN_RADIUS, MAX_RADIUS ); LimitValue( radius2, MIN_RADIUS, MAX_RADIUS ); ashape.NewShape(); // Get parameters from SimpleSpline and place them in the BezierShape int steps; BOOL optimize,adaptive; ipblock->GetValue(IPB_STEPS, t, steps, ivalid); ipblock->GetValue(IPB_OPTIMIZE, t, optimize, ivalid); ipblock->GetValue(IPB_ADAPTIVE, t, adaptive, ivalid); ashape.steps = adaptive ? -1 : steps; ashape.optimize = optimize; MakeCircle(ashape,radius1); MakeCircle(ashape,radius2); ashape.UpdateSels(); // Make sure it readies the selection set info ashape.InvalidateGeomCache(); }
void RectangleObject::BuildShape(TimeValue t, BezierShape& ashape) { // Start the validity interval at forever and whittle it down. ivalid = FOREVER; float length,fillet; float width; pblock->GetValue(PB_LENGTH, t, length, ivalid); pblock->GetValue(PB_WIDTH, t, width, ivalid); pblock->GetValue(PB_FILLET, t, fillet, ivalid); LimitValue( length, MIN_LENGTH, MAX_LENGTH ); LimitValue( width, MIN_WIDTH, MAX_WIDTH ); LimitValue( fillet, MIN_WIDTH, MAX_WIDTH ); // Delete the existing shape and create a new spline in it ashape.NewShape(); // Get parameters from SimpleSpline and place them in the BezierShape int steps; BOOL optimize,adaptive; ipblock->GetValue(IPB_STEPS, t, steps, ivalid); ipblock->GetValue(IPB_OPTIMIZE, t, optimize, ivalid); ipblock->GetValue(IPB_ADAPTIVE, t, adaptive, ivalid); ashape.steps = adaptive ? -1 : steps; ashape.optimize = optimize; Spline3D *spline = ashape.NewSpline(); // Now add all the necessary points // We'll add 'em as auto corners initially, have the spline package compute some vectors (because // I'm basically lazy and it does a great job, besides) then turn 'em into bezier corners! float l2 = length / 2.0f; float w2 = width / 2.0f; Point3 p = Point3(w2, l2, 0.0f); int pts=4; if (fillet>0) { pts=8; float cf=fillet*CIRCLE_VECTOR_LENGTH; Point3 wvec=Point3(fillet,0.0f,0.0f),lvec=Point3(0.0f,fillet,0.0f); Point3 cwvec=Point3(cf,0.0f,0.0f),clvec=Point3(0.0f,cf,0.0f); Point3 p3=p-lvec,p2; spline->AddKnot(SplineKnot(KTYPE_BEZIER,LTYPE_CURVE,p3,p3-clvec,p3+clvec)); p=p-wvec; spline->AddKnot(SplineKnot(KTYPE_BEZIER,LTYPE_CURVE,p,p+cwvec,p-cwvec)); p=Point3(-w2,l2,0.0f);p2=p+wvec; spline->AddKnot(SplineKnot(KTYPE_BEZIER,LTYPE_CURVE,p2,p2+cwvec,p2-cwvec)); p=p-lvec; spline->AddKnot(SplineKnot(KTYPE_BEZIER,LTYPE_CURVE,p,p+clvec,p-clvec)); p=Point3(-w2,-l2,0.0f);p3=p+lvec; spline->AddKnot(SplineKnot(KTYPE_BEZIER,LTYPE_CURVE,p3,p3+clvec,p3-clvec)); p=p+wvec; spline->AddKnot(SplineKnot(KTYPE_BEZIER,LTYPE_CURVE,p,p-cwvec,p+cwvec)); p = Point3(w2, -l2, 0.0f);p3=p-wvec; spline->AddKnot(SplineKnot(KTYPE_BEZIER,LTYPE_CURVE,p3,p3-cwvec,p3+cwvec)); p=p+lvec; spline->AddKnot(SplineKnot(KTYPE_BEZIER,LTYPE_CURVE,p,p-clvec,p+clvec)); spline->SetClosed(); spline->ComputeBezPoints(); } else {spline->AddKnot(SplineKnot(KTYPE_CORNER,LTYPE_CURVE,p,p,p)); p = Point3(-w2, l2, 0.0f); spline->AddKnot(SplineKnot(KTYPE_CORNER,LTYPE_CURVE,p,p,p)); p = Point3(-w2, -l2, 0.0f); spline->AddKnot(SplineKnot(KTYPE_CORNER,LTYPE_CURVE,p,p,p)); p = Point3(w2, -l2, 0.0f); spline->AddKnot(SplineKnot(KTYPE_CORNER,LTYPE_CURVE,p,p,p)); spline->SetClosed(); spline->ComputeBezPoints(); for(int i = 0; i < 4; ++i) spline->SetKnotType(i, KTYPE_BEZIER_CORNER); } spline->SetClosed(); spline->ComputeBezPoints(); for(int i = 0; i < pts; ++i) spline->SetKnotType(i, KTYPE_BEZIER_CORNER); ashape.UpdateSels(); // Make sure it readies the selection set info ashape.InvalidateGeomCache(); }
BOOL TrueTypeImport::CreateCharacterShape(LPTTPOLYGONHEADER lpHeader, int size, BezierShape &shape, int fontShapeVersion) { LPTTPOLYGONHEADER lpStart; LPTTPOLYCURVE lpCurve; WORD i = 0; POINTFX work; //DebugPrint(_T("Start of letter\n")); lpStart = lpHeader; while ((DWORD_PTR)lpHeader < (DWORD_PTR)(((LPSTR)lpStart) + size)) { if (lpHeader->dwType == TT_POLYGON_TYPE) { // Get to first curve. lpCurve = (LPTTPOLYCURVE) (lpHeader + 1); // iFirstCurve = cTotal; //DebugPrint(_T("Poly start\n")); while ((DWORD_PTR)lpCurve < (DWORD_PTR)(((LPSTR)lpHeader) + lpHeader->cb)) { if (lpCurve->wType == TT_PRIM_LINE) { work = *(LPPOINTFX)((LPSTR)lpCurve - sizeof(POINTFX)); Point3 p0(FloatFromFixed(work.x), FloatFromFixed(work.y), 0.0f); for (i = 0; i < lpCurve->cpfx; i++) { work = lpCurve->apfx[i]; Point3 p1(FloatFromFixed(work.x), FloatFromFixed(work.y), 0.0f); bezier(shape, p0.x, p0.y, p0.x, p0.y, p1.x, p1.y, p1.x, p1.y); p0 = p1; } } else if (lpCurve->wType == TT_PRIM_QSPLINE) { //********************************************** // Format assumption: // The bytes immediately preceding a POLYCURVE // structure contain a valid POINTFX. // // If this is first curve, this points to the // pfxStart of the POLYGONHEADER. // Otherwise, this points to the last point of // the previous POLYCURVE. // // In either case, this is representative of the // previous curve's last point. //********************************************** work = *(LPPOINTFX)((LPSTR)lpCurve - sizeof(POINTFX)); Point3 p0(FloatFromFixed(work.x), FloatFromFixed(work.y), 0.0f); Point3 p1, p2, p3, pa, pb; for (i = 0; i < lpCurve->cpfx;) { // This point is off the curve -- Hold onto it work = lpCurve->apfx[i++]; pa = Point3(FloatFromFixed(work.x), FloatFromFixed(work.y), 0.0f); // Calculate the C point. if (i == (lpCurve->cpfx - 1)) { // It's the last point, and therefore on the curve. // We need to compute the bezier handles between it and p0... work = lpCurve->apfx[i++]; p3 = Point3(FloatFromFixed(work.x), FloatFromFixed(work.y), 0.0f); } else { // It's not the last point -- Need to compute midpoint to get // a point on the curve work = lpCurve->apfx[i]; // Don't inc i -- We'll use it next time around! Point3 pb(FloatFromFixed(work.x), FloatFromFixed(work.y), 0.0f); p3 = (pa + pb) / 2.0f; } // Also compute the appropriate handles... if(fontShapeVersion == 1) { // Release 1.x-compatible p1 = (p0 + pa) / 2.0f; p2 = (pa + p3) / 2.0f; } else{ p1 = (p0 + 2.0f * pa) / 3.0f; // Release 2 p2 = (p3 + 2.0f * pa) / 3.0f; } // Let's add it to the output bezier! bezier(shape, p0.x, p0.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); // New A point for next slice of spline. p0 = p3; } } else ; // error, error, error // Move on to next curve. lpCurve = (LPTTPOLYCURVE)&(lpCurve->apfx[i]); } //DebugPrint(_T("Poly end\n")); if(curSpline) { curSpline->SetClosed(); curSpline = NULL; } // Move on to next polygon. lpHeader = (LPTTPOLYGONHEADER)(((LPSTR)lpHeader) + lpHeader->cb); } else ; // error, error, error } //DebugPrint(_T("End of letter\n")); // Make sure any splines are closed and reset if(curSpline) { curSpline->SetClosed(); curSpline = NULL; } // Update the selection set info -- Just to be safe shape.UpdateSels(); return TRUE; }