bool XMLElement::SetMatrix3(const String& name, const Matrix3& value) { return SetAttribute(name, value.ToString()); }
int ScubaObjCreateCallBack::proc(ViewExp *vpt,int msg, int point, int flags, IPoint2 m, Matrix3& mat ) { if ( ! vpt || ! vpt->IsAlive() ) { // why are we here DbgAssert(!_T("Invalid viewport!")); return FALSE; } #ifdef _3D_CREATE DWORD snapdim = SNAP_IN_3D; #else DWORD snapdim = SNAP_IN_PLANE; #endif #ifdef _OSNAP if (msg == MOUSE_FREEMOVE) { vpt->SnapPreview(m,m,NULL, snapdim); } #endif if (msg==MOUSE_POINT||msg==MOUSE_MOVE) { switch(point) { case 0: ob->suspendSnap = TRUE; sp0 = m; p[0] = vpt->SnapPoint(m,m,NULL,snapdim); mat.SetTrans(p[0]); // Set Node's transform ob->pblock->SetValue(PB_RADIUS,0,0.01f); ob->pblock->SetValue(PB_HEIGHT,0,0.01f); ob->increate=TRUE; break; case 1: mat.IdentityMatrix(); //mat.PreRotateZ(HALFPI); sp1 = m; p[1] = vpt->SnapPoint(m,m,NULL,snapdim); if (ob->dlgCreateMeth) { // radius r = Length(p[1]-p[0]); mat.SetTrans(p[0]); } else { // diameter Point3 center = (p[0]+p[1])/float(2); r = Length(center-p[0]); mat.SetTrans(center); // Modify Node's transform } ob->pblock->SetValue(PB_RADIUS,0,r); ob->pblock->SetValue(PB_HEIGHT,0,2.0f*r); ob->pmapParam->Invalidate(); if (flags&MOUSE_CTRL) { float ang = (float)atan2(p[1].y-p[0].y,p[1].x-p[0].x); mat.PreRotateZ(ob->ip->SnapAngle(ang)); } if (msg==MOUSE_POINT) { if (Length(m-sp0)<3 || Length(p[1]-p[0])<0.1f) { ob->increate=FALSE; return CREATE_ABORT; } h=2.0f*r; } break; case 2: { #ifdef _OSNAP float h1 = vpt->SnapLength(vpt->GetCPDisp(p[1],Point3(0,0,1),sp1,m,TRUE)); #else float h1 = vpt->SnapLength(vpt->GetCPDisp(p[1],Point3(0,0,1),sp1,m)); #endif float hmin=2.0f*r; h1+=(h1<0.0f?-hmin:hmin); ob->pblock->SetValue(PB_HEIGHT,0,h1); ob->pmapParam->Invalidate(); if (msg==MOUSE_POINT) { ob->suspendSnap = FALSE; ob->increate=FALSE; return (Length(m-sp0)<3)?CREATE_ABORT:CREATE_STOP; } } break; } } else if (msg == MOUSE_ABORT) { ob->increate=FALSE; return CREATE_ABORT; } return TRUE; }
/* ==================== Save ==================== */ int G3DSExport::Save(const Str& path) { ////////////////////////////////////////////////////////////////////////// // merge the skin ////////////////////////////////////////////////////////////////////////// struct PRIMITIVE { Str name; Str texture; std::vector<INode*>bones; std::vector<Matrix3>transforms; std::vector<VPTNIW>vertexes; std::vector<unsigned int>indexes; Box3 box; int AddBone(const INode* node, const Matrix3& mat) { std::vector<INode*>::iterator it = std::find(bones.begin(), bones.end(), node); if(it==bones.end()) { bones.push_back((INode*)node); transforms.push_back(mat); return bones.size()-1; } return it - bones.begin(); } }; // get all of the textures std::vector<Str>textures; for(std::vector<SKIN>::iterator it = mSkins.begin(); it != mSkins.end(); ++it) { if(std::find(textures.begin(),textures.end(),it->texture) == textures.end()) { textures.push_back(it->texture); } } // merge all of the skin to the primitive by the textures std::vector<PRIMITIVE>primitives; for(int i = 0; i < textures.size(); i++) { PRIMITIVE primitive; primitive.texture = textures[i]; for(int j = 0; j < mSkins.size(); j++) { SKIN& skin = mSkins[j]; if(skin.texture != primitive.texture) continue; if(primitive.name.size() == 0) primitive.name = skin.name; // get the start vertex int start_vertex = primitive.vertexes.size(); // set all of the vertexes for(int k = 0; k < skin.vertexes.size(); k++ ) { VPTNIS& v1 = skin.vertexes[k]; VPTNIW v2; v2.position[0] = v1.pos.x; v2.position[1] = v1.pos.y; v2.position[2] = v1.pos.z; v2.texcoord[0] = v1.uv.x; v2.texcoord[1] = v1.uv.y; v2.normal[0] = v1.normal.x; v2.normal[1] = v1.normal.y; v2.normal[2] = v1.normal.z; v2.index[0] = primitive.AddBone(skin.bones[skin.weights[v1.index].index[2]], skin.transforms[skin.weights[v1.index].index[2]]); v2.index[1] = primitive.AddBone(skin.bones[skin.weights[v1.index].index[1]], skin.transforms[skin.weights[v1.index].index[1]]); v2.index[2] = primitive.AddBone(skin.bones[skin.weights[v1.index].index[0]], skin.transforms[skin.weights[v1.index].index[0]]); v2.weight[0] = skin.weights[v1.index].weight[2]; v2.weight[1] = skin.weights[v1.index].weight[1]; v2.weight[2] = skin.weights[v1.index].weight[0]; primitive.vertexes.push_back(v2); } // set the index for(int k = 0; k < skin.triangles.size(); k++) { TRIANGLE& tri = skin.triangles[k]; primitive.indexes.push_back(start_vertex + tri.index1[0]); primitive.indexes.push_back(start_vertex + tri.index1[1]); primitive.indexes.push_back(start_vertex + tri.index1[2]); } // set the box primitive.box += skin.box; } // there is a 75 bone limit for each skinned object. if(primitive.bones.size()>75) { G3DAssert("There are more %d bones in the primitive and the texture is %s.",primitive.bones.size(), textures[i].c_str()); return 1; } // add the primitive to the table primitives.push_back(primitive); } ////////////////////////////////////////////////////////////////////////// // save the skin ////////////////////////////////////////////////////////////////////////// // open the skin file to save it FILE *output = fopen(path.c_str(), "wb"); if(output==NULL) { G3DAssert("Can`t open the file : %s.", path.c_str()); return 1; } // begin to write the skin fprintf( output, "<skeletal_mesh>\n" ); // write all of the primitives for(int i = 0; i < primitives.size(); i++) { PRIMITIVE& primitive = primitives[i]; // begin to write the primitive fprintf(output, "<primitive type=\"PT_TRIANGLES\">\n"); // wirte all of the vertexes fprintf(output, "<vertex format=\"VT_3F VT_2F VT_3F VT_3F VT_3F\">\n"); for(int j = 0; j < primitive.vertexes.size(); j++) { VPTNIW& v = primitive.vertexes[j]; fprintf(output, "%f %f %f %f %f %f %f %f %f %f %f %f %f %f\n", v.position[0], v.position[1], v.position[2], v.texcoord[0], v.texcoord[1], v.normal[0], v.normal[1], v.normal[2], v.index[0], v.index[1], v.index[2], v.weight[0], v.weight[1], v.weight[2] ); } fprintf(output, "</vertex>\n"); // wirte all of the indexes fprintf(output, "<index stride=\"%d\">\n", primitive.vertexes.size()<=0xFFFF ? sizeof(unsigned short) : sizeof(unsigned int)); for(int j = 0; j < primitive.indexes.size(); j++ ) fprintf(output, "%u ", primitive.indexes[j]); fprintf( output, "</index>\n" ); // wirte the bones for(int j = 0; j < primitive.bones.size(); j++) { Str node_name = primitive.bones[j]->GetName(); Matrix3 m = primitive.transforms[j]; Point3 r0 = m.GetRow(0); Point3 r1 = m.GetRow(1); Point3 r2 = m.GetRow(2); Point3 r3 = m.GetRow(3); fprintf(output, "<bone name=\"%s\">\n", node_name.c_str()); fprintf(output, "%f %f %f %f\n", r0.x, r0.y, r0.z, 0.0); fprintf(output, "%f %f %f %f\n", r1.x, r1.y, r1.z, 0.0); fprintf(output, "%f %f %f %f\n", r2.x, r2.y, r2.z, 0.0); fprintf(output, "%f %f %f %f\n", r3.x, r3.y, r3.z, 1.0); fprintf(output, "</bone>\n" ); } // write the shader info fprintf(output, "<shader name=\"shader/skeletal.xml\">\n"); fprintf(output, "<constant name=\"gVP\" type = \"CT_MATRIX\">\n 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 \n </constant>\n"); fprintf(output, "<constant name=\"gWorld\" type = \"CT_MATRIX\">\n 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 \n </constant>\n"); fprintf(output, "<constant name=\"gBones\" type = \"CT_VECTOR_ARRAY\">\n 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 \n </constant>\n"); fprintf(output, "<constant name=\"gBaseTex\" type = \"CT_TEXTURE\">\n %s\n </constant>\n", primitive.texture.c_str()); fprintf(output, "</shader>\n" ); // write the primitive box fprintf( output, "<bounding_box>\n %f %f %f %f %f %f\n </bounding_box>\n", primitive.box.Min().x, primitive.box.Min().y, primitive.box.Min().z, primitive.box.Max().x, primitive.box.Max().y, primitive.box.Max().z ); // end to write the primitive fprintf(output, "</primitive>\n"); } // end to wirte the skin fprintf(output, "</skeletal_mesh>\n"); // close file fclose(output); return 1; }
void BombMod::ModifyObject( TimeValue t, ModContext &mc, ObjectState *os, INode *node) { BombObject *bobj = GetWSMObject(t); if (bobj && nodeRef && (bobj->ClassID() == Class_ID(BOMB_OBJECT_CLASS_ID,0))) { assert(os->obj->IsSubClassOf(triObjectClassID)); TriObject *triOb = (TriObject *)os->obj; Interval valid = FOREVER; if (os->GetTM()) { Matrix3 tm = *(os->GetTM()); for (int i=0; i<triOb->GetMesh().getNumVerts(); i++) { triOb->GetMesh().verts[i] = triOb->GetMesh().verts[i] * tm; } os->obj->UpdateValidity(GEOM_CHAN_NUM,os->tmValid()); os->SetTM(NULL,FOREVER); } if (waitPostLoad) { valid.SetInstant(t); triOb->UpdateValidity(GEOM_CHAN_NUM,valid); triOb->UpdateValidity(TOPO_CHAN_NUM,valid); return; } Matrix3 tm; TimeValue det = bobj->GetDetonation(t,valid); float strength = bobj->GetStrength(t,valid) * STRENGTH_CONSTANT; float grav = bobj->GetGravity(t,valid); float chaos = bobj->GetChaos(t,valid); float chaosBase = (float(1)-chaos/2); float rotSpeed = bobj->GetSpin(t,valid) * TWOPI/float(TIME_TICKSPERSEC); int minClust = bobj->GetMinFrag(t,valid), maxClust = bobj->GetMaxFrag(t,valid); if (minClust<1) minClust = 1; if (maxClust<1) maxClust = 1; int clustVar = maxClust-minClust+1; float falloff = bobj->GetFalloff(t,valid); int useFalloff = bobj->GetFalloffOn(t,valid); int seed = bobj->GetSeed(t,valid); //tm = nodeRef->GetNodeTM(t,&valid); tm = nodeRef->GetObjectTM(t,&valid); if (t<det) { valid.Set(TIME_NegInfinity,det-1); triOb->UpdateValidity(GEOM_CHAN_NUM,valid); triOb->UpdateValidity(TOPO_CHAN_NUM,valid); triOb->PointsWereChanged(); return; } float dt = float(t-det); valid.SetInstant(t); int n0=0,n1=1,n2=2,nv; Point3 v, p0, p1, g(0.0f,0.0f,grav*GRAVITY_CONSTANT); Tab<Point3> l_newVerts ; Face *f = triOb->GetMesh().faces; float dot; Mesh &mesh = triOb->GetMesh(); // First, segment the faces. srand((unsigned int)seed); Tab<DWORD> vclust; Tab<DWORD> vmap; Tab<Point3> nverts; vclust.SetCount(mesh.getNumVerts()); vmap.SetCount(mesh.getNumVerts()); int numClust = 0; if (minClust==1 && maxClust==1) { // Simple case... 1 face per cluster nv = triOb->GetMesh().getNumFaces() * 3; l_newVerts.SetCount(nv); vclust.SetCount(nv); for (int i=0; i<nv; i++) { vclust[i] = i/3; } for (int i=0,j=0; i<mesh.getNumFaces(); i++) { l_newVerts[j] = mesh.verts[mesh.faces[i].v[0]]; l_newVerts[j+1] = mesh.verts[mesh.faces[i].v[1]]; l_newVerts[j+2] = mesh.verts[mesh.faces[i].v[2]]; mesh.faces[i].v[0] = j; mesh.faces[i].v[1] = j+1; mesh.faces[i].v[2] = j+2; j += 3; } numClust = triOb->GetMesh().getNumFaces(); } else { // More complex case... clusters are randomely sized for (int i=0; i<mesh.getNumVerts(); i++) { vclust[i] = UNDEFINED; vmap[i] = i; } int cnum = 0; for (int i=0; i<mesh.getNumFaces(); ) { int csize = int(Rand1()*float(clustVar)+float(minClust)); if (i+csize>mesh.getNumFaces()) { csize = mesh.getNumFaces()-i; } // Make sure each face in the cluster has at least 2 verts in common with another face. BOOL verified = FALSE; while (!verified) { verified = TRUE; if (csize<2) break; for (int j=0; j<csize; j++) { BOOL match = FALSE; for (int k=0; k<csize; k++) { if (k==j) continue; int common = 0; for (int i1=0; i1<3; i1++) { for (int i2=0; i2<3; i2++) { if (mesh.faces[i+j].v[i1]== mesh.faces[i+k].v[i2]) common++; } } if (common>=2) { match = TRUE; break; } } if (!match) { csize = j; verified = FALSE; // Have to check again break; } } } if (csize==0) csize = 1; // Clear the vert map for (int j=0; j<mesh.getNumVerts(); j++) vmap[j] = UNDEFINED; // Go through the cluster and remap verts. for (int j=0;j<csize; j++) { for (int k=0; k<3; k++) { if (vclust[mesh.faces[i+j].v[k]]==UNDEFINED) { vclust[mesh.faces[i+j].v[k]] = cnum; } else if (vclust[mesh.faces[i+j].v[k]]!=(DWORD)cnum) { if (vmap[mesh.faces[i+j].v[k]]==UNDEFINED) { vclust.Append(1,(DWORD*)&cnum,50); nverts.Append(1,&mesh.verts[mesh.faces[i+j].v[k]],50); mesh.faces[i+j].v[k] = vmap[mesh.faces[i+j].v[k]] = mesh.getNumVerts()+nverts.Count()-1; } else { mesh.faces[i+j].v[k] = vmap[mesh.faces[i+j].v[k]]; } } } } cnum++; numClust++; i += csize; } nv = mesh.getNumVerts() + nverts.Count(); l_newVerts.SetCount(nv); int i; for (i=0; i<mesh.getNumVerts(); i++) l_newVerts[i] = mesh.verts[i]; for ( ; i<mesh.getNumVerts()+nverts.Count(); i++) l_newVerts[i] = nverts[i-mesh.getNumVerts()]; } // Find the center of all clusters Tab<Point3> clustCent; Tab<DWORD> clustCounts; clustCent.SetCount(numClust); clustCounts.SetCount(numClust); for (int i=0; i<numClust; i++) { clustCent[i] = Point3(0,0,0); clustCounts[i] = 0; } for (int i=0; i<nv; i++) { if (vclust[i]==UNDEFINED) continue; clustCent[vclust[i]] += l_newVerts[i]; clustCounts[vclust[i]]++; } // Build transformations for all clusters Tab<Matrix3> mats; mats.SetCount(numClust); srand((unsigned int)seed); for (int i=0; i<numClust; i++) { if (clustCounts[i]) clustCent[i] /= float(clustCounts[i]); v = clustCent[i] - tm.GetTrans(); float u = 1.0f; if (useFalloff) { u = 1.0f - Length(v)/falloff; if (u<0.0f) u = 0.0f; } dot = DotProd(v,v); if (dot==0.0f) dot = 0.000001f; v = v / dot * strength * u; v.x *= chaosBase + chaos * Rand1(); v.y *= chaosBase + chaos * Rand1(); v.z *= chaosBase + chaos * Rand1(); p1 = v*dt + 0.5f*g*dt*dt; // projectile motion // Set rotation Point3 axis; axis.x = -1.0f + 2.0f*Rand1(); axis.y = -1.0f + 2.0f*Rand1(); axis.z = -1.0f + 2.0f*Rand1(); axis = Normalize(axis); float angle = dt*rotSpeed*(chaosBase + chaos * Rand1())*u; Quat q = QFromAngAxis(angle, axis); q.MakeMatrix(mats[i]); mats[i].PreTranslate(-clustCent[i]); mats[i].Translate(clustCent[i]+p1); } // Now transform the clusters for (int i=0; i<nv; i++) { if (vclust[i]==UNDEFINED) continue; l_newVerts[i] = l_newVerts[i] * mats[vclust[i]]; } triOb->UpdateValidity(GEOM_CHAN_NUM,valid); triOb->UpdateValidity(TOPO_CHAN_NUM,valid); triOb->PointsWereChanged(); triOb->GetMesh().setNumVerts(nv,FALSE,TRUE); //assign the new vertices to the mesh for ( int i=0; i < nv; i++) triOb->GetMesh().setVert( i,l_newVerts[i]); } }
void CopyMatrixToArray ( Matrix3& myMatrix, GLfloat a[9] ) { for(int i=0;i<9;++i) a[i] = myMatrix.getData(i); }
inline void right_cauchy_green_deformation_tensor( const Matrix3<T>& F, Matrix3<T>& C) { C = F.transpose() * F; }
Mesh* TriObject::GetRenderMesh(TimeValue t, INode *inode, View &view, BOOL& needDelete) { if (mDisableDisplacement || !(view.flags & RENDER_MESH_DISPLACEMENT_MAP)) { needDelete = FALSE; return &mesh; } // need to check the mesh and see if any face has a matId the requires displacment mapping BOOL needDisp = FALSE; // Get the material Mtl* pMtl = inode ? inode->GetMtl() : NULL; if (pMtl) { // does the mesh as a whole need it if (pMtl->Requirements(mesh.mtlIndex)&MTLREQ_DISPLACEMAP) needDisp = TRUE; if (!needDisp) { for (int f = 0; f < mesh.numFaces; f++) { if (pMtl->Requirements(mesh.getFaceMtlIndex(f))&MTLREQ_DISPLACEMAP) { needDisp = TRUE; break; } } } if (needDisp) { if (mesh.getNumFaces() == 0) return &mesh; Matrix3 otm; if (inode) otm = inode->GetObjectTM(t); else otm.IdentityMatrix(); GetGTessFunction(); if (mSubDivideDisplacement && psGTessFunc) { // if we have a material that does displacement mapping and if we can do it Mesh *pMesh = new Mesh(); needDelete = TRUE; (*psGTessFunc)((void *)&mesh, MAX_MESH, &otm, pMesh, NULL, &mDispApprox, &view, pMtl, FALSE, mSplitMesh); needDelete = TRUE; return pMesh; } else { Mesh *pMesh = new Mesh(mesh); needDelete = TRUE; BOOL hasUVs = pMesh->tvFace != NULL; pMesh->buildRenderNormals(); // now displace the verts BitArray vertsSet; vertsSet.SetSize(pMesh->numVerts); for (int f = 0; f < pMesh->numFaces; f++) { Face *pFace = &pMesh->faces[f]; TVFace *pTVFace = &pMesh->tvFace[f]; int matid = pFace->getMatID(); for (int v = 0; v < 3; v++) { int vidx = pFace->v[v]; if (vertsSet[vidx]) continue; // displace only once Point3 norm = pMesh->getNormal(vidx); norm.Normalize(); Point3& vert = pMesh->getVert(vidx); UVVert uvvert; if (hasUVs) uvvert = pMesh->getTVert(pTVFace->t[v]); else { uvvert.x = 0.0; uvvert.y = 0.0; } pMesh->buildBoundingBox(); Box3 bbox = pMesh->getBoundingBox(); float dispScale = Length(bbox.pmax - bbox.pmin)/10.0f; float disp = GetDisp(pMtl, pMesh, f, pFace->getMatID(), vert, uvvert.x, uvvert.y, otm) * dispScale; vert += (norm * disp); vertsSet.Set(vidx); } } return pMesh; } } } needDelete = FALSE; return &mesh; }
ErrorCode EvalSet::evaluate_reverse(EvalFcn eval, JacobianFcn jacob, InsideFcn inside_f, const double *posn, const double *verts, const int nverts, const int ndim, const double iter_tol, const double inside_tol, double *work, double *params, int *inside) { // TODO: should differentiate between epsilons used for // Newton Raphson iteration, and epsilons used for curved boundary geometry errors // right now, fix the tolerance used for NR const double error_tol_sqr = iter_tol*iter_tol; CartVect *cvparams = reinterpret_cast<CartVect*>(params); const CartVect *cvposn = reinterpret_cast<const CartVect*>(posn); // initialize to center of element *cvparams = CartVect(-.4); CartVect new_pos; // evaluate that first guess to get a new position ErrorCode rval = (*eval)(cvparams->array(), verts, ndim, 3, // hardwire to num_tuples to 3 since the field is coords work, new_pos.array()); if (MB_SUCCESS != rval) return rval; // residual is diff between old and new pos; need to minimize that CartVect res = new_pos - *cvposn; Matrix3 J; int dum, *tmp_inside = (inside ? inside : &dum); int iters=0; // while |res| larger than tol while (res % res > error_tol_sqr) { if(++iters>10) { // if we haven't converged but we're outside, that's defined as success *tmp_inside = (*inside_f)(params, ndim, inside_tol); if (!(*tmp_inside)) return MB_SUCCESS; else return MB_FAILURE; } // get jacobian at current params rval = (*jacob)(cvparams->array(), verts, nverts, ndim, work, J[0]); double det = J.determinant(); if (det < std::numeric_limits<double>::epsilon()) { *tmp_inside = (*inside_f)(params, ndim, inside_tol); if (!(*tmp_inside)) return MB_SUCCESS; else return MB_INDEX_OUT_OF_RANGE; } // new params tries to eliminate residual *cvparams -= J.inverse(1.0/det) * res; // get the new forward-evaluated position, and its difference from the target pt rval = (*eval)(params, verts, ndim, 3, // hardwire to num_tuples to 3 since the field is coords work, new_pos.array()); if (MB_SUCCESS != rval) return rval; res = new_pos - *cvposn; } if (inside) *inside = (*inside_f)(params, ndim, inside_tol); return MB_SUCCESS; }// Map::evaluate_reverse()
bool PFOperatorSimpleSpeed::Proceed(IObject* pCont, PreciseTimeValue timeStart, PreciseTimeValue& timeEnd, Object* pSystem, INode* pNode, INode* actionNode, IPFIntegrator* integrator) { // acquire all necessary channels, create additional if needed IParticleChannelNewR* chNew = GetParticleChannelNewRInterface(pCont); if(chNew == NULL) return false; IParticleChannelPTVR* chTime = GetParticleChannelTimeRInterface(pCont); if(chTime == NULL) return false; IParticleChannelAmountR* chAmount = GetParticleChannelAmountRInterface(pCont); if(chAmount == NULL) return false; // the position channel may not be present. For some option configurations it is okay IParticleChannelPoint3R* chPos = GetParticleChannelPositionRInterface(pCont); int iDir = _pblock()->GetInt(kSimpleSpeed_direction, timeStart); if ((chPos == NULL) && ((iDir == kSS_Icon_Center_Out) || (iDir == kSS_Icon_Arrow_Out))) return false; IChannelContainer* chCont; chCont = GetChannelContainerInterface(pCont); if (chCont == NULL) return false; // the channel of interest bool initSpeed = false; IParticleChannelPoint3W* chSpeed = (IParticleChannelPoint3W*)chCont->EnsureInterface(PARTICLECHANNELSPEEDW_INTERFACE, ParticleChannelPoint3_Class_ID, true, PARTICLECHANNELSPEEDR_INTERFACE, PARTICLECHANNELSPEEDW_INTERFACE, true, actionNode, (Object*)NULL, &initSpeed); IParticleChannelPoint3R* chSpeedR = GetParticleChannelSpeedRInterface(pCont); if ((chSpeed == NULL) || (chSpeedR == NULL)) return false; // there are no new particles if (chNew->IsAllOld()) return true; float fUPFScale = 1.0f/TIME_TICKSPERSEC; // conversion units per seconds to units per tick Point3 pt3SpeedVec; RandGenerator* prg = randLinker().GetRandGenerator(pCont); int iQuant = chAmount->Count(); bool wasIgnoringEmitterTMChange = IsIgnoringEmitterTMChange(); if (!wasIgnoringEmitterTMChange) SetIgnoreEmitterTMChange(); for(int i = 0; i < iQuant; i++) { if(chNew->IsNew(i)) { // apply only to new particles TimeValue tv = chTime->GetValue(i).TimeValue(); Matrix3 nodeTM = pNode->GetObjectTM(tv); float fSpeedParam = fUPFScale * GetPFFloat(pblock(), kSimpleSpeed_speed, tv); // change speed in user selected direction switch(iDir) { case kSS_Along_Icon_Arrow: { // icon arrow appears to be in the negative z direction pt3SpeedVec = -Normalize(nodeTM.GetRow(2)); } break; case kSS_Icon_Center_Out: { Point3 pt3IconCenter = nodeTM.GetTrans(); Point3 pt3PartPos = chPos->GetValue(i); pt3SpeedVec = Normalize(pt3PartPos - pt3IconCenter); } break; case kSS_Icon_Arrow_Out: { Point3 pt3PartPos = chPos->GetValue(i); Point3 pt3ArrowVec = nodeTM.GetRow(2); Point3 pt3Tmp = CrossProd(pt3PartPos - nodeTM.GetTrans(), pt3ArrowVec); pt3SpeedVec = Normalize(CrossProd(pt3ArrowVec, pt3Tmp)); } break; case kSS_Rand_3D: { pt3SpeedVec = RandSphereSurface(prg); } break; case kSS_Rand_Horiz: { float fAng = TWOPI * prg->Rand01(); // establish x, y coordinates of random angle, z component zero float x = cos(fAng); float y = sin(fAng); float z = 0.0f; pt3SpeedVec = Point3(x, y, z); } break; case kSS_Inherit_Prev: { if (initSpeed) pt3SpeedVec = Point3::Origin; else pt3SpeedVec = Normalize(chSpeedR->GetValue(i)); } break; } // account for reverse check box int iRev = _pblock()->GetInt(kSimpleSpeed_reverse, 0); float fDirMult = iRev > 0 ? -1.f : 1.f; // calculate variation float fVar = fUPFScale * GetPFFloat(pblock(), kSimpleSpeed_variation, tv); if(fVar > 0.f) fSpeedParam = fSpeedParam + fVar * prg->Rand11(); pt3SpeedVec = fDirMult * fSpeedParam * pt3SpeedVec; // calculate divergence float fDiv = GetPFFloat(pblock(), kSimpleSpeed_divergence, tv); pt3SpeedVec = DivergeVectorRandom(pt3SpeedVec, prg, fDiv); chSpeed->SetValue(i, pt3SpeedVec); } } if (!wasIgnoringEmitterTMChange) ClearIgnoreEmitterTMChange(); return true; }
bool AlembicCamera::Save(double time, bool bLastFrame) { TimeValue ticks = GetTimeValueFromFrame(time); Object *obj = mMaxNode->EvalWorldState(ticks).obj; if (mNumSamples == 0) { bForever = CheckIfObjIsValidForever(obj, ticks); } else { bool bNewForever = CheckIfObjIsValidForever(obj, ticks); if (bForever && bNewForever != bForever) { ESS_LOG_INFO("bForever has changed"); } } bForever = false; SaveMetaData(mMaxNode, this); // Set the xform sample Matrix3 wm = mMaxNode->GetObjTMAfterWSM(ticks); if (mJob) { Point3 worldMaxPoint = wm.GetTrans(); Abc::V3f alembicWorldPoint = ConvertMaxPointToAlembicPoint(worldMaxPoint); mJob->GetArchiveBBox().extendBy(alembicWorldPoint); } // check if the camera is animated if (mNumSamples > 0) { if (bForever) { return true; } } // Return a pointer to a Camera given an INode or return false if the node // cannot be converted to a Camera CameraObject *cam = NULL; if (obj->CanConvertToType(Class_ID(SIMPLE_CAM_CLASS_ID, 0))) { cam = reinterpret_cast<CameraObject *>( obj->ConvertToType(ticks, Class_ID(SIMPLE_CAM_CLASS_ID, 0))); } else if (obj->CanConvertToType(Class_ID(LOOKAT_CAM_CLASS_ID, 0))) { cam = reinterpret_cast<CameraObject *>( obj->ConvertToType(ticks, Class_ID(LOOKAT_CAM_CLASS_ID, 0))); } else { return false; } CameraState cs; Interval valid = FOREVER; cam->EvalCameraState(ticks, valid, &cs); float tDist = cam->GetTDist(ticks); float ratio = GetCOREInterface()->GetRendImageAspect(); float aperatureWidth = GetCOREInterface()->GetRendApertureWidth(); // this may differ from the // imported value // unfortunately float focalLength = (float)((aperatureWidth / 2.0) / tan(cs.fov / 2.0)); // alembic wants this one in millimeters aperatureWidth /= 10.0f; // convert to centimeters IMultiPassCameraEffect *pCameraEffect = cam->GetIMultiPassCameraEffect(); Interval interval = FOREVER; BOOL bUseTargetDistance = FALSE; const int TARGET_DISTANCE = 0; pCameraEffect->GetParamBlockByID(0)->GetValue(TARGET_DISTANCE, ticks, bUseTargetDistance, interval); float fFocalDepth = 0.0f; const int FOCAL_DEPTH = 1; pCameraEffect->GetParamBlockByID(0)->GetValue(FOCAL_DEPTH, ticks, fFocalDepth, interval); // store the camera data mCameraSample.setNearClippingPlane(cs.hither); mCameraSample.setFarClippingPlane(cs.yon); // mCameraSample.setLensSqueezeRatio(ratio); // should set to 1.0 according the article "Maya to Softimage: Camera // Interoperability" mCameraSample.setLensSqueezeRatio(1.0); mCameraSample.setFocalLength(focalLength); mCameraSample.setHorizontalAperture(aperatureWidth); mCameraSample.setVerticalAperture(aperatureWidth / ratio); if (bUseTargetDistance) { mCameraSample.setFocusDistance(tDist); } else { mCameraSample.setFocusDistance(fFocalDepth); } // save the samples mCameraSchema.set(mCameraSample); mNumSamples++; // Note that the CamObject should only be deleted if the pointer to it is not // equal to the object pointer that called ConvertToType() if (cam != NULL && obj != cam) { delete cam; cam = NULL; return false; } return true; }
void perfMatrix3() { printf("Matrix3:\n"); uint64 raw, opt, overhead, naive; // 0.5 million operations int n = 1024 * 1024 / 2; // Use two copies to avoid nice cache behavior Matrix3 A = Matrix3::fromAxisAngle(Vector3(1, 2, 1), 1.2f); Matrix3 B = Matrix3::fromAxisAngle(Vector3(0, 1, -1), .2f); Matrix3 C = Matrix3::zero(); Matrix3 D = Matrix3::fromAxisAngle(Vector3(1, 2, 1), 1.2f); Matrix3 E = Matrix3::fromAxisAngle(Vector3(0, 1, -1), .2f); Matrix3 F = Matrix3::zero(); int i; System::beginCycleCount(overhead); for (i = n - 1; i >= 0; --i) { } System::endCycleCount(overhead); System::beginCycleCount(raw); for (i = n - 1; i >= 0; --i) { C = A.transpose(); F = D.transpose(); C = B.transpose(); } System::endCycleCount(raw); System::beginCycleCount(opt); for (i = n - 1; i >= 0; --i) { Matrix3::transpose(A, C); Matrix3::transpose(D, F); Matrix3::transpose(B, C); } System::endCycleCount(opt); raw -= overhead; opt -= overhead; printf(" Transpose Performance outcome\n"); printf(" transpose(A, C): %g cycles/mul %s\n\n", (double)opt / (3*n), (opt/(3*n) < 400) ? " ok " : "FAIL"); printf(" C = A.transpose(): %g cycles/mul %s\n", (double)raw / (3*n), (raw/(3*n) < 150) ? " ok " : "FAIL"); printf("\n"); ///////////////////////////////// printf(" Matrix-Matrix Multiplication\n"); System::beginCycleCount(raw); for (i = n - 1; i >= 0; --i) { C = A * B; F = D * E; C = A * D; } System::endCycleCount(raw); System::beginCycleCount(opt); for (i = n - 1; i >= 0; --i) { Matrix3::mul(A, B, C); Matrix3::mul(D, E, F); Matrix3::mul(A, D, C); } System::endCycleCount(opt); { float A[3][3], B[3][3], C[3][3], D[3][3], E[3][3], F[3][3]; System::beginCycleCount(naive); for (i = n - 1; i >= 0; --i) { mul(A, B, C); mul(D, E, F); mul(A, D, C); } System::endCycleCount(naive); } raw -= overhead; opt -= overhead; printf(" mul(A, B, C) %g cycles/mul %s\n", (double)opt / (3*n), (opt/(3*n) < 250) ? " ok " : "FAIL"); printf(" C = A * B %g cycles/mul %s\n", (double)raw / (3*n), (raw/(3*n) < 500) ? " ok " : "FAIL"); printf(" naive for-loops %g cycles/mul\n", (double)naive / (3*n)); printf("\n\n"); }
// Determine is the node has negative scaling. // This is used for mirrored objects for example. They have a negative scale factor // so when calculating the normal we should take the vertices counter clockwise. // If we don't compensate for this the objects will be 'inverted'. BOOL ElMaxPlugin::TMNegParity(Matrix3 &m) { return (DotProd(CrossProd(m.GetRow(0), m.GetRow(1)), m.GetRow(2)) < 0.0f) ? 1 : 0; }
void SGP_MaxInterface::GetTracks( int nNodeCount, INode** nodes, Track** tracks ) { StartProgressInfo(_M("Get node track...")); TimeValue nStartTick = GetStartTick(); TimeValue nEndTick = GetEndTick(); int nTickPerFrame = GetTickPerFrame(); int nFrameCount = 0; for( TimeValue t = nStartTick; t <= nEndTick; t += nTickPerFrame ) nFrameCount++; for( int i = 0; i < nNodeCount; i++ ) { tracks[i]->vectorVisible.resize( nFrameCount ); tracks[i]->vectorTrans.resize( nFrameCount ); tracks[i]->vectorRot.resize( nFrameCount ); tracks[i]->vectorScale.resize( nFrameCount ); Matrix3 matrix = nodes[i]->GetObjTMAfterWSM ( 0 ); bool bMirror = DotProd ( CrossProd ( matrix.GetRow ( 0 ), matrix.GetRow ( 1 ) ), matrix.GetRow ( 2 ) ) < 0.0 ? true : false; tracks[i]->bMirror = bMirror; } TimeValue t = nStartTick; for( int nFrameId = 0; nFrameId < nFrameCount; nFrameId++, t += nTickPerFrame ) { SetProgressInfo( 100.0f*nFrameId/nFrameCount ); for( int nNodeId = 0; nNodeId < nNodeCount; nNodeId++ ) { INode* pNode = nodes[nNodeId]; Track* pTrack = tracks[nNodeId]; Matrix3 tm = pNode->GetNodeTM(t); // The coordinate system of 3DMax9 is Right-X Up-Z Screenin-Y // But coordinate system of SGP Engine is like D3D Right-X Up-Y Screenin-Z // Node Transform Matrix should be swaped. /* If your matrix looks like this: { rx, ry, rz, 0 } { ux, uy, uz, 0 } { lx, ly, lz, 0 } { px, py, pz, 1 } To change it from left to right or right to left, flip it like this: { rx, rz, ry, 0 } { lx, lz, ly, 0 } { ux, uz, uy, 0 } { px, pz, py, 1 } */ Point3 Row0 = tm.GetRow(0); Point3 Row1 = tm.GetRow(1); Point3 Row2 = tm.GetRow(2); Point3 Row3 = tm.GetRow(3); sgp::swapVariables( Row0.y, Row0.z ); sgp::swapVariables( Row1.x, Row2.x ); sgp::swapVariables( Row1.y, Row2.z ); sgp::swapVariables( Row1.z, Row2.y ); sgp::swapVariables( Row3.y, Row3.z ); tm.SetRow(0, Row0); tm.SetRow(1, Row1); tm.SetRow(2, Row2); tm.SetRow(3, Row3); Point3 trans; Quat quat; Point3 scale; { // calculate the translation component Point3 p; p = tm.GetTrans(); trans.x = p.x; trans.y = p.y; trans.z = p.z; scale.x = tm.GetRow(0).Length(); scale.y = tm.GetRow(1).Length(); scale.z = tm.GetRow(2).Length(); tm.NoScale(); // calculate the rotation component Quat q(tm); if( tracks[nNodeId]->bMirror ) { float m[4][3]; memcpy( m, &tm, sizeof(float)*4*3 ); m[0][0] *= -1; m[1][0] *= -1; m[2][0] *= -1; Matrix3 mm(m); Quat q0(mm); q = q0; } quat.x = q.x; quat.y = q.y; quat.z = q.z; quat.w = q.w; } pTrack->vectorTrans.getReference(nFrameId) = trans; pTrack->vectorRot.getReference(nFrameId) = quat; pTrack->vectorScale.getReference(nFrameId) = scale; float fv = pNode->GetVisibility( t ); if( fv == 0 ) pTrack->vectorVisible.getReference(nFrameId) = false; else pTrack->vectorVisible.getReference(nFrameId) = true; } } StopProgressInfo(); }
void NCLDebug::DrawMatrix(const Matrix3& mtx, const Vector3& position) { DrawHairLine(position, position + mtx.GetCol(0), Vector4(1.0f, 0.0f, 0.0f, 1.0f)); DrawHairLine(position, position + mtx.GetCol(1), Vector4(0.0f, 1.0f, 0.0f, 1.0f)); DrawHairLine(position, position + mtx.GetCol(2), Vector4(0.0f, 0.0f, 1.0f, 1.0f)); }
void GridMapEditor::_duplicate_paste() { if (!selection.active) return; int idx = options->get_popup()->get_item_index(MENU_OPTION_DUPLICATE_SELECTS); bool reselect = options->get_popup()->is_item_checked( idx ); List< __Item > items; Matrix3 rot; rot.set_orthogonal_index(selection.duplicate_rot); for(int i=selection.begin.x;i<=selection.end.x;i++) { for(int j=selection.begin.y;j<=selection.end.y;j++) { for(int k=selection.begin.z;k<=selection.end.z;k++) { int itm = node->get_cell_item(i,j,k); if (itm==GridMap::INVALID_CELL_ITEM) continue; int orientation = node->get_cell_item_orientation(i,j,k); __Item item; Vector3 rel=Vector3(i,j,k)-selection.begin; rel = rot.xform(rel); Matrix3 orm; orm.set_orthogonal_index(orientation); orm = rot * orm; item.pos=selection.begin+rel; item.item=itm; item.rot=orm.get_orthogonal_index(); items.push_back(item); } } } Vector3 ofs=selection.current-selection.click; if (items.size()) { undo_redo->create_action("GridMap Duplicate Selection"); for(List< __Item >::Element *E=items.front();E;E=E->next()) { __Item &it=E->get(); Vector3 pos = it.pos+ofs; undo_redo->add_do_method(node,"set_cell_item",pos.x,pos.y,pos.z,it.item,it.rot); undo_redo->add_undo_method(node,"set_cell_item",pos.x,pos.y,pos.z,node->get_cell_item(pos.x,pos.y,pos.z),node->get_cell_item_orientation(pos.x,pos.y,pos.z)); } undo_redo->commit_action(); } if (reselect) { selection.begin+=ofs; selection.end+=ofs; selection.click=selection.begin; selection.current=selection.end; _validate_selection(); } }
String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_assign_left) { String code; switch(p_node->type) { case SL::Node::TYPE_PROGRAM: { SL::ProgramNode *pnode=(SL::ProgramNode*)p_node; code+=dump_node_code(pnode->body,p_level); } break; case SL::Node::TYPE_FUNCTION: { } break; case SL::Node::TYPE_BLOCK: { SL::BlockNode *bnode=(SL::BlockNode*)p_node; //variables for(Map<StringName,SL::DataType>::Element *E=bnode->variables.front();E;E=E->next()) { code+=_mktab(p_level)+_typestr(E->value())+" "+replace_string(E->key())+";"ENDL; } for(int i=0;i<bnode->statements.size();i++) { code+=_mktab(p_level)+dump_node_code(bnode->statements[i],p_level)+";"ENDL; } } break; case SL::Node::TYPE_VARIABLE: { SL::VariableNode *vnode=(SL::VariableNode*)p_node; if (type==ShaderLanguage::SHADER_MATERIAL_VERTEX) { if (vnode->name==vname_vertex && p_assign_left) { vertex_code_writes_vertex=true; } } if (type==ShaderLanguage::SHADER_MATERIAL_FRAGMENT) { if (vnode->name==vname_discard) { uses_discard=true; } if (vnode->name==vname_screen_uv) { uses_screen_uv=true; } if (vnode->name==vname_diffuse_alpha && p_assign_left) { uses_alpha=true; } if (vnode->name==vname_color_interp) { flags->use_color_interp=true; } if (vnode->name==vname_uv_interp) { flags->use_uv_interp=true; } if (vnode->name==vname_uv2_interp) { flags->use_uv2_interp=true; } if (vnode->name==vname_var1_interp) { flags->use_var1_interp=true; } if (vnode->name==vname_var2_interp) { flags->use_var2_interp=true; } if (vnode->name==vname_tangent_interp || vnode->name==vname_binormal_interp) { flags->use_tangent_interp=true; } } if (type==ShaderLanguage::SHADER_MATERIAL_LIGHT) { if (vnode->name==vname_light) { uses_light=true; } } code=replace_string(vnode->name); } break; case SL::Node::TYPE_CONSTANT: { SL::ConstantNode *cnode=(SL::ConstantNode*)p_node; switch(cnode->datatype) { case SL::TYPE_BOOL: code=cnode->value.operator bool()?"true":"false"; break; case SL::TYPE_FLOAT: code=_mknum(cnode->value); break; //force zeros, so GLSL doesn't confuse with integer. case SL::TYPE_VEC2: { Vector2 v = cnode->value; code="vec2("+_mknum(v.x)+", "+_mknum(v.y)+")"; } break; case SL::TYPE_VEC3: { Vector3 v = cnode->value; code="vec3("+_mknum(v.x)+", "+_mknum(v.y)+", "+_mknum(v.z)+")"; } break; case SL::TYPE_VEC4: { Plane v = cnode->value; code="vec4("+_mknum(v.normal.x)+", "+_mknum(v.normal.y)+", "+_mknum(v.normal.z)+", "+_mknum(v.d)+")"; } break; case SL::TYPE_MAT3: { Matrix3 x = cnode->value; code="mat3( vec3("+_mknum(x.get_axis(0).x)+", "+_mknum(x.get_axis(0).y)+", "+_mknum(x.get_axis(0).z)+"), vec3("+_mknum(x.get_axis(1).x)+", "+_mknum(x.get_axis(1).y)+", "+_mknum(x.get_axis(1).z)+"), vec3("+_mknum(x.get_axis(2).x)+", "+_mknum(x.get_axis(2).y)+", "+_mknum(x.get_axis(2).z)+"))"; } break; case SL::TYPE_MAT4: { Transform x = cnode->value; code="mat4( vec4("+_mknum(x.basis.get_axis(0).x)+", "+_mknum(x.basis.get_axis(0).y)+", "+_mknum(x.basis.get_axis(0).z)+",0.0), vec4("+_mknum(x.basis.get_axis(1).x)+", "+_mknum(x.basis.get_axis(1).y)+", "+_mknum(x.basis.get_axis(1).z)+",0.0), vec4("+_mknum(x.basis.get_axis(2).x)+", "+_mknum(x.basis.get_axis(2).y)+", "+_mknum(x.basis.get_axis(2).z)+",0.0), vec4("+_mknum(x.origin.x)+", "+_mknum(x.origin.y)+", "+_mknum(x.origin.z)+",1.0))"; } break; default: code="<error: "+Variant::get_type_name(cnode->value.get_type())+" ("+itos(cnode->datatype)+">"; } } break; case SL::Node::TYPE_OPERATOR: { SL::OperatorNode *onode=(SL::OperatorNode*)p_node; switch(onode->op) { case SL::OP_ASSIGN_MUL: { if (onode->arguments[0]->get_datatype()==SL::TYPE_VEC3 && onode->arguments[1]->get_datatype()==SL::TYPE_MAT4) { String mul_l=dump_node_code(onode->arguments[0],p_level,true); String mul_r=dump_node_code(onode->arguments[1],p_level); code=mul_l+"=(vec4("+mul_l+",1.0)*("+mul_r+")).xyz"; break; } else if (onode->arguments[0]->get_datatype()==SL::TYPE_MAT4 && onode->arguments[1]->get_datatype()==SL::TYPE_VEC3) { String mul_l=dump_node_code(onode->arguments[0],p_level,true); String mul_r=dump_node_code(onode->arguments[1],p_level); code=mul_l+"=(("+mul_l+")*vec4("+mul_r+",1.0)).xyz"; break; } else if (onode->arguments[0]->get_datatype()==SL::TYPE_VEC2 && onode->arguments[1]->get_datatype()==SL::TYPE_MAT4) { String mul_l=dump_node_code(onode->arguments[0],p_level,true); String mul_r=dump_node_code(onode->arguments[1],p_level); code=mul_l+"=(vec4("+mul_l+",1.0,1.0)*("+mul_r+")).xy"; break; } else if (onode->arguments[0]->get_datatype()==SL::TYPE_MAT4 && onode->arguments[1]->get_datatype()==SL::TYPE_VEC2) { String mul_l=dump_node_code(onode->arguments[0],p_level,true); String mul_r=dump_node_code(onode->arguments[1],p_level); code=mul_l+"=(("+mul_l+")*vec4("+mul_r+",1.0,1.0)).xy"; break; } else if (onode->arguments[0]->get_datatype()==SL::TYPE_VEC2 && onode->arguments[1]->get_datatype()==SL::TYPE_MAT3) { String mul_l=dump_node_code(onode->arguments[0],p_level,true); String mul_r=dump_node_code(onode->arguments[1],p_level); code=mul_l+"=(("+mul_l+")*vec3("+mul_r+",1.0)).xy"; break; } }; case SL::OP_ASSIGN: case SL::OP_ASSIGN_ADD: case SL::OP_ASSIGN_SUB: case SL::OP_ASSIGN_DIV: code="("+dump_node_code(onode->arguments[0],p_level,true)+_opstr(onode->op)+dump_node_code(onode->arguments[1],p_level)+")"; break; case SL::OP_MUL: if (onode->arguments[0]->get_datatype()==SL::TYPE_MAT4 && onode->arguments[1]->get_datatype()==SL::TYPE_VEC3) { code="("+dump_node_code(onode->arguments[0],p_level)+"*vec4("+dump_node_code(onode->arguments[1],p_level)+",1.0)).xyz"; break; } else if (onode->arguments[0]->get_datatype()==SL::TYPE_VEC3 && onode->arguments[1]->get_datatype()==SL::TYPE_MAT4) { code="(vec4("+dump_node_code(onode->arguments[0],p_level)+",1.0)*"+dump_node_code(onode->arguments[1],p_level)+").xyz"; break; } else if (onode->arguments[0]->get_datatype()==SL::TYPE_MAT4 && onode->arguments[1]->get_datatype()==SL::TYPE_VEC2) { code="("+dump_node_code(onode->arguments[0],p_level)+"*vec4("+dump_node_code(onode->arguments[1],p_level)+",1.0,1.0)).xyz"; break; } else if (onode->arguments[0]->get_datatype()==SL::TYPE_VEC2 && onode->arguments[1]->get_datatype()==SL::TYPE_MAT4) { code="(vec4("+dump_node_code(onode->arguments[0],p_level)+",1.0,1.0)*"+dump_node_code(onode->arguments[1],p_level)+").xyz"; break; } else if (onode->arguments[0]->get_datatype()==SL::TYPE_MAT3 && onode->arguments[1]->get_datatype()==SL::TYPE_VEC2) { code="("+dump_node_code(onode->arguments[0],p_level)+"*vec3("+dump_node_code(onode->arguments[1],p_level)+",1.0)).xy"; break; } else if (onode->arguments[0]->get_datatype()==SL::TYPE_VEC2 && onode->arguments[1]->get_datatype()==SL::TYPE_MAT3) { code="(vec3("+dump_node_code(onode->arguments[0],p_level)+",1.0)*"+dump_node_code(onode->arguments[1],p_level)+").xy"; break; } case SL::OP_ADD: case SL::OP_SUB: case SL::OP_DIV: case SL::OP_CMP_EQ: case SL::OP_CMP_NEQ: case SL::OP_CMP_LEQ: case SL::OP_CMP_GEQ: case SL::OP_CMP_LESS: case SL::OP_CMP_GREATER: case SL::OP_CMP_OR: case SL::OP_CMP_AND: //handle binary code="("+dump_node_code(onode->arguments[0],p_level)+_opstr(onode->op)+dump_node_code(onode->arguments[1],p_level)+")"; break; case SL::OP_NEG: case SL::OP_NOT: //handle unary code=_opstr(onode->op)+dump_node_code(onode->arguments[0],p_level); break; case SL::OP_CONSTRUCT: case SL::OP_CALL: { String callfunc=dump_node_code(onode->arguments[0],p_level); code=callfunc+"("; /*if (callfunc=="mat4") { //fix constructor for mat4 for(int i=1;i<onode->arguments.size();i++) { if (i>1) code+=", "; //transform code+="vec4( "+dump_node_code(onode->arguments[i],p_level)+(i==4?",1.0)":",0.0)"); } } else*/ if (callfunc=="tex") { code="texture2D( "+dump_node_code(onode->arguments[1],p_level)+","+dump_node_code(onode->arguments[2],p_level)+")"; break; } else if (callfunc=="texcube") { code="(textureCube( "+dump_node_code(onode->arguments[1],p_level)+",("+dump_node_code(onode->arguments[2],p_level)+")).xyz"; break; } else if (callfunc=="texscreen") { //create the call to sample the screen, and clamp it uses_texscreen=true; code="(texture2D( texscreen_tex, min(("+dump_node_code(onode->arguments[1],p_level)+").xy*texscreen_screen_mult,texscreen_screen_mult))).rgb"; //code="(texture2D( screen_texture, ("+dump_node_code(onode->arguments[1],p_level)+").xy).rgb"; break; } else if (callfunc=="texpos") { //create the call to sample the screen, and clamp it uses_texpos=true; code="get_texpos("+dump_node_code(onode->arguments[1],p_level)+""; // code="get_texpos(gl_ProjectionMatrixInverse * texture2D( depth_texture, clamp(("+dump_node_code(onode->arguments[1],p_level)+").xy,vec2(0.0),vec2(1.0))*gl_LightSource[5].specular.zw+gl_LightSource[5].specular.xy)"; //code="(texture2D( screen_texture, ("+dump_node_code(onode->arguments[1],p_level)+").xy).rgb"; break; } else { for(int i=1;i<onode->arguments.size();i++) { if (i>1) code+=", "; //transform code+=dump_node_code(onode->arguments[i],p_level); } } code+=")"; break; } break; default: {} } } break; case SL::Node::TYPE_CONTROL_FLOW: { SL::ControlFlowNode *cfnode=(SL::ControlFlowNode*)p_node; if (cfnode->flow_op==SL::FLOW_OP_IF) { code+="if ("+dump_node_code(cfnode->statements[0],p_level)+") {"ENDL; code+=dump_node_code(cfnode->statements[1],p_level+1); if (cfnode->statements.size()==3) { code+="} else {"ENDL; code+=dump_node_code(cfnode->statements[2],p_level+1); } code+="}"ENDL; } else if (cfnode->flow_op==SL::FLOW_OP_RETURN) { if (cfnode->statements.size()) { code="return "+dump_node_code(cfnode->statements[0],p_level); } else { code="return"; } } } break; case SL::Node::TYPE_MEMBER: { SL::MemberNode *mnode=(SL::MemberNode*)p_node; String m; if (mnode->basetype==SL::TYPE_MAT4) { if (mnode->name=="x") m="[0]"; else if (mnode->name=="y") m="[1]"; else if (mnode->name=="z") m="[2]"; else if (mnode->name=="w") m="[3]"; } else if (mnode->basetype==SL::TYPE_MAT3) { if (mnode->name=="x") m="[0]"; else if (mnode->name=="y") m="[1]"; else if (mnode->name=="z") m="[2]"; } else { m="."+mnode->name; } code=dump_node_code(mnode->owner,p_level)+m; } break; } return code; }
void GridMapEditor::_menu_option(int p_option) { switch(p_option) { case MENU_OPTION_CONFIGURE: { } break; case MENU_OPTION_LOCK_VIEW: { int index=options->get_popup()->get_item_index(MENU_OPTION_LOCK_VIEW); lock_view=!options->get_popup()->is_item_checked(index); options->get_popup()->set_item_checked(index,lock_view); } break; case MENU_OPTION_CLIP_DISABLED: case MENU_OPTION_CLIP_ABOVE: case MENU_OPTION_CLIP_BELOW: { clip_mode=ClipMode(p_option-MENU_OPTION_CLIP_DISABLED); for(int i=0;i<3;i++) { int index=options->get_popup()->get_item_index(MENU_OPTION_CLIP_DISABLED+i); options->get_popup()->set_item_checked(index,i==clip_mode); } _update_clip(); } break; case MENU_OPTION_X_AXIS: case MENU_OPTION_Y_AXIS: case MENU_OPTION_Z_AXIS: { int new_axis = p_option-MENU_OPTION_X_AXIS; for(int i=0;i<3;i++) { int idx=options->get_popup()->get_item_index(MENU_OPTION_X_AXIS+i); options->get_popup()->set_item_checked(idx,i==new_axis); } edit_axis=Vector3::Axis(new_axis); update_grid(); _update_clip(); } break; case MENU_OPTION_CURSOR_ROTATE_Y: { Matrix3 r; if (input_action==INPUT_DUPLICATE) { r.set_orthogonal_index(selection.duplicate_rot); r.rotate(Vector3(0,1,0),Math_PI/2.0); selection.duplicate_rot=r.get_orthogonal_index(); _update_duplicate_indicator(); break; } r.set_orthogonal_index(cursor_rot); r.rotate(Vector3(0,1,0),Math_PI/2.0); cursor_rot=r.get_orthogonal_index(); _update_cursor_transform(); } break; case MENU_OPTION_CURSOR_ROTATE_X: { Matrix3 r; if (input_action==INPUT_DUPLICATE) { r.set_orthogonal_index(selection.duplicate_rot); r.rotate(Vector3(1,0,0),Math_PI/2.0); selection.duplicate_rot=r.get_orthogonal_index(); _update_duplicate_indicator(); break; } r.set_orthogonal_index(cursor_rot); r.rotate(Vector3(1,0,0),Math_PI/2.0); cursor_rot=r.get_orthogonal_index(); _update_cursor_transform(); } break; case MENU_OPTION_CURSOR_ROTATE_Z: { Matrix3 r; if (input_action==INPUT_DUPLICATE) { r.set_orthogonal_index(selection.duplicate_rot); r.rotate(Vector3(0,0,1),Math_PI/2.0); selection.duplicate_rot=r.get_orthogonal_index(); _update_duplicate_indicator(); break; } r.set_orthogonal_index(cursor_rot); r.rotate(Vector3(0,0,1),Math_PI/2.0); cursor_rot=r.get_orthogonal_index(); _update_cursor_transform(); } break; case MENU_OPTION_CURSOR_BACK_ROTATE_Y: { Matrix3 r; r.set_orthogonal_index(cursor_rot); r.rotate(Vector3(0,1,0),-Math_PI/2.0); cursor_rot=r.get_orthogonal_index(); _update_cursor_transform(); } break; case MENU_OPTION_CURSOR_BACK_ROTATE_X: { Matrix3 r; r.set_orthogonal_index(cursor_rot); r.rotate(Vector3(1,0,0),-Math_PI/2.0); cursor_rot=r.get_orthogonal_index(); _update_cursor_transform(); } break; case MENU_OPTION_CURSOR_BACK_ROTATE_Z: { Matrix3 r; r.set_orthogonal_index(cursor_rot); r.rotate(Vector3(0,0,1),-Math_PI/2.0); cursor_rot=r.get_orthogonal_index(); _update_cursor_transform(); } break; case MENU_OPTION_CURSOR_CLEAR_ROTATION: { if (input_action==INPUT_DUPLICATE) { selection.duplicate_rot=0; _update_duplicate_indicator(); break; } cursor_rot=0; _update_cursor_transform(); } break; case MENU_OPTION_DUPLICATE_SELECTS: { int idx = options->get_popup()->get_item_index(MENU_OPTION_DUPLICATE_SELECTS); options->get_popup()->set_item_checked( idx, !options->get_popup()->is_item_checked( idx ) ); } break; case MENU_OPTION_SELECTION_MAKE_AREA: case MENU_OPTION_SELECTION_MAKE_EXTERIOR_CONNECTOR: { if (!selection.active) break; int area = node->get_unused_area_id(); Error err = node->create_area(area,AABB(selection.begin,selection.end-selection.begin+Vector3(1,1,1))); if (err!=OK) { } if (p_option==MENU_OPTION_SELECTION_MAKE_EXTERIOR_CONNECTOR) { node->area_set_exterior_portal(area,true); } _update_areas_display(); update_areas(); } break; case MENU_OPTION_REMOVE_AREA: { if (selected_area<1) return; node->erase_area(selected_area); _update_areas_display(); update_areas(); } break; case MENU_OPTION_SELECTION_CLEAR: { if (!selection.active) return; _delete_selection(); } break; } }
std::string LuxMaxUtils::getMaxNodeTransform(INode* node) { LuxMaxUtils *lmutil; std::string tmpTrans = ""; Matrix3 nodeTransformPos = node->GetObjTMAfterWSM(GetCOREInterface()->GetTime()); Matrix3 nodeTransformRot = nodeTransformPos; Matrix3 nodeTransformScale = nodeTransformPos; nodeTransformRot.NoTrans(); nodeTransformScale.NoTrans(); nodeTransformScale.NoRot(); nodeTransformRot = nodeTransformRot * nodeTransformScale; tmpTrans.append(floatToString(nodeTransformRot.GetColumn(0).x)); tmpTrans.append(" "); tmpTrans.append(floatToString(nodeTransformRot.GetColumn(1).x)); tmpTrans.append(" "); tmpTrans.append(floatToString(nodeTransformRot.GetColumn(2).x)); tmpTrans.append(" "); tmpTrans.append("0 "); tmpTrans.append(floatToString(nodeTransformRot.GetColumn(0).y)); tmpTrans.append(" "); tmpTrans.append(floatToString(nodeTransformRot.GetColumn(1).y)); tmpTrans.append(" "); tmpTrans.append(floatToString(nodeTransformRot.GetColumn(2).y)); tmpTrans.append(" "); tmpTrans.append("0 "); tmpTrans.append(floatToString(nodeTransformRot.GetColumn(0).z)); tmpTrans.append(" "); tmpTrans.append(floatToString(nodeTransformRot.GetColumn(1).z)); tmpTrans.append(" "); tmpTrans.append(floatToString(nodeTransformRot.GetColumn(2).z)); tmpTrans.append(" "); tmpTrans.append("0 "); tmpTrans.append(floatToString(nodeTransformPos.GetTrans().x)); tmpTrans.append(" "); tmpTrans.append(floatToString(nodeTransformPos.GetTrans().y)); tmpTrans.append(" "); tmpTrans.append(floatToString(nodeTransformPos.GetTrans().z)); tmpTrans.append(" 1.0"); return tmpTrans; }
bool PlasmaImport::IImportObject(plSceneObject *obj, ImpInterface *imp) { if (!obj->getDrawInterface().isLoaded()) return false; plDrawInterface* draw = plDrawInterface::Convert(obj->getDrawInterface()->getObj()); plCoordinateInterface* coord = NULL; if (obj->getCoordInterface().Exists()) coord = plCoordinateInterface::Convert(obj->getCoordInterface()->getObj()); TriObject *maxObj = CreateNewTriObject(); Mesh *msh = &maxObj->GetMesh(); std::vector<Point3> vertexList; std::vector<int> indexList; if (!maxObj) return false; // read the object from PRP for (size_t i = 0; i < draw->getNumDrawables(); i++) { if (draw->getDrawableKey(i) == -1) continue; plDrawableSpans* span = plDrawableSpans::Convert(draw->getDrawable(i)->getObj()); plDISpanIndex di = span->getDIIndex(draw->getDrawableKey(i)); if ((di.fFlags & plDISpanIndex::kMatrixOnly) != 0) continue; for (size_t idx = 0; idx < di.fIndices.size(); idx++) { plIcicle* ice = (plIcicle*)span->getSpan(di.fIndices[idx]); std::vector<plGBufferVertex> verts = span->getVerts(ice); std::vector<unsigned short> indices = span->getIndices(ice); for (size_t j = 0; j < verts.size(); j++) { hsVector3 pos; if (coord != NULL) pos = coord->getLocalToWorld().multPoint(verts[j].fPos) * 10.0f; else pos = ice->getLocalToWorld().multPoint(verts[j].fPos) * 10.0f; vertexList.push_back(Point3(pos.X, pos.Y, pos.Z)); } indexList.insert(indexList.end(), indices.begin(), indices.end()); } } //create the Mesh msh->setNumVerts(vertexList.size()); msh->setNumFaces(indexList.size()/3); for (size_t i = 0; i < vertexList.size(); i++) msh->setVert(i, vertexList[i]); for (size_t i = 0; i < indexList.size()/3; i++) { int v1, v2, v3; v1 = indexList[3*i]; v2 = indexList[3*i+1]; v3 = indexList[3*i+2]; msh->faces[i].setVerts(v1, v2, v3); msh->faces[i].setEdgeVisFlags(1,1,1); //we asume we have Triangles obnly } msh->buildNormals(); msh->buildBoundingBox(); msh->InvalidateEdgeList(); //Add Object To Scene ImpNode *node = imp->CreateNode(); Matrix3 tm; tm.IdentityMatrix(); node->Reference(maxObj); node->SetTransform(0,tm); imp->AddNodeToScene(node); node->SetName(obj->getKey()->getName()); imp->RedrawViews(); return true; }
void Matrix3::Multiply(const Matrix3& other, Matrix3* result) const { Matrix3 tempResult; tempResult.SetElem(0, (m_Elems[0] * other.GetElem(0)) + (m_Elems[1] * other.GetElem(3)) + (m_Elems[2] * other.GetElem(6))); tempResult.SetElem(1, (m_Elems[0] * other.GetElem(1)) + (m_Elems[1] * other.GetElem(4)) + (m_Elems[2] * other.GetElem(7))); tempResult.SetElem(2, (m_Elems[0] * other.GetElem(2)) + (m_Elems[1] * other.GetElem(5)) + (m_Elems[2] * other.GetElem(8))); tempResult.SetElem(3, (m_Elems[3] * other.GetElem(0)) + (m_Elems[4] * other.GetElem(3)) + (m_Elems[5] * other.GetElem(6))); tempResult.SetElem(4, (m_Elems[3] * other.GetElem(1)) + (m_Elems[4] * other.GetElem(4)) + (m_Elems[5] * other.GetElem(7))); tempResult.SetElem(5, (m_Elems[3] * other.GetElem(2)) + (m_Elems[4] * other.GetElem(5)) + (m_Elems[5] * other.GetElem(8))); tempResult.SetElem(6, (m_Elems[6] * other.GetElem(0)) + (m_Elems[7] * other.GetElem(3)) + (m_Elems[8] * other.GetElem(6))); tempResult.SetElem(7, (m_Elems[6] * other.GetElem(1)) + (m_Elems[7] * other.GetElem(4)) + (m_Elems[8] * other.GetElem(7))); tempResult.SetElem(8, (m_Elems[6] * other.GetElem(2)) + (m_Elems[7] * other.GetElem(5)) + (m_Elems[8] * other.GetElem(8))); (*result) = tempResult; }
ColMesh* RBExport::GetColMesh( INode* node ) { ObjectState os = node->EvalWorldState( m_CurTime ); Object* pObject = os.obj; if (!pObject) { Warn( "Could not evaluate object state. Collision mesh %s was skipped.", node->GetName() ); return NULL; } Matrix3 nodeTM = node->GetNodeTM( m_CurTime ); Matrix3 nodeTMAfterWSM = node->GetObjTMAfterWSM( m_CurTime ); Matrix3 mOffs = nodeTMAfterWSM*Inverse( nodeTM ); // triangulate TriObject* pTriObj = NULL; if (pObject->CanConvertToType( Class_ID( TRIOBJ_CLASS_ID, 0 ) )) { pTriObj = (TriObject*)pObject->ConvertToType( m_CurTime, Class_ID( TRIOBJ_CLASS_ID, 0 ) ); } bool bReleaseTriObj = (pTriObj != pObject); if (!pTriObj) { Warn( "Could not triangulate mesh in node. Collision mesh %s was skipped.", node->GetName() ); return NULL; } // ensure, that vertex winding direction in polygon is CCW Matrix3 objTM = node->GetObjTMAfterWSM( m_CurTime ); bool bNegScale = (DotProd( CrossProd( objTM.GetRow(0), objTM.GetRow(1) ), objTM.GetRow(2) ) >= 0.0); int vx[3]; vx[0] = bNegScale ? 2 : 0; vx[1] = bNegScale ? 1 : 1; vx[2] = bNegScale ? 0 : 2; Mesh& mesh = pTriObj->GetMesh(); // some cosmetics mesh.RemoveDegenerateFaces(); mesh.RemoveIllegalFaces(); // create collision mesh ColMesh* pMesh = new ColMesh(); int numPri = mesh.getNumFaces(); int numVert = mesh.numVerts; // copy vertices for (int i = 0; i < numVert; i++) { Point3 pt = mesh.verts[i]; pt = mOffs.PointTransform( pt ); pt = c_FlipTM.PointTransform( pt ); pMesh->AddVertex( Vec3( pt.x, pt.y, pt.z ) ); } // loop on mesh faces for (int i = 0; i < numPri; i++) { Face& face = mesh.faces[i]; pMesh->AddPoly( face.v[vx[0]], face.v[vx[1]], face.v[vx[2]] ); } Msg( LogType_Stats, "Physics collision trimesh has %d vertices and %d faces.", numVert, numPri ); return pMesh; } // RBExport::GetColMesh
SimulatedObject * MainEngine::makeSimulatedObject3D(TypeObject _typeObject) { SimulatedObject * simulatedObject = new SimulatedObject(); simulatedObject->setTypeObject(_typeObject); simulatedObject->setMass(MASS); simulatedObject->setRestitution(COEF_RESTITUTION); simulatedObject->setPosition(POSITION_X, POSITION_Y, POSITION_Z); simulatedObject->setLinearDamping(COEF_LINEAR_DAMPING); simulatedObject->setAngularDamping(COEF_ANGULAR_DAMPING); simulatedObject->setCanSleep(CAN_AWAKE); simulatedObject->setAwake(); simulatedObject->setSelected(true); switch (_typeObject) { case SPHERE: { simulatedObject->setMode(TRIANGLE_STRIP); simulatedObject->setRadius(0.1f); simulatedObject->addAllVectors(this->createSphere(simulatedObject->getPosition(), simulatedObject->getRadius())); Matrix3 tensor; real coeff = 0.4f*simulatedObject->getMass() * simulatedObject->getRadius()*simulatedObject->getRadius(); tensor.setInertiaTensorCoeffs(coeff,coeff,coeff); simulatedObject->setInertiaTensor(tensor); break; } case BOX: { simulatedObject->setHalfSize(0.1f, 0.1f, 0.1f); simulatedObject->addAllVectors(this->createBox(simulatedObject->getPosition(), simulatedObject->getHalfSize())); Matrix3 tensor; tensor.setBlockInertiaTensor(simulatedObject->getHalfSize(), simulatedObject->getMass()); simulatedObject->setInertiaTensor(tensor); break; } case PLAN: { simulatedObject->setSelected(false); simulatedObject->setPosition(0.0f, 0.0f, 0.0f); simulatedObject->setMass(0.0f); simulatedObject->setFriction(COEF_FRICTION); simulatedObject->setMode(LINES); simulatedObject->setColorAux(0, 0, 0, 0); simulatedObject->setHalfSize(3.0f, 0.0f, 3.0f); simulatedObject->addAllVectors(this->createPlan(simulatedObject->getPosition())); break; } case PYRAMID: simulatedObject->setHalfSize(0.05f, 0.05f, 0.05f); simulatedObject->addAllVectors(this->createTriangleWithSquareBase(simulatedObject->getPosition(), simulatedObject->getHalfSize())); break; // case TRIANGLE_TRIANGULAR_BASE: // simulatedObject->setHalfSize(0.1f, 0.1f, 0.1f); // simulatedObject->addAllVectors(this->createTriangleWithTriangularBase(simulatedObject->getPosition(), simulatedObject->getHalfSize())); // break; case CONE: simulatedObject->setHalfSize(1.01f, 1.01f, 1.01f); simulatedObject->addAllVectors(this->createCone(simulatedObject->getPosition(), simulatedObject->getHalfSize())); break; default: break; } if (simulatedObject->getMode() == -1) { simulatedObject->setMode(TRIANGLES); } return simulatedObject; }
// DIVISION A/B = A * (1/B) = A * Inverse(B) Matrix3 Matrix3::operator/ ( const Matrix3& myMatrix ) const { Matrix3 temp = myMatrix; return( *this * temp.Inverse() ); }
Matrix3 Matrix3::scaled( const Vector3& p_scale ) const { Matrix3 m = *this; m.scale(p_scale); return m; }
//---------------------------------------------------------------------------- PX2::Transform SceneBuilder::GetLocalTransform (INode *node, TimeValue time) { // 计算节点的本地变换。Max节点的变换方法提供的节点的世界变换,所以我们 // 必须做一些操纵去获得节点的本地变换。 Matrix3 maxLocal = node->GetObjTMAfterWSM(time) * Inverse(node->GetParentNode()->GetObjTMAfterWSM(time)); // 分解变换 AffineParts affParts; decomp_affine(maxLocal, &affParts); // Position bool isTranslationZero = fabsf(affParts.t.x) < MIN_DIFFERENCE && fabsf(affParts.t.y) < MIN_DIFFERENCE && fabsf(affParts.t.z) < MIN_DIFFERENCE; // Rotation float qSign = (affParts.q.w >= 0.0f ? 1.0f : -1.0f); bool isRotationIndentity = fabsf(qSign*affParts.q.w - 1.0f) < MIN_DIFFERENCE && fabsf(affParts.q.x) < MIN_DIFFERENCE && fabsf(affParts.q.y) < MIN_DIFFERENCE && fabsf(affParts.q.z) < MIN_DIFFERENCE; // Reflect bool hasReflection = (affParts.f < 0.0f); // Uniform scale bool isScaleUniform = (fabsf(affParts.k.x - affParts.k.y)<MIN_DIFFERENCE && fabsf(affParts.k.y - affParts.k.z)<MIN_DIFFERENCE); // Unity scale bool isScaleUnity = isScaleUniform && fabsf(affParts.k.x - 1.0f) < MIN_DIFFERENCE; // Scale orientation is identity? float uSign = (affParts.u.w >= 0.0f ? 1.0f : -1.0f); bool isOrientIndentity = isScaleUniform || ( fabsf(uSign*affParts.u.w - 1.0f) < MIN_DIFFERENCE && fabsf(affParts.u.x) < MIN_DIFFERENCE && fabsf(affParts.u.y) < MIN_DIFFERENCE && fabsf(affParts.u.z) < MIN_DIFFERENCE); // 计算Phoenix2等价变换 PX2::Transform local; if (!isTranslationZero) { local.SetTranslate(PX2::APoint(affParts.t.x, affParts.t.y, affParts.t.z)); } if (hasReflection) { affParts.k *= -1.0f; } if (isScaleUniform) { // 矩阵的形式为R*(s*I),s是统一缩放矩阵。 if (!isRotationIndentity) { PX2::HMatrix rot; PX2::HQuaternion(affParts.q.w, -affParts.q.x, -affParts.q.y, -affParts.q.z).ToRotationMatrix(rot); local.SetRotate(rot); } if (!isScaleUnity) { local.SetUniformScale(affParts.k.x); } } else if (isOrientIndentity) { if (!isRotationIndentity) { PX2::HMatrix rot; PX2::HQuaternion(affParts.q.w, -affParts.q.x, -affParts.q.y, -affParts.q.z).ToRotationMatrix(rot); local.SetRotate(rot); } local.SetScale(PX2::APoint(affParts.k.x, affParts.k.y, affParts.k.z)); } else { PX2::Matrix3f mat( maxLocal.GetAddr()[0][0], maxLocal.GetAddr()[1][0], maxLocal.GetAddr()[2][0], maxLocal.GetAddr()[0][1], maxLocal.GetAddr()[1][1], maxLocal.GetAddr()[2][1], maxLocal.GetAddr()[0][2], maxLocal.GetAddr()[1][2], maxLocal.GetAddr()[2][2]); local.SetMatrix(PX2::HMatrix(mat)); } return local; }
Matrix3 Matrix3::orthonormalized() const { Matrix3 c = *this; c.orthonormalize(); return c; }
/* ==================== GatherSkin ==================== */ void G3DSExport::GatherSkin(INode* i_node) { SKIN skin; // get the name of the node skin.name = i_node->GetName(); // get the skin interface Modifier *modifier = GetModifier(i_node,SKIN_CLASSID); ISkin* i_skin = (ISkin*)modifier->GetInterface(I_SKIN); MAX_CHECK(i_skin); // convert to the triangle type Mesh* i_mesh = NULL; Object* obj = i_node->EvalWorldState(mTime).obj; if(obj && ( obj->SuperClassID() == GEOMOBJECT_CLASS_ID )) { if(obj->CanConvertToType(Class_ID(TRIOBJ_CLASS_ID, 0))) { TriObject *tri_obj = (TriObject*)obj->ConvertToType(mTime, Class_ID(TRIOBJ_CLASS_ID, 0)); MAX_CHECK(tri_obj); i_mesh = &tri_obj->mesh; } } MAX_CHECK(i_mesh&&i_mesh->getNumFaces()&&i_mesh->getNumVerts()); // get the material skin.texture = "textures/default.tga"; Mtl* mtl = i_node->GetMtl(); if(mtl && (mtl->ClassID()==Class_ID(DMTL_CLASS_ID, 0)) && ((StdMat*)mtl)->MapEnabled(ID_DI)) { Texmap *texmap = mtl->GetSubTexmap(ID_DI); if(texmap && texmap->ClassID() == Class_ID(BMTEX_CLASS_ID, 0x00)) { skin.texture = UnifySlashes(((BitmapTex *)texmap)->GetMapName()); if( !strstr( skin.texture.c_str(), mPath.c_str() ) ) { G3DAssert("The material(%s) is error : the texture path(%s) is illegal!",mtl->GetName(), skin.texture.c_str()); } else { skin.texture = strstr(skin.texture.c_str(),mPath.c_str()) + strlen(mPath.c_str()); } } } // if it has uvs int map_count = i_mesh->getNumMaps(); bool has_uvs = i_mesh->getNumTVerts() && i_mesh->tvFace; if(!(has_uvs&&map_count)) { G3DAssert("The skin(%s) has not the uv coordinates.",skin.name.c_str()); return; } // get the transform Matrix3 mesh_matrix = i_node->GetObjectTM(mTime); Matrix3 node_matrix = i_node->GetNodeTM(mTime); Matrix3 transform = mesh_matrix * Inverse(node_matrix); // get the points skin.points.assign(i_mesh->verts, i_mesh->verts+i_mesh->getNumVerts()); // get the triangles for(int i = 0; i < i_mesh->getNumFaces(); i++) { Face& face = i_mesh->faces[i]; TRIANGLE tri; tri.smoothing = face.smGroup; for(int j = 0; j < 3; j++) { VPTNIS v; v.pos = transform * i_mesh->verts[face.v[j]]; // get the uv UVVert * map_verts = i_mesh->mapVerts(1); TVFace * map_faces = i_mesh->mapFaces(1); v.uv = reinterpret_cast<Point2&>(map_verts[map_faces[i].t[j]]); v.uv.y = 1 - v.uv.y; // initialize the normal v.normal = Point3::Origin; // get the vertex index v.index = face.v[j]; // get the smoothing group v.smoothing = face.smGroup; // set the index for the triangle tri.index0[j] = v.index; // reassemble the vertex list tri.index1[j] = AddVertex(skin, v); } // add the triangle to the table skin.triangles.push_back(tri); } // build the index map for( int i = 0; i < skin.vertexes.size(); i++ ) { skin.vertex_index_map[skin.vertexes[i].index].push_back(i); } // get the skin context data ISkinContextData* i_skin_context_data = i_skin->GetContextInterface(i_node); if(i_skin_context_data == NULL) { G3DAssert("The skin(%s) has not the weight.",skin.name.c_str()); return; } // gets the initial matrix of the skinned object Matrix3 initial_object_transform; i_skin->GetSkinInitTM(i_node, initial_object_transform, true); // process the points int num_points = i_skin_context_data->GetNumPoints(); for(int i = 0; i < num_points; i++) { MAX_CHECK(i < skin.points.size()); VPIW viw; // get the initial point viw.pos = initial_object_transform * skin.points[i]; // process the weights std::multimap< float, int > weights; // get the number of bones that control this vertex int num_bones = i_skin_context_data->GetNumAssignedBones(i); if(num_bones>0) { for (int j = 0; j < num_bones; j++) { Matrix3 transform; // get the assigned bone of the point INode* i_bone_node = i_skin->GetBone(i_skin_context_data->GetAssignedBone(i, j)); MAX_CHECK(i_bone_node != NULL); // get the weight of the bone float weight = i_skin_context_data->GetBoneWeight(i, j); // add the weight to the table weights.insert(std::make_pair(weight, AddBone(skin,i_bone_node))); } } else { // add the weight to the table weights.insert(std::make_pair(1.f, AddBone(skin,i_node))); } // recalculate the weights float weight0 = 0.f, weight1 = 0.f, weight2 = 0.f; int index0 = 0, index1 = 0, index2 = 0; std::multimap< float, int >::iterator it = weights.end(); it--; weight0 = it->first; index0 = it->second; if(it != weights.begin()) { it--; weight1 = it->first; index1 = it->second; if(it != weights.begin()) { it--; weight2 = it->first; index2 = it->second; } } float sum_weights = weight0 + weight1 + weight2; // store the skin weights viw.weight[0] = weight0/sum_weights; viw.index[0] = index0; viw.weight[1] = weight1/sum_weights; viw.index[1] = index1; viw.weight[2] = weight2/sum_weights; viw.index[2] = index2; skin.weights.push_back(viw); } // get the initial transforms skin.transforms.resize(skin.bones.size()); for(int i = 0; i < skin.bones.size(); i++) { INode* node = skin.bones[i]; Matrix3 mat; if (SKIN_INVALID_NODE_PTR == i_skin->GetBoneInitTM( node, mat )) { if (SKIN_INVALID_NODE_PTR == i_skin->GetSkinInitTM( node, mat )) { mat.IdentityMatrix(); } } skin.transforms[i] = Inverse(mat); } // there is a 75 bone limit for each skinned object. if(skin.bones.size()>75) { G3DAssert("There are more %d bones in the skin(%s).",skin.bones.size(), i_node->GetName()); return; } // reset the skin vertex position for(int i = 0; i < skin.vertexes.size(); i++) { VPTNIS& v0 = skin.vertexes[i]; VPIW& v1 = skin.weights[v0.index]; v0.pos = v1.pos; } // build the normal space BuildNormal(skin); // calculate the bounding box skin.box.Init(); for(int i = 0; i < skin.vertexes.size(); i++) { Point3 pt = node_matrix * skin.vertexes[i].pos; skin.box += pt; } // add the skin to the table mSkins.push_back(skin); }
// Here we process mesh geometry for given node. // Vertices for the geometry from the all meshes of the scene are allocated in // one big vertex pool. One vertex can occur several times in this pool, because // we add 3 new vertices for every face. // After all meshes in the scene are processed, this pool is collapsed to remove // duplicate vertices. void RBExport::ProcessMesh( INode* node ) { if (!node->Renderable() || node->IsNodeHidden()) { return; } ObjectState os = node->EvalWorldState( m_CurTime ); Object* pObject = os.obj; if (!pObject) { Warn( "Could not evaluate object state in node <%s>. Mesh was skipped.", node->GetName() ); return; } Matrix3 nodeTM = node->GetNodeTM( m_CurTime ); Matrix3 nodeTMAfterWSM = node->GetObjTMAfterWSM( m_CurTime ); Matrix3 mOffs = nodeTMAfterWSM*Inverse( nodeTM ); // triangulate TriObject* pTriObj = 0; if (pObject->CanConvertToType( Class_ID( TRIOBJ_CLASS_ID, 0 ) )) { pTriObj = (TriObject*)pObject->ConvertToType( m_CurTime, Class_ID( TRIOBJ_CLASS_ID, 0 ) ); } bool bReleaseTriObj = (pTriObj != pObject); if (!pTriObj) { Warn( "Could not triangulate mesh in node <%s>. Node was skipped", node->GetName() ); return; } if (!MeshModStackIsValid( node )) { Warn( "Modifier stack for node %s should be collapsed or contain only Skin modifier.", node->GetName() ); } // ensure, that vertex winding direction in polygon is CCW Matrix3 objTM = node->GetObjTMAfterWSM( m_CurTime ); bool bNegScale = (DotProd( CrossProd( objTM.GetRow(0), objTM.GetRow(1) ), objTM.GetRow(2) ) >= 0.0); int vx[3]; if (bNegScale) { vx[0] = 0; vx[1] = 1; vx[2] = 2; } else { vx[0] = 2; vx[1] = 1; vx[2] = 0; } Mesh& mesh = pTriObj->GetMesh(); bool bHasTexCoord = (mesh.numTVerts != 0); bool bHasVertexColor = (mesh.numCVerts != 0) && m_pConfig->m_bExportVertexColors; bool bHasNormal = m_pConfig->m_bExportNormals; bool bHasSkin = ProcessSkin( node ); // some cosmetics BOOL res = mesh.RemoveDegenerateFaces(); if (res) { Spam( "Degenerate faces were fixed." ); } res = mesh.RemoveIllegalFaces(); if (res) { Spam( "Degenerate indices were fixed." ); } ExpNode* pExpNode = GetExportedNode( node ); if (!pExpNode) { return; } int numPri = mesh.getNumFaces(); int numVert = mesh.numVerts; // initialize helper array for building vertices' 0-circles VertexPtrArray vertexEntry; vertexEntry.resize( numVert ); memset( &vertexEntry[0], 0, sizeof( ExpVertex* )*numVert ); Spam( "Original mesh has %d vertices and %d faces.", numVert, numPri ); bool bHasVoidFaces = false; // loop on mesh faces for (int i = 0; i < numPri; i++) { Face& face = mesh.faces[i]; // calculate face normal const Point3& v0 = mesh.verts[face.v[vx[0]]]; const Point3& v1 = mesh.verts[face.v[vx[1]]]; const Point3& v2 = mesh.verts[face.v[vx[2]]]; Point3 normal = -Normalize( (v1 - v0)^(v2 - v1) ); normal = mOffs.VectorTransform( normal ); normal = c_FlipTM.VectorTransform( normal ); // loop on face vertices ExpVertex* pFaceVertex[3]; for (int j = 0; j < 3; j++) { ExpVertex v; v.mtlID = pExpNode->GetMaterialIdx( face.getMatID() ); v.nodeID = pExpNode->m_Index; if (v.mtlID < 0) { bHasVoidFaces = true; } // extract vertex position and apply world-space modifier to it int vIdx = face.v[vx[j]]; Point3 pt = mesh.verts[vIdx]; pt = mOffs.PointTransform( pt ); pt = c_FlipTM.PointTransform( pt ); v.index = vIdx; v.pos = Vec3( pt.x, pt.y, pt.z ); //v.pos *= m_WorldScale; // extract skinning info if (bHasSkin) { GetSkinInfo( v ); } // assign normal if (bHasNormal) { v.normal = Vec3( normal.x, normal.y, normal.z ); v.smGroup = face.smGroup; } // extract vertex colors if (bHasVertexColor) { const VertColor& vcol = mesh.vertCol[mesh.vcFace[i].t[vx[j]]]; v.color = ColorToDWORD( Color( vcol.x, vcol.y, vcol.z ) ); } // extract texture coordinates if (bHasTexCoord) { const Point3& texCoord = mesh.tVerts[mesh.tvFace[i].t[vx[j]]]; v.uv.x = texCoord.x; v.uv.y = 1.0f - texCoord.y; // second texture coordinate channel if (mesh.getNumMaps() > 1 && mesh.mapSupport( 2 )) { UVVert* pUVVert = mesh.mapVerts( 2 ); TVFace* pTVFace = mesh.mapFaces( 2 ); if (pUVVert && pTVFace) { const Point3& tc2 = pUVVert[pTVFace[i].t[vx[j]]]; v.uv2.x = tc2.x; v.uv2.y = 1.0f - tc2.y; } } } // allocate new vertex pFaceVertex[j] = AddVertex( v ); // we want vertices in the 0-ring neighborhood to be linked into closed linked list if (vertexEntry[vIdx] == NULL) { vertexEntry[vIdx] = pFaceVertex[j]; pFaceVertex[j]->pNext = pFaceVertex[j]; } else { vertexEntry[vIdx]->AddToZeroRing( pFaceVertex[j] ); } } AddPolygon( pFaceVertex[0], pFaceVertex[1], pFaceVertex[2] ); if (IsCanceled()) { return; } } // correct normals at vertices corresponding to smoothing groups SmoothNormals( vertexEntry ); // put vertices into set (this removes duplicate vertices) for (int i = 0; i < numVert; i++) { ExpVertex::ZeroRingIterator it( vertexEntry[i] ); while (it) { VertexSet::iterator sIt = m_VertexSet.find( it ); if (sIt == m_VertexSet.end()) { m_VertexSet.insert( it ); } else { it->pBase = (*sIt); } ++it; } } if (bReleaseTriObj) { delete pTriObj; } if (bHasVoidFaces) { Warn( "Mesh %s has faces with no material assigned.", node->GetName() ); } } // RBExport::ProcessMesh
void RigidBodyMotionSimulation::CreateObjects() { for(int i = 0 ; i < 0 ; i++) { RigidBodyPtr body(new RigidBody()); body->SetMass(1); // Point3 newPos(0,20,30); Point3 newPos(30,10,0); body->SetPos(newPos); Matrix3 inertiaTensor; inertiaTensor.SetBlockInertiaTensor(Vector3(1,1,1), 1); body->SetInertiaTensor(inertiaTensor); // body->LoadModel("../../media/models/torus.obj"); body->LoadModel("../../media/models/cube.obj"); //matrix3 orientation = body->getorientation(); //orientation.createrotationmatrixaboutxaxis(45, &orientation); //body->setorientation(orientation); Quaternion orientation; Vector3 rotationVec(1,1,1); orientation.RotateByVector(rotationVec); body->SetOrientation(orientation); body->CalculateInternals(); //m_CollisionDetector->AddAABB(body->GetAABB()); /* if(i==0) { body->AddForceAtBodyPoint(Vector3(10,10, 0),Point3(0,0,0)); } else { body->AddForceAtBodyPoint(Vector3(-10,-10, 0),Point3(0,0,0)); } */ body->AddForceAtBodyPoint(Vector3(0,-90,0),Point3(0,0,0)); //body->CalculateInternals(); m_RigidBodies.push_back(body); } m_Plane = new CollisionPlane(); m_Plane->SetPoint(Point3(0,0,0)); m_Plane->SetNormal(Vector3(0,1,0)); m_Particle = new Particle(); m_Particle->SetPos(Point3(0,10,1)); m_Particle->SetVel(Vector3(0,-10,0)); /* m_Triangle_0->SetPoint( Point3(1.0f,3.0f,0.0f), 0 ); m_Triangle_0->SetPoint( Point3(2.0f,1.0f,0.0f), 1 ); m_Triangle_0->SetPoint( Point3(2.0f,2.0f,0.0f), 2 ); */ m_Triangle_0->SetPoint( Point3(0.3f,0.3f,0.0f), 0 ); m_Triangle_0->SetPoint( Point3(1.3f,1.3f,0.0f), 1 ); m_Triangle_0->SetPoint( Point3(2.3f,0.3f,0.0f), 2 ); m_Triangle_0->CreateEdges(); // m_Contact = new Contact(); }
void Import::ApplyModifiers (dScene& scene, const MaxNodeChache& maxNodeCache) { dScene::Iterator iter (scene); for (iter.Begin(); iter; iter ++) { dScene::dTreeNode* meshNode = iter.GetNode(); dNodeInfo* info = scene.GetInfoFromNode(meshNode); if (info->IsType(dGeometryNodeInfo::GetRttiType())) { dScene::dTreeNode* skinModifierNode = NULL; for (void* ptr = scene.GetFirstChild(meshNode); ptr; ptr = scene.GetNextChild(meshNode, ptr)) { dScene::dTreeNode* node = scene.GetNodeFromLink(ptr); dNodeInfo* info = scene.GetInfoFromNode(node); if (info->GetTypeId() == dGeometryNodeSkinModifierInfo::GetRttiType()) { skinModifierNode = node; break; } } if (skinModifierNode) { //create a skin modifier and add it Modifier* skinMod = (Modifier*) CreateInstance(OSM_CLASS_ID, SKIN_CLASSID); ISkinImportData* iskinImport = (ISkinImportData*) skinMod->GetInterface(I_SKINIMPORTDATA); INode* maxNode = maxNodeCache.Find(meshNode)->GetInfo(); _ASSERTE (maxNode); IDerivedObject *derob = NULL; Object* obj = maxNode->GetObjectRef(); if(obj->SuperClassID() != GEN_DERIVOB_CLASS_ID) { derob = CreateDerivedObject(obj); maxNode->SetObjectRef(derob); } else { derob = (IDerivedObject*) obj; } derob->AddModifier(skinMod); dGeometryNodeSkinModifierInfo* skinModifier = (dGeometryNodeSkinModifierInfo*) scene.GetInfoFromNode(skinModifierNode); dMatrix matrix (skinModifier->m_shapeBindMatrix); Matrix3 bindPoseMatrix; bindPoseMatrix.SetRow (0, *((Point3*) &matrix[0])); bindPoseMatrix.SetRow (1, *((Point3*) &matrix[1])); bindPoseMatrix.SetRow (2, *((Point3*) &matrix[2])); bindPoseMatrix.SetRow (3, *((Point3*) &matrix[3])); iskinImport->SetSkinTm(maxNode, bindPoseMatrix, bindPoseMatrix); int maxNodeCount = 0; INode* maxNodes[1024]; for (void* ptr = scene.GetFirstChild(skinModifierNode); ptr; ptr = scene.GetNextChild(skinModifierNode, ptr)) { dScene::dTreeNode* boneNode = scene.GetNodeFromLink(ptr); INode* skelBone = maxNodeCache.Find(boneNode)->GetInfo(); maxNodes[maxNodeCount] = skelBone; maxNodeCount ++; skelBone->SetBoneNodeOnOff(TRUE, 0); skelBone->BoneAsLine(TRUE); skelBone->ShowBone(1); if (iskinImport->AddBoneEx(skelBone, TRUE)) { dSceneNodeInfo* sceneNode = (dSceneNodeInfo*) scene.GetInfoFromNode(boneNode); dMatrix matrix (sceneNode->GetTransform()); Matrix3 bindPoseMatrix; bindPoseMatrix.SetRow (0, *((Point3*) &matrix[0])); bindPoseMatrix.SetRow (1, *((Point3*) &matrix[1])); bindPoseMatrix.SetRow (2, *((Point3*) &matrix[2])); bindPoseMatrix.SetRow (3, *((Point3*) &matrix[3])); iskinImport->SetBoneTm(skelBone, bindPoseMatrix, bindPoseMatrix); } } // must evaluate the node after adding bones maxNode->EvalWorldState(0); for (int i = 0; i < skinModifier->m_vertexCount; i ++) { Tab<float> weightList; Tab<INode*> boneNodeList; for (int j = 0; j < 4; j ++) { if (skinModifier->m_vertexWeights[i][j] > 1.0e-5f) { int boneIndex = skinModifier->m_boneWeightIndex[i].m_index[j]; INode *skelBone = maxNodes[boneIndex]; _ASSERTE (skelBone); boneNodeList.Append (1, &skelBone); weightList.Append (1, &skinModifier->m_vertexWeights[i][j]); } } iskinImport->AddWeights(maxNode, i, boneNodeList, weightList); } } } } }