Beispiel #1
0
static void
bezier(BezierShape &shape,float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)
{
//DebugPrint(_T("Bezier creating %.2f %.2f-%.2f %.2f-%.2f %.2f-%.2f %.2f\n"),x0,y0,x1,y1,x2,y2,x3,y3);
if(!curSpline)
	curSpline = shape.NewSpline();
int knots = curSpline->KnotCount();
if(knots == 0) {
	curSpline->AddKnot(SplineKnot(KTYPE_BEZIER, LTYPE_CURVE, Point3(x0,y0,0.0f), Point3(x0,y0,0.0f), Point3(x1,y1,0.0f)));
	curSpline->AddKnot(SplineKnot(KTYPE_BEZIER, LTYPE_CURVE, Point3(x3,y3,0.0f), Point3(x2,y2,0.0f), Point3(x3,y3,0.0f)));
	}
else {
	// First point of this curve must be the same as the last point on the output curve
	assert(curSpline->GetKnotPoint(knots-1) == Point3(x0,y0,0.0f));
	curSpline->SetOutVec(knots-1, Point3(x1,y1,0.0f));
	if(Point3(x3,y3,0.0f) == curSpline->GetKnotPoint(0)) {
		curSpline->SetInVec(0, Point3(x2,y2,0.0f));
		curSpline->SetClosed();
//DebugPrint(_T("Bezier autoclosed\n"));
		curSpline = NULL;
		}
	else
		curSpline->AddKnot(SplineKnot(KTYPE_BEZIER, LTYPE_CURVE, Point3(x3,y3,0.0f), Point3(x2,y2,0.0f), Point3(x3,y3,0.0f)));
	}
}
Beispiel #2
0
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();
	}
Beispiel #3
0
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();
	}
Beispiel #4
0
static void MakeCircle(BezierShape& ashape, float radius) {
	float vector = CIRCLE_VECTOR_LENGTH * radius;
	// Delete all points in the existing spline
	Spline3D *spline = ashape.NewSpline();
	// Now add all the necessary points
	for(int ix=0; ix<4; ++ix) {
		float angle = 6.2831853f * (float)ix / 4.0f;
		float sinfac = (float)sin(angle), cosfac = (float)cos(angle);
		Point3 p(cosfac * radius, sinfac * radius, 0.0f);
		Point3 rotvec = Point3(sinfac * vector, -cosfac * vector, 0.0f);
		spline->AddKnot(SplineKnot(KTYPE_BEZIER,LTYPE_CURVE,p,p + rotvec,p - rotvec));
		}
	spline->SetClosed();
	spline->ComputeBezPoints();
	}
Beispiel #5
0
BOOL TrueTypeImport::BuildCharacter(UINT index, float height, BezierShape &shape, float &width, int fontShapeVersion) {
    assert(hFont);
	if(!hFont)
		return 0;

	// Set up for the font and release it when this function returns
	FontReady fontRdy(hFont);
			    
	// allocate space for the bitmap/outline
	GLYPHMETRICS gm;
    // init it to prevent UMR in GetGlyphOutline
    gm.gmBlackBoxX = 
    gm.gmBlackBoxY = 
    gm.gmptGlyphOrigin.x =
    gm.gmptGlyphOrigin.y =
    gm.gmCellIncX = 
    gm.gmCellIncY = 0; 

	// Give it an identity matrix
	MAT2 mat;
	IdentityMat(&mat);

	// get unicode outline 
	DWORD size= GetGlyphOutlineW(fontRdy.hdc, index, GGO_GLYPH_INDEX|GGO_NATIVE, &gm, 0, NULL, &mat); 
	if(size != GDI_ERROR && size > 0) {
		GenericAlloc mem(size);
		if(!mem.ptr)
			goto failure;
		// get unicode outline
		if ((GetGlyphOutlineW(fontRdy.hdc, index, GGO_GLYPH_INDEX|GGO_NATIVE, &gm, size, mem.ptr, &mat)) != size)
			goto failure;
		curSpline = NULL;	// reset the current spline pointer
		if(!CreateCharacterShape((TTPOLYGONHEADER *)mem.ptr, size, shape, fontShapeVersion))
			goto failure;
		// Make sure the height matches the request
		float scaleFactor = height / 1000.0f;
		Matrix3 tm = ScaleMatrix(Point3(scaleFactor, scaleFactor, 0.0f));
		shape.Transform(tm);
		width = float(gm.gmCellIncX) * scaleFactor;
		return TRUE;
		}

	// Character wasn't found!
	failure:
	width = 0.0f;
	return FALSE;
	}
