IPoint2 mSp0; Point3 mP0; public: int proc( ViewExp *vpt,int msg, int point, int flags, IPoint2 m, Matrix3& mat ); void SetObj(LuminaireObject *obj) { mpObject = obj; } }; static LuminaireObjectCreateCallBack gLuminaireCreateCB; //=========================================================================== // LuminaireObject implementation //=========================================================================== const TCHAR LuminaireObject::mInternalClassName[] = _T("LuminaireHelper"); const Box3 LuminaireObject::mDefBoxSize(Point3(-10, -10, 0), Point3(10, 10, 20)); //--------------------------------------------------------------------------- // Constructor/Destructor LuminaireObject::LuminaireObject() : mpBlock(NULL) { GetLuminaireDesc()->MakeAutoParamBlocks(this); SetBox(const_cast<Box3&>(mDefBoxSize)); dumFlags &= ~MESH_VALID; } LuminaireObject::~LuminaireObject() { DeleteAllRefsFromMe();
static inline Point3 pabs(Point3 p) { return Point3(fabs(p.x),fabs(p.y),fabs(p.z)); }
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(); }
bool Lighting::EvaluateLighting(LPDIRECT3DDEVICE9 Device, RenderMesh *RMesh, ShaderMat *Mat) { D3DLIGHT9 DLight; D3DXVECTOR3 Pos,Dir; RenderLight Light; int i; if(!Device || !RMesh || !m_Ready) { return(false); } m_Device = Device; // // Setup // // The force update is used when the scene is in an unknwon state - usual after a an undo of a light if(m_forceUpdate) GetLightsFromScene(); UpdateLights(); SetRenderStates(); // m_Lights.clear(); if(m_Lights.size()) { for(i=0; i < m_Lights.size(); i++) { SetShader(m_Lights[i].m_Type,Mat); SetMaterialConst(Mat); SetShaderConst(i,&m_Lights[i],Mat); RMesh->Render(m_Device); } } else { m_Device->GetLight(0,&DLight); Light.m_Dir = Point3(-DLight.Direction.x, -DLight.Direction.y, -DLight.Direction.z); Light.m_Color.x = DLight.Diffuse.r; Light.m_Color.y = DLight.Diffuse.g; Light.m_Color.z = DLight.Diffuse.b; Light.m_Pos.x = DLight.Position.x; Light.m_Pos.y = DLight.Position.y; Light.m_Pos.z = DLight.Position.z; Light.m_InnerRange = 1.0f; Light.m_OuterRange = 1.0f / (DLight.Range * 2.0f); SetShader(LIGHT_DIR,Mat); SetMaterialConst(Mat); SetShaderConst(0,&Light,Mat); RMesh->Render(m_Device); } return(true); }
Point3 SContext::DP(void) { float d = (1.0f+DFACT)*(RayDiam())/(DFACT+(float)fabs(DotProd(Normal(),viewDir))); return Point3(d,d,d); }
Point3 UVtex::EvalNormalPerturb(ShadeContext& sc) { return Point3(0,0,0); }
//The display function that is used to display the formation. int FormationBhvr::Display(TimeValue t, ViewExp *vpt) { if ( ! vpt || ! vpt->IsAlive() ) { // why are we here DbgAssert(!_T("Doing Display() on invalid viewport!")); return FALSE; } // setup int i,j; if(DisplayFormation(t)==FALSE) return FALSE; if(GetFollowerCount(t)<=0) return FALSE; if(GetFollowerMatrixCount(t)<=0) return FALSE; INode *leaderNode; leaderNode = GetLeader(t); if(leaderNode==NULL) return FALSE; //check tgo see if we have created a default sphere for drawing yet... //if we haven't then create it.. if (numpts == 0) GetSpherePoints(Point3(0.0f,0.0f,0.0f), 1.0, SpherePts); GraphicsWindow *gw = vpt->getGW(); //set the identity matrix... Matrix3 idMat; idMat.IdentityMatrix(); gw->setTransform(idMat); gw->setColor(LINE_COLOR,.815f,.976f,1.0f); float scaleRadius = GetDisplayScale(t); //set the drawing radius values based upon what the radius size is. for (i=0; i<NUMAROUND * 3; i++) ScaledPts[i] = ((SpherePts[i] * scaleRadius)); //for each follower we need to increase the bounding box by it's //world position location... for(i =0;i<GetFollowerCount(t);i++) { INode *followerNode = GetFollower(t,i); if(followerNode) //if we have a a node... { Matrix3 leaderMat = GetCurrentMatrix(leaderNode,t); leaderMat.NoScale(); Matrix3 followerMat = GetFollowerMatrix(t,i); Matrix3 worldSpace = followerMat *leaderMat; for (j=0; j<NUMAROUND * 3; j++) CurPts[j] = worldSpace*ScaledPts[j]; //adding the center to the point positions gw->polyline(NUMAROUND,&CurPts[0],NULL,NULL,TRUE,NULL); gw->polyline(NUMAROUND,&CurPts[NUMAROUND],NULL,NULL,TRUE,NULL); gw->polyline(NUMAROUND,&CurPts[NUMAROUND * 2],NULL,NULL,TRUE,NULL); } } return TRUE; }
const Point3 TrigonometricCurve::operator()(const double u, Vector3 *dp_du, Vector3 *d2p_du2) const // // returns ths position of the curve at the parameter `u` (0 <= `u` // <= 1). If `dp_du` is not NULL, it will be set to the path // derivative vector at `u`. If `d2p_du2` is not NULL, it will be set // the the second path derivative vector. // // Note: the path derivatives are *not* normalized. If the components // of the path had dimensions of length (i.e. the path was a // position) and `u` had dimensions of time, the path derivatives // `dp_du` and `d2p_du2` would be a velocity and an acceleration, // respectively. If the caller wants a unit-length (dimensionless) // vector, it is up to them to normalize a derivative upon its // return. // { // // ASSIGNMENT (PA09) // // Enhance your previous (PA06) solution to set `*d2p_du2` to the // (second) path derivative as per the function header. Use your // knowledge of calculus to compute it. // // 15 lines in instructor solution (YMMV) // if (dp_du) { /* * Derivative is -2PI * freq * mag * sin(2PI *( freq * u + phase)) */ // Derivative dp_du->u.g.x = -2 * M_PI * freq.u.g.x * mag.u.g.x * sin(2 * M_PI * (freq.u.g.x * u + phase.u.g.x)); dp_du->u.g.y = -2 * M_PI * freq.u.g.y * mag.u.g.y * sin(2 * M_PI * (freq.u.g.y * u + phase.u.g.y)); dp_du->u.g.z = -2 * M_PI * freq.u.g.z * mag.u.g.z * sin(2 * M_PI * (freq.u.g.z * u + phase.u.g.z)); } if (d2p_du2) { /* * Second derivative is -4PI^2 * freq^2 * max * cos(2PI * (freq * u + phase)) */ dp_du->u.g.x = (-4 * (M_PI * M_PI) * (freq.u.g.x * freq.u.g.x) * mag.u.g.x) * cos(2 * M_PI * (freq.u.g.x * u + phase.u.g.x)); dp_du->u.g.y = (-4 * (M_PI * M_PI) * (freq.u.g.y * freq.u.g.y) * mag.u.g.y) * cos(2 * M_PI * (freq.u.g.y * u + phase.u.g.y)); dp_du->u.g.z = (-4 * (M_PI * M_PI) * (freq.u.g.z * freq.u.g.z) * mag.u.g.z) * cos(2 * M_PI * (freq.u.g.z * u + phase.u.g.z)); } Vec3 angle = 2 * M_PI * (freq * u + phase); double x = mag.u.g.x * cos(angle.u.g.x) + offset.u.g.x; double y = mag.u.g.y * cos(angle.u.g.y) + offset.u.g.y; double z = mag.u.g.z * cos(angle.u.g.z) + offset.u.g.z; Point3 value = Point3(x, y, z); return value; }
// Let the plug-in register itself for deferred loading __declspec( dllexport ) ULONG CanAutoDefer() { return 1; } /* rand returns a number between 0 and 32767 */ /* number between 0 and 1 */ const float IntMax=32767.0f; const float IntMax1=32768.0f; const float HalfIntMax=16383.5f; typedef float Matrix3By3[3][3]; typedef float Matrix4By3[4][3]; Point3 Zero=Point3(0.0f,0.0f,0.0f); int FloatEQ0(float number) { return((FLOAT_EPSILON>=number)&&(number>=-FLOAT_EPSILON));} int SmallerEQ0(float number) { return((SMALL_EPSILON>=number)&&(SMALL_EPSILON>=-FLOAT_EPSILON));} int FGT0(Point3 p1) { return((fabs(p1[0])>SMALL_EPSILON)||(fabs(p1[1])>SMALL_EPSILON)||(fabs(p1[2])>SMALL_EPSILON));} void Mult1X4(float *A,Matrix4By4 B,float *C) { C[0]=A[0]*B[0][0]+A[1]*B[1][0]+A[2]*B[2][0]+A[3]*B[3][0]; C[1]=A[0]*B[0][1]+A[1]*B[1][1]+A[2]*B[2][1]+A[3]*B[3][1]; C[2]=A[0]*B[0][2]+A[1]*B[1][2]+A[2]*B[2][2]+A[3]*B[3][2]; C[3]=A[0]*B[0][3]+A[1]*B[1][3]+A[2]*B[2][3]+A[3]*B[3][3];
void UnwrapMod::fnAlignAndFit(int axis) { //get our selection Box3 bounds; bounds.Init(); //get the bounding box Point3 pnorm(0.0f,0.0f,0.0f); int ct = 0; TimeValue t = GetCOREInterface()->GetTime(); for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++) { MeshTopoData *ld = mMeshTopoData[ldID]; Matrix3 tm = mMeshTopoData.GetNodeTM(t,ldID); for (int k = 0; k < ld->GetNumberFaces(); k++) { if (ld->GetFaceSelected(k)) { // Grap the three points, xformed int pcount = 3; // if (gfaces[k].flags & FLAG_QUAD) pcount = 4; pcount = ld->GetFaceDegree(k);//gfaces[k]->count; Point3 temp_point[4]; for (int j=0; j<pcount; j++) { int index = ld->GetFaceGeomVert(k,j);//gfaces[k]->t[j]; bounds += ld->GetGeomVert(index) *tm;//gverts.d[index].p; if (j < 4) temp_point[j] = ld->GetGeomVert(index);//gverts.d[index].p; } pnorm += VectorTransform(Normalize(temp_point[1]-temp_point[0]^temp_point[2]-temp_point[1]),tm); ct++; } } } if (ct == 0) return; theHold.Begin(); SuspendAnimate(); AnimateOff(); pnorm = pnorm / (float) ct; Matrix3 tm(1); //if just a primary axis set the tm; Point3 center = bounds.Center(); // build the scale Point3 scale(bounds.Width().x ,bounds.Width().y , bounds.Width().z); if (scale.x == 0.0f) scale.x = 1.0f; if (scale.y == 0.0f) scale.y = 1.0f; if (scale.z == 0.0f) scale.z = 1.0f; if (axis == 0) // x axi { tm.SetRow(0,Point3(0.0f,-scale.y,0.0f)); tm.SetRow(1,Point3(0.0f,0.0f,scale.z)); tm.SetRow(2,Point3(scale.x,0.0f,0.0f)); if ((fnGetMapMode() == PLANARMAP) || (fnGetMapMode() == PELTMAP) || (fnGetMapMode() == SPHERICALMAP) || (fnGetMapMode() == BOXMAP)) tm.SetRow(3,center); else if (fnGetMapMode() == CYLINDRICALMAP) { center.x = bounds.pmin.x; tm.SetRow(3,center); } Matrix3 ptm(1), id(1); tm = tm ; SetXFormPacket tmpck(tm,ptm); tmControl->SetValue(t,&tmpck,TRUE,CTRL_RELATIVE); } else if (axis == 1) // y axi { tm.SetRow(0,Point3(scale.x,0.0f,0.0f)); tm.SetRow(1,Point3(0.0f,0.0f,scale.z)); tm.SetRow(2,Point3(0.0f,scale.y,0.0f)); if ((fnGetMapMode() == PLANARMAP) || (fnGetMapMode() == PELTMAP)|| (fnGetMapMode() == SPHERICALMAP) || (fnGetMapMode() == BOXMAP)) tm.SetRow(3,center); else if (fnGetMapMode() == CYLINDRICALMAP) { center.y = bounds.pmin.y; tm.SetRow(3,center); } Matrix3 ptm(1), id(1); tm = tm; SetXFormPacket tmpck(tm,ptm); tmControl->SetValue(t,&tmpck,TRUE,CTRL_RELATIVE); } else if (axis == 2) //z axi { tm.SetRow(0,Point3(scale.x,0.0f,0.0f)); tm.SetRow(1,Point3(0.0f,scale.y,0.0f)); tm.SetRow(2,Point3(0.0f,0.0f,scale.z)); if ((fnGetMapMode() == PLANARMAP) || (fnGetMapMode() == PELTMAP)|| (fnGetMapMode() == SPHERICALMAP) || (fnGetMapMode() == BOXMAP)) tm.SetRow(3,center); else if (fnGetMapMode() == CYLINDRICALMAP) { center.z = bounds.pmin.z; tm.SetRow(3,center); } Matrix3 ptm(1), id(1); tm = tm; SetXFormPacket tmpck(tm,ptm); tmControl->SetValue(t,&tmpck,TRUE,CTRL_RELATIVE); } else if (axis == 3) // normal { int numberOfSelectionGroups = 0; for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++) { MeshTopoData *ld = mMeshTopoData[ldID]; if (ld->GetFaceSelection().NumberSet()) numberOfSelectionGroups++; } if ((fnGetMapMode() == PLANARMAP) || (fnGetMapMode() == PELTMAP) || (numberOfSelectionGroups > 1)) { //get our tm Matrix3 tm; UnwrapMatrixFromNormal(pnorm,tm); Matrix3 itm = Inverse(tm); //find our x and y scale float xmax = 0.0f; float ymax = 0.0f; float zmax = 0.0f; Box3 localBounds; localBounds.Init(); for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++) { MeshTopoData *ld = mMeshTopoData[ldID]; Matrix3 tm = mMeshTopoData.GetNodeTM(t,ldID); for (int k = 0; k < ld->GetNumberFaces(); k++) { if (ld->GetFaceSelected(k)) { // Grap the three points, xformed int pcount = 3; // if (gfaces[k].flags & FLAG_QUAD) pcount = 4; pcount = ld->GetFaceDegree(k);//gfaces[k]->count; Point3 temp_point[4]; for (int j=0; j<pcount; j++) { int index = ld->GetFaceGeomVert(k,j);//gfaces[k]->t[j]; Point3 p = ld->GetGeomVert(index) * tm * itm;//gverts.d[index].p * itm; localBounds += p; } } } } // center = localBounds.Center(); xmax = localBounds.pmax.x - localBounds.pmin.x; ymax = localBounds.pmax.y - localBounds.pmin.y; zmax = localBounds.pmax.z - localBounds.pmin.z; if (xmax < 0.001f) xmax = 1.0f; if (ymax < 0.001f) ymax = 1.0f; if (zmax < 0.001f) zmax = 1.0f; Point3 vec; vec = Normalize(tm.GetRow(0)) * xmax; tm.SetRow(0,vec); vec = Normalize(tm.GetRow(1)) * ymax; tm.SetRow(1,vec); vec = Normalize(tm.GetRow(2)) * zmax; tm.SetRow(2,vec); tm.SetRow(3,center); Matrix3 ptm(1), id(1); tm = tm ; SetXFormPacket tmpck(tm,ptm); tmControl->SetValue(t,&tmpck,TRUE,CTRL_RELATIVE); } else if ((fnGetMapMode() == CYLINDRICALMAP) || (fnGetMapMode() == SPHERICALMAP)|| (fnGetMapMode() == BOXMAP)) { for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++) { //get our first 2 rings Tab<int> openEdges; Tab<int> startRing; Tab<int> endRing; MeshTopoData *ld = mMeshTopoData[ldID]; //skip any local data that has no selections if (ld->GetFaceSelection().NumberSet() == 0) continue; Matrix3 nodeTM = mMeshTopoData.GetNodeTM(t,ldID); for (int i = 0; i < ld->GetNumberGeomEdges(); i++)//TVMaps.gePtrList.Count(); i++) { int numberSelectedFaces = 0; int ct = ld->GetGeomEdgeNumberOfConnectedFaces(i);//TVMaps.gePtrList[i]->faceList.Count(); for (int j = 0; j < ct; j++) { int faceIndex = ld->GetGeomEdgeConnectedFace(i,j);//TVMaps.gePtrList[i]->faceList[j]; if (ld->GetFaceSelected(faceIndex))//fsel[faceIndex]) numberSelectedFaces++; } if (numberSelectedFaces == 1) { openEdges.Append(1,&i,1000); } } GetOpenEdges(ld,openEdges, startRing); GetOpenEdges(ld,openEdges, endRing); Point3 zVec = pnorm; Point3 centerS(0.0f,0.0f,0.0f), centerE; if ((startRing.Count() != 0) && (endRing.Count() != 0)) { //get the center start Box3 BoundsS, BoundsE; BoundsS.Init(); BoundsE.Init(); //get the center end for (int i = 0; i < startRing.Count(); i++) { int eIndex = startRing[i]; int a = ld->GetGeomEdgeVert(eIndex,0);//TVMaps.gePtrList[eIndex]->a; int b = ld->GetGeomEdgeVert(eIndex,1);//TVMaps.gePtrList[eIndex]->b; BoundsS += ld->GetGeomVert(a) * nodeTM;//TVMaps.geomPoints[a]; BoundsS += ld->GetGeomVert(b) * nodeTM;//TVMaps.geomPoints[b]; } for (int i = 0; i < endRing.Count(); i++) { int eIndex = endRing[i]; int a = ld->GetGeomEdgeVert(eIndex,0);//TVMaps.gePtrList[eIndex]->a; int b = ld->GetGeomEdgeVert(eIndex,1);//TVMaps.gePtrList[eIndex]->b; BoundsE += ld->GetGeomVert(a) * nodeTM;//TVMaps.geomPoints[a]; BoundsE += ld->GetGeomVert(b) * nodeTM;//TVMaps.geomPoints[b]; } centerS = BoundsS.Center(); centerE = BoundsE.Center(); //create the vec zVec = centerE - centerS; } else if ((startRing.Count() != 0) && (endRing.Count() == 0)) { //get the center start Box3 BoundsS; BoundsS.Init(); //get the center end for (int i = 0; i < startRing.Count(); i++) { int eIndex = startRing[i]; int a = ld->GetGeomEdgeVert(eIndex,0);//TVMaps.gePtrList[eIndex]->a; int b = ld->GetGeomEdgeVert(eIndex,1);//TVMaps.gePtrList[eIndex]->b; BoundsS += ld->GetGeomVert(a) * nodeTM;//TVMaps.geomPoints[a]; BoundsS += ld->GetGeomVert(b) * nodeTM;//TVMaps.geomPoints[b]; } centerS = BoundsS.Center(); int farthestPoint= -1; Point3 fp; float farthestDist= 0.0f; for (int k=0; k < ld->GetNumberFaces(); k++) { if (ld->GetFaceSelected(k)) { // Grap the three points, xformed int pcount = 3; // if (gfaces[k].flags & FLAG_QUAD) pcount = 4; pcount = ld->GetFaceDegree(k);//gfaces[k]->count; for (int j=0; j<pcount; j++) { int index = ld->GetFaceGeomVert(k,j);//gfaces[k]->t[j]; Point3 p = ld->GetGeomVert(index)* nodeTM;//gverts.d[index].p; float d = LengthSquared(p-centerS); if ((d > farthestDist) || (farthestPoint == -1)) { farthestDist = d; farthestPoint = index; fp = p; } } } } centerE = fp; //create the vec zVec = centerE - centerS; } else { zVec = Point3(0.0f,0.0f,1.0f); } //get our tm Matrix3 tm; UnwrapMatrixFromNormal(zVec,tm); tm.SetRow(3,centerS); Matrix3 itm = Inverse(tm); //find our x and y scale float xmax = 0.0f; float ymax = 0.0f; float zmax = 0.0f; Box3 localBounds; localBounds.Init(); for (int k = 0; k < ld->GetNumberFaces(); k++)//gfaces.Count(); k++) { if (ld->GetFaceSelected(k)) { // Grap the three points, xformed int pcount = 3; // if (gfaces[k].flags & FLAG_QUAD) pcount = 4; pcount = ld->GetFaceDegree(k);//gfaces[k]->count; Point3 temp_point[4]; for (int j=0; j<pcount; j++) { int index = ld->GetFaceGeomVert(k,j);//gfaces[k]->t[j]; Point3 p = ld->GetGeomVert(index) * nodeTM * itm;//gverts.d[index].p * itm; localBounds += p; } } } center = localBounds.Center() * tm; if (fnGetMapMode() == CYLINDRICALMAP) { if ((startRing.Count() == 0) && (endRing.Count() == 0)) { centerS = center; centerS.z = localBounds.pmin.z; } else { centerS = centerS * itm; centerS.z = localBounds.pmin.z; centerS = centerS * tm; } } else if ((fnGetMapMode() == SPHERICALMAP) || (fnGetMapMode() == BOXMAP)) { centerS = center; } Point3 bc = localBounds.Center(); bc.z = localBounds.pmin.z; bc = bc * tm; xmax = localBounds.pmax.x - localBounds.pmin.x; ymax = localBounds.pmax.y - localBounds.pmin.y; zmax = localBounds.pmax.z - localBounds.pmin.z; Point3 vec; vec = Normalize(tm.GetRow(0)) * xmax; tm.SetRow(0,vec); vec = Normalize(tm.GetRow(1)) * ymax; tm.SetRow(1,vec); vec = Normalize(tm.GetRow(2)) * zmax; tm.SetRow(2,vec); tm.SetRow(3,centerS); Matrix3 ptm(1), id(1); tm = tm; SetXFormPacket tmpck(tm,ptm); tmControl->SetValue(t,&tmpck,TRUE,CTRL_RELATIVE); } } } ResumeAnimate(); if ((fnGetMapMode() == PLANARMAP) || (fnGetMapMode() == CYLINDRICALMAP) || (fnGetMapMode() == SPHERICALMAP) || (fnGetMapMode() == BOXMAP)) ApplyGizmo(); theHold.Accept(GetString(IDS_MAPPING_ALIGN)); fnGetGizmoTM(); if (ip) ip->RedrawViews(ip->GetTime()); }
void UnwrapMod::DrawGizmo(TimeValue t, INode* inode,/*w4 ModContext *mc, */GraphicsWindow *gw) { ComputeSelectedFaceData(); Matrix3 vtm(1); Interval iv; if (inode) vtm = inode->GetObjectTM(t,&iv); Point3 a(-0.5f,-0.5f,0.0f),b(0.5f,-0.5f,0.0f),c(0.5f,0.5f,0.0f),d(-0.5f,0.5f,0.0f); Matrix3 modmat, ntm = inode->GetObjectTM(t); modmat = GetMapGizmoMatrix(t); gw->setTransform(modmat); if ( (fnGetMapMode() == PLANARMAP) || (fnGetMapMode() == PELTMAP) ) { Point3 line[5]; line[0] = a; line[1] = b; line[2] = c; line[3] = d; line[4] = line[0]; gw->setColor(LINE_COLOR,GetUIColor(COLOR_SEL_GIZMOS)); gw->polyline(5, line, NULL, NULL, 0); } else if (fnGetMapMode() == CYLINDRICALMAP) { //draw the bottom circle int segs = 32; float angle = 0.0f; float inc = 1.0f/(float)segs * 2 * PI; Point3 prevVec; gw->startSegments(); Point3 pl[3]; gw->setColor(LINE_COLOR,GetUIColor(COLOR_SEL_GIZMOS)); for (int i = 0; i < (segs+1); i++) { Matrix3 tm(1); tm.RotateZ(angle); Point3 vec (0.50f,0.0f,0.0f); vec = vec * tm; if ( i >= 1) { pl[0] = vec; pl[1] = prevVec; gw->segment(pl,1); pl[0].z = 1.0f; pl[1].z = 1.0f; gw->segment(pl,1); if (((i%4) == 0) && (i != segs)) { pl[0] = vec; pl[1] = vec; pl[1].z = 1.0f; gw->segment(pl,1); } } prevVec = vec; angle += inc; } Color c(openEdgeColor); gw->setColor(LINE_COLOR,c); pl[0] = Point3(0.50f,0.0f,0.0f); pl[1] = Point3(0.50f,0.0f,0.0f); pl[1].z = 1.0f; gw->segment(pl,1); gw->endSegments(); } else if (fnGetMapMode() == SPHERICALMAP) { //draw the bottom circle int segs = 32; float inc = 1.0f/(float)segs * 2 * PI; gw->startSegments(); Point3 pl[3]; Color c(openEdgeColor); gw->setColor(LINE_COLOR,GetUIColor(COLOR_SEL_GIZMOS)); pl[0] = Point3(0.0f,0.0f,.6f); pl[1] = Point3(0.0f,0.0f,-.5f); gw->segment(pl,1); for (int j = 0; j < 3; j++) { float angle = 0.0f; Point3 prevVec; gw->setColor(LINE_COLOR,GetUIColor(COLOR_SEL_GIZMOS)); for (int i = 0; i < (segs+1); i++) { Matrix3 tm(1); Point3 vec (0.50f,0.0f,0.0f); if (j == 0) tm.RotateZ(angle); if (j == 1) { vec = Point3(0.0f,0.5f,0.0f); tm.RotateX(angle); } if (j == 2) { vec = Point3(0.0f,0.0f,-0.5f); if (i < ((segs+2)/2)) gw->setColor(LINE_COLOR,GetUIColor(COLOR_SEL_GIZMOS)); else gw->setColor(LINE_COLOR,c); tm.RotateY(angle); } vec = vec * tm; if ( i >= 1) { pl[0] = vec; pl[1] = prevVec; gw->segment(pl,1); } prevVec = vec; angle += inc; } } gw->endSegments(); } else if (fnGetMapMode() == BOXMAP) { Point3 line[3]; gw->setColor(LINE_COLOR,GetUIColor(COLOR_SEL_GIZMOS)); gw->startSegments(); line[0] = Point3(-0.5f,-0.5f,-0.5f); line[1] = Point3(0.5f,-0.5f,-0.5f); gw->segment(line,1); line[0] = Point3(-0.5f,0.5f,-0.5f); line[1] = Point3(0.5f,0.5f,-0.5f); gw->segment(line,1); line[0] = Point3(0.5f,0.5f,-0.5f); line[1] = Point3(0.5f,-0.5f,-0.5f); gw->segment(line,1); line[0] = Point3(-0.5f,0.5f,-0.5f); line[1] = Point3(-0.5f,-0.5f,-0.5f); gw->segment(line,1); line[0] = Point3(-0.5f,-0.5f,0.5f); line[1] = Point3(0.5f,-0.5f,0.5f); gw->segment(line,1); line[0] = Point3(-0.5f,0.5f,0.5f); line[1] = Point3(0.5f,0.5f,0.5f); gw->segment(line,1); line[0] = Point3(0.5f,0.5f,0.5f); line[1] = Point3(0.5f,-0.5f,0.5f); gw->segment(line,1); line[0] = Point3(-0.5f,0.5f,0.5f); line[1] = Point3(-0.5f,-0.5f,0.5f); gw->segment(line,1); line[0] = Point3(-0.5f,-0.5f,0.5f); line[1] = Point3(-0.5f,-0.5f,-0.5f); gw->segment(line,1); line[0] = Point3(0.5f,-0.5f,0.5f); line[1] = Point3(0.5f,-0.5f,-0.5f); gw->segment(line,1); line[0] = Point3(-0.5f,0.5f,0.5f); line[1] = Point3(-0.5f,0.5f,-0.5f); gw->segment(line,1); line[0] = Point3(0.5f,0.5f,0.5f); line[1] = Point3(0.5f,0.5f,-0.5f); gw->segment(line,1); gw->endSegments(); } }
void UnwrapMod::fnGizmoReset() { theHold.Begin(); SuspendAnimate(); AnimateOff(); TimeValue t = GetCOREInterface()->GetTime(); //get our selection Box3 bounds; bounds.Init(); //get the bounding box for(int ldID = 0; ldID < mMeshTopoData.Count(); ldID++) { MeshTopoData *ld = mMeshTopoData[ldID]; Matrix3 tm = mMeshTopoData.GetNodeTM(t,ldID); for (int k = 0; k < ld->GetNumberFaces(); k++)//gfaces.Count(); k++) { if (ld->GetFaceSelected(k)) { // Grap the three points, xformed int pcount = 3; // if (gfaces[k].flags & FLAG_QUAD) pcount = 4; pcount = ld->GetFaceDegree(k);//gfaces[k]->count; Point3 temp_point[4]; for (int j=0; j<pcount; j++) { int index = ld->GetFaceGeomVert(k,j);//gfaces[k]->t[j]; bounds += ld->GetGeomVert(index) * tm;//gverts.d[index].p; } } } } Matrix3 tm(1); //if just a primary axis set the tm; Point3 center = bounds.Center(); // build the scale Point3 scale(bounds.Width().x ,bounds.Width().y , bounds.Width().z); if (scale.x == 0.0f) scale.x = 1.0f; if (scale.y == 0.0f) scale.y = 1.0f; if (scale.z == 0.0f) scale.z = 1.0f; float scl = scale.x; if (scale.y > scl) scl = scale.y; if (scale.z > scl) scl = scale.z; scale.x = scl; scale.y = scl; scale.z = scl; tm.SetRow(0,Point3(scale.x,0.0f,0.0f)); tm.SetRow(1,Point3(0.0f,scale.y,0.0f)); tm.SetRow(2,Point3(0.0f,0.0f,scale.z)); if ((fnGetMapMode() == PLANARMAP) || (fnGetMapMode() == PELTMAP)|| (fnGetMapMode() == SPHERICALMAP)) tm.SetRow(3,center); else if (fnGetMapMode() == CYLINDRICALMAP) { center.z = bounds.pmin.z; tm.SetRow(3,center); } Matrix3 ptm(1), id(1); tm = tm ; SetXFormPacket tmpck(tm,ptm); tmControl->SetValue(t,&tmpck,TRUE,CTRL_RELATIVE); ResumeAnimate(); if ((fnGetMapMode() == PLANARMAP) || (fnGetMapMode() == CYLINDRICALMAP) || (fnGetMapMode() == SPHERICALMAP) || (fnGetMapMode() == BOXMAP)) ApplyGizmo(); theHold.Accept(GetString(IDS_MAPPING_RESET)); fnGetGizmoTM(); if (ip) ip->RedrawViews(ip->GetTime()); }
void UnwrapMod::ApplyGizmo() { if ((fnGetMapMode() == PLANARMAP) || (fnGetMapMode() == PELTMAP) || (fnGetMapMode() == SPHERICALMAP) || (fnGetMapMode() == CYLINDRICALMAP)) { ApplyGizmoPrivate(); } else { theHold.Begin(); //compute the center //get our normal list for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++) { MeshTopoData *ld = mMeshTopoData[ldID]; ld->HoldFaceSel(); } for (int ldID = 0; ldID < mMeshTopoData.Count(); ldID++) { MeshTopoData *ld = mMeshTopoData[ldID]; ld->HoldFaceSel(); Tab<Point3> fnorms; fnorms.SetCount(ld->GetNumberFaces()); for (int k=0; k< fnorms.Count(); k++) fnorms[k] = Point3(0.0f,0.0f,0.0f); //get our projection normal Point3 projectionNorm(0.0f,0.0f,0.0f); //build normals for (int k = 0; k < fnorms.Count(); k++) { if (ld->GetFaceSelected(k)) { // Grap the three points, xformed int pcount = 3; // if (gfaces[k].flags & FLAG_QUAD) pcount = 4; pcount = ld->GetFaceDegree(k);//gfaces[k]->count; Point3 temp_point[4]; for (int j=0; j<pcount; j++) { int index = ld->GetFaceGeomVert(k,j);//gfaces[k]->t[j]; if (j < 4) temp_point[j] = ld->GetGeomVert(index);//gverts.d[index].p; } fnorms[k] = Normalize(temp_point[1]-temp_point[0]^temp_point[2]-temp_point[1]); } } BitArray front,back,left,right,top,bottom; front.SetSize(ld->GetNumberFaces()); front.ClearAll(); back = front; left = front; right = front; top = front; bottom = front; Tab<Point3> norms; Matrix3 gtm(1); TimeValue t = 0; if (ip) t = ip->GetTime(); if (tmControl) tmControl->GetValue(t,>m,FOREVER,CTRL_RELATIVE); norms.SetCount(6); for (int i = 0; i < 3; i++) { Point3 v = gtm.GetRow(i); norms[i*2] = Normalize(v); norms[i*2+1] = norms[i*2] * -1.0f; } for (int k=0; k< ld->GetNumberFaces(); k++) { if (ld->GetFaceSelected(k)) { int closestFace = -1; float closestAngle = -10.0f; for (int j = 0; j < 6; j++) { float dot = DotProd(norms[j],fnorms[k]); if (dot > closestAngle) { closestAngle = dot; closestFace = j; } } if (closestFace == 0) front.Set(k,TRUE); else if (closestFace == 1) back.Set(k,TRUE); else if (closestFace == 2) left.Set(k,TRUE); else if (closestFace == 3) right.Set(k,TRUE); else if (closestFace == 4) top.Set(k,TRUE); else if (closestFace == 5) bottom.Set(k,TRUE); } } gtm.IdentityMatrix(); if (tmControl) tmControl->GetValue(t,>m,FOREVER,CTRL_RELATIVE); Point3 xvec,yvec,zvec; xvec = gtm.GetRow(0); yvec = gtm.GetRow(1); zvec = gtm.GetRow(2); Point3 center = gtm.GetRow(3); for (int k = 0; k < 6; k++) { Matrix3 tm(1); if (k == 0) { tm.SetRow(0,yvec); tm.SetRow(1,zvec); tm.SetRow(2,xvec); ld->SetFaceSelection(front); } else if (k == 1) { tm.SetRow(0,yvec); tm.SetRow(1,zvec); tm.SetRow(2,(xvec*-1.0f)); ld->SetFaceSelection(back); } else if (k == 2) { tm.SetRow(0,xvec); tm.SetRow(1,zvec); tm.SetRow(2,yvec); ld->SetFaceSelection(left); } else if (k == 3) { tm.SetRow(0,xvec); tm.SetRow(1,zvec); tm.SetRow(2,(yvec *-1.0f)); ld->SetFaceSelection(right); } else if (k == 4) { tm.SetRow(0,xvec); tm.SetRow(1,yvec); tm.SetRow(2,zvec); ld->SetFaceSelection(top); } else if (k == 5) { tm.SetRow(0,xvec); tm.SetRow(1,yvec); tm.SetRow(2,(zvec*-1.0f)); ld->SetFaceSelection(bottom); } tm.SetRow(3,center); if (!fnGetNormalizeMap()) { for (int i = 0; i < 3; i++) { Point3 vec = tm.GetRow(i); vec = Normalize(vec); tm.SetRow(i,vec); } } tm = mMeshTopoData.GetNodeTM(t,ldID) * Inverse(tm); ld->ApplyMap(fnGetMapMode(), fnGetNormalizeMap(), tm, this); } ld->RestoreFaceSel(); } theHold.Accept(GetString(IDS_PW_PLANARMAP)); } }
void LuminaireObject::BuildMesh() { mesh.setNumVerts(120); mesh.setNumFaces(106); // aszabo|Feb.10.03|Compute scale of mesh. DummyObject::box has been scaled, // while our mDefBoxSize wasn't, but it was used to initialize the box. float s = box.Max().x/mDefBoxSize.Max().x; mesh.setVert(0, s*Point3(2.812824,-4.221277,0.000000)); mesh.setVert(1, s*Point3(-2.731174,-4.221277,0.000000)); mesh.setVert(2, s*Point3(-2.731174,-4.972452,0.000000)); mesh.setVert(3, s*Point3(2.812824,-4.972452,0.000000)); mesh.setVert(4, s*Point3(0.430951,-0.504076,0.000000)); mesh.setVert(5, s*Point3(0.373688,-0.540217,0.000000)); mesh.setVert(6, s*Point3(0.312884,-0.570737,0.000000)); mesh.setVert(7, s*Point3(0.248868,-0.595212,0.000000)); mesh.setVert(8, s*Point3(0.181967,-0.613220,0.000000)); mesh.setVert(9, s*Point3(0.112510,-0.624335,0.000000)); mesh.setVert(10, s*Point3(0.040825,-0.628134,0.000000)); mesh.setVert(11, s*Point3(-0.030860,-0.624335,0.000000)); mesh.setVert(12, s*Point3(-0.100318,-0.613220,0.000000)); mesh.setVert(13, s*Point3(-0.167219,-0.595213,0.000000)); mesh.setVert(14, s*Point3(-0.231235,-0.570737,0.000000)); mesh.setVert(15, s*Point3(-0.292039,-0.540217,0.000000)); mesh.setVert(16, s*Point3(-0.349302,-0.504076,0.000000)); mesh.setVert(17, s*Point3(-0.402695,-0.462737,0.000000)); mesh.setVert(18, s*Point3(-0.402695,-4.025318,0.000000)); mesh.setVert(19, s*Point3(0.484345,-4.025318,0.000000)); mesh.setVert(20, s*Point3(0.484345,-0.462738,0.000000)); mesh.setVert(21, s*Point3(0.373465,-4.025318,0.000000)); mesh.setVert(22, s*Point3(-0.291815,-4.025318,0.000000)); mesh.setVert(23, s*Point3(-0.291815,-4.221277,0.000000)); mesh.setVert(24, s*Point3(0.373465,-4.221277,0.000000)); mesh.setVert(25, s*Point3(4.419012,5.754055,0.000000)); mesh.setVert(26, s*Point3(2.964259,4.637785,0.000000)); mesh.setVert(27, s*Point3(3.340581,4.051188,0.000000)); mesh.setVert(28, s*Point3(3.598334,3.467271,0.000000)); mesh.setVert(29, s*Point3(3.784944,2.884963,0.000000)); mesh.setVert(30, s*Point3(3.947842,2.303191,0.000000)); mesh.setVert(31, s*Point3(4.134453,1.720884,0.000000)); mesh.setVert(32, s*Point3(4.392206,1.136967,0.000000)); mesh.setVert(33, s*Point3(4.768528,0.550370,0.000000)); mesh.setVert(34, s*Point3(7.900172,2.953366,0.000000)); mesh.setVert(35, s*Point3(7.430962,3.468688,0.000000)); mesh.setVert(36, s*Point3(6.933653,3.868786,0.000000)); mesh.setVert(37, s*Point3(6.419484,4.199750,0.000000)); mesh.setVert(38, s*Point3(5.899698,4.507671,0.000000)); mesh.setVert(39, s*Point3(5.385530,4.838635,0.000000)); mesh.setVert(40, s*Point3(4.888222,5.238734,0.000000)); mesh.setVert(41, s*Point3(2.805657,2.557596,0.000000)); mesh.setVert(42, s*Point3(2.664196,2.574949,0.000000)); mesh.setVert(43, s*Point3(2.533501,2.619650,0.000000)); mesh.setVert(44, s*Point3(2.416477,2.688673,0.000000)); mesh.setVert(45, s*Point3(2.316031,2.778996,0.000000)); mesh.setVert(46, s*Point3(2.235066,2.887594,0.000000)); mesh.setVert(47, s*Point3(2.176486,3.011443,0.000000)); mesh.setVert(48, s*Point3(2.143197,3.147520,0.000000)); mesh.setVert(49, s*Point3(-0.028124,0.736024,0.000000)); mesh.setVert(50, s*Point3(-0.018348,0.737188,0.000000)); mesh.setVert(51, s*Point3(-0.008572,0.738606,0.000000)); mesh.setVert(52, s*Point3(0.001220,0.740119,0.000000)); mesh.setVert(53, s*Point3(0.011041,0.741571,0.000000)); mesh.setVert(54, s*Point3(0.020906,0.742804,0.000000)); mesh.setVert(55, s*Point3(0.030829,0.743659,0.000000)); mesh.setVert(56, s*Point3(0.040825,0.743979,0.000000)); mesh.setVert(57, s*Point3(0.174745,0.730856,0.000000)); mesh.setVert(58, s*Point3(0.299803,0.693174,0.000000)); mesh.setVert(59, s*Point3(0.413514,0.633459,0.000000)); mesh.setVert(60, s*Point3(0.513398,0.554243,0.000000)); mesh.setVert(61, s*Point3(0.596971,0.458053,0.000000)); mesh.setVert(62, s*Point3(0.661752,0.347418,0.000000)); mesh.setVert(63, s*Point3(0.705257,0.224866,0.000000)); mesh.setVert(64, s*Point3(0.726882,0.057922,0.000000)); mesh.setVert(65, s*Point3(0.708744,0.215121,0.000000)); mesh.setVert(66, s*Point3(0.657090,0.359483,0.000000)); mesh.setVert(67, s*Point3(0.576055,0.486872,0.000000)); mesh.setVert(68, s*Point3(0.469775,0.593152,0.000000)); mesh.setVert(69, s*Point3(0.342386,0.674188,0.000000)); mesh.setVert(70, s*Point3(0.198024,0.725842,0.000000)); mesh.setVert(71, s*Point3(0.040825,0.743979,0.000000)); mesh.setVert(72, s*Point3(-0.116374,0.725842,0.000000)); mesh.setVert(73, s*Point3(-0.260736,0.674188,0.000000)); mesh.setVert(74, s*Point3(-0.388125,0.593152,0.000000)); mesh.setVert(75, s*Point3(-0.494405,0.486872,0.000000)); mesh.setVert(76, s*Point3(-0.575440,0.359483,0.000000)); mesh.setVert(77, s*Point3(-0.627095,0.215121,0.000000)); mesh.setVert(78, s*Point3(-0.645232,0.057922,0.000000)); mesh.setVert(79, s*Point3(-0.627095,-0.099276,0.000000)); mesh.setVert(80, s*Point3(-0.575440,-0.243638,0.000000)); mesh.setVert(81, s*Point3(-0.494405,-0.371027,0.000000)); mesh.setVert(82, s*Point3(-0.388125,-0.477308,0.000000)); mesh.setVert(83, s*Point3(-0.260736,-0.558343,0.000000)); mesh.setVert(84, s*Point3(-0.116374,-0.609997,0.000000)); mesh.setVert(85, s*Point3(0.040825,-0.628134,0.000000)); mesh.setVert(86, s*Point3(0.198024,-0.609997,0.000000)); mesh.setVert(87, s*Point3(0.342386,-0.558343,0.000000)); mesh.setVert(88, s*Point3(0.469775,-0.477308,0.000000)); mesh.setVert(89, s*Point3(0.576055,-0.371027,0.000000)); mesh.setVert(90, s*Point3(0.657090,-0.243638,0.000000)); mesh.setVert(91, s*Point3(0.708744,-0.099276,0.000000)); mesh.setVert(92, s*Point3(3.504380,3.242251,0.000000)); mesh.setVert(93, s*Point3(3.486243,3.399450,0.000000)); mesh.setVert(94, s*Point3(3.434589,3.543813,0.000000)); mesh.setVert(95, s*Point3(3.353553,3.671200,0.000000)); mesh.setVert(96, s*Point3(3.247273,3.777481,0.000000)); mesh.setVert(97, s*Point3(3.119884,3.858516,0.000000)); mesh.setVert(98, s*Point3(2.975523,3.910170,0.000000)); mesh.setVert(99, s*Point3(2.818324,3.928308,0.000000)); mesh.setVert(100, s*Point3(2.661125,3.910171,0.000000)); mesh.setVert(101, s*Point3(2.516763,3.858516,0.000000)); mesh.setVert(102, s*Point3(2.389374,3.777481,0.000000)); mesh.setVert(103, s*Point3(2.283094,3.671201,0.000000)); mesh.setVert(104, s*Point3(2.202058,3.543812,0.000000)); mesh.setVert(105, s*Point3(2.150404,3.399450,0.000000)); mesh.setVert(106, s*Point3(2.132267,3.242251,0.000000)); mesh.setVert(107, s*Point3(2.150404,3.085053,0.000000)); mesh.setVert(108, s*Point3(2.202059,2.940691,0.000000)); mesh.setVert(109, s*Point3(2.283093,2.813301,0.000000)); mesh.setVert(110, s*Point3(2.389374,2.707022,0.000000)); mesh.setVert(111, s*Point3(2.516763,2.625986,0.000000)); mesh.setVert(112, s*Point3(2.661125,2.574332,0.000000)); mesh.setVert(113, s*Point3(2.818324,2.556195,0.000000)); mesh.setVert(114, s*Point3(2.975523,2.574332,0.000000)); mesh.setVert(115, s*Point3(3.119885,2.625987,0.000000)); mesh.setVert(116, s*Point3(3.247273,2.707021,0.000000)); mesh.setVert(117, s*Point3(3.353554,2.813302,0.000000)); mesh.setVert(118, s*Point3(3.434589,2.940691,0.000000)); mesh.setVert(119, s*Point3(3.486243,3.085052,0.000000)); Face f; f.v[0] = 2; f.v[1] = 3; f.v[2] = 0; f.smGroup = 1; f.flags = 67; mesh.faces[0] = f; f.v[0] = 2; f.v[1] = 0; f.v[2] = 1; f.smGroup = 1; f.flags = 70; mesh.faces[1] = f; f.v[0] = 16; f.v[1] = 17; f.v[2] = 18; f.smGroup = 1; f.flags = 67; mesh.faces[2] = f; f.v[0] = 19; f.v[1] = 20; f.v[2] = 4; f.smGroup = 1; f.flags = 67; mesh.faces[3] = f; f.v[0] = 15; f.v[1] = 16; f.v[2] = 18; f.smGroup = 1; f.flags = 65; mesh.faces[4] = f; f.v[0] = 19; f.v[1] = 4; f.v[2] = 5; f.smGroup = 1; f.flags = 66; mesh.faces[5] = f; f.v[0] = 19; f.v[1] = 5; f.v[2] = 6; f.smGroup = 1; f.flags = 66; mesh.faces[6] = f; f.v[0] = 14; f.v[1] = 15; f.v[2] = 18; f.smGroup = 1; f.flags = 65; mesh.faces[7] = f; f.v[0] = 13; f.v[1] = 14; f.v[2] = 18; f.smGroup = 1; f.flags = 65; mesh.faces[8] = f; f.v[0] = 19; f.v[1] = 6; f.v[2] = 7; f.smGroup = 1; f.flags = 66; mesh.faces[9] = f; f.v[0] = 19; f.v[1] = 7; f.v[2] = 8; f.smGroup = 1; f.flags = 66; mesh.faces[10] = f; f.v[0] = 12; f.v[1] = 13; f.v[2] = 18; f.smGroup = 1; f.flags = 65; mesh.faces[11] = f; f.v[0] = 18; f.v[1] = 19; f.v[2] = 8; f.smGroup = 1; f.flags = 65; mesh.faces[12] = f; f.v[0] = 18; f.v[1] = 8; f.v[2] = 9; f.smGroup = 1; f.flags = 66; mesh.faces[13] = f; f.v[0] = 18; f.v[1] = 9; f.v[2] = 10; f.smGroup = 1; f.flags = 66; mesh.faces[14] = f; f.v[0] = 18; f.v[1] = 10; f.v[2] = 11; f.smGroup = 1; f.flags = 66; mesh.faces[15] = f; f.v[0] = 12; f.v[1] = 18; f.v[2] = 11; f.smGroup = 1; f.flags = 68; mesh.faces[16] = f; f.v[0] = 23; f.v[1] = 24; f.v[2] = 21; f.smGroup = 1; f.flags = 67; mesh.faces[17] = f; f.v[0] = 23; f.v[1] = 21; f.v[2] = 22; f.smGroup = 1; f.flags = 70; mesh.faces[18] = f; f.v[0] = 32; f.v[1] = 33; f.v[2] = 34; f.smGroup = 1; f.flags = 67; mesh.faces[19] = f; f.v[0] = 32; f.v[1] = 34; f.v[2] = 35; f.smGroup = 1; f.flags = 66; mesh.faces[20] = f; f.v[0] = 32; f.v[1] = 35; f.v[2] = 36; f.smGroup = 1; f.flags = 66; mesh.faces[21] = f; f.v[0] = 31; f.v[1] = 32; f.v[2] = 36; f.smGroup = 1; f.flags = 65; mesh.faces[22] = f; f.v[0] = 31; f.v[1] = 36; f.v[2] = 37; f.smGroup = 1; f.flags = 66; mesh.faces[23] = f; f.v[0] = 30; f.v[1] = 31; f.v[2] = 37; f.smGroup = 1; f.flags = 65; mesh.faces[24] = f; f.v[0] = 29; f.v[1] = 30; f.v[2] = 37; f.smGroup = 1; f.flags = 65; mesh.faces[25] = f; f.v[0] = 29; f.v[1] = 37; f.v[2] = 38; f.smGroup = 1; f.flags = 66; mesh.faces[26] = f; f.v[0] = 28; f.v[1] = 29; f.v[2] = 38; f.smGroup = 1; f.flags = 65; mesh.faces[27] = f; f.v[0] = 28; f.v[1] = 38; f.v[2] = 39; f.smGroup = 1; f.flags = 66; mesh.faces[28] = f; f.v[0] = 27; f.v[1] = 28; f.v[2] = 39; f.smGroup = 1; f.flags = 65; mesh.faces[29] = f; f.v[0] = 27; f.v[1] = 39; f.v[2] = 40; f.smGroup = 1; f.flags = 66; mesh.faces[30] = f; f.v[0] = 27; f.v[1] = 40; f.v[2] = 25; f.smGroup = 1; f.flags = 66; mesh.faces[31] = f; f.v[0] = 27; f.v[1] = 25; f.v[2] = 26; f.smGroup = 1; f.flags = 70; mesh.faces[32] = f; f.v[0] = 48; f.v[1] = 49; f.v[2] = 50; f.smGroup = 1; f.flags = 67; mesh.faces[33] = f; f.v[0] = 48; f.v[1] = 50; f.v[2] = 51; f.smGroup = 1; f.flags = 66; mesh.faces[34] = f; f.v[0] = 48; f.v[1] = 51; f.v[2] = 52; f.smGroup = 1; f.flags = 66; mesh.faces[35] = f; f.v[0] = 48; f.v[1] = 52; f.v[2] = 53; f.smGroup = 1; f.flags = 66; mesh.faces[36] = f; f.v[0] = 48; f.v[1] = 53; f.v[2] = 54; f.smGroup = 1; f.flags = 66; mesh.faces[37] = f; f.v[0] = 48; f.v[1] = 54; f.v[2] = 55; f.smGroup = 1; f.flags = 66; mesh.faces[38] = f; f.v[0] = 48; f.v[1] = 55; f.v[2] = 56; f.smGroup = 1; f.flags = 66; mesh.faces[39] = f; f.v[0] = 48; f.v[1] = 56; f.v[2] = 57; f.smGroup = 1; f.flags = 66; mesh.faces[40] = f; f.v[0] = 47; f.v[1] = 48; f.v[2] = 57; f.smGroup = 1; f.flags = 65; mesh.faces[41] = f; f.v[0] = 63; f.v[1] = 41; f.v[2] = 42; f.smGroup = 1; f.flags = 67; mesh.faces[42] = f; f.v[0] = 62; f.v[1] = 63; f.v[2] = 42; f.smGroup = 1; f.flags = 65; mesh.faces[43] = f; f.v[0] = 47; f.v[1] = 57; f.v[2] = 58; f.smGroup = 1; f.flags = 66; mesh.faces[44] = f; f.v[0] = 46; f.v[1] = 47; f.v[2] = 58; f.smGroup = 1; f.flags = 65; mesh.faces[45] = f; f.v[0] = 62; f.v[1] = 42; f.v[2] = 43; f.smGroup = 1; f.flags = 66; mesh.faces[46] = f; f.v[0] = 61; f.v[1] = 62; f.v[2] = 43; f.smGroup = 1; f.flags = 65; mesh.faces[47] = f; f.v[0] = 46; f.v[1] = 58; f.v[2] = 59; f.smGroup = 1; f.flags = 66; mesh.faces[48] = f; f.v[0] = 45; f.v[1] = 46; f.v[2] = 59; f.smGroup = 1; f.flags = 65; mesh.faces[49] = f; f.v[0] = 61; f.v[1] = 43; f.v[2] = 44; f.smGroup = 1; f.flags = 66; mesh.faces[50] = f; f.v[0] = 60; f.v[1] = 61; f.v[2] = 44; f.smGroup = 1; f.flags = 65; mesh.faces[51] = f; f.v[0] = 45; f.v[1] = 59; f.v[2] = 60; f.smGroup = 1; f.flags = 66; mesh.faces[52] = f; f.v[0] = 45; f.v[1] = 60; f.v[2] = 44; f.smGroup = 1; f.flags = 68; mesh.faces[53] = f; f.v[0] = 91; f.v[1] = 64; f.v[2] = 65; f.smGroup = 1; f.flags = 67; mesh.faces[54] = f; f.v[0] = 91; f.v[1] = 65; f.v[2] = 66; f.smGroup = 1; f.flags = 66; mesh.faces[55] = f; f.v[0] = 90; f.v[1] = 91; f.v[2] = 66; f.smGroup = 1; f.flags = 65; mesh.faces[56] = f; f.v[0] = 90; f.v[1] = 66; f.v[2] = 67; f.smGroup = 1; f.flags = 66; mesh.faces[57] = f; f.v[0] = 89; f.v[1] = 90; f.v[2] = 67; f.smGroup = 1; f.flags = 65; mesh.faces[58] = f; f.v[0] = 88; f.v[1] = 89; f.v[2] = 67; f.smGroup = 1; f.flags = 65; mesh.faces[59] = f; f.v[0] = 88; f.v[1] = 67; f.v[2] = 68; f.smGroup = 1; f.flags = 66; mesh.faces[60] = f; f.v[0] = 88; f.v[1] = 68; f.v[2] = 69; f.smGroup = 1; f.flags = 66; mesh.faces[61] = f; f.v[0] = 88; f.v[1] = 69; f.v[2] = 70; f.smGroup = 1; f.flags = 66; mesh.faces[62] = f; f.v[0] = 88; f.v[1] = 70; f.v[2] = 71; f.smGroup = 1; f.flags = 66; mesh.faces[63] = f; f.v[0] = 88; f.v[1] = 71; f.v[2] = 72; f.smGroup = 1; f.flags = 66; mesh.faces[64] = f; f.v[0] = 88; f.v[1] = 72; f.v[2] = 73; f.smGroup = 1; f.flags = 66; mesh.faces[65] = f; f.v[0] = 88; f.v[1] = 73; f.v[2] = 74; f.smGroup = 1; f.flags = 66; mesh.faces[66] = f; f.v[0] = 88; f.v[1] = 74; f.v[2] = 75; f.smGroup = 1; f.flags = 66; mesh.faces[67] = f; f.v[0] = 88; f.v[1] = 75; f.v[2] = 76; f.smGroup = 1; f.flags = 66; mesh.faces[68] = f; f.v[0] = 88; f.v[1] = 76; f.v[2] = 77; f.smGroup = 1; f.flags = 66; mesh.faces[69] = f; f.v[0] = 88; f.v[1] = 77; f.v[2] = 78; f.smGroup = 1; f.flags = 66; mesh.faces[70] = f; f.v[0] = 88; f.v[1] = 78; f.v[2] = 79; f.smGroup = 1; f.flags = 66; mesh.faces[71] = f; f.v[0] = 88; f.v[1] = 79; f.v[2] = 80; f.smGroup = 1; f.flags = 66; mesh.faces[72] = f; f.v[0] = 88; f.v[1] = 80; f.v[2] = 81; f.smGroup = 1; f.flags = 66; mesh.faces[73] = f; f.v[0] = 88; f.v[1] = 81; f.v[2] = 82; f.smGroup = 1; f.flags = 66; mesh.faces[74] = f; f.v[0] = 88; f.v[1] = 82; f.v[2] = 83; f.smGroup = 1; f.flags = 66; mesh.faces[75] = f; f.v[0] = 88; f.v[1] = 83; f.v[2] = 84; f.smGroup = 1; f.flags = 66; mesh.faces[76] = f; f.v[0] = 88; f.v[1] = 84; f.v[2] = 85; f.smGroup = 1; f.flags = 66; mesh.faces[77] = f; f.v[0] = 88; f.v[1] = 85; f.v[2] = 86; f.smGroup = 1; f.flags = 66; mesh.faces[78] = f; f.v[0] = 88; f.v[1] = 86; f.v[2] = 87; f.smGroup = 1; f.flags = 70; mesh.faces[79] = f; f.v[0] = 105; f.v[1] = 106; f.v[2] = 107; f.smGroup = 1; f.flags = 67; mesh.faces[80] = f; f.v[0] = 105; f.v[1] = 107; f.v[2] = 108; f.smGroup = 1; f.flags = 66; mesh.faces[81] = f; f.v[0] = 104; f.v[1] = 105; f.v[2] = 108; f.smGroup = 1; f.flags = 65; mesh.faces[82] = f; f.v[0] = 103; f.v[1] = 104; f.v[2] = 108; f.smGroup = 1; f.flags = 65; mesh.faces[83] = f; f.v[0] = 103; f.v[1] = 108; f.v[2] = 109; f.smGroup = 1; f.flags = 66; mesh.faces[84] = f; f.v[0] = 103; f.v[1] = 109; f.v[2] = 110; f.smGroup = 1; f.flags = 66; mesh.faces[85] = f; f.v[0] = 102; f.v[1] = 103; f.v[2] = 110; f.smGroup = 1; f.flags = 65; mesh.faces[86] = f; f.v[0] = 102; f.v[1] = 110; f.v[2] = 111; f.smGroup = 1; f.flags = 66; mesh.faces[87] = f; f.v[0] = 102; f.v[1] = 111; f.v[2] = 112; f.smGroup = 1; f.flags = 66; mesh.faces[88] = f; f.v[0] = 102; f.v[1] = 112; f.v[2] = 113; f.smGroup = 1; f.flags = 66; mesh.faces[89] = f; f.v[0] = 102; f.v[1] = 113; f.v[2] = 114; f.smGroup = 1; f.flags = 66; mesh.faces[90] = f; f.v[0] = 102; f.v[1] = 114; f.v[2] = 115; f.smGroup = 1; f.flags = 66; mesh.faces[91] = f; f.v[0] = 102; f.v[1] = 115; f.v[2] = 116; f.smGroup = 1; f.flags = 66; mesh.faces[92] = f; f.v[0] = 102; f.v[1] = 116; f.v[2] = 117; f.smGroup = 1; f.flags = 66; mesh.faces[93] = f; f.v[0] = 102; f.v[1] = 117; f.v[2] = 118; f.smGroup = 1; f.flags = 66; mesh.faces[94] = f; f.v[0] = 102; f.v[1] = 118; f.v[2] = 119; f.smGroup = 1; f.flags = 66; mesh.faces[95] = f; f.v[0] = 102; f.v[1] = 119; f.v[2] = 92; f.smGroup = 1; f.flags = 66; mesh.faces[96] = f; f.v[0] = 102; f.v[1] = 92; f.v[2] = 93; f.smGroup = 1; f.flags = 66; mesh.faces[97] = f; f.v[0] = 102; f.v[1] = 93; f.v[2] = 94; f.smGroup = 1; f.flags = 66; mesh.faces[98] = f; f.v[0] = 102; f.v[1] = 94; f.v[2] = 95; f.smGroup = 1; f.flags = 66; mesh.faces[99] = f; f.v[0] = 102; f.v[1] = 95; f.v[2] = 96; f.smGroup = 1; f.flags = 66; mesh.faces[100] = f; f.v[0] = 102; f.v[1] = 96; f.v[2] = 97; f.smGroup = 1; f.flags = 66; mesh.faces[101] = f; f.v[0] = 102; f.v[1] = 97; f.v[2] = 98; f.smGroup = 1; f.flags = 66; mesh.faces[102] = f; f.v[0] = 102; f.v[1] = 98; f.v[2] = 99; f.smGroup = 1; f.flags = 66; mesh.faces[103] = f; f.v[0] = 102; f.v[1] = 99; f.v[2] = 100; f.smGroup = 1; f.flags = 66; mesh.faces[104] = f; f.v[0] = 102; f.v[1] = 100; f.v[2] = 101; f.smGroup = 1; f.flags = 70; mesh.faces[105] = f; // This makes the mesh "float" on top of other objects mesh.InvalidateGeomCache(); mesh.EnableEdgeList(1); }
void processFile(const char* input_filename, Config& config, GCodeExport& gcode, bool firstFile) { for(unsigned int n=1; n<16;n++) gcode.setExtruderOffset(n, config.extruderOffset[n]); double t = getTime(); log("Loading %s from disk...\n", input_filename); SimpleModel* m = loadModel(input_filename, config.matrix); if (!m) { log("Failed to load model: %s\n", input_filename); return; } log("Loaded from disk in %5.3fs\n", timeElapsed(t)); log("Analyzing and optimizing model...\n"); OptimizedModel* om = new OptimizedModel(m, Point3(config.objectPosition.X, config.objectPosition.Y, -config.objectSink)); for(unsigned int v = 0; v < m->volumes.size(); v++) { log(" Face counts: %i -> %i %0.1f%%\n", (int)m->volumes[v].faces.size(), (int)om->volumes[v].faces.size(), float(om->volumes[v].faces.size()) / float(m->volumes[v].faces.size()) * 100); log(" Vertex counts: %i -> %i %0.1f%%\n", (int)m->volumes[v].faces.size() * 3, (int)om->volumes[v].points.size(), float(om->volumes[v].points.size()) / float(m->volumes[v].faces.size() * 3) * 100); } delete m; log("Optimize model %5.3fs \n", timeElapsed(t)); //om->saveDebugSTL("c:\\models\\output.stl"); log("Slicing model...\n"); vector<Slicer*> slicerList; for(unsigned int volumeIdx=0; volumeIdx < om->volumes.size(); volumeIdx++) { slicerList.push_back(new Slicer(&om->volumes[volumeIdx], config.initialLayerThickness / 2, config.layerThickness, config.fixHorrible & FIX_HORRIBLE_KEEP_NONE_CLOSED, config.fixHorrible & FIX_HORRIBLE_EXTENSIVE_STITCHING)); //slicerList[volumeIdx]->dumpSegments("C:\\models\\output.html"); } log("Sliced model in %5.3fs\n", timeElapsed(t)); SliceDataStorage storage; if (config.supportAngle > -1) { fprintf(stdout,"Generating support map...\n"); generateSupportGrid(storage.support, om, config.initialLayerThickness / 2, config.layerThickness); } storage.modelSize = om->modelSize; storage.modelMin = om->vMin; storage.modelMax = om->vMax; delete om; log("Generating layer parts...\n"); for(unsigned int volumeIdx=0; volumeIdx < slicerList.size(); volumeIdx++) { storage.volumes.push_back(SliceVolumeStorage()); createLayerParts(storage.volumes[volumeIdx], slicerList[volumeIdx], config.fixHorrible & (FIX_HORRIBLE_UNION_ALL_TYPE_A | FIX_HORRIBLE_UNION_ALL_TYPE_B)); delete slicerList[volumeIdx]; } //carveMultipleVolumes(storage.volumes); generateMultipleVolumesOverlap(storage.volumes, config.multiVolumeOverlap); log("Generated layer parts in %5.3fs\n", timeElapsed(t)); //dumpLayerparts(storage, "c:/models/output.html"); const unsigned int totalLayers = storage.volumes[0].layers.size(); for(unsigned int layerNr=0; layerNr<totalLayers; layerNr++) { for(unsigned int volumeIdx=0; volumeIdx<storage.volumes.size(); volumeIdx++) { generateInsets(&storage.volumes[volumeIdx].layers[layerNr], config.extrusionWidth, config.insetCount); } logProgress("inset",layerNr+1,totalLayers); } log("Generated inset in %5.3fs\n", timeElapsed(t)); //dumpLayerparts(storage, "c:/models/output.html"); for(unsigned int layerNr=0; layerNr<totalLayers; layerNr++) { for(unsigned int volumeIdx=0; volumeIdx<storage.volumes.size(); volumeIdx++) { generateSkins(layerNr, storage.volumes[volumeIdx], config.extrusionWidth, config.downSkinCount, config.upSkinCount, config.infillOverlap); generateSparse(layerNr, storage.volumes[volumeIdx], config.extrusionWidth, config.downSkinCount, config.upSkinCount); } logProgress("skin",layerNr+1,totalLayers); } log("Generated up/down skin in %5.3fs\n", timeElapsed(t)); generateSkirt(storage, config.skirtDistance, config.extrusionWidth, config.skirtLineCount); generateRaft(storage, config.raftMargin); log("Generated skirt and raft in %5.3fs\n", timeElapsed(t)); for(unsigned int volumeIdx=0; volumeIdx<storage.volumes.size(); volumeIdx++) { for(unsigned int layerNr=0; layerNr<totalLayers; layerNr++) { for(unsigned int partNr=0; partNr<storage.volumes[volumeIdx].layers[layerNr].parts.size(); partNr++) { if (layerNr > 0) storage.volumes[volumeIdx].layers[layerNr].parts[partNr].bridgeAngle = bridgeAngle(&storage.volumes[volumeIdx].layers[layerNr].parts[partNr], &storage.volumes[volumeIdx].layers[layerNr-1]); else storage.volumes[volumeIdx].layers[layerNr].parts[partNr].bridgeAngle = -1; } } } log("Stored volumes in %5.3fs\n", timeElapsed(t)); gcode.setRetractionSettings(config.retractionAmount, config.retractionSpeed, config.retractionAmountExtruderSwitch); if (firstFile) { gcode.addCode(config.startCode); }else{ gcode.resetExtrusionValue(); gcode.addRetraction(); gcode.setZ(maxObjectHeight + 5000); gcode.addMove(config.objectPosition, config.moveSpeed, 0); } gcode.addComment("total_layers=%d",totalLayers); log("Added general info to gcode in %5.3fs\n", timeElapsed(t)); GCodePathConfig skirtConfig(config.printSpeed, config.extrusionWidth, "SKIRT"); GCodePathConfig inset0Config(config.printSpeed, config.extrusionWidth, "WALL-OUTER"); GCodePathConfig inset1Config(config.printSpeed, config.extrusionWidth, "WALL-INNER"); GCodePathConfig fillConfig(config.infillSpeed, config.extrusionWidth, "FILL"); GCodePathConfig supportConfig(config.printSpeed, config.supportLineWidth, "SUPPORT"); if (config.raftBaseThickness > 0 && config.raftInterfaceThickness > 0) { GCodePathConfig raftBaseConfig(config.initialLayerSpeed, config.raftBaseLinewidth, "SUPPORT"); GCodePathConfig raftInterfaceConfig(config.initialLayerSpeed, config.raftInterfaceLinewidth, "SUPPORT"); { gcode.addComment("LAYER:-2"); gcode.addComment("RAFT"); GCodePlanner gcodeLayer(gcode, config.moveSpeed); gcode.setZ(config.raftBaseThickness); gcode.setExtrusion(config.raftBaseThickness, config.filamentDiameter, config.filamentFlow); gcodeLayer.addPolygonsByOptimizer(storage.raftOutline, &raftBaseConfig); Polygons raftLines; generateLineInfill(storage.raftOutline, raftLines, config.raftBaseLinewidth, config.raftLineSpacing, config.infillOverlap, 0); gcodeLayer.addPolygonsByOptimizer(raftLines, &raftBaseConfig); gcodeLayer.writeGCode(false); } { gcode.addComment("LAYER:-1"); gcode.addComment("RAFT"); GCodePlanner gcodeLayer(gcode, config.moveSpeed); gcode.setZ(config.raftBaseThickness + config.raftInterfaceThickness); gcode.setExtrusion(config.raftInterfaceThickness, config.filamentDiameter, config.filamentFlow); Polygons raftLines; generateLineInfill(storage.raftOutline, raftLines, config.raftInterfaceLinewidth, config.raftLineSpacing, config.infillOverlap, 90); gcodeLayer.addPolygonsByOptimizer(raftLines, &raftInterfaceConfig); gcodeLayer.writeGCode(false); } } int volumeIdx = 0; for(unsigned int layerNr=0; layerNr<totalLayers; layerNr++) { logProgress("export", layerNr+1, totalLayers); log("Handling layer %u out of %u \n", layerNr+1, totalLayers); GCodePlanner gcodeLayer(gcode, config.moveSpeed); gcode.addComment("LAYER:%d", layerNr); int32_t z = config.initialLayerThickness + layerNr * config.layerThickness; z += config.raftBaseThickness + config.raftInterfaceThickness; gcode.setZ(z); //if (layerNr == 0) // gcodeLayer.addPolygonsByOptimizer(storage.skirt, &skirtConfig); //log("Mark1 in %5.3fs\n", timeElapsed(t)); for(unsigned int volumeCnt = 0; volumeCnt < storage.volumes.size(); volumeCnt++) { log(" Going through volume %u out of %u \n", volumeCnt+1, storage.volumes.size()); if (volumeCnt > 0) volumeIdx = (volumeIdx + 1) % storage.volumes.size(); SliceLayer* layer = &storage.volumes[volumeIdx].layers[layerNr]; gcodeLayer.setExtruder(volumeIdx); PathOptimizer partOrderOptimizer(gcode.getPositionXY()); for(unsigned int partNr=0; partNr<layer->parts.size(); partNr++) { partOrderOptimizer.addPolygon(layer->parts[partNr].insets[0][0]); } log("partOrderOptimizer polygons %u \n", partOrderOptimizer.polygons.size()); log("partOrderOptimizer polyorder %u \n", partOrderOptimizer.polyOrder.size()); partOrderOptimizer.optimize(); log("POST OPTIM partOrderOptimizer polygons %u \n", partOrderOptimizer.polygons.size()); log("POST OPTIM partOrderOptimizer polyorder %u \n", partOrderOptimizer.polyOrder.size()); //log("POST OPTIM polyorder at 0 %u \n", partOrderOptimizer.polyOrder[0]); log("toto\n"); for(unsigned int partCounter=0; partCounter<partOrderOptimizer.polyOrder.size(); partCounter++) { //log(" Going through part %u out of %u \n", partCounter+1, partOrderOptimizer.polyOrder.size()); SliceLayerPart* part = &layer->parts[partOrderOptimizer.polyOrder[partCounter]]; log("order index %u \n", partOrderOptimizer.polyOrder[partCounter]); try { if(part->skinOutline.size()>0) { if(part->skinOutline[0].size()>0) { Point p0 = (part->skinOutline)[0][0]; log("bla %f pof\n",p0.X); } } } catch (int e) { log("An exception occurred. Exception Nr.%i \n",e); } /*gcodeLayer.setCombBoundary(&part->combBoundery); gcodeLayer.forceRetract(); if (config.insetCount > 0) { for(int insetNr=part->insets.size()-1; insetNr>-1; insetNr--) { if (insetNr == 0) gcodeLayer.addPolygonsByOptimizer(part->insets[insetNr], &inset0Config); else gcodeLayer.addPolygonsByOptimizer(part->insets[insetNr], &inset1Config); } }*/ Polygons fillPolygons; int fillAngle = 45; if (layerNr & 1) fillAngle += 90; //int sparseSteps[1] = {config.extrusionWidth}; //generateConcentricInfill(part->skinOutline, fillPolygons, sparseSteps, 1); log("Passing skinOutline of size %u to generator\n", (part->skinOutline).size()); generateLineInfill(part->skinOutline, fillPolygons, config.extrusionWidth, config.extrusionWidth, config.infillOverlap, (part->bridgeAngle > -1) ? part->bridgeAngle : fillAngle); //int sparseSteps[2] = {config.extrusionWidth*5, config.extrusionWidth * 0.8}; //generateConcentricInfill(part->sparseOutline, fillPolygons, sparseSteps, 2); //log("Mark1-2: after infillLineGen\n"); if (config.sparseInfillLineDistance > 0) { if (config.sparseInfillLineDistance > config.extrusionWidth * 4) { generateLineInfill(part->sparseOutline, fillPolygons, config.extrusionWidth, config.sparseInfillLineDistance * 2, config.infillOverlap, 45); generateLineInfill(part->sparseOutline, fillPolygons, config.extrusionWidth, config.sparseInfillLineDistance * 2, config.infillOverlap, 45 + 90); } else { generateLineInfill(part->sparseOutline, fillPolygons, config.extrusionWidth, config.sparseInfillLineDistance, config.infillOverlap, fillAngle); } } //log("Mark1-3: after before adding polygons\n"); gcodeLayer.addPolygonsByOptimizer(fillPolygons, &fillConfig); } gcodeLayer.setCombBoundary(NULL); } //log("Mark2: before supportAngle\n"); if (config.supportAngle > -1) { SupportPolyGenerator supportGenerator(storage.support, z, config.supportAngle, config.supportEverywhere > 0, true); gcodeLayer.addPolygonsByOptimizer(supportGenerator.polygons, &supportConfig); if (layerNr == 0) { SupportPolyGenerator supportGenerator2(storage.support, z, config.supportAngle, config.supportEverywhere > 0, false); gcodeLayer.addPolygonsByOptimizer(supportGenerator2.polygons, &supportConfig); } } //log("Mark2: before speedup\n"); //Finish the layer by applying speed corrections for minimal layer times and slowdown for the initial layer. if (int(layerNr) < config.initialSpeedupLayers) { int n = config.initialSpeedupLayers; int layer0Factor = config.initialLayerSpeed * 100 / config.printSpeed; gcodeLayer.setSpeedFactor((layer0Factor * (n - layerNr) + 100 * (layerNr)) / n); } gcodeLayer.forceMinimalLayerTime(config.minimalLayerTime, config.minimalFeedrate); if (layerNr == 0) gcode.setExtrusion(config.initialLayerThickness, config.filamentDiameter, config.filamentFlow); else gcode.setExtrusion(config.layerThickness, config.filamentDiameter, config.filamentFlow); //log("Mark3: before fan on\n"); if (int(layerNr) >= config.fanOnLayerNr) { int speed = config.fanSpeedMin; if (gcodeLayer.getSpeedFactor() <= 50) { speed = config.fanSpeedMax; }else{ int n = gcodeLayer.getSpeedFactor() - 50; speed = config.fanSpeedMin * n / 50 + config.fanSpeedMax * (50 - n) / 50; } gcode.addFanCommand(speed); }else{ gcode.addFanCommand(0); } //log("Finished layer in %5.3fs\n", timeElapsed(t)); gcodeLayer.writeGCode(config.coolHeadLift > 0); //log("Finished writing layer in %5.3fs\n", timeElapsed(t)); } /* support debug for(int32_t y=0; y<storage.support.gridHeight; y++) { for(int32_t x=0; x<storage.support.gridWidth; x++) { unsigned int n = x+y*storage.support.gridWidth; if (storage.support.grid[n].size() < 1) continue; int32_t z = storage.support.grid[n][0].z; gcode.addMove(Point3(x * storage.support.gridScale + storage.support.gridOffset.X, y * storage.support.gridScale + storage.support.gridOffset.Y, 0), 0); gcode.addMove(Point3(x * storage.support.gridScale + storage.support.gridOffset.X, y * storage.support.gridScale + storage.support.gridOffset.Y, z), z); gcode.addMove(Point3(x * storage.support.gridScale + storage.support.gridOffset.X, y * storage.support.gridScale + storage.support.gridOffset.Y, 0), 0); } } //*/ log("Wrote layers in %5.2fs.\n", timeElapsed(t)); gcode.tellFileSize(); gcode.addFanCommand(0); logProgress("process", 1, 1); log("Total time elapsed %5.2fs.\n", timeElapsed(t,true)); //Store the object height for when we are printing multiple objects, as we need to clear every one of them when moving to the next position. maxObjectHeight = std::max(maxObjectHeight, storage.modelSize.z); }
BOOL plDistributor::IConformBase(Matrix3& l2w, int iRepNode, plMeshCacheTab& cache, int& iCache) const { Matrix3 OTM = IOTM(iRepNode); Mesh* mesh = cache[iRepNode].fMesh; Point3 dir = l2w.VectorTransform(Point3(0.f, 0.f, 1.f)); dir = FNormalize(dir); const float kOneOverSqrt2 = 0.707107f; Point3 scalePt(kOneOverSqrt2, kOneOverSqrt2, 0.f); scalePt = l2w.VectorTransform(scalePt); float maxScaledDist = fMaxConform * scalePt.Length(); Box3 bnd = mesh->getBoundingBox() * OTM; bnd = Box3(Point3(bnd.Min().x, bnd.Min().y, -bnd.Max().z), bnd.Max()); bnd = bnd * l2w; Tab<int32_t> faces; IFindFaceSet(bnd, faces); // l2w, iRepNode, cache, &iCache, maxScaledDist, dir iCache = cache.Count(); cache.SetCount(iCache + 1); cache[iCache] = cache[iRepNode]; cache[iCache].fMesh = new Mesh(*mesh); mesh = cache[iCache].fMesh; Matrix3 v2w = OTM * l2w; Matrix3 w2v = Inverse(v2w); float maxZ = (mesh->getBoundingBox() * OTM).Max().z; BOOL retVal = true; int i; for( i = 0; i < mesh->getNumVerts(); i++ ) { Point3 pt = mesh->getVert(i) * OTM; const float kMaxConformZ = 0.5f; if( pt.z < kMaxConformZ ) { pt.z = 0; pt = pt * l2w; Point3 projPt; if( !IProjectVertex(pt, dir, maxScaledDist, faces, projPt) ) { retVal = false; break; } Point3 del = w2v.VectorTransform(projPt - pt); mesh->getVert(i) += del; } } if( !retVal ) { delete cache[iCache].fMesh; cache.SetCount(iCache); iCache = iRepNode; } return retVal; }
void processFile(const char* input_filename, ConfigSettings& config, GCodeExport& gcode, bool firstFile) { for(unsigned int n=1; n<16;n++) gcode.setExtruderOffset(n, config.extruderOffset[n].p()); gcode.setFlavor(config.gcodeFlavor); double t = getTime(); log("Loading %s from disk...\n", input_filename); SimpleModel* m = loadModel(input_filename, config.matrix); if (!m) { log("Failed to load model: %s\n", input_filename); return; } log("Loaded from disk in %5.3fs\n", timeElapsed(t)); log("Analyzing and optimizing model...\n"); OptimizedModel* om = new OptimizedModel(m, Point3(config.objectPosition.X, config.objectPosition.Y, -config.objectSink)); for(unsigned int v = 0; v < m->volumes.size(); v++) { log(" Face counts: %i -> %i %0.1f%%\n", (int)m->volumes[v].faces.size(), (int)om->volumes[v].faces.size(), float(om->volumes[v].faces.size()) / float(m->volumes[v].faces.size()) * 100); log(" Vertex counts: %i -> %i %0.1f%%\n", (int)m->volumes[v].faces.size() * 3, (int)om->volumes[v].points.size(), float(om->volumes[v].points.size()) / float(m->volumes[v].faces.size() * 3) * 100); } delete m; log("Optimize model %5.3fs \n", timeElapsed(t)); //om->saveDebugSTL("c:\\models\\output.stl"); log("Slicing model...\n"); vector<Slicer*> slicerList; for(unsigned int volumeIdx=0; volumeIdx < om->volumes.size(); volumeIdx++) { slicerList.push_back(new Slicer(&om->volumes[volumeIdx], config.initialLayerThickness / 2, config.layerThickness, config.fixHorrible & FIX_HORRIBLE_KEEP_NONE_CLOSED, config.fixHorrible & FIX_HORRIBLE_EXTENSIVE_STITCHING)); //slicerList[volumeIdx]->dumpSegments("C:\\models\\output.html"); } log("Sliced model in %5.3fs\n", timeElapsed(t)); SliceDataStorage storage; if (config.supportAngle > -1) { fprintf(stdout,"Generating support map...\n"); generateSupportGrid(storage.support, om); } storage.modelSize = om->modelSize; storage.modelMin = om->vMin; storage.modelMax = om->vMax; delete om; log("Generating layer parts...\n"); for(unsigned int volumeIdx=0; volumeIdx < slicerList.size(); volumeIdx++) { storage.volumes.push_back(SliceVolumeStorage()); createLayerParts(storage.volumes[volumeIdx], slicerList[volumeIdx], config.fixHorrible & (FIX_HORRIBLE_UNION_ALL_TYPE_A | FIX_HORRIBLE_UNION_ALL_TYPE_B)); delete slicerList[volumeIdx]; } //carveMultipleVolumes(storage.volumes); generateMultipleVolumesOverlap(storage.volumes, config.multiVolumeOverlap); log("Generated layer parts in %5.3fs\n", timeElapsed(t)); //dumpLayerparts(storage, "c:/models/output.html"); const unsigned int totalLayers = storage.volumes[0].layers.size(); for(unsigned int layerNr=0; layerNr<totalLayers; layerNr++) { for(unsigned int volumeIdx=0; volumeIdx<storage.volumes.size(); volumeIdx++) { generateInsets(&storage.volumes[volumeIdx].layers[layerNr], config.extrusionWidth, config.insetCount); } logProgress("inset",layerNr+1,totalLayers); } log("Generated inset in %5.3fs\n", timeElapsed(t)); //dumpLayerparts(storage, "c:/models/output.html"); for(unsigned int layerNr=0; layerNr<totalLayers; layerNr++) { for(unsigned int volumeIdx=0; volumeIdx<storage.volumes.size(); volumeIdx++) { generateSkins(layerNr, storage.volumes[volumeIdx], config.extrusionWidth, config.downSkinCount, config.upSkinCount, config.infillOverlap); generateSparse(layerNr, storage.volumes[volumeIdx], config.extrusionWidth, config.downSkinCount, config.upSkinCount); } logProgress("skin",layerNr+1,totalLayers); } log("Generated up/down skin in %5.3fs\n", timeElapsed(t)); generateSkirt(storage, config.skirtDistance, config.extrusionWidth, config.skirtLineCount, config.skirtMinLength); generateRaft(storage, config.raftMargin, config.supportAngle, config.supportEverywhere > 0, config.supportXYDistance); for(unsigned int volumeIdx=0; volumeIdx<storage.volumes.size(); volumeIdx++) { for(unsigned int layerNr=0; layerNr<totalLayers; layerNr++) { for(unsigned int partNr=0; partNr<storage.volumes[volumeIdx].layers[layerNr].parts.size(); partNr++) { if (layerNr > 0) storage.volumes[volumeIdx].layers[layerNr].parts[partNr].bridgeAngle = bridgeAngle(&storage.volumes[volumeIdx].layers[layerNr].parts[partNr], &storage.volumes[volumeIdx].layers[layerNr-1]); else storage.volumes[volumeIdx].layers[layerNr].parts[partNr].bridgeAngle = -1; } } } gcode.setRetractionSettings(config.retractionAmount, config.retractionSpeed, config.retractionAmountExtruderSwitch, config.minimalExtrusionBeforeRetraction); if (firstFile) { if (gcode.getFlavor() == GCODE_FLAVOR_ULTIGCODE) { gcode.addCode(";FLAVOR:UltiGCode"); gcode.addCode(";TIME:<__TIME__>"); gcode.addCode(";MATERIAL:<FILAMENT>"); } gcode.addCode(config.startCode); }else{ gcode.addFanCommand(0); gcode.resetExtrusionValue(); gcode.addRetraction(); gcode.setZ(maxObjectHeight + 5000); gcode.addMove(Point(storage.modelMin.x, storage.modelMin.y), config.moveSpeed, 0); } gcode.addComment("total_layers=%d",totalLayers); GCodePathConfig skirtConfig(config.printSpeed, config.extrusionWidth, "SKIRT"); GCodePathConfig inset0Config(config.printSpeed, config.extrusionWidth, "WALL-OUTER"); GCodePathConfig inset1Config(config.printSpeed, config.extrusionWidth, "WALL-INNER"); GCodePathConfig fillConfig(config.infillSpeed, config.extrusionWidth, "FILL"); GCodePathConfig supportConfig(config.printSpeed, config.extrusionWidth, "SUPPORT"); if (config.raftBaseThickness > 0 && config.raftInterfaceThickness > 0) { GCodePathConfig raftBaseConfig(config.initialLayerSpeed, config.raftBaseLinewidth, "SUPPORT"); GCodePathConfig raftInterfaceConfig(config.initialLayerSpeed, config.raftInterfaceLinewidth, "SUPPORT"); { gcode.addComment("LAYER:-2"); gcode.addComment("RAFT"); GCodePlanner gcodeLayer(gcode, config.moveSpeed, config.retractionMinimalDistance); gcode.setZ(config.raftBaseThickness); gcode.setExtrusion(config.raftBaseThickness, config.filamentDiameter, config.filamentFlow); gcodeLayer.addPolygonsByOptimizer(storage.raftOutline, &raftBaseConfig); Polygons raftLines; generateLineInfill(storage.raftOutline, raftLines, config.raftBaseLinewidth, config.raftLineSpacing, config.infillOverlap, 0); gcodeLayer.addPolygonsByOptimizer(raftLines, &raftBaseConfig); gcodeLayer.writeGCode(false); } { gcode.addComment("LAYER:-1"); gcode.addComment("RAFT"); GCodePlanner gcodeLayer(gcode, config.moveSpeed, config.retractionMinimalDistance); gcode.setZ(config.raftBaseThickness + config.raftInterfaceThickness); gcode.setExtrusion(config.raftInterfaceThickness, config.filamentDiameter, config.filamentFlow); Polygons raftLines; generateLineInfill(storage.raftOutline, raftLines, config.raftInterfaceLinewidth, config.raftLineSpacing, config.infillOverlap, 90); gcodeLayer.addPolygonsByOptimizer(raftLines, &raftInterfaceConfig); gcodeLayer.writeGCode(false); } } int volumeIdx = 0; for(unsigned int layerNr=0; layerNr<totalLayers; layerNr++) { logProgress("export", layerNr+1, totalLayers); GCodePlanner gcodeLayer(gcode, config.moveSpeed, config.retractionMinimalDistance); gcode.addComment("LAYER:%d", layerNr); int32_t z = config.initialLayerThickness + layerNr * config.layerThickness; z += config.raftBaseThickness + config.raftInterfaceThickness; gcode.setZ(z); if (layerNr == 0) gcodeLayer.addPolygonsByOptimizer(storage.skirt, &skirtConfig); for(unsigned int volumeCnt = 0; volumeCnt < storage.volumes.size(); volumeCnt++) { if (volumeCnt > 0) volumeIdx = (volumeIdx + 1) % storage.volumes.size(); SliceLayer* layer = &storage.volumes[volumeIdx].layers[layerNr]; gcodeLayer.setExtruder(volumeIdx); PathOptimizer partOrderOptimizer(gcode.getPositionXY()); for(unsigned int partNr=0; partNr<layer->parts.size(); partNr++) { partOrderOptimizer.addPolygon(layer->parts[partNr].insets[0][0]); } partOrderOptimizer.optimize(); for(unsigned int partCounter=0; partCounter<partOrderOptimizer.polyOrder.size(); partCounter++) { SliceLayerPart* part = &layer->parts[partOrderOptimizer.polyOrder[partCounter]]; if (config.enableCombing) gcodeLayer.setCombBoundary(&part->combBoundery); else gcodeLayer.setAlwaysRetract(true); gcodeLayer.forceRetract(); if (config.insetCount > 0) { for(int insetNr=part->insets.size()-1; insetNr>-1; insetNr--) { if (insetNr == 0) gcodeLayer.addPolygonsByOptimizer(part->insets[insetNr], &inset0Config); else gcodeLayer.addPolygonsByOptimizer(part->insets[insetNr], &inset1Config); } } Polygons fillPolygons; int fillAngle = 45; if (layerNr & 1) fillAngle += 90; //int sparseSteps[1] = {config.extrusionWidth}; //generateConcentricInfill(part->skinOutline, fillPolygons, sparseSteps, 1); generateLineInfill(part->skinOutline, fillPolygons, config.extrusionWidth, config.extrusionWidth, config.infillOverlap, (part->bridgeAngle > -1) ? part->bridgeAngle : fillAngle); //int sparseSteps[2] = {config.extrusionWidth*5, config.extrusionWidth * 0.8}; //generateConcentricInfill(part->sparseOutline, fillPolygons, sparseSteps, 2); if (config.sparseInfillLineDistance > 0) { if (config.sparseInfillLineDistance > config.extrusionWidth * 4) { generateLineInfill(part->sparseOutline, fillPolygons, config.extrusionWidth, config.sparseInfillLineDistance * 2, config.infillOverlap, 45); generateLineInfill(part->sparseOutline, fillPolygons, config.extrusionWidth, config.sparseInfillLineDistance * 2, config.infillOverlap, 45 + 90); } else { generateLineInfill(part->sparseOutline, fillPolygons, config.extrusionWidth, config.sparseInfillLineDistance, config.infillOverlap, fillAngle); } } gcodeLayer.addPolygonsByOptimizer(fillPolygons, &fillConfig); //After a layer part, make sure the nozzle is inside the comb boundary, so we do not retract on the perimeter. gcodeLayer.moveInsideCombBoundary(); } gcodeLayer.setCombBoundary(NULL); } if (config.supportAngle > -1) { if (config.supportExtruder > -1) gcodeLayer.setExtruder(config.supportExtruder); SupportPolyGenerator supportGenerator(storage.support, z, config.supportAngle, config.supportEverywhere > 0, config.supportXYDistance, config.supportZDistance); ClipperLib::Clipper supportClipper; supportClipper.AddPolygons(supportGenerator.polygons, ClipperLib::ptSubject); for(unsigned int volumeCnt = 0; volumeCnt < storage.volumes.size(); volumeCnt++) { SliceLayer* layer = &storage.volumes[volumeIdx].layers[layerNr]; Polygons polys; for(unsigned int n=0; n<layer->parts.size(); n++) for(unsigned int m=0; m<layer->parts[n].outline.size(); m++) polys.push_back(layer->parts[n].outline[m]); ClipperLib::OffsetPolygons(polys, polys, config.supportXYDistance, ClipperLib::jtSquare, 2, false); supportClipper.AddPolygons(polys, ClipperLib::ptClip); } supportClipper.Execute(ClipperLib::ctDifference, supportGenerator.polygons); Polygons supportLines; if (config.supportLineDistance > 0) { if (config.supportLineDistance > config.extrusionWidth * 4) { generateLineInfill(supportGenerator.polygons, supportLines, config.extrusionWidth, config.supportLineDistance*2, config.infillOverlap, 0); generateLineInfill(supportGenerator.polygons, supportLines, config.extrusionWidth, config.supportLineDistance*2, config.infillOverlap, 90); }else{ generateLineInfill(supportGenerator.polygons, supportLines, config.extrusionWidth, config.supportLineDistance, config.infillOverlap, (layerNr & 1) ? 0 : 90); } } gcodeLayer.addPolygonsByOptimizer(supportGenerator.polygons, &supportConfig); gcodeLayer.addPolygonsByOptimizer(supportLines, &supportConfig); } //Finish the layer by applying speed corrections for minimal layer times and slowdown for the initial layer. if (int(layerNr) < config.initialSpeedupLayers) { int n = config.initialSpeedupLayers; int layer0Factor = config.initialLayerSpeed * 100 / config.printSpeed; gcodeLayer.setExtrudeSpeedFactor((layer0Factor * (n - layerNr) + 100 * (layerNr)) / n); } gcodeLayer.forceMinimalLayerTime(config.minimalLayerTime, config.minimalFeedrate); if (layerNr == 0) gcode.setExtrusion(config.initialLayerThickness, config.filamentDiameter, config.filamentFlow); else gcode.setExtrusion(config.layerThickness, config.filamentDiameter, config.filamentFlow); if (int(layerNr) >= config.fanOnLayerNr) { int speed = config.fanSpeedMin; if (gcodeLayer.getExtrudeSpeedFactor() <= 50) { speed = config.fanSpeedMax; }else{ int n = gcodeLayer.getExtrudeSpeedFactor() - 50; speed = config.fanSpeedMin * n / 50 + config.fanSpeedMax * (50 - n) / 50; } gcode.addFanCommand(speed); }else{ gcode.addFanCommand(0); } gcodeLayer.writeGCode(config.coolHeadLift > 0); } /* support debug for(int32_t y=0; y<storage.support.gridHeight; y++) { for(int32_t x=0; x<storage.support.gridWidth; x++) { unsigned int n = x+y*storage.support.gridWidth; if (storage.support.grid[n].size() < 1) continue; int32_t z = storage.support.grid[n][0].z; gcode.addMove(Point3(x * storage.support.gridScale + storage.support.gridOffset.X, y * storage.support.gridScale + storage.support.gridOffset.Y, 0), 0); gcode.addMove(Point3(x * storage.support.gridScale + storage.support.gridOffset.X, y * storage.support.gridScale + storage.support.gridOffset.Y, z), z); gcode.addMove(Point3(x * storage.support.gridScale + storage.support.gridOffset.X, y * storage.support.gridScale + storage.support.gridOffset.Y, 0), 0); } } //*/ log("Wrote layers in %5.2fs.\n", timeElapsed(t)); gcode.tellFileSize(); gcode.addFanCommand(0); logProgress("process", 1, 1); log("Total time elapsed %5.2fs.\n", timeElapsed(t,true)); //Store the object height for when we are printing multiple objects, as we need to clear every one of them when moving to the next position. maxObjectHeight = std::max(maxObjectHeight, storage.modelSize.z); }
// Generate local to world from face info (pos, normal, etc) Matrix3 plDistributor::IGenerateTransform(int iRepNode, int iFace, const Point3& pt, const Point3& bary) const { const float kMinVecLengthSq = 1.e-6f; Matrix3 l2w(true); // First, set the scale Point3 scale; switch( fScaleLock ) { case kLockX | kLockY: scale.x = fRand.RandRangeF(fScaleLo.x, fScaleHi.x); scale.y = scale.x; scale.z = fRand.RandRangeF(fScaleLo.z, fScaleHi.z); break; case kLockX | kLockY | kLockZ: scale.x = fRand.RandRangeF(fScaleLo.x, fScaleHi.x); scale.y = scale.z = scale.x; break; default: scale.x = fRand.RandRangeF(fScaleLo.x, fScaleHi.x); scale.y = fRand.RandRangeF(fScaleLo.y, fScaleHi.y); scale.z = fRand.RandRangeF(fScaleLo.z, fScaleHi.z); break; } l2w.Scale(scale); // Next up, get the rotation. // First we'll randomly rotate about local Z float azimRot = fRand.RandMinusOneToOne() * fAzimuthRange; Matrix3 azimMat; azimMat.SetRotateZ(azimRot); l2w = l2w * azimMat; // Now align with the surface. // Get the interpolated surface normal. Point3 surfNorm = IGetSurfaceNormal(iFace, bary); Matrix3 repNodeTM = fRepNodes[iRepNode]->GetNodeTM(TimeValue(0)); Point3 alignVec = repNodeTM.GetRow(2); alignVec = alignVec * fWorldToSurfVec; alignVec = FNormalize(alignVec); Point3 norm = surfNorm + (alignVec - surfNorm) * fAlignWgt; // The norm can come out of this zero length, if the surace normal // is directly opposite the "natural" up direction and the weight // is 50% (for example). In that case, this is just a bad place // to drop this replicant. if( norm.LengthSquared() < kMinVecLengthSq ) { l2w.IdentityMatrix(); return l2w; } norm = norm.Normalize(); // Randomize through the cone around that. Point3 rndNorm = norm; Point3 rndDir = IPerpAxis(norm); Point3 rndOut = rndDir ^ norm; rndDir *= fRand.RandMinusOneToOne(); float len = sqrt(1.f - rndDir.LengthSquared()); rndOut *= len; if( fRand.RandMinusOneToOne() < 0 ) rndOut *= -1.f; Point3 rndPol = rndDir + rndOut; float polScale = fRand.RandZeroToOne() * fTanPolarRange; // Combine using the bunching factor polScale = polScale * (1.f - fPolarBunch) + polScale * polScale * fPolarBunch; rndPol *= polScale; rndNorm += rndPol; norm = rndNorm.Normalize(); // Have "up" alignment, now just generate random dir vector perpindicular to up Point3 dir = repNodeTM.GetRow(1); dir = dir * fWorldToSurfVec; Point3 out = dir ^ norm; if( out.LengthSquared() < kMinVecLengthSq ) { if( fAzimuthRange < M_PI * 0.5f ) { l2w.IdentityMatrix(); return l2w; } else { dir = IPerpAxis(norm); out = dir ^ norm; } } out = FNormalize(out); dir = norm ^ out; // If our "up" direction points into the surface, return an "up" direction // tangent to the surface. Also, make the "dir" direction point out from // the surface. So if the alignVec/fAlignWgt turns the replicant around // to penetrate the surface, it just lies down instead. // // There's an early out here, for the case where the surface normal is // exactly opposed to the destination normal. This usually means the // surface normal is directly opposite the alignVec. In that // case, we just want to bag it. if( DotProd(norm, surfNorm) < 0 ) { dir = surfNorm; dir = dir.Normalize(); out = dir ^ norm; if( out.LengthSquared() < kMinVecLengthSq ) { l2w.IdentityMatrix(); return l2w; } out = out.Normalize(); norm = out ^ dir; } Matrix3 align; align.Set(out, dir, norm, Point3(0,0,0)); l2w = l2w * align; // Lastly, set the position. Point3 pos = pt; const float offset = fRand.RandRangeF(fOffsetMin, fOffsetMax); pos += norm * offset; l2w.Translate(pos); l2w = l2w * fSurfNode->GetObjectTM(TimeValue(0)); return l2w; }
FormationBhvr::follower_matrix1, _T("formationMatrices"), TYPE_POINT3_TAB, 0, P_VARIABLE_SIZE, IDS_OBJECTS, p_end, FormationBhvr::follower_matrix2, _T("formationMatrices"), TYPE_POINT3_TAB, 0, P_VARIABLE_SIZE, IDS_OBJECTS, p_end, FormationBhvr::follower_matrix3, _T("formationMatrices"), TYPE_POINT3_TAB, 0, P_VARIABLE_SIZE, IDS_OBJECTS, p_end, FormationBhvr::follower_matrix4, _T("formationMatrices"), TYPE_POINT3_TAB, 0, P_VARIABLE_SIZE, IDS_OBJECTS, p_end, FormationBhvr::display_formation, _T("displayFormation"), TYPE_BOOL, P_RESET_DEFAULT, IDS_DISPLAYFORMATION, p_default, TRUE, p_ui, TYPE_SINGLECHEKBOX, IDC_DISPLAYFORMATION, p_end, FormationBhvr::target_color, _T("targetColor"),TYPE_RGBA, P_RESET_DEFAULT, IDS_TARGETCLR, p_default, Point3(0.0,0.0,0.5), p_ui, TYPE_COLORSWATCH, IDC_TARGETCLR, p_end, FormationBhvr::display_target, _T("displayTarget"), TYPE_BOOL, P_RESET_DEFAULT, IDS_DISPLAYTARGET, p_default, TRUE, p_ui, TYPE_SINGLECHEKBOX, IDC_TARGETDSPLY, p_end, FormationBhvr::target_scale, _T("targetScale"), TYPE_FLOAT, P_RESET_DEFAULT, IDS_TARGETSCL, p_default, 5.0, p_range, 0.001f, 100000.0f, p_ui, TYPE_SPINNER, EDITTYPE_POS_FLOAT, IDC_TARGSCALE, IDC_TARGSCALESPIN, 0.1f, p_end, FormationBhvr::force_color, _T("forceColor"),TYPE_RGBA, P_RESET_DEFAULT, IDS_FORCECLR, p_default, Point3(0.0,1.0,1.0), p_ui, TYPE_COLORSWATCH, IDC_FORCECLR,
static inline Matrix3 Transpose(const Matrix3& m) { return Matrix3(m.GetColumn3(0), m.GetColumn3(1), m.GetColumn3(2), Point3(0,0,0)); }
Mesh::Mesh() { position = Point3(0,0,0); }
u32* texture_buffer_ui; u32 texture_offset_ui; u32 textureW_ui = 0; u32 textureH_ui = 0; s32 projMatrix_id = -1; s32 modelViewMatrix_id = -1; s32 vertexPosition_id = -1; s32 vertexNormal_id = -1; s32 vertexTexcoord_id = -1; s32 textureUnit_id = -1; s32 scanline_id = -1; Point3 eye_pos = Point3(0.0f, 0.0f, -10.0f); Point3 eye_dir = Point3(0.0f, 0.0f, 1.0f); Vector3 up_vec = Vector3(0.0f,1.0f,0.0f); void *vp_ucode = NULL; rsxVertexProgram *vpo = (rsxVertexProgram*)arcade_shader_vpo; void *fp_ucode = NULL; rsxFragmentProgram *fpo = (rsxFragmentProgram*)arcade_shader_fpo; static Matrix4 P; static SMeshBuffer* quad = NULL; static SMeshBuffer* quad_ui = NULL; static Matrix4 modelMatrixBase; static Matrix4 modelMatrix; static Matrix4 modelMatrixUi;
if (mesh->numTVerts > 0) { TVFace* tvf = &mesh->tvFace[faceNum]; tverts[0] = mesh->tVerts[tvf->getTVert(0)]; tverts[1] = mesh->tVerts[tvf->getTVert(1)]; tverts[2] = mesh->tVerts[tvf->getTVert(2)]; uvw = baryCoord.x*tverts[0] + baryCoord.y*tverts[1] + baryCoord.z*tverts[2]; } return uvw; } static Point3 basic_tva[3] = { Point3(0.0,0.0,0.0),Point3(1.0,0.0,0.0),Point3(1.0,1.0,0.0)}; static Point3 basic_tvb[3] = { Point3(1.0,1.0,0.0),Point3(0.0,1.0,0.0),Point3(0.0,0.0,0.0)}; static int nextpt[3] = {1,2,0}; static int prevpt[3] = {2,0,1}; void MakeFaceUV(Face *f, UVVert *tv) { int na,nhid,i; Point3 *basetv; /* make the invisible edge be 2->0 */ nhid = 2; if (!(f->flags&EDGE_A)) nhid=0; else if (!(f->flags&EDGE_B)) nhid = 1; else if (!(f->flags&EDGE_C)) nhid = 2; na = 2-nhid; basetv = (f->v[prevpt[nhid]]<f->v[nhid]) ? basic_tva : basic_tvb;
void GameAsset::common_init() { bbox = shared_ptr<BoundingBox>(new BoundingBox(Point3(0,0,0), 1.0, 1.0, 1.0)); // unit cube }
//*************************************************************************** // Calculate ambient or diffuse color at each vertex. // Pass in TRUE as the "diffuse" parameter to calculate the diffuse color. // If FALSE is passed in, ambient color is calculated. //*************************************************************************** BOOL calcMixedVertexColors(INode* node, TimeValue t, int lightModel, ColorTab& vxColTab, EvalColProgressCallback* fn) { ObjectState ostate; BOOL deleteTri; Mesh* mesh; SContext sc; DefaultLight dl1, dl2; MtlBaseLib mtls; Matrix3 tm; sc.SetNodeAndTime(node, t); tm = sc.tmAfterWSM; TriObject* tri = GetTriObjectFromNode(node, t, deleteTri); // We will only work on GeomObjects if (!tri) { return FALSE; } // Get the mesh from the object mesh = &tri->GetMesh(); if (!mesh) { return FALSE; } // If the node doesn't have a material attached, // we create a dummy material. Mtl* mtl = node->GetMtl(); if (!mtl) { mtl = new DumMtl(Color(node->GetWireColor())); } mesh->buildRenderNormals(); vxColTab.ZeroCount(); vxColTab.Shrink(); sc.SetMesh(mesh); sc.CalcBoundObj(); // Add the material to the list mtls.AddMtl(mtl); // Setup ambient light if (lightModel == LIGHT_AMBIENT) { sc.SetAmbientLight(Color(1.0f, 1.0f, 1.0f)); } else { sc.SetAmbientLight(Color(0.0f, 0.0f, 0.0f)); } // If we're using the real lights, we need to find them first if (lightModel == LIGHT_SCENELIGHT) { AddSceneLights(&sc, &mtls); // Add default lights if there are no lights in the scene if (sc.lightTab.Count() == 0) { dl1.ls.intens = 1.0f; dl1.ls.color = Color(0.8f, 0.8f, 0.8f); dl1.ls.type = OMNI_LGT; dl1.tm = TransMatrix(1000.0f * Point3(-900.0f, -1000.0f, 1500.0f)); dl2.ls.intens = 1.0f; dl2.ls.color = Color(0.8f, 0.8f, 0.8f); dl2.ls.type = OMNI_LGT; dl2.tm = TransMatrix(-1000.0f * Point3(-900.0f, -1000.0f, 1500.0f)); sc.AddLight(new LightInfo(&dl1)); sc.AddLight(new LightInfo(&dl2)); } sc.SetAmbientLight(GetCOREInterface()->GetAmbient(t, FOREVER)); } sc.UpdateLights(); // Update material mtl->Update(t, FOREVER); int numVerts = mesh->numVerts; for (unsigned int v = 0; v < (unsigned)numVerts; v++) { if (fn) { if (fn->progress(float(v)/float(numVerts))) { if (deleteTri) { delete tri; } mtls.Empty(); if (mtl->ClassID() == DUMMTL_CLASS_ID) { delete mtl; } // What to return here is up for discussion. // 1) We are aborting so FALSE might be in order. // 2) We have calculated some colors. Let's use what we've got so far. return TRUE; } } // Create a new entry Color* vxCol = new Color; Point3 tmpCol(0.0f, 0.0f, 0.0f); int numShades = 0; BitArray faceList; faceList.SetSize(mesh->numFaces, 0); // Get vertex normal // We also pass in a BitArray that will be filled in with // to inform us to which faces this vertex belongs. // We could do this manually, but we need to do it to get // the vertex normal anyway so this is done to speed things // up a bit. Point3 vxNormal = interpVertexNormal(mesh, tm, v, faceList); Point3 viewDir = -vxNormal; Point3 viewPoint = tm*mesh->verts[v] + 5.0f*vxNormal; Point3 lightPos = viewPoint; Point3 viewTarget = tm*mesh->verts[v]; // We now have a viewpoint and a view target. // Now we just have to shade this point on the mesh in order // to get it's color. // Note: // Since materials are assigned on Face basis we need to render each // vertex as many times as it has connecting faces. // the colors collected are mixed to get the resulting // color at each vertex. for (int nf = 0; nf < faceList.GetSize(); nf++) { if (faceList[nf]) { // render vertex for this face. sc.SetViewPoint(viewPoint); sc.SetTargetPoint(viewTarget); sc.SetViewDir(viewDir); sc.SetFaceNum(nf); Face* f = &mesh->faces[nf]; sc.SetMtlNum(f->getMatID()); sc.CalcNormals(); // Setup the barycentric coordinate if (mesh->faces[nf].v[0] == v) sc.SetBaryCoord(Point3(1.0f, 0.0f, 0.0f)); else if (mesh->faces[nf].v[1] == v) sc.SetBaryCoord(Point3(0.0f, 1.0f, 0.0f)); else if (mesh->faces[nf].v[2] == v) sc.SetBaryCoord(Point3(0.0f, 0.0f, 1.0f)); // Use diffuse color instead of ambient // The only difference is that we create a special light // located at the viewpoint and we set the ambient light to black. if (lightModel == LIGHT_DIFFUSE) { dl1.ls.intens = 1.0f; dl1.ls.color = Color(0.8f, 0.8f, 0.8f); dl1.ls.type = OMNI_LGT; dl1.tm = TransMatrix(lightPos); sc.ClearLights(); sc.AddLight(new LightInfo(&dl1)); sc.UpdateLights(); } // Shade the vertex mtl->Shade(sc); tmpCol.x += sc.out.c.r; tmpCol.y += sc.out.c.g; tmpCol.z += sc.out.c.b; numShades++; } } // The color mixes. We just add the colors together and // then divide with as many colors as we added. if (numShades > 0) { tmpCol = tmpCol / (float)numShades; } vxCol->r = tmpCol.x; vxCol->g = tmpCol.y; vxCol->b = tmpCol.z; vxCol->ClampMinMax(); // Append the Color to the table. If the array needs // to be realloc'ed, allocate extra space for 100 points. vxColTab.Append(1, &vxCol, 100); } // Some objects gives us a temporary mesh that we need to delete afterwards. if (deleteTri) { delete tri; } mtls.Empty(); if (mtl->ClassID() == DUMMTL_CLASS_ID) { delete mtl; } return TRUE; }
void ForceObject::BuildMesh(TimeValue t) { ivalid = FOREVER; float l1,l2,l3,l4,r1,r2,r3,length; pblock->GetValue(PB_ICONSIZE,t,length,ivalid); int dorange,dofrange=0,norvs,norfs; pblock->GetValue(PB_RANGEON,t,dorange,ivalid); if (dorange) { dorange=73; dofrange=72; } l1=0.0f; l2=length/2.0f; l3=0.1f*length; l4=length; r1=length/6.0f; r2=r1/2.0f; r3=(r1+r2)/2.0f; float u,cosu,sinu,r1cosu,r2cosu,r3cosu,r1sinu,r2sinu,r3sinu; mesh.setNumVerts((norvs=76)+dorange); mesh.setNumFaces((norfs=84)+dofrange); int i,i2,i3,i4,i5,i6,i7; i2=NUM_SEGS; i3=2*NUM_SEGS; i4=3*NUM_SEGS; i5=4*NUM_SEGS; i6=5*NUM_SEGS; i7=6*NUM_SEGS; for (i=0; i<NUM_SEGS; i++) { u=float(i)/float(NUM_SEGS)*TWOPI; cosu=(float)cos(u); sinu=(float)sin(u); r1cosu=r1*cosu; r1sinu=r1*sinu; r2cosu=r2*cosu; r2sinu=r2*sinu; r3cosu=r3*cosu; r3sinu=r3*sinu; mesh.setVert(i, Point3(r1cosu,r1sinu,-l4)); mesh.setVert(i+i2,Point3(r1cosu,r1sinu,-l2)); mesh.setVert(i+i3,Point3(r2cosu,r2sinu,-l2)); mesh.setVert(i+i4,Point3(r2cosu,r2sinu,-l3)); mesh.setVert(i+i5,Point3(r3cosu,r3sinu,-l3)); mesh.setVert(i+i6,Point3(r3cosu,r3sinu,-l1)); } mesh.setVert(i7 ,Point3(0.0f,0.0f,-l4)); mesh.setVert(i7+1,Point3(0.0f,0.0f,-l2)); mesh.setVert(i7+2,Point3(0.0f,0.0f,-l3)); mesh.setVert(i7+3,Point3(0.0f,0.0f,-l1)); for (i=0; i<NUM_SEGS; i++) { int v,v2,v3,v4,v5,v6; if (i>(NUM_SEGS-2)) { v=0; v2=i2; v3=i3; v4=i4; v5=i5; v6=i6; } else { v=i+1; v2=v+i2; v3=v+i3; v4=v+i4; v5=v+i5; v6=v+i6; } mesh.faces[i].setEdgeVisFlags(1,0,0); mesh.faces[i].setSmGroup(0); mesh.faces[i].setVerts(i,v,i7); int ii2=i+i2; mesh.faces[ii2].setEdgeVisFlags(1,0,0); mesh.faces[ii2].setSmGroup(0); mesh.faces[ii2].setVerts(ii2,v2,i7+1); int ii3=i+i3; mesh.faces[ii3].setEdgeVisFlags(1,0,0); mesh.faces[ii3].setSmGroup(0); mesh.faces[ii3].setVerts(ii3,v3,i7+1); int ii4=i+i4; mesh.faces[ii4].setEdgeVisFlags(1,0,0); mesh.faces[ii4].setSmGroup(0); mesh.faces[ii4].setVerts(ii4,v4,i7+2); int ii5=i+i5; mesh.faces[ii5].setEdgeVisFlags(1,0,0); mesh.faces[ii5].setSmGroup(0); mesh.faces[ii5].setVerts(ii5,v5,i7+2); int ii6=i+i6; mesh.faces[ii6].setEdgeVisFlags(1,0,0); mesh.faces[ii6].setSmGroup(0); mesh.faces[ii6].setVerts(ii6,v6,i7+3); } mesh.faces[72].setEdgeVisFlags(1,0,0); mesh.faces[72].setSmGroup(2); mesh.faces[72].setVerts(0,12,6); mesh.faces[73].setEdgeVisFlags(0,0,1); mesh.faces[73].setSmGroup(2); mesh.faces[73].setVerts(6,12,18); mesh.faces[74].setEdgeVisFlags(1,0,0); mesh.faces[74].setSmGroup(2); mesh.faces[74].setVerts(3,15,9); mesh.faces[75].setEdgeVisFlags(0,0,1); mesh.faces[75].setSmGroup(2); mesh.faces[75].setVerts(9,15,21); mesh.faces[76].setEdgeVisFlags(1,0,0); mesh.faces[76].setSmGroup(2); mesh.faces[76].setVerts(24,36,30); mesh.faces[77].setEdgeVisFlags(0,0,1); mesh.faces[77].setSmGroup(2); mesh.faces[77].setVerts(30,36,42); mesh.faces[78].setEdgeVisFlags(1,0,0); mesh.faces[78].setSmGroup(2); mesh.faces[78].setVerts(27,39,33); mesh.faces[79].setEdgeVisFlags(0,0,1); mesh.faces[79].setSmGroup(2); mesh.faces[79].setVerts(33,39,45); mesh.faces[80].setEdgeVisFlags(1,0,0); mesh.faces[80].setSmGroup(2); mesh.faces[80].setVerts(48,60,54); mesh.faces[81].setEdgeVisFlags(0,0,1); mesh.faces[81].setSmGroup(2); mesh.faces[81].setVerts(54,60,66); mesh.faces[82].setEdgeVisFlags(1,0,0); mesh.faces[82].setSmGroup(2); mesh.faces[82].setVerts(51,63,57); mesh.faces[83].setEdgeVisFlags(0,0,1); mesh.faces[83].setSmGroup(2); mesh.faces[83].setVerts(57,63,69); if (dorange) { int newv; pblock->GetValue(PB_RANGEVAL,t,length,ivalid); int i; for (i=0; i<NUM_SEGS2; i++) { u = float(i)/float(NUM_SEGS2) * TWOPI; mesh.setVert(i+norvs, Point3((float)cos(u) * length, (float)sin(u) * length, 0.0f)); } newv=NUM_SEGS2+norvs; for (i=0; i<NUM_SEGS2; i++) { u = float(i)/float(NUM_SEGS2) * TWOPI; mesh.setVert(i+newv, Point3(0.0f, (float)cos(u) * length, (float)sin(u) * length)); } newv+=NUM_SEGS2; for (i=0; i<NUM_SEGS2; i++) { u = float(i)/float(NUM_SEGS2) * TWOPI; mesh.setVert(i+newv, Point3((float)cos(u) * length, 0.0f, (float)sin(u) * length)); } newv+=NUM_SEGS2; mesh.setVert(newv, Point3(0.0f, 0.0f, 0.0f)); int vi=norvs; for (i=norfs; i<norfs+dofrange; i++) { int i1 = vi+1; if ((i1-norvs)%NUM_SEGS2==0) i1 -= NUM_SEGS2; mesh.faces[i].setEdgeVisFlags(1,0,0); mesh.faces[i].setSmGroup(0); mesh.faces[i].setVerts(vi,i1,newv); vi++; } } mesh.InvalidateGeomCache(); }
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(); }
Point3 PtForceField::Force(TimeValue t,const Point3 &pos, const Point3 &vel,int index) { Point3 ApplyAt,OutForce,zdir; fValid= FOREVER; if (!tmValid.InInterval(t)) { tmValid=FOREVER; tm=node->GetObjectTM(t,&tmValid); invtm=Inverse(tm); } ApplyAt=tm.GetTrans(); fValid&=tmValid; TimeValue t1,t2; if (obj == NULL) return Point3(0.0f,0.0f,0.0f); //667105 watje xrefs can change the base object type through proxies which will cause this to be null or the user can copy a new object type over ours obj->pblock->GetValue(PB_ONTIME,t,t1,fValid); obj->pblock->GetValue(PB_OFFTIME,t,t2,fValid); if ((t>=t1)&&(t<=t2)) { float BaseF; zdir=tm.GetRow(2); obj->pblock->GetValue(PB_STRENGTH,t,BaseF,fValid); //assume N int tpf=GetTicksPerFrame(); //int tpf2=tpf*tpf; int tps=TIME_TICKSPERSEC; int tps2=tps*tps; //int FToTick=(int)((float)tps/(float)GetFrameRate()); BaseF/=(float)tps2;//convert to kg-m/t2 BaseF*=100.0f; //convert to kg-cm/t2 int UnitsVal; obj->pblock->GetValue(PB_UNITS,t,UnitsVal,fValid); if (UnitsVal!=0) BaseF*=4.4591f; //lbf is this much larger than N=kg-m/s2 TimeValue tage=t-t1; TimeValue Per1,Per2; obj->pblock->GetValue(PB_TIMEPER1,t,Per1,fValid); obj->pblock->GetValue(PB_TIMEPER2,t,Per2,fValid); float scalefactor=1.0f; int sintoggle; obj->pblock->GetValue(PB_ENABLESINES,t,sintoggle,fValid); if (sintoggle) { if (Per1>0) { float phase1,amp1; float relage1=(float)tage/(float)Per1; obj->pblock->GetValue(PB_PHASPER1,t,phase1,fValid); obj->pblock->GetValue(PB_AMP1,t,amp1,fValid); scalefactor+=0.01f*amp1*(float)sin(TWOPI*relage1+phase1); } if (Per2>0) { float phase2,amp2; float relage2=(float)tage/(float)Per2; obj->pblock->GetValue(PB_PHASPER2,t,phase2,fValid); obj->pblock->GetValue(PB_AMP2,t,amp2,fValid); scalefactor+=0.01f*amp2*(float)sin(TWOPI*relage2+phase2); } } int feedback; obj->pblock->GetValue(PB_FEEDBACKON,t,feedback,fValid); float scalefactorg=1.0f; if (feedback) { float targetspeed,loopgain; obj->pblock->GetValue(PB_TARGETVEL,t,targetspeed,fValid); targetspeed/=(float)tpf; obj->pblock->GetValue(PB_CONTROLGAIN,t,loopgain,fValid); float diffspeed=targetspeed-DotProd(vel,zdir); //scalefactorg*=diffspeed*loopgain/(float)tpf; scalefactorg*=diffspeed*loopgain/100.0f; int revon; obj->pblock->GetValue(PB_REVERSIBLE,t,revon,fValid); if ((!revon)&&(scalefactorg<0.0f)) scalefactorg=0.0f; } OutForce=zdir*BaseF*scalefactor*scalefactorg; int rangeon; obj->pblock->GetValue(PB_RANGEON,t,rangeon,fValid); if (rangeon) { float maxrange; obj->pblock->GetValue(PB_RANGEVAL,t,maxrange,fValid); float distance=Length(ApplyAt-pos); if (distance<maxrange) { if (maxrange>FLOAT_EPSILON) OutForce*=(1.0f-distance/maxrange); else OutForce=Zero; } else OutForce=Zero; } } else OutForce=Zero; return OutForce*6.25e-03f; }
void gridSnap::Snap(Object* pobj, IPoint2 *p, TimeValue t) { ViewExp *vpt = theman->GetVpt(); if ( ! vpt || ! vpt->IsAlive() ) { // why are we here DbgAssert(!_T("Invalid viewport!")); return; } DbgAssert(vpt != NULL); //local copy of the cursor position Point2 fp = Point2((float)p->x, (float)p->y); BOOL got_one= FALSE; //Get point on the consttruction plane Point3 local_cp = vpt->GetPointOnCP(*p); Point3 world_snapped; Matrix3 tmconst; vpt->GetConstructionTM( tmconst ); // aszabo|nov.01.05|#596889, #613720, #703875 // In order to allow snapping to the grid sub-divisions computed based on viewport // the zoom facto, the grid spacing is taken from the viewport. // When the grid is invisible and the zoom factor changes, the viewport returns // the grid spacing computed last time the grid was displayed. // When max starts up with hidden grids (via maxstart.max), the viewport's grid // spacing will be zero and in that case we take the grid spacing value specified // in the Grid setting UI. float gridSpacing = vpt->GetGridSize(); if (!(gridSpacing > 0.0f || gridSpacing < 0.0f)) { gridSpacing = GetCOREInterface()->GetGridSpacing(); } //Compute all the hit point candidates if( GetActive(INT_SUB)) { float gridZ = 0.f; #ifdef GAME_VER float gridSpacing = GetCOREInterface()->GetGridSpacing(); SnapInfo si; GetCOREInterface()->InitSnapInfo(&si); if(si.snapType == SNAP_25D) gridZ = GridCoord(local_cp.z,gridSpacing); Point3 intsnapped = Point3(GridCoord(local_cp.x,gridSpacing),GridCoord(local_cp.y,gridSpacing),gridZ); world_snapped = tmconst * intsnapped;//now in world space got_one = TRUE; hitmesh = new HitMesh(5); hitmesh->setVert(0,tmconst * Point3(intsnapped.x,intsnapped.y - gridSpacing,gridZ)); hitmesh->setVert(1,tmconst * Point3(intsnapped.x,intsnapped.y + gridSpacing,gridZ)); hitmesh->setVert(2,tmconst * Point3(intsnapped.x-gridSpacing,intsnapped.y,gridZ)); hitmesh->setVert(3,tmconst * Point3(intsnapped.x + gridSpacing,intsnapped.y,gridZ)); //now register a hit with the osnap manager //possibly screen for proximity to the foreground theman->RecordHit(new OsnapHit(world_snapped, this, INT_SUB, hitmesh)); #else //!GAME_VER // aszabo|sep.15.04|#596889|The gridSpacing spacing shouldn't be zero, but if it is, it can lead to infinite loops DbgAssert(gridSpacing > 0.0f || gridSpacing < 0.0f); if (gridSpacing > 0.0f || gridSpacing < 0.0f) { // Record all hits that fall in the snap preview area. // Grids are infinite, so we can't loop through their "vertexes". // Instead go through only those that are potential snap points, by starting // at the closest grid point to the mouse and extending in all directions // using "grid size" steps. Point3 intsnapped = Point3(GridCoord(local_cp.x,gridSpacing),GridCoord(local_cp.y,gridSpacing),gridZ); Point3 curIntsnapped(intsnapped); world_snapped = tmconst * intsnapped; // set the window transform to identity to guarantee a world-screen transformation. if (theman->GetVpt() && theman->GetVpt()->getGW()) { theman->GetVpt()->getGW()->setTransform(Matrix3(TRUE)); } // Find all snap points on the right side (positive x) of the intsnapped, including the intsnapped while (CheckPotentialHit(&world_snapped,0, fp)) { got_one = TRUE; RecordNewIntSubHit(world_snapped, tmconst, curIntsnapped, gridSpacing); //ktong|Jan.27.2006|#748560|Limit the number of snap points to search only visibly distinct points. // If the grid point is too far away to tell it from the next gridpoint, stop searching. // No point in enumerating snap points a user can't visibly tell apart. // Check after the first snap point (the closest) is registered to at least have one. if (TooDistant(theman, world_snapped, gridSpacing)) { break; } // Go down the vertical grid line curIntsnapped.y -= gridSpacing; FindVerticalIntSubHit(tmconst, curIntsnapped, fp, (-gridSpacing)); // Go up the vertical grid line curIntsnapped.y = intsnapped.y + gridSpacing; FindVerticalIntSubHit(tmconst, curIntsnapped, fp, gridSpacing); // Go to the right of the original vertival grid line curIntsnapped.y = intsnapped.y; curIntsnapped.x += gridSpacing; world_snapped = tmconst * curIntsnapped; } // Find all snap points on the left side (negative x) of the intsnapped curIntsnapped.y = intsnapped.y; curIntsnapped.x = intsnapped.x - gridSpacing; world_snapped = tmconst * curIntsnapped; //ktong|Jan.27.2006|#748560|Limit the number of snap points to search only visibly distinct points. while (CheckPotentialHit(&world_snapped,0, fp) && !TooDistant(theman, world_snapped, gridSpacing) ) { got_one = TRUE; RecordNewIntSubHit(world_snapped, tmconst, curIntsnapped, gridSpacing); // Go down the vertical grid line curIntsnapped.y -= gridSpacing; FindVerticalIntSubHit(tmconst, curIntsnapped, fp, (-gridSpacing)); // Go up the vertical grid line curIntsnapped.y = intsnapped.y + gridSpacing; FindVerticalIntSubHit(tmconst, curIntsnapped, fp, gridSpacing); // Go to the right of the original vertival grid line curIntsnapped.y = intsnapped.y; curIntsnapped.x -= gridSpacing; world_snapped = tmconst * curIntsnapped; } } #endif //GAME_VER } if( GetActive(EDGE_SUB) && !got_one) { BOOL snapx = FALSE; float xSnap = GridCoord(local_cp.x,gridSpacing); float ySnap = GridCoord(local_cp.y,gridSpacing); float xDist = (float)fabs(xSnap - local_cp.x); float yDist = (float)fabs(ySnap - local_cp.y); Point3 esnapped; // Which one is closer? if(xDist < yDist) { snapx = TRUE; esnapped = Point3(xSnap,local_cp.y,0.0f); } else { esnapped = Point3(local_cp.x,ySnap,0.0f); } world_snapped = tmconst * esnapped;//now in world space if (CheckPotentialHit(&world_snapped,0, fp)) { if(clipgrid(world_snapped, *vpt)) { got_one = TRUE; HitMesh* hitmesh = new HitMesh(3); if(snapx) { hitmesh->setVert(0,tmconst * Point3(esnapped.x,esnapped.y - gridSpacing,0.0f)); hitmesh->setVert(1,tmconst * Point3(esnapped.x,esnapped.y + gridSpacing,0.0f)); } else { hitmesh->setVert(0,tmconst * Point3(esnapped.x - gridSpacing, esnapped.y,0.0f)); hitmesh->setVert(1,tmconst * Point3(esnapped.x + gridSpacing, esnapped.y,0.0f)); } theman->RecordHit(new OsnapHit(world_snapped, this, EDGE_SUB, hitmesh)); } } } }
void MeshExtraData::BuildMeshExtraData( Mesh * mesh, int map_channel ) { // UVW Normals setup Tab <Point3> norv; int i_tf, i_tv; SetNumRVerts( mesh->numVerts ); SetNumFaces( mesh->numFaces ); SetNumUVerts( mesh->getNumMapVerts(map_channel) ); faceSel.SetSize( mesh->numFaces ); faceSel.ClearAll(); norv.SetCount( mesh->numVerts ); for (i_tv=0; i_tv<mesh->numVerts; i_tv++) { norv[i_tv] = Point3(0,0,0); } UVVert *mv = mesh->mapVerts( map_channel ); TVFace *tf = mesh->mapFaces( map_channel ); for ( i_tf = 0; i_tf < mesh->numFaces; i_tf++ ) { float a0, a1, a2, dp, lenA, lenB; Point3 v0 = mv[tf[i_tf].getTVert(0)]; Point3 v1 = mv[tf[i_tf].getTVert(1)]; Point3 v2 = mv[tf[i_tf].getTVert(2)]; lenA = Length( v1 - v0 ); lenB = Length( v2 - v0 ); if ( lenA == 0.0f || lenB == 0.0f ) { a0 = 0.0f; } else { dp = DotProd((v1-v0)/lenA,(v2-v0)/lenB); if (dp>1.0f) dp = 1.0f; if (dp<-1.0) dp = -1.0f; a0 = acos(dp); } lenA = Length( v0 - v1 ); lenB = Length( v2 - v1 ); if ( lenA == 0.0f || lenB == 0.0f ) { a1 = 0.0f; } else { dp = DotProd((v0-v1)/lenA,(v2-v1)/lenB); if (dp>1.0f) dp = 1.0f; if (dp<-1.0) dp = -1.0f; a1 = acos(dp); } a2 = PI - ( a0 + a1 ); Point3 vetnorm = (v1-v0)^(v2-v0); norv[mesh->faces[i_tf].getVert(0)] += vetnorm * a0; norv[mesh->faces[i_tf].getVert(1)] += vetnorm * a1; norv[mesh->faces[i_tf].getVert(2)] += vetnorm * a2; SetFace(i_tf, IPoint3( int(mesh->faces[i_tf].getVert(0)), int(mesh->faces[i_tf].getVert(1)), int(mesh->faces[i_tf].getVert(2))) ); } for (i_tv=0; i_tv<mesh->numVerts; i_tv++) { Point3 vnormal = Normalize(norv[i_tv]); SetRvert(i_tv,vnormal); } // Build Face Selections for ( i_tf=0; i_tf<mesh->numFaces; i_tf++ ) { if ( mv[ tf[i_tf].t[0] ] == mv[ tf[i_tf].t[1] ] && mv[ tf[i_tf].t[1] ] == mv[ tf[i_tf].t[2] ] ) faceSel.Clear(i_tf); else faceSel.Set(i_tf); } if ( faceSel.NumberSet() == 0 ) noneSel = TRUE; else noneSel = FALSE; }