Esempio n. 1
0
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());
	}
Esempio n. 2
0
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);
	}
Esempio n. 3
0
RefTargetHandle RendSpline::Clone(RemapDir& remap)
{
	RendSpline* newmod = new RendSpline(false);	
	newmod->ReplaceReference(PBLOCK_REF,remap.CloneRef(pblock));
	BaseClone(this, newmod, remap);
    newmod->SetUsePhysicalScaleUVs(GetUsePhysicalScaleUVs());
	return(newmod);
}
Esempio n. 4
0
RefTargetHandle ExtrudeMod::Clone(RemapDir& remap)
	{
	ExtrudeMod* newmod = new ExtrudeMod(false);	
	newmod->ReplaceReference(0,remap.CloneRef(pblock));
	BaseClone(this, newmod, remap);
    newmod->SetUsePhysicalScaleUVs(GetUsePhysicalScaleUVs());
	return(newmod);
	}
Esempio n. 5
0
RefTargetHandle TorusObject::Clone(RemapDir& remap) 
	{
	TorusObject* newob = new TorusObject(FALSE);	
	newob->ReplaceReference(0,remap.CloneRef(pblock));	
	newob->ivalid.SetEmpty();	
	BaseClone(this, newob, remap);
    newob->SetUsePhysicalScaleUVs(GetUsePhysicalScaleUVs());
	return(newob);
	}
Esempio n. 6
0
void TorusObject::SetUsePhysicalScaleUVs(BOOL flag)
{
    BOOL curState = GetUsePhysicalScaleUVs();
    if (curState == flag)
        return;
    if (theHold.Holding())
        theHold.Put(new RealWorldScaleRecord<TorusObject>(this, curState));
    ::SetUsePhysicalScaleUVs(this, flag);
    if (pblock != NULL)
		pblock->NotifyDependents(FOREVER, PART_GEOM, REFMSG_CHANGE);
	UpdateUI();
	macroRec->SetProperty(this, _T("realWorldMapSize"), mr_bool, flag);
}
Esempio n. 7
0
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());
	}
Esempio n. 8
0
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();
	}
Esempio n. 9
0
Object* TorusObject::ConvertToType(TimeValue t, Class_ID obtype)
	{
#ifndef NO_PATCHES
	if (obtype == patchObjectClassID) {
		Interval valid = FOREVER;
		float radius1, radius2;
		int genUVs;
		pblock->GetValue(PB_RADIUS,t,radius1,valid);
		pblock->GetValue(PB_RADIUS2,t,radius2,valid);
		pblock->GetValue(PB_GENUVS,t,genUVs,valid);
		PatchObject *ob = new PatchObject();
		BuildTorusPatch(t,ob->patch,radius1,radius2,genUVs, GetUsePhysicalScaleUVs());
		ob->SetChannelValidity(TOPO_CHAN_NUM,valid);
		ob->SetChannelValidity(GEOM_CHAN_NUM,valid);
		ob->UnlockObject();
		return ob;
	} 
#endif
#ifndef NO_NURBS
    if (obtype == EDITABLE_SURF_CLASS_ID) {
		Interval valid = FOREVER;
		float radius, radius2, pie1, pie2;
		int sliceon, genUVs;
		pblock->GetValue(PB_RADIUS,t,radius,valid);
		pblock->GetValue(PB_RADIUS2,t,radius2,valid);	
		pblock->GetValue(PB_PIESLICE1,t,pie1,valid);	
		pblock->GetValue(PB_PIESLICE2,t,pie2,valid);	
		pblock->GetValue(PB_SLICEON,t,sliceon,valid);
		pblock->GetValue(PB_GENUVS,t,genUVs,valid);
		Object *ob = BuildNURBSTorus(radius, radius2, sliceon, pie1, pie2, genUVs);
		ob->SetChannelValidity(TOPO_CHAN_NUM,valid);
		ob->SetChannelValidity(GEOM_CHAN_NUM,valid);
		ob->UnlockObject();
		return ob;
		
	}
#endif

#ifdef DESIGN_VER
	if (obtype == GENERIC_AMSOLID_CLASS_ID)
	{
		Interval valid = FOREVER;
		float radius1, radius2, pie1, pie2;
		int sliceon, genUVs, sides, segs;
		pblock->GetValue(PB_RADIUS,t,radius1,valid);
		pblock->GetValue(PB_RADIUS2,t,radius2,valid);
		pblock->GetValue(PB_PIESLICE1,t,pie1,valid);	
		pblock->GetValue(PB_PIESLICE2,t,pie2,valid);	
		pblock->GetValue(PB_SLICEON,t,sliceon,valid);
		pblock->GetValue(PB_GENUVS,t,genUVs,valid);
		pblock->GetValue(PB_SIDES,t,sides,valid);
		pblock->GetValue(PB_SEGMENTS,t,segs,valid);
		int smooth;
		pblock->GetValue(PB_SMOOTH,t,smooth,valid);
		if (radius1 < 0.0f) radius1 = 0.0f;
		if (radius2 < 0.0f) radius2 = 0.0f;
		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 = cacheptr->createTorus(radius1, radius2, sides, segs, smooth);
				solid->ReleaseInterface(I_GEOMIMP, cacheptr);
				if(res)
					return solid;
				else 
				{
					solid->DeleteMe();
				}
			}
		}
		return NULL;
	}
