void SelLum::select(TimeValue t, CompMap &compMap, Bitmap *bm, RenderGlobalContext *gc) { float fTemp; int type; mp_srcAlpha = (WORD*)bm->GetAlphaPtr(&type); mp_srcMap = (WORD*)bm->GetStoragePtr(&type); assert(type == BMM_TRUE_48); // if source bitmap has changed since last call if ( m_lastBMModifyID != bm->GetModifyID() ) { m_lastBMModifyID = bm->GetModifyID(); m_selectValid = m_featherValid = m_compValid = false; if ( (bm->Width() != m_imageW) || (bm->Height() != m_imageH) ) { m_imageW = bm->Width(); m_imageH = bm->Height(); m_imageSz = m_imageW * m_imageH; if (m_imageSz > m_mapSz) { if (mp_radMap) delete[] mp_radMap; mp_radMap = new float[m_imageSz]; m_mapSz = m_imageSz; } } } if (!m_selectValid) { mp_blurMgr->getSelValue(prmLumMin, t, fTemp, FOREVER); LimitValue(fTemp, 0.0f, 100.0f); // mjm - 9.30.99 m_min = fTemp*PERCENT2DEC; mp_blurMgr->getSelValue(prmLumMax, t, fTemp, FOREVER); LimitValue(fTemp, 0.0f, 100.0f); // mjm - 9.30.99 m_max = fTemp*PERCENT2DEC; m_selectValid = doSelect(); } if (!m_featherValid) { mp_blurMgr->getSelValue(prmLumFeathRad, t, fTemp, FOREVER); LimitValue(fTemp, 0.0f, 1000.0f); // mjm - 9.30.99 m_feathRad = (int)floor(max(m_imageW, m_imageH)*(fTemp*PERCENT2DEC)); m_featherValid = SelLum::doFeather(); } mp_blurMgr->getSelValue(prmLumBrighten, t, fTemp, FOREVER); LimitValue(fTemp, 0.0f, 1000.0f); // mjm - 9.30.99 m_brighten = fTemp*PERCENT2DEC; mp_blurMgr->getSelValue(prmLumBlend, t, fTemp, FOREVER); LimitValue(fTemp, 0.0f, 100.0f); // mjm - 9.30.99 m_blend = fTemp*PERCENT2DEC; m_compValid = SelLum::doComposite(t, compMap); }
void ScubaObject::BuildMesh(TimeValue t) { int segs, smooth, hsegs; float radius,height,pie1, pie2,r2; int doPie, genUVs,con; // Start the validity interval at forever and widdle it down. FixHeight(pblock,t,(pmapParam?pmapParam->GetHWnd():NULL),increate); ivalid = FOREVER; pblock->GetValue(PB_RADIUS,t,radius,ivalid); pblock->GetValue(PB_CENTERS,t,con,ivalid); pblock->GetValue(PB_HEIGHT,t,height,ivalid); r2=2.0f*radius; if (con) height+=(height<0.0f?-r2:r2); pblock->GetValue(PB_SIDES,t,segs,ivalid); pblock->GetValue(PB_HSEGS,t,hsegs,ivalid); pblock->GetValue(PB_SMOOTHON,t,smooth,ivalid); pblock->GetValue(PB_SLICEFROM,t,pie1,ivalid); pblock->GetValue(PB_SLICETO,t,pie2,ivalid); pblock->GetValue(PB_SLICEON,t,doPie,ivalid); pblock->GetValue(PB_GENUVS,t,genUVs,ivalid); LimitValue(radius, MIN_RADIUS, MAX_RADIUS); LimitValue(height, MIN_HEIGHT, MAX_HEIGHT); LimitValue(hsegs, MIN_SEGMENTS, MAX_SEGMENTS); LimitValue(segs, MIN_SIDES, MAX_SIDES); LimitValue(smooth, 0, 1); // sides, smooth, cylrad BuildScubaMesh(mesh, segs, smooth, hsegs, doPie,radius, height, pie1, pie2, genUVs, GetUsePhysicalScaleUVs()); }
BOOL HelixObject::ValidForDisplay(TimeValue t) { float radius1, radius2; pblock->GetValue(PB_RADIUS1, t, radius1, ivalid); pblock->GetValue(PB_RADIUS2, t, radius2, ivalid); LimitValue( radius1, MIN_RADIUS, MAX_RADIUS ); LimitValue( radius2, MIN_RADIUS, MAX_RADIUS ); return (radius1 == 0.0f && radius2 == 0.0f) ? FALSE : TRUE; }
void SinWaveObject::BuildMesh(TimeValue t) { int startVert = 1, face = 0, nverts, nfaces, numCircles, numCircleSegs, divs; float radius = float(0); float dr; float a, a2, w, s, d; ivalid = FOREVER; pblock->GetValue(PB_AMPLITUDE,t,a,ivalid); pblock->GetValue(PB_AMPLITUDE2,t,a2,ivalid); pblock->GetValue(PB_WAVELEN,t,w,ivalid); pblock->GetValue(PB_PHASE,t,s,ivalid); pblock->GetValue(PB_DECAY,t,d,ivalid); pblock->GetValue(PB_SEGMENTS,t,numCircleSegs,ivalid); pblock->GetValue(PB_CIRCLES,t,numCircles,ivalid); pblock->GetValue(PB_DIVISIONS,t,divs,ivalid); LimitValue(d,0.0f,float(1.0E30)); dr = w/float(divs); nverts = numCircles * numCircleSegs + 1; nfaces = (numCircles-1) * numCircleSegs * 2; mesh.setNumVerts(nverts); mesh.setNumFaces(nfaces); mesh.setVert( 0, Point3(0,0,0) ); MakeCircle(t,mesh,0,face,radius, a, a2, w, s, d, numCircleSegs); for ( int i = 1; i < numCircles; i++ ) { MakeCircle(t,mesh,startVert,face,radius, a, a2, w, s, d, numCircleSegs); startVert += numCircleSegs; radius += dr; } mesh.InvalidateGeomCache(); }
Deformer& LinWaveMod::GetDeformer( TimeValue t,ModContext &mc,Matrix3& mat,Matrix3& invmat) { Interval valid; static LinWaveDeformer ld; pblock->GetValue(PB_FLEX,t,ld.flex,FOREVER); LinWaveObject *obj = (LinWaveObject*)GetWSMObject(t); obj->pblock->GetValue(PB_AMPLITUDE,t,ld.amp,FOREVER); obj->pblock->GetValue(PB_AMPLITUDE2,t,ld.amp2,FOREVER); obj->pblock->GetValue(PB_WAVELEN,t,ld.wave,FOREVER); obj->pblock->GetValue(PB_PHASE,t,ld.phase,FOREVER); obj->pblock->GetValue(PB_DECAY,t,ld.decay,FOREVER); LimitValue(ld.decay,0.0f,float(1.0E30)); ld.time = t; //ld.itm = nodeRef->GetNodeTM(t,&valid); ld.itm = nodeRef->GetObjectTM(t,&valid); ld.tm = Inverse(ld.itm); //ld.dist = mc.box ? mc.box->Width().x : (4.0f*ld.wave); //ld.dist = (2.0f*ld.wave); // Use wave length for the WSM version int numSides, divs; obj->pblock->GetValue(PB_CIRCLES,t,numSides,FOREVER); obj->pblock->GetValue(PB_DIVISIONS,t,divs,FOREVER); ld.dist = (ld.wave/float(divs)) * 4.0f * float(numSides); if (ld.dist == 0.0f) ld.dist = 1.0f; return ld; }
void ChCylinderObject::BuildMesh(TimeValue t) { int segs, smooth, hsegs, capsegs,fsegs; float radius,height,pie1, pie2,fillet; int doPie, genUVs; FixFillet(pblock,t,(pmapParam?pmapParam->GetHWnd():NULL),increate); // Start the validity interval at forever and widdle it down. ivalid = FOREVER; pblock->GetValue(PB_FSEGS,t,fsegs,ivalid); pblock->GetValue(PB_SIDES,t,segs,ivalid); pblock->GetValue(PB_HSEGS,t,hsegs,ivalid); pblock->GetValue(PB_CSEGS,t,capsegs,ivalid); pblock->GetValue(PB_RADIUS,t,radius,ivalid); pblock->GetValue(PB_HEIGHT,t,height,ivalid); pblock->GetValue(PB_FILLET,t,fillet,ivalid); pblock->GetValue(PB_SMOOTHON,t,smooth,ivalid); pblock->GetValue(PB_SLICEFROM,t,pie1,ivalid); pblock->GetValue(PB_SLICETO,t,pie2,ivalid); pblock->GetValue(PB_SLICEON,t,doPie,ivalid); pblock->GetValue(PB_GENUVS,t,genUVs,ivalid); LimitValue(radius, MIN_RADIUS, MAX_RADIUS); LimitValue(height, MIN_HEIGHT, MAX_HEIGHT); LimitValue(fsegs, MIN_SEGMENTS, MAX_SEGMENTS); LimitValue(hsegs, MIN_SEGMENTS, MAX_SEGMENTS); LimitValue(capsegs, MIN_SEGMENTS, MAX_SEGMENTS); LimitValue(segs, MIN_SIDES, MAX_SIDES); LimitValue(smooth, 0, 1); BuildChCylinderMesh(mesh, segs, smooth, hsegs, capsegs, fsegs,doPie, radius, fillet, height, pie1, pie2, genUVs); }
float SelImage::getBlend(TimeValue t) { float fTemp; mp_blurMgr->getSelValue(prmImageBlend, t, fTemp, FOREVER); LimitValue(fTemp, 0.0f, 100.0f); // mjm - 9.30.99 m_blend = fTemp*PERCENT2DEC; return m_blend; };
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 LinWaveObject::BuildMesh(TimeValue t) { int startVert = 1, face = 0, nverts, nfaces, numSides, numSegs, divs; float radius = float(0); float dx, dy, starty, startx; float a, a2, w, s, d, x, y, z, u; int nv=0, nf=0, ix, den; ivalid = FOREVER; pblock->GetValue(PB_AMPLITUDE,t,a,ivalid); pblock->GetValue(PB_AMPLITUDE2,t,a2,ivalid); pblock->GetValue(PB_WAVELEN,t,w,ivalid); pblock->GetValue(PB_PHASE,t,s,ivalid); pblock->GetValue(PB_DECAY,t,d,ivalid); pblock->GetValue(PB_SEGMENTS,t,numSegs,ivalid); pblock->GetValue(PB_CIRCLES,t,numSides,ivalid); pblock->GetValue(PB_DIVISIONS,t,divs,ivalid); LimitValue(d,0.0f,float(1.0E30)); dy = w/float(divs); dx = dy * 4; starty = -float(numSegs)/2.0f * dy; startx = -float(numSides)/2.0f * dx; nverts = (numSides+1) * (numSegs+1); nfaces = (numSides) * numSegs * 2; mesh.setNumVerts(nverts); mesh.setNumFaces(nfaces); for (int i=0; i<=numSides; i++) { x = startx + dx * float(i); den = (int)(dx*numSides*0.5f); u = (float)fabs(x/(den?den:0.00001f)); u = u*u; //u = smoothstep(0.0f,1.0f,u); for (int j=0; j<=numSegs; j++) { y = starty + float(j) * dy; z = WaveFunc(y, t, a*(1.0f-u)+a2*u, w, s, d); mesh.setVert(nv++,Point3(x, y, z)); } } for (i=0; i<numSides; i++) { ix = i * (numSegs+1); for (int j=0; j<numSegs; j++) { MakeQuad(&(mesh.faces[nf]), ix+numSegs+1+j, ix+numSegs+2+j, ix+1+j, ix+j, 1); nf += 2; } } assert(nv==mesh.numVerts); assert(nf==mesh.numFaces); mesh.InvalidateGeomCache(); }
void PyramidObject::BuildMesh(TimeValue t) { int hsegs,wsegs,dsegs; float height,width,depth; int genUVs; // Start the validity interval at forever and widdle it down. ivalid = FOREVER; pblock->GetValue(PB_HSEGS,t,hsegs,ivalid); pblock->GetValue(PB_WSEGS,t,wsegs,ivalid); pblock->GetValue(PB_DSEGS,t,dsegs,ivalid); pblock->GetValue(PB_HEIGHT,t,height,ivalid); pblock->GetValue(PB_WIDTH,t,width,ivalid); pblock->GetValue(PB_DEPTH,t,depth,ivalid); pblock->GetValue(PB_GENUVS,t,genUVs,ivalid); LimitValue(height, MIN_HEIGHT, MAX_HEIGHT); LimitValue(width, MIN_HEIGHT, MAX_HEIGHT); LimitValue(depth, MIN_HEIGHT, MAX_HEIGHT); LimitValue(hsegs, MIN_SEGMENTS, MAX_SEGMENTS); LimitValue(wsegs, MIN_SEGMENTS, MAX_SEGMENTS); LimitValue(dsegs, MIN_SEGMENTS, MAX_SEGMENTS); BOOL usePhysUVs = GetUsePhysicalScaleUVs(); BuildPyramidMesh(mesh, hsegs, wsegs, dsegs, height, width, depth, genUVs, usePhysUVs); }
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 HelixObject::ReadyInterpParams(TimeValue t) { interpValid = FOREVER; pblock->GetValue(PB_RADIUS1,t,radius1,interpValid); pblock->GetValue(PB_RADIUS2,t,radius2,interpValid); pblock->GetValue(PB_HEIGHT,t,height,interpValid); pblock->GetValue(PB_TURNS,t,turns,interpValid); pblock->GetValue(PB_BIAS,t,bias,interpValid); pblock->GetValue(PB_DIRECTION,t,direction,interpValid); LimitValue( radius1, MIN_RADIUS, MAX_RADIUS ); LimitValue( radius2, MIN_RADIUS, MAX_RADIUS ); LimitValue( height, MIN_HEIGHT, MAX_HEIGHT ); LimitValue( turns, MIN_TURNS, MAX_TURNS ); LimitValue( bias, MIN_BIAS, MAX_BIAS ); totalRadians = TWOPI * turns * ((direction == DIR_CCW) ? 1.0f : -1.0f); deltaRadius = radius2 - radius1; float quarterTurns = turns * 4.0f; power = 1.0f; if(bias > 0.0f) power = bias * 9.0f + 1.0f; else if(bias < 0.0f) power = -bias * 9.0f + 1.0f; }
Deformer& SinWaveOMod::GetDeformer( TimeValue t,ModContext &mc,Matrix3& mat,Matrix3& invmat) { Interval valid; static SinWaveDeformer sd; pblock->GetValue(PB_AMPLITUDE,t,sd.amp,FOREVER); pblock->GetValue(PB_AMPLITUDE2,t,sd.amp2,FOREVER); pblock->GetValue(PB_WAVELEN,t,sd.wave,FOREVER); pblock->GetValue(PB_PHASE,t,sd.phase,FOREVER); pblock->GetValue(PB_DECAY,t,sd.decay,FOREVER); LimitValue(sd.decay,0.0f,float(1.0E30)); sd.time = t; sd.itm = invmat; sd.tm = mat; sd.flex = 1.0f; return sd; }
void BlurUniform::blur(TimeValue t, CompMap *pCompMap, Bitmap *bm, RenderGlobalContext *gc) { // get source bitmap data int type; mp_srcAlpha = (WORD*)bm->GetAlphaPtr(&type); mp_srcMap = (WORD*)bm->GetStoragePtr(&type); assert(type == BMM_TRUE_48); // if source bitmap has changed since last call if ( m_lastBMModifyID != bm->GetModifyID() ) { m_lastBMModifyID = bm->GetModifyID(); m_blurValid = false; if ( (bm->Width() != m_imageW) || (bm->Height() != m_imageH) ) { m_imageW = bm->Width(); m_imageH = bm->Height(); m_imageSz = m_imageW * m_imageH; } } // get ui parameters float fTemp; mp_blurMgr->getBlurValue(prmUnifPixRad, t, fTemp, FOREVER); LimitValue(fTemp, 0.0f, 1000.0f); // mjm - 9.30.99 m_pixRad = (int)( 0.5*floor( max(m_imageW, m_imageH)*(fTemp*PERCENT2DEC) ) ); mp_blurMgr->getBlurValue(prmUnifAlpha, t, m_affectAlpha, FOREVER); mp_blurMgr->getSelValue(prmGenBrightType, t, m_brightenType, FOREVER); // setup buffers if (m_imageSz > m_mapSz) { if (mp_scratchMap) delete[] mp_scratchMap; mp_scratchMap = new AColor[m_imageSz]; if (mp_blurCache) delete[] mp_blurCache; mp_blurCache = new AColor[m_imageSz]; m_mapSz = m_imageSz; } m_blurValid = doBlur(pCompMap, mp_srcMap, mp_srcMap, mp_srcAlpha, (m_affectAlpha) ? mp_srcAlpha : NULL); };
Deformer& LinWaveOMod::GetDeformer( TimeValue t,ModContext &mc,Matrix3& mat,Matrix3& invmat) { Interval valid; static LinWaveDeformer ld; pblock->GetValue(PB_AMPLITUDE,t,ld.amp,FOREVER); pblock->GetValue(PB_AMPLITUDE2,t,ld.amp2,FOREVER); pblock->GetValue(PB_WAVELEN,t,ld.wave,FOREVER); pblock->GetValue(PB_PHASE,t,ld.phase,FOREVER); pblock->GetValue(PB_DECAY,t,ld.decay,FOREVER); LimitValue(ld.decay,0.0f,float(1.0E30)); ld.time = t; ld.itm = invmat; ld.tm = mat; ld.flex = 1.0f; ld.dist = mc.box ? mc.box->Width().x : (4.0f*ld.wave); return ld; }
Deformer& SinWaveMod::GetDeformer( TimeValue t,ModContext &mc,Matrix3& mat,Matrix3& invmat) { Interval valid; static SinWaveDeformer sd; pblock->GetValue(PB_FLEX,t,sd.flex,FOREVER); SinWaveObject *obj = (SinWaveObject*)GetWSMObject(t); obj->pblock->GetValue(PB_AMPLITUDE,t,sd.amp,FOREVER); obj->pblock->GetValue(PB_AMPLITUDE2,t,sd.amp2,FOREVER); obj->pblock->GetValue(PB_WAVELEN,t,sd.wave,FOREVER); obj->pblock->GetValue(PB_PHASE,t,sd.phase,FOREVER); obj->pblock->GetValue(PB_DECAY,t,sd.decay,FOREVER); LimitValue(sd.decay,0.0f,float(1.0E30)); sd.time = t; //sd.itm = nodeRef->GetNodeTM(t,&valid); sd.itm = nodeRef->GetObjectTM(t,&valid); sd.tm = Inverse( sd.itm ); return sd; }
void PrismObject::BuildMesh(TimeValue t) { int hsegs,s1segs,s2segs,s3segs; float height,s1len,s2len,s3len; int genUVs; if (isdone) { FixSide1(pblock,t,(pmapParam?pmapParam->GetHWnd():NULL)); FixSide2(pblock,t,(pmapParam?pmapParam->GetHWnd():NULL)); FixSide3(pblock,t,(pmapParam?pmapParam->GetHWnd():NULL)); } // Start the validity interval at forever and widdle it down. ivalid = FOREVER; pblock->GetValue(PB_HSEGS,t,hsegs,ivalid); pblock->GetValue(PB_S1SEGS,t,s1segs,ivalid); pblock->GetValue(PB_S2SEGS,t,s2segs,ivalid); pblock->GetValue(PB_S3SEGS,t,s3segs,ivalid); pblock->GetValue(PB_HEIGHT,t,height,ivalid); pblock->GetValue(PB_SIDE1,t,s1len,ivalid); pblock->GetValue(PB_SIDE2,t,s2len,ivalid); pblock->GetValue(PB_SIDE3,t,s3len,ivalid); pblock->GetValue(PB_GENUVS,t,genUVs,ivalid); LimitValue(height, MIN_HEIGHT, MAX_HEIGHT); LimitValue(s1len, BMIN_HEIGHT, MAX_HEIGHT); LimitValue(s2len, BMIN_HEIGHT, MAX_HEIGHT); LimitValue(s3len, BMIN_HEIGHT, MAX_HEIGHT); LimitValue(hsegs, MIN_SEGMENTS, MAX_SEGMENTS); LimitValue(s1segs, MIN_SEGMENTS, MAX_SEGMENTS); LimitValue(s2segs, MIN_SEGMENTS, MAX_SEGMENTS); LimitValue(s3segs, MIN_SEGMENTS, MAX_SEGMENTS); BuildPrismMesh(mesh, s1segs, s2segs, s3segs, hsegs, s1len, s2len, s3len, height, genUVs); }
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(); }
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(); }
void SelMaps::select(TimeValue t, CompMap &compMap, Bitmap *bm, RenderGlobalContext *gc) { int type; mp_srcAlpha = (WORD*)bm->GetAlphaPtr(&type); mp_srcMap = (WORD*)bm->GetStoragePtr(&type); assert(type == BMM_TRUE_48); m_shadeContext.globContext = gc; // if source bitmap has changed since last call if ( m_lastBMModifyID != bm->GetModifyID() ) { m_lastBMModifyID = bm->GetModifyID(); m_selectValid = m_featherValid = m_compValid = false; if ( (bm->Width() != m_imageW) || (bm->Height() != m_imageH) ) { m_imageW = bm->Width(); m_imageH = bm->Height(); m_imageSz = m_imageW * m_imageH; if (m_imageSz > m_mapSz) { if (mp_radMap) delete[] mp_radMap; mp_radMap = new float[m_imageSz]; m_mapSz = m_imageSz; } } } float fTemp; if (!m_selectValid) { m_brightenMap = NULL; mp_blurMgr->getSelValue(prmMaskMap, 0, m_brightenMap, FOREVER); if (!m_brightenMap) return; m_shadeContext.scale = 1.0f; m_shadeContext.duvw = Point3(1.0f/float(m_imageW), 1.0f/float(m_imageH), 0.0f); m_shadeContext.uvw.z = 0.0f; m_shadeContext.filterMaps = TRUE; m_brightenMap->Update(t, Interval()); m_brightenMap->LoadMapFiles(t); mp_blurMgr->getSelValue(prmMaskChannel, t, m_channel, FOREVER); mp_blurMgr->getSelValue(prmMaskMin, t, fTemp, FOREVER); LimitValue(fTemp, 0.0f, 100.0f); // mjm - 9.30.99 m_min = fTemp*PERCENT2DEC; mp_blurMgr->getSelValue(prmMaskMax, t, fTemp, FOREVER); LimitValue(fTemp, 0.0f, 100.0f); // mjm - 9.30.99 m_max = fTemp*PERCENT2DEC; m_selectValid = doSelect(); } if (!m_featherValid) { mp_blurMgr->getSelValue(prmMaskFeathRad, t, fTemp, FOREVER); LimitValue(fTemp, 0.0f, 1000.0f); // mjm - 9.30.99 m_feathRad = (int)floor(max(m_imageW, m_imageH)*(fTemp*PERCENT2DEC)); m_featherValid = doFeather(); } mp_blurMgr->getSelValue(prmMaskBrighten, t, fTemp, FOREVER); LimitValue(fTemp, 0.0f, 1000.0f); // mjm - 9.30.99 m_brighten = fTemp*PERCENT2DEC; mp_blurMgr->getSelValue(prmMaskBlend, t, fTemp, FOREVER); LimitValue(fTemp, 0.0f, 100.0f); // mjm - 9.30.99 m_blend = fTemp*PERCENT2DEC; m_compValid = doComposite(t, compMap); }
void TorusObject::BuildMesh(TimeValue t) { Point3 p; int ix,na,nb,nc,nd,jx,kx; int nf=0,nv=0; float delta,ang; float delta2,ang2; int sides,segs,smooth; float radius,radius2, rotation; float sinang,cosang, sinang2,cosang2,rt; float twist, pie1, pie2, totalPie, startAng = 0.0f; int doPie = TRUE; int genUVs = TRUE; // Start the validity interval at forever and widdle it down. ivalid = FOREVER; pblock->GetValue(PB_RADIUS,t,radius,ivalid); pblock->GetValue(PB_RADIUS2,t,radius2,ivalid); pblock->GetValue(PB_ROTATION,t,rotation,ivalid); pblock->GetValue(PB_TWIST,t,twist,ivalid); pblock->GetValue(PB_SEGMENTS,t,segs,ivalid); pblock->GetValue(PB_SIDES,t,sides,ivalid); pblock->GetValue(PB_SMOOTH,t,smooth,ivalid); pblock->GetValue(PB_PIESLICE1,t,pie1,ivalid); pblock->GetValue(PB_PIESLICE2,t,pie2,ivalid); pblock->GetValue(PB_SLICEON,t,doPie,ivalid); pblock->GetValue(PB_GENUVS,t,genUVs,ivalid); LimitValue( radius, MIN_RADIUS, MAX_RADIUS ); LimitValue( radius2, MIN_RADIUS, MAX_RADIUS ); LimitValue( segs, MIN_SEGMENTS, MAX_SEGMENTS ); LimitValue( sides, MIN_SIDES, MAX_SIDES ); // Convert doPie to a 0 or 1 value since it is used in arithmetic below // Controllers can give it non- 0 or 1 values doPie = doPie ? 1 : 0; // We do the torus backwards from the cylinder pie1 = -pie1; pie2 = -pie2; // Make pie2 < pie1 and pie1-pie2 < TWOPI while (pie1 < pie2) pie1 += TWOPI; while (pie1 > pie2+TWOPI) pie1 -= TWOPI; if (pie1==pie2) totalPie = TWOPI; else totalPie = pie1-pie2; if (doPie) { segs++; //*** O.Z. fix for bug 240436 delta = totalPie/(float)(segs-1); startAng = pie2; } else { delta = (float)2.0*PI/(float)segs; } delta2 = (float)2.0*PI/(float)sides; if (TestAFlag(A_PLUGIN1)) startAng -= HALFPI; int nverts; int nfaces; if (doPie) { nverts = sides*segs + 2; nfaces = 2*sides*segs; } else { nverts = sides*segs; nfaces = 2*sides*segs; } mesh.setNumVerts(nverts); mesh.setNumFaces(nfaces); mesh.setSmoothFlags(smooth); if (genUVs) { if (doPie) { mesh.setNumTVerts((sides+1)*segs+2); mesh.setNumTVFaces(2*sides*segs); } else { mesh.setNumTVerts((sides+1)*(segs+1)); mesh.setNumTVFaces(2*sides*segs); } } else { mesh.setNumTVerts(0); mesh.setNumTVFaces(0); } ang = startAng; // make verts for(ix=0; ix<segs; ix++) { sinang = (float)sin(ang); cosang = (float)cos(ang); ang2 = rotation + twist * float(ix+1)/float(segs); for (jx = 0; jx<sides; jx++) { sinang2 = (float)sin(ang2); cosang2 = (float)cos(ang2); rt = radius+radius2*cosang2; p.x = rt*cosang; p.y = -rt*sinang; p.z = radius2*sinang2; mesh.setVert(nv++, p); ang2 += delta2; } ang += delta; } if (doPie) { p.x = radius * (float)cos(startAng); p.y = -radius * (float)sin(startAng); p.z = 0.0f; mesh.setVert(nv++, p); ang -= delta; p.x = radius * (float)cos(ang); p.y = -radius * (float)sin(ang); p.z = 0.0f; mesh.setVert(nv++, p); } // Make faces BOOL usePhysUVs = GetUsePhysicalScaleUVs(); BitArray startSliceFaces; BitArray endSliceFaces; if (usePhysUVs) { startSliceFaces.SetSize(mesh.numFaces); endSliceFaces.SetSize(mesh.numFaces); } /* Make midsection */ for(ix=0; ix<segs-doPie; ++ix) { jx=ix*sides; for (kx=0; kx<sides; ++kx) { na = jx+kx; nb = (ix==(segs-1))?kx:na+sides; nd = (kx==(sides-1))? jx : na+1; nc = nb+nd-na; DWORD grp = 0; if (smooth==SMOOTH_SIDES) { if (kx==sides-1 && (sides&1)) { grp = (1<<2); } else { grp = (kx&1) ? (1<<0) : (1<<1); } } else if (smooth==SMOOTH_STRIPES) { if (ix==segs-1 && (segs&1)) { grp = (1<<2); } else { grp = (ix&1) ? (1<<0) : (1<<1); } } else if (smooth > 0) { grp = 1; } mesh.faces[nf].setEdgeVisFlags(0,1,1); mesh.faces[nf].setSmGroup(grp); mesh.faces[nf].setMatID(0); mesh.faces[nf++].setVerts( na,nc,nb); mesh.faces[nf].setEdgeVisFlags(1,1,0); mesh.faces[nf].setSmGroup(grp); mesh.faces[nf].setMatID(0); mesh.faces[nf++].setVerts(na,nd,nc); } } if (doPie) { na = nv -2; for(ix=0; ix<sides; ++ix) { nb = ix; nc = (ix==(sides-1))?0:ix+1; mesh.faces[nf].setEdgeVisFlags(0,1,0); mesh.faces[nf].setSmGroup((1<<3)); mesh.faces[nf].setMatID(1); if (usePhysUVs) startSliceFaces.Set(nf); mesh.faces[nf++].setVerts(na,nc,nb); } na = nv -1; jx = sides*(segs-1); for(ix=0; ix<sides; ++ix) { nb = jx+ix; nc = (ix==(sides-1))?jx:nb+1; mesh.faces[nf].setEdgeVisFlags(0,1,0); mesh.faces[nf].setSmGroup((1<<3)); mesh.faces[nf].setMatID(2); if (usePhysUVs) endSliceFaces.Set(nf); mesh.faces[nf++].setVerts(na,nb,nc); } } // UVWs ------------------- if (genUVs) { float uScale = usePhysUVs ? ((float) 2.0f * PI * radius) : 1.0f; float vScale = usePhysUVs ? ((float) 2.0f * PI * radius2) : 1.0f; if (doPie) { float pieScale = float(totalPie/(2.0*PI)); uScale *= float(pieScale); } nv=0; for(ix=0; ix<=segs-doPie; ix++) { for (jx=0; jx<=sides; jx++) { if (usePhysUVs) mesh.setTVert(nv++,uScale*(1.0f - float(ix)/float(segs-doPie)),vScale*float(jx)/float(sides),0.0f); else mesh.setTVert(nv++,float(jx)/float(sides),float(ix)/float(segs),0.0f); } } int pie1 = 0; int pie2 = 0; if (doPie) { pie1 = nv; if (usePhysUVs) mesh.setTVert(nv++,0.0f,vScale*0.5f,0.0f); else mesh.setTVert(nv++,0.5f,1.0f,0.0f); pie2 = nv; if (usePhysUVs) mesh.setTVert(nv++,uScale*0.5f,vScale*0.0f,0.0f); else mesh.setTVert(nv++,1.0f,0.5f,0.0f); } nf=0; for(ix=0; ix<segs-doPie; ix++) { na = ix*(sides+1); nb = (ix+1)*(sides+1); for (jx=0; jx<sides; jx++) { mesh.tvFace[nf++].setTVerts(na,nb+1,nb); mesh.tvFace[nf++].setTVerts(na,na+1,nb+1); na++; nb++; } } if (doPie) { if (usePhysUVs) { Matrix3 tm = RotateZMatrix(startAng) * RotateXMatrix(float(-PI/2.0)); tm.Scale(Point3(-1.0f, 1.0f, 1.0f)); MakeMeshCapTexture(mesh, tm, startSliceFaces, usePhysUVs); tm = RotateZMatrix(ang) * RotateXMatrix(float(-PI/2.0)); MakeMeshCapTexture(mesh, tm, endSliceFaces, usePhysUVs); } else { for (jx=0; jx<sides; jx++) { mesh.tvFace[nf++].setTVerts(pie1,jx+1,jx); } nb = (sides+1)*(segs-1); for (jx=0; jx<sides; jx++) { mesh.tvFace[nf++].setTVerts(pie2,nb,nb+1); nb++; } } } } mesh.InvalidateTopologyCache(); }
inline BOOL HitLimit(void) { return CountValue() == LimitValue(); }
bool ExtrudeMod::BuildAMSolidFromShape(TimeValue t,ModContext &mc, ObjectState * os, IGeomImp* igeom) { ShapeObject *shape = (ShapeObject *)os->obj; float amount; pblock->GetValue(PB_AMOUNT,t,amount,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); if(fabs(amount)<MIN_EXT) amount = MIN_EXT; // 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; PolyShape pShape; shape->MakePolyShape(t, pShape, PSHAPE_BUILTIN_STEPS, true); ShapeHierarchy hier; pShape.OrganizeCurves(t, &hier); // Need to flip the reversed curves in the shape! pShape.Reverse(hier.reverse); //Now add the extrusion for each polygon bool res = false;//assume the best //make a solid to hold our work Object* solid = (Object*)CreateInstance(GEOMOBJECT_CLASS_ID, GENERIC_AMSOLID_CLASS_ID); IGeomImp* workgeom = NULL; assert(solid); if(solid) { workgeom = (IGeomImp*)(solid->GetInterface(I_GEOMIMP)); assert(workgeom); } for(int i=0;i<pShape.numLines; i++) { PolyLine poly = pShape.lines[i]; if(poly.numPts) poly.pts[0].aux = poly.flags; bool localres = workgeom->createExtrusion(poly.pts, poly.numPts, amount, smooth, genMatIDs, useShapeIDs); if(localres) { //need to figure out how deeply nested this shape is //order is this value with zero meaning not nested HierarchyEntry *entry = hier.hier.FindEntry(i); assert(entry); int order = 0; while(entry && (entry->parent != (HierarchyEntry *)-1)) { entry = entry->parent; ++order; } if(order%2) igeom->operator-=(*workgeom); else igeom->operator+=(*workgeom); } res |= localres; } //do some cleanup if(workgeom) { assert(solid); solid->ReleaseInterface(I_GEOMIMP, workgeom); solid->DeleteMe(); } return res; }
void CExtObject::BuildMesh(TimeValue t) { int hsegs,tsegs,ssegs,bsegs,wsegs; float height,toplen,sidelen,botlen,topwidth,sidewidth,botwidth; int genUVs; // Start the validity interval at forever and widdle it down. FixTopWidth(pblock,t,(pmapParam?pmapParam->GetHWnd():NULL),increate); FixBotWidth(pblock,t,(pmapParam?pmapParam->GetHWnd():NULL),increate); FixSideWidth(pblock,t,(pmapParam?pmapParam->GetHWnd():NULL),increate); ivalid = FOREVER; pblock->GetValue(PB_HSEGS,t,hsegs,ivalid); pblock->GetValue(PB_TSEGS,t,tsegs,ivalid); pblock->GetValue(PB_SSEGS,t,ssegs,ivalid); pblock->GetValue(PB_BSEGS,t,bsegs,ivalid); pblock->GetValue(PB_WSEGS,t,wsegs,ivalid); pblock->GetValue(PB_TOPLENGTH,t,toplen,ivalid); pblock->GetValue(PB_SIDELENGTH,t,sidelen,ivalid); pblock->GetValue(PB_BOTLENGTH,t,botlen,ivalid); pblock->GetValue(PB_TOPWIDTH,t,topwidth,ivalid); pblock->GetValue(PB_SIDEWIDTH,t,sidewidth,ivalid); pblock->GetValue(PB_BOTWIDTH,t,botwidth,ivalid); pblock->GetValue(PB_HEIGHT,t,height,ivalid); pblock->GetValue(PB_GENUVS,t,genUVs,ivalid); LimitValue(height, MIN_HEIGHT, BMAX_HEIGHT); LimitValue(toplen, MIN_HEIGHT, BMAX_LENGTH); LimitValue(sidelen, MIN_HEIGHT,BMAX_WIDTH); LimitValue(botlen, MIN_HEIGHT, BMAX_HEIGHT); LimitValue(topwidth, BMIN_LENGTH,BMAX_LENGTH); LimitValue(sidewidth, BMIN_WIDTH,BMAX_WIDTH); LimitValue(botwidth, BMIN_HEIGHT,BMAX_HEIGHT); LimitValue(hsegs, MIN_SEGMENTS, MAX_SEGMENTS); LimitValue(tsegs, MIN_SEGMENTS, MAX_SEGMENTS); LimitValue(ssegs, MIN_SEGMENTS, MAX_SEGMENTS); LimitValue(bsegs, MIN_SEGMENTS, MAX_SEGMENTS); LimitValue(wsegs, MIN_SEGMENTS, MAX_SEGMENTS); BuildCExtMesh(mesh,hsegs,tsegs,ssegs,bsegs,wsegs,height, toplen,sidelen,botlen,topwidth,sidewidth,botwidth, genUVs,createmeth,GetUsePhysicalScaleUVs()); }
void SelObjIds::select(TimeValue t, CompMap &compMap, Bitmap *bm, RenderGlobalContext *gc) { float fTemp; ULONG chanType; mp_srcObjId = (WORD *)bm->GetChannel(BMM_CHAN_NODE_ID, chanType); if (chanType != BMM_CHAN_TYPE_16) mp_blurMgr->blurError(IDS_ERR_GBUF_INVALID); mp_srcColor = (Color24*)bm->GetChannel(BMM_CHAN_COLOR, chanType); if (chanType != BMM_CHAN_TYPE_24) mp_blurMgr->blurError(IDS_ERR_GBUF_INVALID); // if source bitmap has changed since last call if ( m_lastBMModifyID != bm->GetModifyID() ) { m_lastBMModifyID = bm->GetModifyID(); m_selectValid = m_featherValid = m_compValid = false; if ( (bm->Width() != m_imageW) || (bm->Height() != m_imageH) ) { m_imageW = bm->Width(); m_imageH = bm->Height(); m_imageSz = m_imageW * m_imageH; if (m_imageSz > m_mapSz) { if (mp_radMap) delete[] mp_radMap; mp_radMap = new float[m_imageSz]; m_mapSz = m_imageSz; } } } if (!m_selectValid) { // make list of desired ids m_idCount = mp_blurMgr->getSelTabCount(prmObjIdsIds); if (m_idCount > m_idListSz) { if (mp_idList) delete[] mp_idList; mp_idList = new int[m_idCount]; m_idListSz = m_idCount; } for (int i=0; i<m_idCount; i++) mp_blurMgr->getSelValue(prmObjIdsIds, t, mp_idList[i], FOREVER, i); // get luminance parameters mp_blurMgr->getSelValue(prmObjIdsLumMin, t, fTemp, FOREVER); LimitValue(fTemp, 0.0f, 100.0f); // mjm - 9.30.99 m_min = fTemp*PERCENT2DEC; mp_blurMgr->getSelValue(prmObjIdsLumMax, t, fTemp, FOREVER); LimitValue(fTemp, 0.0f, 100.0f); // mjm - 9.30.99 m_max = fTemp*PERCENT2DEC; // select the appropriate pixels m_selectValid = doSelect(); } if (!m_featherValid) { mp_blurMgr->getSelValue(prmObjIdsFeathRad, t, fTemp, FOREVER); LimitValue(fTemp, 0.0f, 1000.0f); // mjm - 9.30.99 m_feathRad = (int)floor(max(m_imageW, m_imageH)*(fTemp*PERCENT2DEC)); m_featherValid = doFeather(); } mp_blurMgr->getSelValue(prmObjIdsBrighten, t, fTemp, FOREVER); LimitValue(fTemp, 0.0f, 1000.0f); // mjm - 9.30.99 m_brighten = fTemp*PERCENT2DEC; mp_blurMgr->getSelValue(prmObjIdsBlend, t, fTemp, FOREVER); LimitValue(fTemp, 0.0f, 100.0f); // mjm - 9.30.99 m_blend = fTemp*PERCENT2DEC; m_compValid = doComposite(t, compMap); }
void ChBoxObject::BuildMesh(TimeValue t) { int smooth,dsegs,vertices; int WLines,HLines,DLines,CLines,VertexPerSlice; int VertexPerFace,FacesPerSlice,chamferend; float usedw,usedd,usedh,cradius,zdelta,CurRadius; Point3 va,vb,p; float depth, width, height; int genUVs = 1,sqvertex,CircleLayers; BOOL bias = 0,minusd; // Start the validity interval at forever and widdle it down. ivalid = FOREVER; pblock->GetValue(PB_LENGTH,t,height,ivalid); pblock->GetValue(PB_WIDTH,t,width,ivalid); pblock->GetValue(PB_HEIGHT,t,depth,ivalid); minusd=depth<0.0f; depth=(float)fabs(depth); pblock->GetValue(PB_RADIUS,t,cradius,ivalid); pblock->GetValue(PB_LSEGS,t,hsegs,ivalid); pblock->GetValue(PB_WSEGS,t,wsegs,ivalid); pblock->GetValue(PB_HSEGS,t,dsegs,ivalid); pblock->GetValue(PB_CSEGS,t,csegs,ivalid); pblock->GetValue(PB_GENUVS,t,genUVs,ivalid); pblock->GetValue(PB_SMOOTH,t,smooth,ivalid); LimitValue(csegs, MIN_SEGMENTS, MAX_SEGMENTS); LimitValue(dsegs, MIN_SEGMENTS, MAX_SEGMENTS); LimitValue(wsegs, MIN_SEGMENTS, MAX_SEGMENTS); LimitValue(hsegs, MIN_SEGMENTS, MAX_SEGMENTS); smooth=(smooth>0?1:0); mesh.setSmoothFlags(smooth); float twocrad,usedm,mindim=(height>width?(width>depth?depth:width):(height>depth?depth:height)); usedm=mindim-2*cradius; if (usedm<0.01f) cradius=(mindim-0.01f)/2.0f; twocrad=2.0f*cradius; usedh=height-twocrad; usedw=width-twocrad; usedd=depth-twocrad; float cangincr=PI/(2.0f*csegs),cudelta,udist; CircleLayers=csegs; cudelta=cradius*(float)sqrt(2.0f*(1.0f-(float)cos(cangincr))); udist=4.0f*csegs*cudelta+2.0f*width+2.0f*height-4.0f*cradius; chamferinfo[0].surface=1;chamferinfo[0].deltavert=1; chamferinfo[1].surface=2;chamferinfo[1].deltavert=1; chamferinfo[2].surface=1;chamferinfo[2].deltavert=-1; chamferinfo[3].surface=2;chamferinfo[3].deltavert=-1; WLines=wsegs-1; HLines=hsegs-1; DLines=dsegs-1; CLines=csegs+1; VertexPerSlice=2*(WLines+HLines)+4*CLines; /* WLines*HLines on middle, 2*Clines*(WLines+HLines) on sides, 4*CLines*csegs+4 for circles */ VertexPerFace=WLines*HLines+2*CLines*(WLines+HLines+2*csegs)+4; vertices=VertexPerFace*2+VertexPerSlice*DLines; sqvertex=(wsegs+1)*(hsegs+1); /* 4 vertices, 2 faces/cseg + 2 each hseg & wseg sides, each seg w/ 2 faces*/ SidesPerSlice=2*(2*csegs+hsegs+wsegs); FacesPerSlice=SidesPerSlice*2; /* this one only has 1 face/ cseg */ topchamferfaces=4*(csegs+hsegs+wsegs); /*top chamfer + top face(2 faces/seg)(*2 for bottom) plus any depth faces*/ maxfaces=2*(topchamferfaces+2*hsegs*wsegs)+(2*(CircleLayers-1)+dsegs)*FacesPerSlice; chamferstart=2*hsegs*wsegs; chamferend=chamferstart+topchamferfaces+(CircleLayers-1)*FacesPerSlice; chamferinfo[0].deltavert +=wsegs; chamferinfo[2].deltavert -=wsegs; int bottomvertex,vertexnum,tverts; int twomapped,endvert=vertices+(twomapped=2*VertexPerSlice); float xmax,ymax; mesh.setNumVerts(vertices); mesh.setNumFaces(maxfaces); tverts=endvert+DLines+2; if (genUVs) { mesh.setNumTVerts(tverts); mesh.setNumTVFaces(maxfaces); } else { mesh.setNumTVerts(0); mesh.setNumTVFaces(0); } zdelta=depth/2; wsegcount=0;vertexnum=0; bottomvertex=vertices-1; CornerPt.z=zdelta; CornerPt.x=(xmax=width/2)-cradius; CornerPt.y=(ymax=height/2)-cradius; NewPt.x=Toppt.x=-CornerPt.x; NewPt.y=Toppt.y=CornerPt.y; NewPt.z=Toppt.z=zdelta; /* Do top and bottom faces */ hincr=usedh/hsegs; //yincr wincr=usedw/wsegs; //xincr BOOL usePhysUVs = GetUsePhysicalScaleUVs(); int segcount,topvertex,tvcounter=0,tvbottom=endvert-1; float udiv=usePhysUVs ? 1.0f : 2.0f*xmax,vdiv=usePhysUVs ? 1.0f :2.0f*ymax, u = 0.0f, v = 0.0f; for (hseg=0;hseg<=hsegs;hseg++) { if (hseg>0) {NewPt.y=(hseg==hsegs?-CornerPt.y:Toppt.y-hseg*hincr); NewPt.x=Toppt.x; } for (segcount=0;segcount<=wsegs;segcount++) { /* make top point */ NewPt.z=Toppt.z; NewPt.x=(segcount==wsegs?CornerPt.x:Toppt.x+segcount*wincr); if (genUVs) mesh.setTVert(vertexnum,u=(xmax+NewPt.x)/udiv,v=(ymax+NewPt.y)/vdiv,0.0f); mesh.setVert(vertexnum++,NewPt); /* make bottom pt */ NewPt.z=-zdelta; if (genUVs) mesh.setTVert(tvbottom--,u,(usePhysUVs ? 2.0f*ymax : 1.0f)-v,0.0f); mesh.setVert(bottomvertex--,NewPt); } } /* start on the chamfer */ int layer,vert; layer=0; hseg=0; tvcounter=vertexnum; bottomvertex-=(VertexPerSlice-1); topvertex=vertexnum; BOOL done = FALSE,atedge = FALSE; float dincr=usedd/dsegs,cincr=2.0f*CircleLayers,RotationAngle; float dx,dy; int cornervert[4],PtRotation; for (layer=1;layer<=CircleLayers;layer++) /* add chamfer layer */ { if (layer==CircleLayers) {zdelta=cradius;CurRadius=cradius;} else { RotationAngle=(PI*layer)/cincr; zdelta=cradius-(cradius*(float)cos(RotationAngle)); CurRadius=cradius*(float)sin(RotationAngle); } zdelta=CornerPt.z-zdelta; atedge=(layer==CircleLayers); int vfromedge=0,oldside=0,vfromstart=0; sidenum=0; float u1 = 0.0f, v1 = 0.0f; BOOL atstart=TRUE; while (vertexnum<topvertex+csegs) /* add vertex loop */ { PtRotation=hseg=wsegcount=0;done=FALSE; RotationAngle=(vertexnum-topvertex)*cangincr; curvertex=vert=vertexnum; NewPt.x=Toppt.x-(dx=CurRadius*(float)sin(RotationAngle)); NewPt.y=Toppt.y+(dy=CurRadius*(float)cos(RotationAngle)); NewPt.z=zdelta; while (!done) { mesh.setVert(vert,NewPt); if (genUVs) mesh.setTVert(vert,u1=(xmax+NewPt.x)/udiv,v1=(ymax+NewPt.y)/vdiv,0.0f); /* reflected vertex to second face */ vert=bottomvertex+curvertex-topvertex; NewPt.z=-zdelta; mesh.setVert(vert,NewPt); if (genUVs) mesh.setTVert(vert+twomapped,u1,(usePhysUVs ? 2.0f*ymax : 1.0f)-v1,0.0f); if ((atedge)&&(DLines>0)) /* add non-corner points */ for (segcount=1;segcount<=DLines;segcount++) { NewPt.z=zdelta-segcount*dincr; mesh.setVert(vert=curvertex+VertexPerSlice*segcount,NewPt); } /* Rotate Pt */ done=PtRotation>5; if (done == FALSE) { if (vertexnum==topvertex) { FillinSquare(&PtRotation,cornervert,CurRadius); if (curvertex==topvertex+VertexPerSlice-1) (PtRotation)=6; } else CalculateNewPt(dx,dy,&PtRotation,cornervert,vertexnum-topvertex); vert=curvertex; NewPt.z=zdelta; } } vertexnum++; /* done rotation */ } vertexnum=topvertex +=VertexPerSlice; bottomvertex -=VertexPerSlice; } float dfromedge=0.0f; int tvnum,j,i,chsegs=csegs+1,cwsegs=wsegs; if (genUVs) { u=0.0f; dfromedge=-cudelta; tvnum=vertexnum; vertexnum=topvertex-VertexPerSlice; float uDenom = usePhysUVs ? 1.0f : udist; float vScale = usePhysUVs ? usedd : 1.0f; float maxU = 0.0f; for (j=0;j<2;j++) { int gverts; for (gverts=0;gverts<chsegs;gverts++) { dfromedge+=cudelta; mesh.setTVert(tvnum,u=dfromedge/uDenom,vScale,0.0f); if (u > maxU) maxU = u; for (i=1;i<=dsegs;i++) mesh.setTVert(tvnum+VertexPerSlice*i,u,vScale*(1.0f-(float)i/dsegs),0.0f); vertexnum++; tvnum++; } chsegs=csegs; for (gverts=0;gverts<hsegs;gverts++) { dfromedge+=(float)fabs(mesh.verts[vertexnum].y-mesh.verts[vertexnum-1].y); mesh.setTVert(tvnum,u=dfromedge/uDenom,vScale,0.0f); if (u > maxU) maxU = u; for (i=1;i<=dsegs;i++) mesh.setTVert(tvnum+VertexPerSlice*i,u,vScale*(1.0f-(float)i/dsegs),0.0f); vertexnum++; tvnum++; } for (gverts=0;gverts<csegs;gverts++) { dfromedge+=cudelta; mesh.setTVert(tvnum,u=dfromedge/uDenom,vScale,0.0f); if (u > maxU) maxU = u; for (i=1;i<=dsegs;i++) mesh.setTVert(tvnum+VertexPerSlice*i,u,vScale*(1.0f-(float)i/dsegs),0.0f); vertexnum++; tvnum++; } if (j==1) cwsegs--; for (gverts=0;gverts<cwsegs;gverts++) { dfromedge+=(float)fabs(mesh.verts[vertexnum].x-mesh.verts[vertexnum-1].x); mesh.setTVert(tvnum,u=dfromedge/uDenom,vScale,0.0f); if (u > maxU) maxU = u; for (i=1;i<=dsegs;i++) mesh.setTVert(tvnum+VertexPerSlice*i,u,vScale*(1.0f-(float)i/dsegs),0.0f); vertexnum++; tvnum++; } } int lastvert=endvert; float uScale = usePhysUVs ? udist-4*cradius : 1.0f; mesh.setTVert(lastvert++,uScale, vScale,0.0f); for (j=1;j<dsegs;j++) mesh.setTVert(lastvert++,uScale, vScale*(1.0f-(float)j/dsegs),0.0f); mesh.setTVert(lastvert,uScale, 0.0f,0.0f); } /* all vertices calculated - Now specify faces*/ int tvdelta=0; sidenum=topnum=face=fcount=scount=circleseg=0; curvertex=wsegs+1; firstface=layer=1; // smooth=(csegs>1?1:0); tstartpt=cstartpt=endpt=0; boxpos=topsquare;cstartpt=chamferinfo[0].deltavert; AddFace(&mesh.faces[face],smooth,tvdelta,&mesh.tvFace[face],genUVs); while (face<chamferstart) /* Do Square Layer */ { firstface=!firstface; AddFace(&mesh.faces[face],smooth,tvdelta,&mesh.tvFace[face],genUVs); } boxpos=messyedge;firstface=1; topnum=tstartpt=0; cstartpt=curvertex=topnum+sqvertex;circleseg=1; endpt=hsegs*(wsegs+1); /* Do Chamfer */ while (face<chamferend) { AddFace(&mesh.faces[face],smooth,tvdelta,&mesh.tvFace[face],genUVs); if (circleseg==0) firstface=!firstface; } fcount=scount=0; boxpos=middle;tvdelta+=VertexPerSlice; /*Do box sides */ int tpt,lastv=tverts-1; BOOL inside=TRUE; while (face<maxfaces-chamferstart-topchamferfaces) { tpt=face; AddFace(&mesh.faces[face],smooth,tvdelta,&mesh.tvFace[face],genUVs); if (genUVs && inside) { if ((firstface)&&(mesh.tvFace[tpt].t[2]<mesh.tvFace[tpt].t[1])) mesh.tvFace[tpt].t[2]=endvert+1; else if (mesh.tvFace[tpt].t[2]<mesh.tvFace[tpt].t[0]) { mesh.tvFace[tpt].t[1]=endvert+1; mesh.tvFace[tpt].t[2]=endvert; endvert++; inside=endvert<lastv; if (inside==FALSE) tvdelta+=VertexPerSlice; } } firstface=!firstface; } /* back in chamfer */ circleseg=2;firstface=0; boxpos=bottomedge; sidenum=0;tstartpt=topnum; cstartpt=curvertex=vertices-1; endpt=cstartpt-hsegs*chamferinfo[0].deltavert; while (face<maxfaces-chamferstart) /* Do Second Chamfer */ { AddFace(&mesh.faces[face],smooth,tvdelta,&mesh.tvFace[face],genUVs); if (circleseg==0) firstface=!firstface; } boxpos=bottomsquare; curvertex=topnum; topnum=curvertex+chamferinfo[0].deltavert; firstface=1;fcount=0; while (face<maxfaces) { AddFace(&mesh.faces[face],smooth,tvdelta,&mesh.tvFace[face],genUVs); firstface=!firstface; } float deltaz=(minusd?-depth/2.0f:depth/2.0f); for (i=0;i<vertices;i++) { mesh.verts[i].z+=deltaz; } mesh.InvalidateTopologyCache(); }
void RelaxMod::ModifyObject(TimeValue t, ModContext &mc, ObjectState * os, INode *node) { // Get our personal validity interval... Interval valid = GetValidity(t); // and intersect it with the channels we use as input (see ChannelsUsed) valid &= os->obj->ChannelValidity (t, GEOM_CHAN_NUM); valid &= os->obj->ChannelValidity (t, TOPO_CHAN_NUM); valid &= os->obj->ChannelValidity (t, SUBSEL_TYPE_CHAN_NUM); valid &= os->obj->ChannelValidity (t, SELECT_CHAN_NUM); Matrix3 modmat,minv; if (mc.localData == NULL) mc.localData = new RelaxModData; RelaxModData *rd = (RelaxModData *) mc.localData; TriObject *triObj = NULL; PatchObject *patchObj = NULL; PolyObject *polyObj = NULL; BOOL converted = FALSE; // For version 4 and later, we process patch or poly meshes as they are and pass them on. // Earlier versions converted to TriMeshes (done below). // For adding other new types of objects, add them here! #ifndef NO_PATCHES if(version >= RELAXMOD_VER4 && os->obj->IsSubClassOf(patchObjectClassID)) { patchObj = (PatchObject *)os->obj; } else // If it's a TriObject, process it #endif // NO_PATCHES if(os->obj->IsSubClassOf(triObjectClassID)) { triObj = (TriObject *)os->obj; } else if (os->obj->IsSubClassOf (polyObjectClassID)) { polyObj = (PolyObject *) os->obj; } else // If it can convert to a TriObject, do it if(os->obj->CanConvertToType(triObjectClassID)) { triObj = (TriObject *)os->obj->ConvertToType(t, triObjectClassID); converted = TRUE; } else return; // We can't deal with it! Mesh *mesh = triObj ? &(triObj->GetMesh()) : NULL; #ifndef NO_PATCHES PatchMesh &pmesh = patchObj ? patchObj->GetPatchMesh(t) : *((PatchMesh *)NULL); #else PatchMesh &pmesh = *((PatchMesh *)NULL); #endif // NO_PATCHES float relax, wtdRelax; // mjm - 4.8.99 int iter; BOOL boundary, saddle; pblock->GetValue (PB_RELAX, t, relax, FOREVER); pblock->GetValue (PB_ITER, t, iter, FOREVER); pblock->GetValue (PB_BOUNDARY, t, boundary, FOREVER); pblock->GetValue (PB_SADDLE, t, saddle, FOREVER); LimitValue (relax, MIN_RELAX, MAX_RELAX); LimitValue (iter, MIN_ITER, MAX_ITER); if(triObj) { int i, j, max; DWORD selLevel = mesh->selLevel; // mjm - 4.8.99 - add support for soft selection // sca - 4.29.99 - extended soft selection support to cover EDGE and FACE selection levels. float *vsw = (selLevel!=MESH_OBJECT) ? mesh->getVSelectionWeights() : NULL; if (rd->ivalid.InInterval(t) && (mesh->numVerts != rd->vnum)) { // Shouldn't happen, but does with Loft bug and may with other bugs. rd->ivalid.SetEmpty (); } if (!rd->ivalid.InInterval(t)) { rd->SetVNum (mesh->numVerts); for (i=0; i<rd->vnum; i++) { rd->fnum[i]=0; rd->nbor[i].ZeroCount(); } rd->sel.ClearAll (); DWORD *v; int k1, k2, origmax; for (i=0; i<mesh->numFaces; i++) { v = mesh->faces[i].v; for (j=0; j<3; j++) { if ((selLevel==MESH_FACE) && mesh->faceSel[i]) rd->sel.Set(v[j]); if ((selLevel==MESH_EDGE) && mesh->edgeSel[i*3+j]) rd->sel.Set(v[j]); if ((selLevel==MESH_EDGE) && mesh->edgeSel[i*3+(j+2)%3]) rd->sel.Set(v[j]); origmax = max = rd->nbor[v[j]].Count(); rd->fnum[v[j]]++; for (k1=0; k1<max; k1++) if (rd->nbor[v[j]][k1] == v[(j+1)%3]) break; if (k1==max) { rd->nbor[v[j]].Append (1, v+(j+1)%3, 1); max++; } for (k2=0; k2<max; k2++) if (rd->nbor[v[j]][k2] == v[(j+2)%3]) break; if (k2==max) { rd->nbor[v[j]].Append (1, v+(j+2)%3, 1); max++; } if (max>origmax) rd->vis[v[j]].SetSize (max, TRUE); if (mesh->faces[i].getEdgeVis (j)) rd->vis[v[j]].Set (k1); else if (k1>=origmax) rd->vis[v[j]].Clear (k1); if (mesh->faces[i].getEdgeVis ((j+2)%3)) rd->vis[v[j]].Set (k2); else if (k2>= origmax) rd->vis[v[j]].Clear (k2); } } // mjm - begin - 4.8.99 // if (selLevel==MESH_VERTEX) rd->sel = mesh->vertSel; if (selLevel==MESH_VERTEX) rd->sel = mesh->vertSel; else if (selLevel==MESH_OBJECT) rd->sel.SetAll (); // mjm - end rd->ivalid = os->obj->ChannelValidity (t, TOPO_CHAN_NUM); rd->ivalid &= os->obj->ChannelValidity (t, SUBSEL_TYPE_CHAN_NUM); rd->ivalid &= os->obj->ChannelValidity (t, SELECT_CHAN_NUM); } Tab<float> vangles; if (saddle) vangles.SetCount (rd->vnum); Point3 *hold = new Point3[rd->vnum]; int act; for (int k=0; k<iter; k++) { for (i=0; i<rd->vnum; i++) hold[i] = triObj->GetPoint(i); if (saddle) mesh->FindVertexAngles (vangles.Addr(0)); for (i=0; i<rd->vnum; i++) { // mjm - begin - 4.8.99 // if ((selLevel!=MESH_OBJECT) && (!rd->sel[i])) continue; if ( (!rd->sel[i] ) && (!vsw || vsw[i] == 0) ) continue; // mjm - end if (saddle && (vangles[i] <= 2*PI*.99999f)) continue; max = rd->nbor[i].Count(); if (boundary && (rd->fnum[i] < max)) continue; if (max<1) continue; Point3 avg(0.0f, 0.0f, 0.0f); for (j=0,act=0; j<max; j++) { if (!rd->vis[i][j]) continue; act++; avg += hold[rd->nbor[i][j]]; } if (act<1) continue; // mjm - begin - 4.8.99 wtdRelax = (!rd->sel[i]) ? relax * vsw[i] : relax; triObj->SetPoint (i, hold[i]*(1-wtdRelax) + avg*wtdRelax/((float)act)); // triObj->SetPoint (i, hold[i]*(1-relax) + avg*relax/((float)act)); // mjm - end } } delete [] hold; } if (polyObj) { int i, j, max; MNMesh & mm = polyObj->mm; float *vsw = (mm.selLevel!=MNM_SL_OBJECT) ? mm.getVSelectionWeights() : NULL; if (rd->ivalid.InInterval(t) && (mm.numv != rd->vnum)) { // Shouldn't happen, but does with Loft bug and may with other bugs. rd->ivalid.SetEmpty (); } if (!rd->ivalid.InInterval(t)) { rd->SetVNum (mm.numv); for (i=0; i<rd->vnum; i++) { rd->fnum[i]=0; rd->nbor[i].ZeroCount(); } rd->sel = mm.VertexTempSel (); int k1, k2, origmax; for (i=0; i<mm.numf; i++) { int deg = mm.f[i].deg; int *vtx = mm.f[i].vtx; for (j=0; j<deg; j++) { Tab<DWORD> & nbor = rd->nbor[vtx[j]]; origmax = max = nbor.Count(); rd->fnum[vtx[j]]++; DWORD va = vtx[(j+1)%deg]; DWORD vb = vtx[(j+deg-1)%deg]; for (k1=0; k1<max; k1++) if (nbor[k1] == va) break; if (k1==max) { nbor.Append (1, &va, 1); max++; } for (k2=0; k2<max; k2++) if (nbor[k2] == vb) break; if (k2==max) { nbor.Append (1, &vb, 1); max++; } } } rd->ivalid = os->obj->ChannelValidity (t, TOPO_CHAN_NUM); rd->ivalid &= os->obj->ChannelValidity (t, SUBSEL_TYPE_CHAN_NUM); rd->ivalid &= os->obj->ChannelValidity (t, SELECT_CHAN_NUM); } Tab<float> vangles; if (saddle) vangles.SetCount (rd->vnum); Tab<Point3> hold; hold.SetCount (rd->vnum); int act; for (int k=0; k<iter; k++) { for (i=0; i<rd->vnum; i++) hold[i] = mm.P(i); if (saddle) FindVertexAngles (mm, vangles.Addr(0)); for (i=0; i<rd->vnum; i++) { if ((!rd->sel[i]) && (!vsw || vsw[i] == 0) ) continue; if (saddle && (vangles[i] <= 2*PI*.99999f)) continue; max = rd->nbor[i].Count(); if (boundary && (rd->fnum[i] < max)) continue; if (max<1) continue; Point3 avg(0.0f, 0.0f, 0.0f); for (j=0,act=0; j<max; j++) { act++; avg += hold[rd->nbor[i][j]]; } if (act<1) continue; wtdRelax = (!rd->sel[i]) ? relax * vsw[i] : relax; polyObj->SetPoint (i, hold[i]*(1-wtdRelax) + avg*wtdRelax/((float)act)); } } } #ifndef NO_PATCHES else if(patchObj) { int i, j, max; DWORD selLevel = pmesh.selLevel; // mjm - 4.8.99 - add support for soft selection // sca - 4.29.99 - extended soft selection support to cover EDGE and FACE selection levels. float *vsw = (selLevel!=PATCH_OBJECT) ? pmesh.GetVSelectionWeights() : NULL; if (rd->ivalid.InInterval(t) && (pmesh.numVerts != rd->vnum)) { // Shouldn't happen, but does with Loft bug and may with other bugs. rd->ivalid.SetEmpty (); } if (!rd->ivalid.InInterval(t)) { int vecBase = pmesh.numVerts; rd->SetVNum (pmesh.numVerts + pmesh.numVecs); for (i=0; i<rd->vnum; i++) { rd->fnum[i]=1; // For patches, this means it's not a boundary rd->nbor[i].ZeroCount(); } rd->sel.ClearAll (); for (i=0; i<pmesh.numPatches; i++) { Patch &p = pmesh.patches[i]; int vecLimit = p.type * 2; for (j=0; j<p.type; j++) { PatchEdge &e = pmesh.edges[p.edge[j]]; BOOL isBoundary = (e.patches.Count() < 2) ? TRUE : FALSE; int theVert = p.v[j]; int nextVert = p.v[(j+1)%p.type]; int nextVec = p.vec[j*2] + vecBase; int nextVec2 = p.vec[j*2+1] + vecBase; int prevEdge = (j+p.type-1)%p.type; int prevVec = p.vec[prevEdge*2+1] + vecBase; int prevVec2 = p.vec[prevEdge*2] + vecBase; int theInterior = p.interior[j] + vecBase; // Establish selection bits if ((selLevel==PATCH_PATCH) && pmesh.patchSel[i]) { rd->sel.Set(theVert); rd->sel.Set(nextVec); rd->sel.Set(prevVec); rd->sel.Set(theInterior); } else if ((selLevel==PATCH_EDGE) && pmesh.edgeSel[p.edge[j]]) { rd->sel.Set(e.v1); rd->sel.Set(e.vec12 + vecBase); rd->sel.Set(e.vec21 + vecBase); rd->sel.Set(e.v2); } else if ((selLevel==PATCH_VERTEX) && pmesh.vertSel[theVert]) { rd->sel.Set(theVert); rd->sel.Set(nextVec); rd->sel.Set(prevVec); rd->sel.Set(theInterior); } // Set boundary flags if necessary if(isBoundary) { rd->fnum[theVert] = 0; rd->fnum[nextVec] = 0; rd->fnum[nextVec2] = 0; rd->fnum[nextVert] = 0; } // First process the verts int work = theVert; max = rd->nbor[work].Count(); // Append the neighboring vectors rd->MaybeAppendNeighbor(work, nextVec, max); rd->MaybeAppendNeighbor(work, prevVec, max); rd->MaybeAppendNeighbor(work, theInterior, max); // Now process the edge vectors work = nextVec; max = rd->nbor[work].Count(); // Append the neighboring points rd->MaybeAppendNeighbor(work, theVert, max); rd->MaybeAppendNeighbor(work, theInterior, max); rd->MaybeAppendNeighbor(work, prevVec, max); rd->MaybeAppendNeighbor(work, nextVec2, max); rd->MaybeAppendNeighbor(work, p.interior[(j+1)%p.type] + vecBase, max); work = prevVec; max = rd->nbor[work].Count(); // Append the neighboring points rd->MaybeAppendNeighbor(work, theVert, max); rd->MaybeAppendNeighbor(work, theInterior, max); rd->MaybeAppendNeighbor(work, nextVec, max); rd->MaybeAppendNeighbor(work, prevVec2, max); rd->MaybeAppendNeighbor(work, p.interior[(j+p.type-1)%p.type] + vecBase, max); // Now append the interior, if not auto if(!p.IsAuto()) { work = theInterior; max = rd->nbor[work].Count(); // Append the neighboring points rd->MaybeAppendNeighbor(work, p.v[j], max); rd->MaybeAppendNeighbor(work, nextVec, max); rd->MaybeAppendNeighbor(work, nextVec2, max); rd->MaybeAppendNeighbor(work, prevVec, max); rd->MaybeAppendNeighbor(work, prevVec2, max); for(int k = 1; k < p.type; ++k) rd->MaybeAppendNeighbor(work, p.interior[(j+k)%p.type] + vecBase, max); } } } // mjm - begin - 4.8.99 if (selLevel==PATCH_VERTEX) { for (int i=0; i<pmesh.numVerts; ++i) { if (pmesh.vertSel[i]) rd->sel.Set(i); } } else if (selLevel==PATCH_OBJECT) rd->sel.SetAll(); // mjm - end rd->ivalid = os->obj->ChannelValidity (t, TOPO_CHAN_NUM); rd->ivalid &= os->obj->ChannelValidity (t, SUBSEL_TYPE_CHAN_NUM); rd->ivalid &= os->obj->ChannelValidity (t, SELECT_CHAN_NUM); } Tab<float> vangles; if (saddle) vangles.SetCount (rd->vnum); Point3 *hold = new Point3[rd->vnum]; int act; for (int k=0; k<iter; k++) { for (i=0; i<rd->vnum; i++) hold[i] = patchObj->GetPoint(i); if (saddle) FindVertexAngles(pmesh, vangles.Addr(0)); for (i=0; i<rd->vnum; i++) { // mjm - begin - 4.8.99 // if ((selLevel!=MESH_OBJECT) && (!rd->sel[i])) continue; if ( (!rd->sel[i] ) && (!vsw || vsw[i] == 0) ) continue; // mjm - end if (saddle && (i < pmesh.numVerts) && (vangles[i] <= 2*PI*.99999f)) continue; max = rd->nbor[i].Count(); if (boundary && !rd->fnum[i]) continue; if (max<1) continue; Point3 avg(0.0f, 0.0f, 0.0f); for (j=0,act=0; j<max; j++) { act++; avg += hold[rd->nbor[i][j]]; } if (act<1) continue; // mjm - begin - 4.8.99 wtdRelax = (!rd->sel[i]) ? relax * vsw[i] : relax; patchObj->SetPoint (i, hold[i]*(1-wtdRelax) + avg*wtdRelax/((float)act)); // patchObj->SetPoint (i, hold[i]*(1-relax) + avg*relax/((float)act)); // mjm - end } } delete [] hold; patchObj->patch.computeInteriors(); patchObj->patch.ApplyConstraints(); } #endif // NO_PATCHES if(!converted) { os->obj->SetChannelValidity(GEOM_CHAN_NUM, valid); } else { // Stuff converted object into the pipeline! triObj->SetChannelValidity(TOPO_CHAN_NUM, valid); triObj->SetChannelValidity(GEOM_CHAN_NUM, valid); triObj->SetChannelValidity(TEXMAP_CHAN_NUM, valid); triObj->SetChannelValidity(MTL_CHAN_NUM, valid); triObj->SetChannelValidity(SELECT_CHAN_NUM, valid); triObj->SetChannelValidity(SUBSEL_TYPE_CHAN_NUM, valid); triObj->SetChannelValidity(DISP_ATTRIB_CHAN_NUM, valid); os->obj = triObj; } }
void ExtrudeMod::ModifyObject(TimeValue t, ModContext &mc, ObjectState * os, INode *node) { //DebugPrint(_T("Extrude modifying object\n")); // Get our personal validity interval... Interval valid = GetValidity(t); // and intersect it with the channels we use as input (see ChannelsUsed) valid &= os->obj->ChannelValidity(t,TOPO_CHAN_NUM); valid &= os->obj->ChannelValidity(t,GEOM_CHAN_NUM); int output; pblock->GetValue(PB_OUTPUT, TimeValue(0), output, FOREVER); switch (output) { case NURBS_OUTPUT: #ifndef NO_NURBS { // Here is where all the fun stuff happens -- GenerateExtrudeSurface fills in the EM, // then we stuff the EditableSurface into the pipeline. ShapeObject *shape = (ShapeObject *)os->obj; float amount; BOOL texturing, genMatIds, useShapeIDs; pblock->GetValue(PB_MAPPING, TimeValue(0), texturing, FOREVER); pblock->GetValue(PB_GEN_MATIDS, TimeValue(0), genMatIds, FOREVER); pblock->GetValue(PB_USE_SHAPEIDS, TimeValue(0), useShapeIDs, FOREVER); int levels,capStart,capEnd,capType; 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); pblock->GetValue(PB_AMOUNT,t,amount,FOREVER); LimitValue(amount, -1000000.0f, 1000000.0f); BOOL suspended = FALSE; if (theHold.Holding()) { theHold.Suspend(); suspended = TRUE; } Object *nobj = CreateNURBSExtrudeShape(ip, GetString(IDS_RB_EXTRUDE), t, shape, amount, capStart, capEnd, capType, texturing, genMatIds, useShapeIDs); if (suspended) { theHold.Resume(); } // We only set geom validity because we preserve animation on clone // and copying other cahnnels causes problems -- SCM 9/2/97 nobj->SetChannelValidity(GEOM_CHAN_NUM, valid); os->obj = nobj; break;} #endif #ifndef NO_PATCHES case PATCH_OUTPUT: { // Here is where all the fun stuff happens -- BuildPatchFromShape fills in the PatchObject's patch mesh, // then we stuff the PatchObject into the pipeline. PatchObject *pat = new PatchObject; BuildPatchFromShape(t, mc, os, pat->patch); pat->SetChannelValidity(TOPO_CHAN_NUM, valid); pat->SetChannelValidity(GEOM_CHAN_NUM, valid); pat->SetChannelValidity(TEXMAP_CHAN_NUM, valid); pat->SetChannelValidity(MTL_CHAN_NUM, valid); pat->SetChannelValidity(SELECT_CHAN_NUM, valid); pat->SetChannelValidity(SUBSEL_TYPE_CHAN_NUM, valid); pat->SetChannelValidity(DISP_ATTRIB_CHAN_NUM, valid); os->obj = pat; break;} #endif // NO_PATCHES case MESH_OUTPUT: { // Here is where all the fun stuff happens -- BuildMeshFromShape fills in the TriObject's mesh, // then we stuff the TriObj into the pipeline. TriObject *tri = CreateNewTriObject(); BuildMeshFromShape(t, mc, os, tri->GetMesh()); tri->SetChannelValidity(TOPO_CHAN_NUM, valid); tri->SetChannelValidity(GEOM_CHAN_NUM, valid); tri->SetChannelValidity(TEXMAP_CHAN_NUM, valid); tri->SetChannelValidity(MTL_CHAN_NUM, valid); tri->SetChannelValidity(SELECT_CHAN_NUM, valid); tri->SetChannelValidity(SUBSEL_TYPE_CHAN_NUM, valid); tri->SetChannelValidity(DISP_ATTRIB_CHAN_NUM, valid); os->obj = tri; break; } #ifdef XXDESIGN_VER case AMSOLID_OUTPUT: { //Create an extrusion solid using Facet Modeler Object* solid = (Object*)CreateInstance(GEOMOBJECT_CLASS_ID, GENERIC_AMSOLID_CLASS_ID); assert(solid); if(solid) { IGeomImp* cacheptr = (IGeomImp*)(solid->GetInterface(I_GEOMIMP)); assert(cacheptr); if(cacheptr) { bool res = BuildAMSolidFromShape(t, mc, os, cacheptr); solid->ReleaseInterface(I_GEOMIMP, cacheptr); if(!res) { valid.SetInstant(t); // assert(!cacheptr->isNull()); } for(int i=0; i<NUM_OBJ_CHANS;i++) solid->SetChannelValidity(i, valid); os->obj = solid; } } break; } #endif } os->obj->UnlockObject(); }
void ExtrudeMod::BuildMeshFromShape(TimeValue t,ModContext &mc, ObjectState * os, Mesh &mesh, BOOL simple) { 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); ShapeObject *shape = (ShapeObject *)os->obj; float amount; int levels,capStart,capEnd,capType; pblock->GetValue(PB_AMOUNT,t,amount,FOREVER); if(simple) { levels = 1; capStart = capEnd = FALSE; } else { 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); 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; // Make the shape convert itself to a PolyShape -- This makes our mesh conversion MUCH easier! PolyShape pShape; shape->MakePolyShape(t, pShape); ShapeHierarchy hier; pShape.OrganizeCurves(t, &hier); // Need to flip the reversed curves in the shape! pShape.Reverse(hier.reverse); int polys = pShape.numLines; int levelVerts = 0, levelFaces = 0, levelTVerts = 0; int verts = 0, faces = 0, tVerts = 0; int poly, piece; BOOL anyClosed = FALSE; for(poly = 0; poly < polys; ++poly) { PolyLine &line = pShape.lines[poly]; if(!line.numPts) continue; if(line.IsClosed()) { anyClosed = TRUE; levelTVerts++; } levelVerts += line.numPts; levelTVerts += line.numPts; levelFaces += (line.Segments() * 2); } int vertsPerLevel = levelVerts; int numLevels = levels; verts = levelVerts * (levels + 1); tVerts = levelTVerts * (levels + 1); faces = levelFaces * levels; mesh.setNumVerts(verts); mesh.setNumFaces(faces); if(texturing) { mesh.setNumTVerts(tVerts); mesh.setNumTVFaces(faces); } // Create the vertices! int vert = 0; int tvertex = 0; int level; Point3 offset1, offset2; for(poly = 0; poly < polys; ++poly) { PolyLine &line = pShape.lines[poly]; if(!line.numPts) continue; if(texturing) { //DebugPrint(_T("Texture Verts:\n")); BOOL usePhysUVs = GetUsePhysicalScaleUVs(); int tp; int texPts = line.numPts + (line.IsClosed() ? 1 : 0); float *texPt = new float [texPts]; float lastPt = (float)(texPts - 1); float cumLen = 0.0f; float totLen = line.CurveLength(); Point3 prevPt = line.pts[0].p; for(tp = 0; tp < texPts; ++tp) { int ltp = tp % line.numPts; if(tp == (texPts - 1)) texPt[tp] = usePhysUVs ? totLen : 1.0f; else { Point3 &pt = line.pts[ltp].p; cumLen += Length(pt - prevPt); if (usePhysUVs) texPt[tp] = cumLen; else texPt[tp] = cumLen / totLen; prevPt = pt; } } float flevels = (float)levels; for(level = 0; level <= levels; ++level) { float tV = (float)level / flevels; float vScale = usePhysUVs ? amount : 1.0f; for(tp = 0; tp < texPts; ++tp) { mesh.setTVert(tvertex++, UVVert(texPt[tp], vScale*tV, 0.0f)); } } delete [] texPt; } int lverts = line.numPts; 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(int v = 0; v < lverts; ++v) { line.pts[v].aux = vert; // Gives the capper this vert's location in the mesh! mesh.setVert(vert++, line.pts[v].p + offset); } } } assert(vert == verts); // If capping, do it! if(anyClosed && (capStart || capEnd)) { MeshCapInfo capInfo; pShape.MakeCap(t, capInfo, capType); // Build information for capping MeshCapper capper(pShape); if(capStart) { vert = 0; for(poly = 0; poly < polys; ++poly) { PolyLine &line = pShape.lines[poly]; if(!line.numPts) continue; MeshCapPoly &capline = capper[poly]; int lverts = line.numPts; for(int v = 0; v < lverts; ++v) capline.SetVert(v, vert++); // Gives this vert's location in the mesh! vert += lverts * levels; } // Create a work matrix for grid capping Matrix3 gridMat = TransMatrix(offset1); int oldFaces = mesh.numFaces; capper.CapMesh(mesh, capInfo, TRUE, 16, &gridMat, genMatIDs ? -1 : 0); // If texturing, create the texture faces and vertices if(texturing) MakeMeshCapTexture(mesh, Inverse(gridMat), oldFaces, mesh.numFaces, GetUsePhysicalScaleUVs()); } if(capEnd) { int baseVert = 0; for(poly = 0; poly < polys; ++poly) { PolyLine &line = pShape.lines[poly]; if(!line.numPts) continue; MeshCapPoly &capline = capper[poly]; int lverts = line.numPts; 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); } // Create a work matrix for grid capping Matrix3 gridMat = TransMatrix(offset2); int oldFaces = mesh.numFaces; capper.CapMesh(mesh, capInfo, FALSE, 16, &gridMat, genMatIDs ? -1 : 0); // If texturing, create the texture faces and vertices if(texturing) MakeMeshCapTexture(mesh, Inverse(gridMat), oldFaces, mesh.numFaces, GetUsePhysicalScaleUVs()); } } // Create the faces! int face = 0; int TVface = 0; int baseVert = 0; int baseTVert = 0; for(poly = 0; poly < polys; ++poly) { PolyLine &line = pShape.lines[poly]; if(!line.numPts) continue; int pieces = line.Segments(); int closed = line.IsClosed(); int segVerts = pieces + ((closed) ? 0 : 1); int segTVerts = pieces + 1; for(level = 0; level < levels; ++level) { int sm = 0; // Initial smoothing group BOOL firstSmooth = (line.pts[0].flags & POLYPT_SMOOTH) ? TRUE : FALSE; for(piece = 0; piece < pieces; ++piece) { int v1 = baseVert + piece; int v2 = baseVert + ((piece + 1) % segVerts); int v3 = v1 + segVerts; int v4 = v2 + segVerts; // If the vertex is not smooth, go to the next group! BOOL thisSmooth = line.pts[piece].flags & POLYPT_SMOOTH; MtlID mtl = useShapeIDs ? line.pts[piece].GetMatID() : 2; if(piece > 0 && !thisSmooth) { sm++; if(sm > 2) sm = 1; } DWORD smoothGroup = 1 << sm; // Advance to the next smoothing group right away if(sm == 0) sm++; // Special case for smoothing from first segment if(piece == 1 && thisSmooth) smoothGroup |= 1; // Special case for smoothing from last segment if((piece == pieces - 1) && firstSmooth) smoothGroup |= 1; mesh.faces[face].setEdgeVisFlags(1,1,0); mesh.faces[face].setSmGroup(smooth ? smoothGroup : 0); mesh.faces[face].setMatID(genMatIDs ? mtl : 0); mesh.faces[face++].setVerts(v1, v2, v4); mesh.faces[face].setEdgeVisFlags(0,1,1); mesh.faces[face].setSmGroup(smooth ? smoothGroup : 0); mesh.faces[face].setMatID(genMatIDs ? mtl : 0); mesh.faces[face++].setVerts(v1, v4, v3); //DebugPrint(_T("BV:%d V:%d v1:%d v2:%d v3:%d v4:%d\n"),baseVert, vert, v1, v2, v3, v4); if(texturing) { int tv1 = baseTVert + piece; int tv2 = tv1 + 1; int tv3 = tv1 + segTVerts; int tv4 = tv2 + segTVerts; mesh.tvFace[TVface++].setTVerts(tv1, tv2, tv4); mesh.tvFace[TVface++].setTVerts(tv1, tv4, tv3); } } baseVert += segVerts; baseTVert += segTVerts; } baseVert += segVerts; // Increment to next poly start (skips last verts of this poly) baseTVert += segTVerts; } assert(face == faces); mesh.InvalidateGeomCache(); }