Beispiel #6
0
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 AlembicCurves::Save(double time, bool bLastFrame)
{
    ESS_PROFILE_FUNC();

    //TimeValue ticks = GET_MAX_INTERFACE()->GetTime();
    TimeValue ticks = GetTimeValueFromFrame(time);
	Object *obj = mMaxNode->EvalWorldState(ticks).obj;
	if(mNumSamples == 0){
		bForever = CheckIfObjIsValidForever(obj, ticks);
	}
	else{
		bool bNewForever = CheckIfObjIsValidForever(obj, ticks);
		if(bForever && bNewForever != bForever){
			ESS_LOG_INFO( "bForever has changed" );
		}
	}

	SaveMetaData(mMaxNode, this);

    // check if the spline is animated
    if(mNumSamples > 0) 
    {
        if(bForever)
        {
            return true;
        }
    }

    AbcG::OCurvesSchema::Sample curvesSample;

	std::vector<AbcA::int32_t> nbVertices;
    std::vector<Point3> vertices;
    std::vector<float> knotVector;
    std::vector<Abc::uint16_t> orders;

    if(obj->ClassID() == EDITABLE_SURF_CLASS_ID){

       NURBSSet nurbsSet;   
       BOOL success = GetNURBSSet(obj, ticks, nurbsSet, TRUE);   

       AbcG::CurvePeriodicity cPeriod = AbcG::kNonPeriodic;
       AbcG::CurveType cType = AbcG::kCubic;
       AbcG::BasisType cBasis = AbcG::kNoBasis;

       int n = nurbsSet.GetNumObjects();
       for(int i=0; i<n; i++){
          NURBSObject* pObject = nurbsSet.GetNURBSObject((int)i);

          //NURBSType type = pObject->GetType();
          if(!pObject){
             continue;
          }

          if( pObject->GetKind() == kNURBSCurve ){
             NURBSCurve* pNurbsCurve = (NURBSCurve*)pObject;

             int degree;
             int numCVs;
             NURBSCVTab cvs;
			 int numKnots;
		     NURBSKnotTab knots;
             pNurbsCurve->GetNURBSData(ticks, degree, numCVs, cvs, numKnots, knots);

             orders.push_back(degree+1);

             const int cvsCount = cvs.Count();
             const int knotCount = knots.Count();

             for(int j=0; j<cvs.Count(); j++){
                NURBSControlVertex cv = cvs[j];
                double x, y, z;
                cv.GetPosition(ticks, x, y, z);
                vertices.push_back( Point3((float)x, (float)y, (float)z) );
             }

             nbVertices.push_back(cvsCount);

             //skip the first and last entry because Maya and XSI use this format
             for(int j=1; j<knots.Count()-1; j++){
                knotVector.push_back((float)knots[j]);
             }

             if(i == 0){
                if(pNurbsCurve->IsClosed()){
                   cPeriod = AbcG::kPeriodic;
                }  
             }
             else{
                if(pNurbsCurve->IsClosed()){
                   if(cPeriod != AbcG::kPeriodic){
                      ESS_LOG_WARNING("Mixed curve wrap types not supported.");
                   }
                }
                else{
                   if(cPeriod != AbcG::kNonPeriodic){
                      ESS_LOG_WARNING("Mixed curve wrap types not supported.");
                   }
                }
             }

          }
          
       }
       

       curvesSample.setType(cType);
       curvesSample.setWrap(cPeriod);
       curvesSample.setBasis(cBasis);
    }
    else
    {
          BezierShape beziershape;
          PolyShape polyShape;
          bool bBezier = false;

          // Get a pointer to the spline shpae
          ShapeObject *pShapeObject = NULL;
          if (obj->IsShapeObject())
          {
              pShapeObject = reinterpret_cast<ShapeObject *>(obj);
          }
          else
          {
              return false;
          }

          // Determine if we are a bezier shape
          if (pShapeObject->CanMakeBezier())
          {
              pShapeObject->MakeBezier(ticks, beziershape);
              bBezier = true;
          }
          else
          {
              pShapeObject->MakePolyShape(ticks, polyShape);
              bBezier = false;
          }

          // Get the control points

          //std::vector<Point3> inTangents;
	      //std::vector<Point3> outTangents;
          if (bBezier)
          {
              int oldVerticesCount = (int)vertices.size();
              for (int i = 0; i < beziershape.SplineCount(); i += 1)
              {
                  Spline3D *pSpline = beziershape.GetSpline(i);
                  int knots = pSpline->KnotCount();
                  for(int ix = 0; ix < knots; ++ix) 
                  {
                      Point3 in = pSpline->GetInVec(ix);
                      Point3 p = pSpline->GetKnotPoint(ix);
                      Point3 out = pSpline->GetOutVec(ix);

                      vertices.push_back( p );
				      //inTangents.push_back( in );
				      //outTangents.push_back( out );
                  }

                  int nNumVerticesAdded = (int)vertices.size() - oldVerticesCount;
                  nbVertices.push_back( nNumVerticesAdded );
                  oldVerticesCount = (int)vertices.size();
              }
          }
          else
          {
              for (int i = 0; i < polyShape.numLines; i += 1)
              {
                  PolyLine &refLine = polyShape.lines[i];
                  nbVertices.push_back(refLine.numPts);
                  for (int j = 0; j < refLine.numPts; j += 1)
                  {
                      Point3 p = refLine.pts[j].p;
                      vertices.push_back(p);
                  }
              }
          }

          // set the type + wrapping
	      curvesSample.setType(bBezier ? AbcG::kCubic : AbcG::kLinear);
          curvesSample.setWrap(pShapeObject->CurveClosed(ticks, 0) ? AbcG::kPeriodic : AbcG::kNonPeriodic);
          curvesSample.setBasis(AbcG::kNoBasis);
    }

    if(nbVertices.size() == 0 || vertices.size() == 0){
       ESS_LOG_WARNING("No curve data to export.");
       return false;
    }
 

    const int vertCount = (int)vertices.size();

    // prepare the bounding box
    Abc::Box3d bbox;

    // allocate the points and normals
    std::vector<Abc::V3f> posVec(vertCount);
    Matrix3 wm = mMaxNode->GetObjTMAfterWSM(ticks);

    for(int i=0;i<vertCount;i++)
    {
        posVec[i] = ConvertMaxPointToAlembicPoint(vertices[i] );
        bbox.extendBy(posVec[i]);

        // Set the archive bounding box
        if (mJob)
        {
            Point3 worldMaxPoint = wm * vertices[i];
            Abc::V3f alembicWorldPoint = ConvertMaxPointToAlembicPoint(worldMaxPoint);
            mJob->GetArchiveBBox().extendBy(alembicWorldPoint);
        }
    }

    if(knotVector.size() > 0 && orders.size() > 0){
       if(!mKnotVectorProperty.valid()){
          mKnotVectorProperty = Abc::OFloatArrayProperty(mCurvesSchema.getArbGeomParams(), ".knot_vector", mCurvesSchema.getMetaData(), mJob->GetAnimatedTs() );
       }
       mKnotVectorProperty.set(Abc::FloatArraySample(knotVector));

       if(!mOrdersProperty.valid()){
          mOrdersProperty = Abc::OUInt16ArrayProperty(mCurvesSchema.getArbGeomParams(), ".orders", mCurvesSchema.getMetaData(), mJob->GetAnimatedTs() );
       }
       mOrdersProperty.set(Abc::UInt16ArraySample(orders));
    }

    // store the bbox
    curvesSample.setSelfBounds(bbox);
	mCurvesSchema.getChildBoundsProperty().set(bbox);

 
    Abc::Int32ArraySample nbVerticesSample(&nbVertices.front(),nbVertices.size());
    curvesSample.setCurvesNumVertices(nbVerticesSample);


 
    // allocate for the points and normals
    Abc::P3fArraySample posSample(&posVec.front(),posVec.size());
	curvesSample.setPositions(posSample);


    mCurvesSchema.set(curvesSample);

   mNumSamples++;

   return true;
}
Beispiel #8
0
int CrossSectionMouseProc::proc(
			HWND hwnd, 
			int msg, 
			int point, 
			int flags, 
			IPoint2 m )
	{
	ViewExp *vpt = NULL;
	HitRecord *rec = NULL;
	int res = TRUE;

	switch ( msg ) {
		case MOUSE_ABORT:
			if (mCreating) {
				if (mCrossingDrawn)
					DrawCrossing(hwnd);		// erase the previous line
				mCreating = false;
				es->EndCrossSection(mSelectedSplines.Count() > 1 ? TRUE : FALSE);
			}
			res = FALSE;
			break;

		case MOUSE_PROPCLICK:
			ip->SetStdCommandMode(CID_OBJMOVE);
			res = FALSE;
			break;

		case MOUSE_POINT:
			vpt = ip->GetViewport(hwnd);
			if((rec = HitTest(vpt,&m,HITTYPE_POINT,0)) != NULL) {
				ShapeHitData *hit = ((ShapeHitData *)rec->hitData);
				int poly = hit->poly;
				mObjToWorldTM = rec->nodeRef->GetObjectTM(ip->GetTime());

				if (!mCreating) {
					if (!es->StartCrossSection(&mShapeData))
						return CREATE_ABORT;
					mCreating = true;
					mSelectedSplines.ZeroCount();
					BezierShape *shape = mShapeData->TempData(es)->GetShape(ip->GetTime());
					mPolys = (shape == NULL) ? 0 : shape->SplineCount();
					}
				mSelectedSplines.Append(1, &poly, 1);
				es->DoCrossSection(mShapeData, mSelectedSplines);
				mMouse = m;
				mCrossingDrawn = false;
				}
			ip->ReleaseViewport(vpt);
			if (!mCreating) res = FALSE;
			break;
		
		case MOUSE_MOVE:
			if (mCreating) {
				if (mCrossingDrawn)
					DrawCrossing(hwnd);		// erase the previous line
				mMouse = m;
				DrawCrossing(hwnd);
				mCrossingDrawn = true;
				}
			// continue to the next case to set cursor.
			
		case MOUSE_FREEMOVE:
			vpt = ip->GetViewport(hwnd);
			if ( HitTest(vpt,&m,HITTYPE_POINT,HIT_ABORTONHIT) )
				SetCursor(GetTransformCursor());
			else
				SetCursor(LoadCursor(NULL,IDC_ARROW));
			ip->ReleaseViewport(vpt);
			break;
		}

	return res;
	}