#endif

	return SimpleObject::ConvertToType(t,obtype);
	}
Esempio n. 10
0
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();
	}
Esempio n. 11
0
void RendSpline::ModifyObject(TimeValue t, ModContext &mc, ObjectState * os, INode *node) 
{
	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);

//	float nlength;
	
	BOOL doRender = false, doDisplay = false, doUVW = false, useView = false, autosmooth = false, aspectLock = false, vAspectLock;
	float threshold, width, length, angle2, vwidth, vlength, vangle2;
	int rectangular, vRectangular;
	pblock->GetValue(rnd_thickness,t,nlength,valid);
	pblock->GetValue(rnd_sides,t,nsides,valid);
	pblock->GetValue(rnd_angle,t,nangle,valid);
	pblock->GetValue(rnd_viewThickness,t,vthickness,valid);
	pblock->GetValue(rnd_viewSides,t,vsides,valid);
	pblock->GetValue(rnd_viewAngle,t,vangle,valid);
	pblock->GetValue(rnd_render,t,doRender,valid);
	pblock->GetValue(rnd_display,t,doDisplay,valid);
	pblock->GetValue(rnd_genuvw,t,doUVW,valid);
	pblock->GetValue(rnd_useView,t,useView,valid);
	pblock->GetValue(rnd_v2_symm_or_rect,t,rectangular,valid);
	pblock->GetValue(rnd_v2_length,t,length,valid);
	pblock->GetValue(rnd_v2_width,t,width,valid);
	pblock->GetValue(rnd_v2_angle2,t,angle2,valid);
	pblock->GetValue(rnd_v2_aspect_lock,t,aspectLock,valid);
	pblock->GetValue(rnd_v2_vpt_symm_or_rect,t,vRectangular,valid);
	pblock->GetValue(rnd_v2_vpt_length,t,vlength,valid);
	pblock->GetValue(rnd_v2_vpt_width,t,vwidth,valid);
	pblock->GetValue(rnd_v2_vpt_angle2,t,vangle2,valid);
	pblock->GetValue(rnd_v2_vpt_aspect_lock,t,vAspectLock,valid);
	pblock->GetValue(rnd_v2_autosmooth,t,autosmooth,valid);
	pblock->GetValue(rnd_v2_threshold,t,threshold,valid);
	BOOL usePhysUVs = GetUsePhysicalScaleUVs();
	
	mAspectLock = aspectLock;

	theHold.Suspend(); // need to suspend Undo
	SplineShape *shape = (SplineShape *)os->obj; //->ConvertToType(t,splineShapeClassID);
	
	shape->SetRenderable(doRender);
		shape->SetDispRenderMesh(doDisplay);
	if(doRender || doDisplay)
		shape->SetGenUVW(doUVW);

	nlength = nlength < 0.0f ? 0.0f : (nlength > 1000000.0f ? 1000000.0f : nlength);
	vthickness = vthickness < 0.0f ? 0.0f : (vthickness > 1000000.0f ? 1000000.0f : vthickness);

	nsides = nsides < 0 ? 0 : (nsides > 100? 100 : nsides);
	vsides = vsides < 0 ? 0 : (vsides > 100? 100 : vsides);

	shape->SetThickness(t,nlength);
	shape->SetSides(t,nsides);
	shape->SetAngle(t,nangle);

	shape->SetViewportAngle(vangle);
	shape->SetViewportSides(vsides);
	shape->SetViewportThickness(vthickness);

	shape->SetUseViewport(useView);

	shape->SetUsePhysicalScaleUVs(usePhysUVs);

	IShapeRectRenderParams *rparams = (IShapeRectRenderParams *)shape->GetProperty(SHAPE_RECT_RENDERPARAMS_PROPID);
	if(rparams)
	{
		rparams->SetAutosmooth(t,autosmooth);
		rparams->SetAutosmoothThreshold(t, threshold);
		rparams->SetRectangular(t,rectangular == rbRectangular);

		rparams->SetAngle2(t,angle2);
		rparams->SetLength(t,length);
		rparams->SetWidth(t,width);

		rparams->SetVPTRectangular(t,vRectangular == rbRectangular);
		rparams->SetVPTAngle2(t,vangle2);
		rparams->SetVPTLength(t,vlength);
		rparams->SetVPTWidth(t,vwidth);
	}

	shape->shape.UpdateSels();	
	shape->shape.InvalidateGeomCache();
	theHold.Resume(); // it's now safe to resume Undo


	os->obj->SetChannelValidity(TOPO_CHAN_NUM, valid);
	os->obj->SetChannelValidity(GEOM_CHAN_NUM, valid);
	os->obj->SetChannelValidity(TEXMAP_CHAN_NUM, valid);
	os->obj->SetChannelValidity(MTL_CHAN_NUM, valid);
	os->obj->SetChannelValidity(SELECT_CHAN_NUM, valid);
	os->obj->SetChannelValidity(SUBSEL_TYPE_CHAN_NUM, valid);
	os->obj->SetChannelValidity(DISP_ATTRIB_CHAN_NUM, valid);

	os->obj = shape;

	//os->obj->UnlockObject();


}
Esempio n. 12
0
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();
	}
Esempio n. 13
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();
	}