void Config_Touch(int touch, u32 x, u32 y) { if (touch != 0) return; // bounding boxes are gross // TODO: eventually adopt a real widget system? if (y >= 24 && y < 44) { Config.HardwareRenderer = !Config.HardwareRenderer; configdirty = 2; } else if (y >= 50 && y < 70) { Config.ScaleMode++; if (Config.ScaleMode > 4) Config.ScaleMode = 0; configdirty = 2; } else if (x < 106 && y >= 200) { LoadConfig(); UI_Restore(); } else if (x > 212 && y >= 200) { SaveConfig(); UI_Restore(); } PPU_SwitchRenderers(); ApplyScaling(); }
void PictureWidget::Draw(const Point2i &/*mousePosition*/) { if (!loaded) { if (name.empty()) return; Profile *res = GetResourceManager().LoadXMLProfile("graphism.xml", false); SetSurface(LOAD_RES_IMAGE(name), type); // Needed to set the resizing ApplyScaling(type); } if (!spr) return; Surface & surf = GetMainWindow(); Point2i pos = GetPicturePosition(); spr->Blit(surf, pos); // Draw a transparency mask if (disabled) { surf.BoxColor(Rectanglei(pos, spr->GetSize()), defaultOptionColorBox); } }
void SlaveScaleControl::GetValue(TimeValue t, void *val, Interval &valid, GetSetMethod method) { if ( (sub == NULL) || (!masterPresent) || (blockID.Count()==0)) { Quat f; f.Identity(); Point3 p(1.0f,1.0f,1.0f); if (method == CTRL_ABSOLUTE) { ScaleValue s(p,f); ScaleValue *v = ((ScaleValue*)val); *v = s; return; } else { Matrix3 *mat = (Matrix3*)val; ScaleValue s(p,f); ApplyScaling(*mat,s); return; } } if (scratchControl == NULL) UpdateSlave(); if (master) master->GetValue3(scratchControl,t,val,valid,blockID,subID,range,method); }
void PivotSnap::Snap(Object* pobj, IPoint2 *p, TimeValue t) { // This snap computes the bounding box points of a node as // well as the pivot point //local copy of the cursor position Point2 fp = Point2((float)p->x, (float)p->y); //In this snap mode we actually need to get a pointer to the node so that we // can check for WSM's and compute the pivot point INode *inode = theman->GetNode(); Matrix3 atm(1); //This will hold the nodes tm before WSMs //See if this guys has any spacewarps applied BOOL wsm = (BOOL) inode->GetProperty(PROPID_HAS_WSM); //If it does then we'll need to get a meaningful tm as follows if(wsm) atm = inode->GetObjTMBeforeWSM(t); //get the node's bounding box Box3 box; box.Init(); pobj->GetDeformBBox(t, box, NULL ); if(EssentiallyEmpty(box)) pobj->GetLocalBoundBox(t, inode, theman->GetVpt() , box); //We need a hitmesh which shows the bounding box of the node //This automatic variable gets passed to the hitmesh copy constructor // in every case HitMesh thehitmesh, *phitmesh; thehitmesh.setNumVerts(8); for(int jj = 0;jj<8;++jj) thehitmesh.setVert(jj,box[jj]); BOOL got_one= FALSE; //Compute all the hit point candidates if( GetActive(PIV_SUB)) { got_one = FALSE; Point3 *pivpt; //JH 10/02/01 //DID 296059 Matrix3 tm(1); Point3 pos = inode->GetObjOffsetPos(); tm.PreTranslate(pos); Quat quat = inode->GetObjOffsetRot(); PreRotateMatrix(tm, quat); ScaleValue scale = inode->GetObjOffsetScale(); ApplyScaling(tm, scale); Matrix3 InvTm = Inverse(tm); //JH 10/02/01 //atm contains the identity normally, or the node TM before spacewarps, when space warps are applied //We're computing a point relative to the node TM, so in the former case the inverse of //the object offset pos is what we want. In the latter (when the node TM is identtity, we must add //in the node TM before WSM. pivpt = new Point3(atm.GetTrans() + InvTm.GetTrans()); //Make a hitmesh phitmesh = new HitMesh(thehitmesh); //now register a hit with the osnap manager theman->RecordHit(new OsnapHit(*pivpt, this, PIV_SUB, phitmesh)); } if( GetActive(BBOX_SUB)) { //set up our highlight mesh for(int ii = 0;ii<8;++ii) { phitmesh = new HitMesh(thehitmesh); theman->RecordHit(new OsnapHit(box[ii], this, BBOX_SUB, phitmesh)); } } };
void XsiExp::ExportMesh( INode * node, TimeValue t, int indentLevel) { ObjectState os = node->EvalWorldState(t); if (!os.obj || os.obj->SuperClassID() != GEOMOBJECT_CLASS_ID) { return; // Safety net. This shouldn't happen. } BOOL needDel; TriObject * tri = GetTriObjectFromNode(node, t, needDel); if (!tri) { // no tri object return; } // prepare mesh Mesh * mesh = &tri->GetMesh(); mesh->buildNormals(); // object offset matrix; apply to verts // swap y and z; max to soft correction Matrix3 matrix(1); // translate matrix.PreTranslate( Point3( node->GetObjOffsetPos().x, node->GetObjOffsetPos().z, -node->GetObjOffsetPos().y)); // rotate AngAxis aa( node->GetObjOffsetRot()); float temp = aa.axis.z; aa.axis.z = -aa.axis.y; aa.axis.y = temp; PreRotateMatrix(matrix, Quat( aa)); // scale ScaleValue scale = node->GetObjOffsetScale(); aa.Set( scale.q); temp = aa.axis.z; aa.axis.z = -aa.axis.y; aa.axis.y = temp; scale.q.Set( aa); temp = scale.s.z; scale.s.z = scale.s.y; scale.s.y = temp; ApplyScaling(matrix, scale); // apply root transform matrix = matrix * topMatrix; // only rotation for normals AffineParts ap; Matrix3 rotMatrix(1); decomp_affine( matrix, &ap); PreRotateMatrix( rotMatrix, ap.q); // set winding order int vx1 = 0, vx2 = 1, vx3 = 2; if (TMNegParity( node->GetNodeTM(GetStaticFrame())) != TMNegParity( matrix) ) { // negative scaling; invert winding order and normal rotation vx1 = 2; vx2 = 1; vx3 = 0; rotMatrix = rotMatrix * Matrix3( Point3(-1,0,0), Point3(0,-1,0), Point3(0,0,-1), Point3(0,0,0)); } // header TSTR indent = GetIndent(indentLevel+1); fprintf(pStream, "%s%s %s {\n",indent.data(), "Mesh", FixupName(node->GetName())); // write number of verts int numLoop = mesh->getNumVerts(); fprintf(pStream, "%s\t%d;\n",indent.data(), numLoop); // write verts for (int i = 0; i < numLoop; i++) { Point3 v = mesh->verts[i]; float temp = v.z; v.z = -v.y; v.y = temp; v = matrix * v; fprintf(pStream, "%s\t%.6f;%.6f;%.6f;%s\n", indent.data(), v.x, v.y, v.z, i == numLoop - 1 ? ";\n" : ","); } // write number of faces numLoop = mesh->getNumFaces(); fprintf(pStream, "%s\t%d;\n", indent.data(), numLoop); // write faces for (i = 0; i < numLoop; i++) { fprintf(pStream, "%s\t3;%d,%d,%d;%s\n", indent.data(), mesh->faces[i].v[vx1], mesh->faces[i].v[vx2], mesh->faces[i].v[vx3], i == numLoop - 1 ? ";\n" : ","); } // face materials Mtl * nodeMtl = node->GetMtl(); int numMtls = !nodeMtl || !nodeMtl->NumSubMtls() ? 1 : nodeMtl->NumSubMtls(); // write face material list header fprintf(pStream, "%s\tMeshMaterialList {\n", indent.data()); // write number of materials fprintf(pStream, "%s\t\t%d;\n", indent.data(), numMtls); // write number of faces fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop); // write face material indices (1 for each face) for (i = 0; i < numLoop; i++) { int index = numMtls ? mesh->faces[i].getMatID() % numMtls : 0; fprintf(pStream,"%s\t\t%d%s\n", indent.data(), index, i == numLoop - 1 ? ";\n" : ","); } // write the materials ExportMaterial( node, indentLevel+2); // verts close brace fprintf(pStream, "%s\t}\n\n",indent.data()); // write normals header fprintf(pStream, "%s\t%s {\n", indent.data(), "SI_MeshNormals"); // write number of normals fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop * 3); // write normals (3 for each face) for (i = 0; i < numLoop; i++) { Face * f = &mesh->faces[i]; int vert = f->getVert(vx1); Point3 vn = GetVertexNormal(mesh, i, mesh->getRVertPtr(vert)); float temp = vn.z; vn.z = -vn.y; vn.y = temp; vn = rotMatrix * vn; fprintf(pStream,"%s\t\t%.6f;%.6f;%.6f;,\n", indent.data(), vn.x, vn.y, vn.z); vert = f->getVert(vx2); vn = GetVertexNormal(mesh, i, mesh->getRVertPtr(vert)); temp = vn.z; vn.z = -vn.y; vn.y = temp; vn = rotMatrix * vn; fprintf(pStream,"%s\t\t%.6f;%.6f;%.6f;,\n", indent.data(), vn.x, vn.y, vn.z); vert = f->getVert(vx3); vn = GetVertexNormal(mesh, i, mesh->getRVertPtr(vert)); temp = vn.z; vn.z = -vn.y; vn.y = temp; vn = rotMatrix * vn; fprintf(pStream,"%s\t\t%.6f;%.6f;%.6f;%s\n", indent.data(), vn.x, vn.y, vn.z, i == numLoop - 1 ? ";\n" : ","); } // write number of faces fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop); // write faces for (i = 0; i < numLoop; i++) { fprintf(pStream, "%s\t\t%d;3;%d,%d,%d;%s\n", indent.data(), i, i * 3 + vx1, i * 3 + vx2, i * 3 + vx3, i == numLoop - 1 ? ";\n" : ","); } // normals close brace fprintf(pStream, "%s\t}\n\n",indent.data()); // texcoords if (nodeMtl && mesh && (nodeMtl->Requirements(-1) & MTLREQ_FACEMAP)) { // facemapping numLoop = mesh->getNumFaces() * 3; // write texture coords header fprintf(pStream, "%s\tSI_MeshTextureCoords {\n", indent.data()); // write number of texture coords fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop); // write texture coords for (int i = 0; i < numLoop; i++) { Point3 tv[3]; Face * f = &mesh->faces[i]; make_face_uv( f, tv); fprintf(pStream, "%s\t\t%.6f;%.6f;,\n", indent.data(), tv[0].x, tv[0].y); fprintf(pStream, "%s\t\t%.6f;%.6f;,\n", indent.data(), tv[1].x, tv[1].y); fprintf(pStream, "%s\t\t%.6f;%.6f;%s\n", indent.data(), tv[2].x, tv[2].y, i == numLoop - 1 ? ";\n" : ","); } // write number of faces numLoop = mesh->getNumFaces(); fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop); // write faces for (i = 0; i < numLoop; i++) { fprintf(pStream,"%s\t\t%d;3;%d,%d,%d;%s\n", indent.data(), i, mesh->tvFace[i].t[vx1], mesh->tvFace[i].t[vx2], mesh->tvFace[i].t[vx3], i == numLoop - 1 ? ";\n" : ","); } // texture coords close brace fprintf(pStream, "%s\t}\n\n", indent.data()); } else { numLoop = mesh->getNumTVerts(); if (numLoop) { // write texture coords header fprintf(pStream, "%s\tSI_MeshTextureCoords {\n", indent.data()); // write number of texture coords fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop); // write texture coords for (i = 0; i < numLoop; i++) { UVVert tv = mesh->tVerts[i]; fprintf(pStream, "%s\t\t%.6f;%.6f;%s\n", indent.data(), tv.x, tv.y, i == numLoop - 1 ? ";\n" : ","); } // write number of faces numLoop = mesh->getNumFaces(); fprintf(pStream, "%s\t\t%d;\n", indent.data(), numLoop); // write faces for (i = 0; i < numLoop; i++) { fprintf(pStream,"%s\t\t%d;3;%d,%d,%d;%s\n", indent.data(), i, mesh->tvFace[i].t[vx1], mesh->tvFace[i].t[vx2], mesh->tvFace[i].t[vx3], i == numLoop - 1 ? ";\n" : ","); } // texture coords close brace fprintf(pStream, "%s\t}\n\n", indent.data()); } } /* // Export color per vertex info if (GetIncludeVertexColors()) { int numCVx = mesh->numCVerts; fprintf(pStream, "%s\t%s %d\n",indent.data(), ID_MESH_NUMCVERTEX, numCVx); if (numCVx) { fprintf(pStream,"%s\t%s {\n",indent.data(), ID_MESH_CVERTLIST); for (i=0; i<numCVx; i++) { Point3 vc = mesh->vertCol[i]; fprintf(pStream, "%s\t\t%s %d\t%s\n",indent.data(), ID_MESH_VERTCOL, i, Format(vc)); } fprintf(pStream,"%s\t}\n",indent.data()); fprintf(pStream, "%s\t%s %d\n",indent.data(), ID_MESH_NUMCVFACES, mesh->getNumFaces()); fprintf(pStream, "%s\t%s {\n",indent.data(), ID_MESH_CFACELIST); for (i=0; i<mesh->getNumFaces(); i++) { fprintf(pStream,"%s\t\t%s %d\t%d\t%d\t%d\n", indent.data(), ID_MESH_CFACE, i, mesh->vcFace[i].t[vx1], mesh->vcFace[i].t[vx2], mesh->vcFace[i].t[vx3]); } fprintf(pStream, "%s\t}\n",indent.data()); } } */ // Mesh close brace fprintf(pStream, "%s}\n",indent.data()); // dispose of tri object if (needDel) { delete tri; } }
/* Transfer the max Node's mesh to PhysX unit and store it. */ void ccMaxNode::SyncFromMaxMesh() { //MaxMsgBox(NULL, _T("SyncFromMaxMesh"), _T("Error"), MB_OK); ShapeType = NX_SHAPE_MESH; const TimeValue t = ccMaxWorld::MaxTime(); Matrix3 tm = MaxINode->GetNodeTM(t); NodePosInPhysics = tm.GetRow(3); NodePosInPhysics = ccMaxWorld::ChangeToPhysXUnit(NodePosInPhysics); ScaleValue sv = MaxINode->GetObjOffsetScale(); bool objectIsScaled = PivotScaled(sv); //if(objectIsScaled) // RemovePivotScale(MaxINode); //------------------------ MaxNodeTM = MaxINode->GetNodeTM(t); // get pivot TM MaxPivotTM.IdentityMatrix(); MaxPivotTM.SetTrans(MaxINode->GetObjOffsetPos()); PreRotateMatrix(MaxPivotTM, MaxINode->GetObjOffsetRot()); ApplyScaling(MaxPivotTM, MaxINode->GetObjOffsetScale()); // char blaat[1024]; // sprintf(blaat,"MaxPivotTM.MaxPivotTM.GetTrans()=(%f,%f,%f)",MaxPivotTM.GetTrans().x,MaxPivotTM.GetTrans().y,MaxPivotTM.GetTrans().z); // MaxMsgBox(NULL, _T(blaat), _T("Error"), MB_OK); // GetObjectTM() = MaxPivotTM * MaxNodeTM MaxNodeObjectTM = MaxINode->GetObjectTM(t); //----------------------------------------------------------------------------------------------- // object might be modified by world space modifiers. We need a solution in future for this case. bool isWorldSpace = MaxINode->GetObjTMAfterWSM(t).IsIdentity(); //----------------------------------------------------------------------------------------------- Matrix3 PhysicsNodeTM = ccMaxWorld::ChangeToPhysXUnit(MaxNodeObjectTM); // get scale TM // PhysicsNodeTM == PhysicsNodeScaleTM * PhysicsNodePoseTM Point3 maxNodeScale = ccMaxWorld::ParseScale(PhysicsNodeTM, PhysicsNodeScaleTM, PhysicsNodePoseTM); //Matrix3 right; //ParseMatrix(PhysicsNodePoseTM, right); //PhysicsNodePoseTM = right; //PhysicsNodeScaleTM = PhysicsNodeTM * Inverse(PhysicsNodePoseTM); //if(IsScaled(PhysicsNodeScaleTM)) // objectIsScaled = true; // check whether the Node's mesh is scaled equally at x/y/z ScaledIsUnified = (fabs((maxNodeScale.x - maxNodeScale.z)/maxNodeScale.z) < gTolerenceEpsilon) && (fabs((maxNodeScale.y - maxNodeScale.z)/maxNodeScale.z) < gTolerenceEpsilon); ScaledIsUnified = (! objectIsScaled) && ScaledIsUnified; //if(! ScaledIsUnified) { // PhysicsNodePoseTM.IdentityMatrix(); // PhysicsNodePoseTM.SetRow(3, NodePosInPhysics); // PhysicsNodeScaleTM = PhysicsNodeTM * Inverse(PhysicsNodePoseTM); //} PhysicsNodePoseTMInv = Inverse(PhysicsNodePoseTM); //gCurrentstream->printf("\nNxScaleTM = "); MxUtils::PrintMatrix3(PhysicsNodeScaleTM); //gCurrentstream->printf("\nNxPoseTM = "); MxUtils::PrintMatrix3(PhysicsNodePoseTM); //gCurrentstream->printf("\n"); //Matrix3 t1 = PhysicsNodeScaleTM * PhysicsNodePoseTM; //bool e1 = (t1 == MaxNodeObjectTM); Object* obj = MaxINode->EvalWorldState(t).obj; if (obj != NULL) { SimpleObject* so = (SimpleObject*)obj; Class_ID id = obj->ClassID(); if (id == Class_ID(SPHERE_CLASS_ID, 0)) { ShapeType = NX_SHAPE_SPHERE; so->pblock->GetValue(SPHERE_RADIUS, 0, PrimaryShapePara.Radius, FOREVER); PrimaryShapePara.Radius *= maxNodeScale.x * ccMaxWorld::GetUnitChange(); // x/y/z is scaled with a same value } else if (id == Class_ID(BOXOBJ_CLASS_ID, 0)) { ShapeType = NX_SHAPE_BOX; so->pblock->GetValue(BOXOBJ_WIDTH , 0, PrimaryShapePara.BoxDimension[0], FOREVER); so->pblock->GetValue(BOXOBJ_LENGTH, 0, PrimaryShapePara.BoxDimension[1], FOREVER); so->pblock->GetValue(BOXOBJ_HEIGHT, 0, PrimaryShapePara.BoxDimension[2], FOREVER); PrimaryShapePara.BoxDimension *= (0.5f * maxNodeScale.x * ccMaxWorld::GetUnitChange()); // x/y/z is scaled with a same value // Physics box is half the size } else if (id == CAPS_CLASS_ID) { ShapeType = NX_SHAPE_CAPSULE; int centersflag = 0; so->pblock->GetValue(CAPS_RADIUS , 0, PrimaryShapePara.Radius, FOREVER); so->pblock->GetValue(CAPS_HEIGHT , 0, PrimaryShapePara.Height, FOREVER); so->pblock->GetValue(CAPS_CENTERS, 0, centersflag, FOREVER); if(!centersflag) //there are some different ways in which you can specify a capsule in 3ds max, adjust length if "center" mode is not used PrimaryShapePara.Height -= PrimaryShapePara.Radius * 2.0f; PrimaryShapePara.Radius *= maxNodeScale.x * ccMaxWorld::GetUnitChange(); // x/y/z is scaled with a same value PrimaryShapePara.Height *= maxNodeScale.x * ccMaxWorld::GetUnitChange(); // x/y/z is scaled with a same value } } if(! ScaledIsUnified) ShapeType = NX_SHAPE_MESH; // Disable backface culling for cloth //MaxINode->BackCull(FALSE); // get mesh BOOL needDel = FALSE; TriObject* tri = MxUtils::GetTriObjectFromNode(MaxINode, t, needDel); if (tri == NULL) return; Mesh& mesh = tri->GetMesh(); SimpleMesh.alloc(mesh.getNumVerts(), mesh.getNumFaces()); //Matrix3 change = PhysicsNodeTM * Inverse(PhysicsNodePoseTM); for(NxU32 i = 0; i < SimpleMesh.numPoints; i++) { Point3 tmp = mesh.verts[i] * ccMaxWorld::GetUnitChange() * PhysicsNodeScaleTM; ((Point3*)SimpleMesh.points)[i] = tmp; // systemTM is unit change TM. } for(NxU32 i = 0; i < SimpleMesh.numFaces; i++) { for(NxU32 j = 0; j < 3; j++) { SimpleMesh.faces[i*3+j] = mesh.faces[i].v[j]; } } if (needDel) tri->DeleteMe(); }
void ResetXForm::ResetNodes(const INodeTab& nodesToReset) { Interface *ip = GetCOREInterface(); for (int i = 0; i < nodesToReset.Count(); i++) { INode *node = nodesToReset[i]; if (!node || node->IsGroupMember() || node->IsGroupHead()) continue; if (SelectedAncestor(node)) continue; Matrix3 ntm, ptm, rtm(1), piv(1), tm; // Get Parent and Node TMs ntm = node->GetNodeTM(ip->GetTime()); ptm = node->GetParentTM(ip->GetTime()); // Compute the relative TM ntm = ntm * Inverse(ptm); // The reset TM only inherits position rtm.SetTrans(ntm.GetTrans()); // Set the node TM to the reset TM tm = rtm*ptm; node->SetNodeTM(ip->GetTime(), tm); // Compute the pivot TM piv.SetTrans(node->GetObjOffsetPos()); PreRotateMatrix(piv,node->GetObjOffsetRot()); ApplyScaling(piv,node->GetObjOffsetScale()); // Reset the offset to 0 node->SetObjOffsetPos(Point3(0,0,0)); node->SetObjOffsetRot(IdentQuat()); node->SetObjOffsetScale(ScaleValue(Point3(1,1,1))); // Take the position out of the matrix since we don't reset position ntm.NoTrans(); // Apply the offset to the TM ntm = piv * ntm; // Apply a derived object to the node's object Object *obj = node->GetObjectRef(); IDerivedObject *dobj = CreateDerivedObject(obj); // Create an XForm mod SimpleMod *mod = (SimpleMod*)ip->CreateInstance( OSM_CLASS_ID, Class_ID(CLUSTOSM_CLASS_ID,0)); // Apply the transformation to the mod. SetXFormPacket pckt(ntm); mod->tmControl->SetValue(ip->GetTime(),&pckt); // Add the modifier to the derived object. dobj->SetAFlag(A_LOCK_TARGET); // RB 3/11/99: When the macro recorder is on the derived object will get deleted unless it is locked. dobj->AddModifier(mod); dobj->ClearAFlag(A_LOCK_TARGET); // Replace the node's object node->SetObjectRef(dobj); } // Why on earth were we clearing the undo stack? // GetSystemSetting(SYSSET_CLEAR_UNDO); ip->RedrawViews(ip->GetTime()); SetSaveRequiredFlag(TRUE); }