Beispiel #9
0
void ExtrudeMod::BuildPatchFromShape(TimeValue t,ModContext &mc, ObjectState * os, PatchMesh &pmesh) {
	ShapeObject *shape = (ShapeObject *)os->obj;

	float amount;
	int levels,capStart,capEnd,capType;

	pblock->GetValue(PB_AMOUNT,t,amount,FOREVER);
	pblock->GetValue(PB_SEGS,t,levels,FOREVER);
	if (levels<1) levels = 1;
	pblock->GetValue(PB_CAPSTART,t,capStart,FOREVER);
	pblock->GetValue(PB_CAPEND,t,capEnd,FOREVER);
	pblock->GetValue(PB_CAPTYPE,t,capType,FOREVER);

	BOOL texturing;
	pblock->GetValue(PB_MAPPING, TimeValue(0), texturing, FOREVER);
	BOOL genMatIDs;
	pblock->GetValue(PB_GEN_MATIDS, TimeValue(0), genMatIDs, FOREVER);
	BOOL useShapeIDs;
	pblock->GetValue(PB_USE_SHAPEIDS, TimeValue(0), useShapeIDs, FOREVER);
	BOOL smooth;
	pblock->GetValue(PB_SMOOTH, TimeValue(0), smooth, FOREVER);

	LimitValue(amount, -1000000.0f, 1000000.0f);

	// Get the basic dimension stuff
	float zSize = (float)fabs(amount);
	float baseZ = 0.0f;
	if(amount < 0.0f)
		baseZ = amount;

	// If the shape can convert itself to a BezierShape, have it do so!
	BezierShape bShape;
	if(shape->CanMakeBezier())
		shape->MakeBezier(t, bShape);
	else {
		PolyShape pShape;
		shape->MakePolyShape(t, pShape);
		bShape = pShape;	// UGH -- Convert it from a PolyShape -- not good!
		}
	
//DebugPrint(_T("Extrude organizing shape\n"));
	ShapeHierarchy hier;
	bShape.OrganizeCurves(t, &hier);
	// Need to flip the reversed polys...
	bShape.Reverse(hier.reverse);
	// ...and tell the hierarchy they're no longer reversed!
	hier.reverse.ClearAll();

	// Our shapes are now organized for patch-making -- Let's do the sides!
	int polys = bShape.splineCount;
	int poly, knot;
	int levelVerts = 0, levelVecs = 0, levelPatches = 0, nverts = 0, nvecs = 0, npatches = 0;
	int TVlevels = levels + 1, levelTVerts = 0, ntverts = 0, ntpatches = 0;
	BOOL anyClosed = FALSE;
	for(poly = 0; poly < polys; ++poly) {
		Spline3D *spline = bShape.splines[poly];
		if(!spline->KnotCount())
			continue;
		if(spline->Closed())
			anyClosed = TRUE;
		levelVerts += spline->KnotCount();
		levelTVerts += (spline->Segments() + 1);
		levelVecs += (spline->Segments() * 2);
		levelPatches += spline->Segments();
		}
	nverts = levelVerts * (levels + 1);
	npatches = levelPatches * levels;
	nvecs = (levelVecs * (levels + 1)) + levels * levelVerts * 2 + npatches * 4;
	if(texturing) {
		ntverts = levelTVerts * TVlevels;
		ntpatches = npatches;
		}

	pmesh.setNumVerts(nverts);
	pmesh.setNumVecs(nvecs);
	pmesh.setNumPatches(npatches);
	pmesh.setNumTVerts(ntverts);
	pmesh.setNumTVPatches(ntpatches);

	// Create the vertices!
	int vert = 0;
	int level;
	Point3 offset1, offset2;
	for(poly = 0; poly < polys; ++poly) {
		Spline3D *spline = bShape.splines[poly];
		if(!spline->KnotCount())
			continue;
		int knots = spline->KnotCount();
		for(level = 0; level <= levels; ++level) {
			Point3 offset = Point3(0.0f, 0.0f, baseZ + (float)level / (float)levels * zSize);
			if(level == 0)
				offset1 = offset;
			else
			if(level == levels)
				offset2 = offset;
			for(knot = 0; knot < knots; ++knot) {
				Point3 p = spline->GetKnotPoint(knot);
				pmesh.setVert(vert++, p + offset);
				}
			}
		}
	assert(vert == nverts);

    BOOL usePhysUVs = GetUsePhysicalScaleUVs();
	// Maybe create the texture vertices
	if(texturing) {
		int tvert = 0;
		int level;
		for(poly = 0; poly < polys; ++poly) {
			Spline3D *spline = bShape.splines[poly];
			if(!spline->KnotCount())
				continue;
			// Make it a polyline
			PolyLine pline;
			spline->MakePolyLine(pline, 10);
			int knots = spline->KnotCount();
			for(level = 0; level < TVlevels; ++level) {
				float tV = (float)level / (float)(TVlevels - 1);
                float vScale = usePhysUVs ? amount : 1.0f;
				int lverts = pline.numPts;
				int tp = 0;
				int texPts = spline->Segments() + 1;
				float cumLen = 0.0f;
				float totLen = pline.CurveLength();
                float uScale = usePhysUVs ? totLen : 1.0f;
				Point3 prevPt = pline.pts[0].p;
				int plix = 0;
				while(tp < texPts) {
					Point3 &pt = pline[plix].p;
					cumLen += Length(pt - prevPt);
					prevPt = pt;
					if(pline[plix].flags & POLYPT_KNOT) {
						float tU;
						if(tp == (texPts - 1))
							tU = 1.0f;
						else
							tU = cumLen / totLen;
						pmesh.setTVert(tvert++, UVVert(uScale*tU, vScale*tV, 0.0f));
						tp++;
						}
					plix = (plix + 1) % pline.numPts;
					}
				}
			}
		assert(tvert == ntverts);
		}

	// Create the vectors!
	int seg;
	int vec = 0;
	for(poly = 0; poly < polys; ++poly) {
		Spline3D *spline = bShape.splines[poly];
		if(!spline->KnotCount())
			continue;
		int segs = spline->Segments();
		int knots = spline->KnotCount();
		// First, the vectors on each level
		for(level = 0; level <= levels; ++level) {
			Point3 offset = Point3(0.0f, 0.0f, baseZ + (float)level / (float)levels * zSize);
			for(seg = 0; seg < segs; ++seg) {
				int seg2 = (seg + 1) % knots;
				if(spline->GetLineType(seg) == LTYPE_CURVE) {
					Point3 p = spline->GetOutVec(seg);
					pmesh.setVec(vec++, p + offset);
					p = spline->GetInVec(seg2);
					pmesh.setVec(vec++, p + offset);
					}
				else {
					Point3 p = spline->InterpBezier3D(seg, 0.333333f);
					pmesh.setVec(vec++, p + offset);
					p = spline->InterpBezier3D(seg, 0.666666f);
					pmesh.setVec(vec++, p + offset);
					}
				}
			}
		// Now, the vectors between the levels
		int baseVec = vec;
		for(level = 0; level < levels; ++level) {
			Point3 offsetA = Point3(0.0f, 0.0f, baseZ + (float)level / (float)levels * zSize);
			Point3 offsetB = Point3(0.0f, 0.0f, baseZ + (float)(level + 1) / (float)levels * zSize);
			Point3 offset1 = offsetA + (offsetB - offsetA) * 0.333333333f;
			Point3 offset2 = offsetA + (offsetB - offsetA) * 0.666666666f;
			for(knot = 0; knot < knots; ++knot) {
				Point3 p = spline->GetKnotPoint(knot);
				pmesh.setVec(vec++, p + offset1);
				pmesh.setVec(vec++, p + offset2);
				}
			}
		}

	// Create the patches!
	int np = 0;
	int baseVert = 0;
	int baseVec = 0;
	for(poly = 0; poly < polys; ++poly) {
		Spline3D *spline = bShape.splines[poly];
		if(!spline->KnotCount())
			continue;
		int knots = spline->KnotCount();
		int segs = spline->Segments();
		int baseVec1 = baseVec;	// Base vector index for this level
		int baseVec2 = baseVec + segs * 2 * (levels + 1);	// Base vector index for between levels
		for(level = 0; level < levels; ++level) {
			int sm = 0;
			BOOL firstSmooth = (spline->GetLineType(0) == LTYPE_CURVE && spline->GetLineType(segs-1) == LTYPE_CURVE && (spline->GetKnotType(0) == KTYPE_AUTO || spline->GetKnotType(0) == KTYPE_BEZIER)) ? TRUE : FALSE;
			for(seg = 0; seg < segs; ++seg, vec += 4) {
				int prevseg = (seg + segs - 1) % segs;
				int seg2 = (seg + 1) % knots;
				int a,b,c,d,ab,ba,bc,cb,cd,dc,da,ad;
				MtlID mtl = useShapeIDs ? spline->GetMatID(seg) : 2;
				a = baseVert + seg;
				b = baseVert + seg2;
				c = b + knots;
				d = a + knots;
				ab = baseVec1 + seg * 2;
				ba = ab + 1;
				bc = baseVec2 + seg2 * 2;
				cb = bc + 1;
				cd = ba + (segs * 2);
				dc = ab + (segs * 2);
				da = baseVec2 + seg * 2 + 1;
				ad = da - 1;
//DebugPrint(_T("Making patch %d: %d (%d %d) %d (%d %d) %d (%d %d) %d (%d %d)\n"),np, a, ab, ba, b, bc, cb, c, cd, dc, d, da, ad);
				// If the vertex is not smooth, go to the next group!
				if(seg > 0 && !(spline->GetLineType(prevseg) == LTYPE_CURVE && spline->GetLineType(seg) == LTYPE_CURVE && (spline->GetKnotType(seg) == KTYPE_AUTO || spline->GetKnotType(seg) == KTYPE_BEZIER))) {
					sm++;
					if(sm > 2)
						sm = 1;
					}
				DWORD smoothGroup = 1 << sm;
				if(seg == segs - 1 && firstSmooth) {
					smoothGroup |= 1;
					}
				pmesh.MakeQuadPatch(np, a, ab, ba, b, bc, cb, c, cd, dc, d, da, ad, vec, vec+1, vec+2, vec+3, smooth ? smoothGroup : 0);
				pmesh.setPatchMtlIndex(np++, genMatIDs ? mtl : 0);
				}
			baseVert += knots;
			baseVec1 += (segs * 2);
			baseVec2 += (knots * 2);
			}
		baseVert += knots;
		baseVec += (segs * 2 * (levels + 1) + knots * 2 * levels);
		}
	assert(vec == nvecs);
	assert(np == npatches);

 	// Maybe create the texture patches!
	if(texturing) {
		int ntp = 0;
		int baseTVert = 0;
		for(poly = 0; poly < polys; ++poly) {
			Spline3D *spline = bShape.splines[poly];
			if(!spline->KnotCount())
				continue;
			int pknots = spline->Segments() + 1;
			int pverts = pknots * TVlevels;
			int segs = spline->Segments();
			for(level = 0; level < levels; ++level) {
				for(seg = 0; seg < segs; ++seg) {
					int prevseg = (seg + segs - 1) % segs;
					int seg2 = seg + 1;
					int a,b,c,d;
					a = baseTVert + seg;
					b = baseTVert + seg2;
					c = b + pknots;
					d = a + pknots;
					TVPatch &tp = pmesh.getTVPatch(ntp++);
					tp.setTVerts(a, b, c, d);
					
					}
				baseTVert += pknots;
				}
			baseTVert += pknots;
			}
		assert(ntp == ntpatches);
		}

	// If capping, do it!
	if(anyClosed && (capStart || capEnd)) {
		PatchCapInfo capInfo;
		bShape.MakeCap(t, capInfo);

		// Build information for capping
		PatchCapper capper(bShape);
		if(capStart) {
			vert = 0;
			int baseVec = 0;
			for(poly = 0; poly < polys; ++poly) {
				Spline3D *spline = bShape.splines[poly];
				if(!spline->KnotCount())
					continue;
				PatchCapPoly &capline = capper[poly];
				int lverts = spline->KnotCount();
				for(int v = 0; v < lverts; ++v)
					capline.SetVert(v, vert++);			// Gives this vert's location in the mesh!
				vert += lverts * levels;
				vec = baseVec;
				int lvecs = spline->Segments() * 2;
				for(int v = 0; v < lvecs; ++v)
					capline.SetVec(v, vec++);			// Gives this vec's location in the mesh!
				baseVec += lvecs * (levels + 1) + spline->KnotCount() * levels * 2;
				}
			// Create a work matrix for capping
			Matrix3 mat = TransMatrix(offset1);
			int oldPatches = pmesh.numPatches;
			capper.CapPatchMesh(pmesh, capInfo, TRUE, 16, &mat, genMatIDs ? -1 : 0);
			// If texturing, create the texture patches and vertices
			if(texturing)
				MakePatchCapTexture(pmesh, Inverse(mat), oldPatches, pmesh.numPatches, usePhysUVs);
			}
		if(capEnd) {
			int baseVert = 0;
			int baseVec = 0;
			for(poly = 0; poly < polys; ++poly) {
				Spline3D *spline = bShape.splines[poly];
				if(!spline->KnotCount())
					continue;
				PatchCapPoly &capline = capper[poly];
				int lverts = spline->KnotCount();
				int vert = baseVert + lverts * levels;
				for(int v = 0; v < lverts; ++v)
					capline.SetVert(v, vert++);			// Gives this vert's location in the mesh!
				baseVert += lverts * (levels + 1);
				int lvecs = spline->Segments()*2;
				int vec = baseVec + lvecs * levels;
				for(int v = 0; v < lvecs; ++v)
					capline.SetVec(v, vec++);			// Gives this vec's location in the mesh!
				baseVec += lvecs * (levels + 1) + spline->KnotCount() * levels * 2;
				}
			// Create a work matrix for grid capping
			Matrix3 mat = TransMatrix(offset2);
			int oldPatches = pmesh.numPatches;
			capper.CapPatchMesh(pmesh, capInfo, FALSE, 16, &mat, genMatIDs ? -1 : 0);
			// If texturing, create the texture patches and vertices
			if(texturing)
				MakePatchCapTexture(pmesh, Inverse(mat), oldPatches, pmesh.numPatches, usePhysUVs);
			}
		}

	//watje new mapping
	if(texturing)
		{
		if (ver < 4)
			{
			for (int i = 0; i < pmesh.numPatches; i++)
				pmesh.patches[i].flags |= PATCH_LINEARMAPPING;
			}
		}


	// Ready the patch representation!
	if( !pmesh.buildLinkages() )
   {
      assert(0);
   }
	pmesh.computeInteriors();
	}
