void TriPatchObject::BuildPatch(TimeValue t,PatchMesh& amesh) { int nverts = 4; int nvecs = 16; float l, w; int tex; // Start the validity interval at forever and whittle it down. ivalid = FOREVER; pblock->GetValue( PB_LENGTH, t, l, ivalid ); pblock->GetValue( PB_WIDTH, t, w, ivalid ); pblock->GetValue( PB_TEXTURE, t, tex, ivalid ); amesh.setNumVerts(nverts); amesh.setNumTVerts(tex ? nverts : 0); amesh.setNumVecs(nvecs); amesh.setNumPatches(2); amesh.setNumTVPatches(tex ? 2 : 0); Point3 v0 = Point3(-w, -l, 0.0f) / 2.0f; Point3 v1 = v0 + Point3(w, 0.0f, 0.0f); Point3 v2 = v0 + Point3(w, l, 0.0f); Point3 v3 = v0 + Point3(0.0f, l, 0.0f); // Create the vertices. amesh.verts[0].flags = PVERT_COPLANAR; amesh.verts[1].flags = PVERT_COPLANAR; amesh.verts[2].flags = PVERT_COPLANAR; amesh.verts[3].flags = PVERT_COPLANAR; if(tex) { amesh.setTVert(0, UVVert(0,0,0)); amesh.setTVert(1, UVVert(1,0,0)); amesh.setTVert(2, UVVert(1,1,0)); amesh.setTVert(3, UVVert(0,1,0)); } amesh.setVert(0, v0); amesh.setVert(1, v1); amesh.setVert(2, v2); amesh.setVert(3, v3); // Create the vectors MAKEVEC(0, v0, v1); MAKEVEC(2, v1, v2); MAKEVEC(4, v2, v3); MAKEVEC(6, v3, v0); MAKEVEC(8, v3, v1); // Create patches. amesh.MakeTriPatch(0, 0, 0, 1, 1, 9, 8, 3, 6, 7, 10, 11, 12, 1); amesh.MakeTriPatch(1, 1, 2, 3, 2, 4, 5, 3, 8, 9, 13, 14, 15, 1); Patch &p1 = amesh.patches[0]; Patch &p2 = amesh.patches[1]; if(tex) { amesh.getTVPatch(0).setTVerts(0,1,3); amesh.getTVPatch(1).setTVerts(1,2,3); } // Finish up patch internal linkages (and bail out if it fails!) assert(amesh.buildLinkages()); // Calculate the interior bezier points on the PatchMesh's patches amesh.computeInteriors(); amesh.InvalidateGeomCache(); // Tell the PatchMesh it just got changed amesh.InvalidateMesh(); }
void BuildTorusPatch( TimeValue t, PatchMesh &patch, float radius1, float radius2, int genUVs, BOOL usePhysUVs) { int segs = 8, sides = 4; int nverts = segs * sides; int nvecs = segs*sides*8; int npatches = segs * sides; patch.setNumVerts(nverts); patch.setNumTVerts(genUVs ? (segs + 1) * (sides + 1) : 0); patch.setNumVecs(nvecs); patch.setNumPatches(npatches); patch.setNumTVPatches(genUVs ? npatches : 0); int ix=0, jx=0, kx=sides*segs*4, i, j; float ang1 = 0.0f, delta1 = TWOPI/float(segs); float ang2 = 0.0f, delta2 = TWOPI/float(sides); float circleLenIn = CIRCLE_FACT8*(radius1-radius2); float circleLenOut = CIRCLE_FACT8*(radius1+radius2); float circleLenMid = CIRCLE_FACT4*radius2; float circleLen; float sinang1, cosang1, sinang2, cosang2, rt, u; Point3 p, v; DWORD a, b, c, d; for (i=0; i<segs; i++) { sinang1 = (float)sin(ang1); cosang1 = (float)cos(ang1); ang2 = 0.0f; for (j=0; j<sides; j++) { sinang2 = (float)sin(ang2); cosang2 = (float)cos(ang2); rt = radius1+radius2*cosang2; // Vertex p.x = rt*cosang1; p.y = rt*sinang1; p.z = radius2*sinang2; patch.setVert(ix, p); // Tangents u = (cosang2+1.0f)/2.0f; circleLen = u*circleLenOut + (1.0f-u)*circleLenIn; v.x = -sinang1*circleLen; v.y = cosang1*circleLen; v.z = 0.0f; patch.setVec(jx++,patch.verts[ix] + v); v.x = sinang1*circleLen; v.y = -cosang1*circleLen; v.z = 0.0f; patch.setVec(jx++,patch.verts[ix] + v); v.x = -sinang2*cosang1*circleLenMid; v.y = -sinang2*sinang1*circleLenMid; v.z = cosang2*circleLenMid; patch.setVec(jx++,patch.verts[ix] + v); v.x = sinang2*cosang1*circleLenMid; v.y = sinang2*sinang1*circleLenMid; v.z = -cosang2*circleLenMid; patch.setVec(jx++,patch.verts[ix] + v); // Build the patch a = ((i+1)%segs)*sides + (j+1)%sides; b = i*sides + (j+1)%sides; c = i*sides + j; d = ((i+1)%segs)*sides + j; patch.patches[ix].SetType(PATCH_QUAD); patch.patches[ix].setVerts(a, b, c, d); patch.patches[ix].setVecs( Tang(a,1),Tang(b,0),Tang(b,3),Tang(c,2), Tang(c,0),Tang(d,1),Tang(d,2),Tang(a,3)); patch.patches[ix].setInteriors(kx, kx+1, kx+2, kx+3); patch.patches[ix].smGroup = 1; kx += 4; ix++; ang2 += delta2; } ang1 += delta1; } if(genUVs) { int tv = 0; int tvp = 0; float fsegs = (float)segs; float fsides = (float)sides; float uScale = usePhysUVs ? ((float) 2.0f * PI * radius1) : 1.0f; float vScale = usePhysUVs ? ((float) 2.0f * PI * radius2) : 1.0f; for (i=0; i<=segs; i++) { float u = (float)i / (fsegs-1); for (j=0; j<=sides; j++,++tv) { float v = (float)j / (fsides-1); if (usePhysUVs) patch.setTVert(tv, UVVert(vScale*v, uScale*u, 0.0f)); else patch.setTVert(tv, UVVert(uScale*(1.0f-u), vScale*v, 0.0f)); if(j < sides && i < segs) patch.getTVPatch(tvp++).setTVerts(tv, tv+1, tv+sides+2, tv+sides+1); } } } if( !patch.buildLinkages() ) { assert(0); } patch.computeInteriors(); patch.InvalidateGeomCache(); }