Beispiel #10
0
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;
	}
Beispiel #11
0
void SWrapMod::ModifyObject(
		TimeValue t, ModContext &mc, ObjectState *os, INode *node)
{	SWrapObject *obj = (SWrapObject *)GetWSMObject(t);
	INode *pnode;
	TriObject *towrapOb=NULL;Object *pobj=NULL;
	if (obj) pnode=obj->custnode;
	if (obj && nodeRef && pnode) 
	{	Interval valid = FOREVER;
		if (!obj->cmValid.InInterval(t))
		{   pobj = pnode->EvalWorldState(t).obj;
			obj->cmValid=pobj->ObjectValidity(t);
			Matrix3 tm=pnode->GetObjectTM(t,&(obj->cmValid));
			TriObject *wrapOb=IsUseable(pobj,t);
			if (wrapOb)
			{ if (obj->cmesh) delete obj->cmesh; 
			  obj->cmesh=new Mesh;
			   obj->cmesh->DeepCopy(&wrapOb->GetMesh(),
			     PART_GEOM|SELECT_CHANNEL|PART_SUBSEL_TYPE|PART_TOPO|TM_CHANNEL);
			   for (int ic=0;ic<obj->cmesh->getNumVerts();ic++)
			     obj->cmesh->verts[ic]=obj->cmesh->verts[ic]*tm;
			  GetVFLst(obj->cmesh,&obj->vnorms,&obj->fnorms);
			  if (wrapOb!=pobj) wrapOb->DeleteThis();
			}
 		}
		if (!obj->cmesh) return;
		if ((obj->cmesh->getNumVerts()==0)||(obj->cmesh->getNumFaces()==0)) 
			return;		 
//		Matrix3 invtm=Inverse(obj->tm);
		valid=obj->cmValid;
		Matrix3 ctm;
		ctm = nodeRef->GetNodeTM(t,&valid);
		Ray ray;
		Point3 v=-ctm.GetRow(2);
//		Matrix3 nooff=invtm;nooff.NoTrans();
		ray.dir=v;//*nooff;
		int selverts;
		float kdef,standoff;
		obj->pblock->GetValue(PB_USESELVERTS,t,selverts,valid);
		obj->pblock->GetValue(PB_KIDEFAULT,t,kdef,valid);
		obj->pblock->GetValue(PB_STANDOFF,t,standoff,valid);
		BezierShape stowrapOb;
		int found=0;
		Matrix3 towtm(1);
		if (os->GetTM()) 
			towtm=*(os->GetTM());
		Matrix3 invtowtm=Inverse(towtm);
		Point3 vert;
		Class_ID cid=os->obj->ClassID(),es=EDITABLE_SURF_CLASS_ID,efp=FITPOINT_PLANE_CLASS_ID,ecv=EDITABLE_CVCURVE_CLASS_ID,ecfp=EDITABLE_FPCURVE_CLASS_ID;
		if (((cid==EDITABLE_SURF_CLASS_ID)||(cid==FITPOINT_PLANE_CLASS_ID))||((cid==EDITABLE_CVCURVE_CLASS_ID)||(cid==EDITABLE_FPCURVE_CLASS_ID)))
		{ Object* nurbobj=os->obj;
		  int num=nurbobj->NumPoints();
		  for (int i=0;i<num;i++)
		  {	vert=DoIntersect(nurbobj->GetPoint(i)*towtm,ray,obj->cmesh,kdef,standoff,&found,v,obj->vnorms,obj->fnorms); 
		    nurbobj->SetPoint(i,(vert*invtowtm));
		  }
		}
#ifndef NO_PATCHES
		else if (os->obj->IsSubClassOf(patchObjectClassID))
		{ PatchObject* patchob=(PatchObject *)os->obj;
		  PatchMesh *pm=&(patchob->patch);
		  int nv=pm->getNumVerts();
		  BitArray sel = pm->VertSel();
		  for (int i=0;i<nv;i++)
		  { if (!selverts||sel[i])
			{ vert=DoIntersect(pm->getVert(i).p*towtm,ray,obj->cmesh,kdef,standoff,&found,v,obj->vnorms,obj->fnorms); 
		      vert=vert*invtowtm;
		      pm->setVert(i,vert);
			}
		  }
/*		  pm->buildLinkages();
		  pm->computeInteriors();
		  pm->InvalidateGeomCache();*/
		}
#endif // NO_PATCHES
		else if (towrapOb=IsUseable(os->obj,t))
		{	Point3 tvector;
			float dist;
			float *vssel = NULL;
		  if (selverts) 
			  vssel = towrapOb->GetMesh().getVSelectionWeights();
		  for (int i=0;i<towrapOb->GetMesh().getNumVerts();i++)
		  { 
				if ((!selverts)||(towrapOb->GetMesh().vertSel[i])
							   ||(vssel&&vssel[i]))
				{
					vert = DoIntersect(towrapOb->GetMesh().verts[i]*towtm,ray,obj->cmesh,kdef,standoff,&found,v,obj->vnorms,obj->fnorms); 
					vert = vert*invtowtm;
					if (vssel&&vssel[i])
					{
						tvector = vert - towrapOb->GetMesh().verts[i];
						dist = Length(tvector);
						if ((float)fabs(dist) > EPSILON)
							tvector = tvector/dist;
						else
							tvector = Zero;
						vert = towrapOb->GetMesh().verts[i] + dist*vssel[i]*tvector;
					}
					towrapOb->GetMesh().verts[i] = vert;
				}
		  }
		  if (towrapOb!=os->obj) 
			  towrapOb->DeleteThis();
		}
		else if((os->obj->IsSubClassOf(splineShapeClassID))||(os->obj->CanConvertToType(splineShapeClassID))) 
		{ SplineShape *attSplShape = (SplineShape *)os->obj->ConvertToType(t,splineShapeClassID);
		if (attSplShape) 
		{ stowrapOb=attSplShape->shape;
		  for (int poly=0; poly<stowrapOb.splineCount; ++poly)
		  { Spline3D *spline = stowrapOb.GetSpline(poly);
			int verts = spline->Verts();
			int knots = spline->KnotCount();
			BitArray sel = stowrapOb.VertexTempSel(poly);
			Point3 cknot,cknot2;
			{ for(int k=0; k<knots; ++k) 
			  {	int vert = k * 3 + 1;
				if (!selverts||sel[vert])  
				{ cknot=DoIntersect(spline->GetKnotPoint(k)*towtm,ray,obj->cmesh,kdef,standoff,&found,v,obj->vnorms,obj->fnorms);
				  attSplShape->shape.SetVert(poly,vert,cknot*invtowtm);
				  if (found)
				  { int knotType = spline->GetKnotType(k);
				    if(knotType & KTYPE_BEZIER) 
				    { cknot2= DoIntersect(spline->GetInVec(k)*towtm,ray,obj->cmesh,kdef,standoff,&found,v,obj->vnorms,obj->fnorms);
					attSplShape->shape.SetVert(poly,vert-1,(found?cknot2:cknot)*invtowtm);
				  	  cknot2= DoIntersect(spline->GetOutVec(k)*towtm,ray,obj->cmesh,kdef,standoff,&found,v,obj->vnorms,obj->fnorms);
					  attSplShape->shape.SetVert(poly,vert+1,(found?cknot2:cknot)*invtowtm);
					}
				  }
				}
			  }
			}
		  }
		  if (attSplShape!=os->obj) attSplShape->DeleteThis();
		}
	  }
//	os->obj->PointsWereChanged();
	os->obj->UpdateValidity(GEOM_CHAN_NUM,valid);	
//	NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);

  }
}