void TSShapeInstance::MeshObjectInstance::render( S32 objectDetail, TSMaterialList *materials, const TSRenderState &rdata, F32 alpha ) { PROFILE_SCOPE( TSShapeInstance_MeshObjectInstance_render ); if ( forceHidden || ( ( visible * alpha ) <= 0.01f ) ) return; TSMesh *mesh = getMesh(objectDetail); if ( !mesh ) return; const MatrixF &transform = getTransform(); if ( rdata.getCuller() ) { Box3F box( mesh->getBounds() ); transform.mul( box ); if ( rdata.getCuller()->isCulled( box ) ) return; } GFX->pushWorldMatrix(); GFX->multWorld( transform ); mesh->setFade( visible * alpha ); // Pass a hint to the mesh that time has advanced and that the // skin is dirty and needs to be updated. This should result // in the skin only updating once per frame in most cases. const U32 currTime = Sim::getCurrentTime(); bool isSkinDirty = currTime != mLastTime; mesh->render( materials, rdata, isSkinDirty, *mTransforms, mVertexBuffer, mPrimitiveBuffer ); // Update the last render time. mLastTime = currTime; GFX->popWorldMatrix(); }
PhysicsCollision* CollisionComponent::buildColShapes() { PROFILE_SCOPE(CollisionComponent_buildColShapes); PhysicsCollision *colShape = NULL; U32 surfaceKey = 0; TSShape* shape = mOwnerRenderInterface->getShape(); if (mCollisionType == VisibleMesh) { // Here we build triangle collision meshes from the // visible detail levels. // A negative subshape on the detail means we don't have geometry. const TSShape::Detail &detail = shape->details[0]; if (detail.subShapeNum < 0) return NULL; // We don't try to optimize the triangles we're given // and assume the art was created properly for collision. ConcretePolyList polyList; polyList.setTransform(&MatrixF::Identity, mOwner->getScale()); // Create the collision meshes. S32 start = shape->subShapeFirstObject[detail.subShapeNum]; S32 end = start + shape->subShapeNumObjects[detail.subShapeNum]; for (S32 o = start; o < end; o++) { const TSShape::Object &object = shape->objects[o]; if (detail.objectDetailNum >= object.numMeshes) continue; // No mesh or no verts.... nothing to do. TSMesh *mesh = shape->meshes[object.startMeshIndex + detail.objectDetailNum]; if (!mesh || mesh->mNumVerts == 0) continue; // Gather the mesh triangles. polyList.clear(); mesh->buildPolyList(0, &polyList, surfaceKey, NULL); // Create the collision shape if we haven't already. if (!colShape) colShape = PHYSICSMGR->createCollision(); // Get the object space mesh transform. MatrixF localXfm; shape->getNodeWorldTransform(object.nodeIndex, &localXfm); colShape->addTriangleMesh(polyList.mVertexList.address(), polyList.mVertexList.size(), polyList.mIndexList.address(), polyList.mIndexList.size() / 3, localXfm); } // Return what we built... if anything. return colShape; } else if (mCollisionType == CollisionMesh) { // Scan out the collision hulls... // // TODO: We need to support LOS collision for physics. // for (U32 i = 0; i < shape->details.size(); i++) { const TSShape::Detail &detail = shape->details[i]; const String &name = shape->names[detail.nameIndex]; // Is this a valid collision detail. if (!dStrStartsWith(name, colisionMeshPrefix) || detail.subShapeNum < 0) continue; // Now go thru the meshes for this detail. S32 start = shape->subShapeFirstObject[detail.subShapeNum]; S32 end = start + shape->subShapeNumObjects[detail.subShapeNum]; if (start >= end) continue; for (S32 o = start; o < end; o++) { const TSShape::Object &object = shape->objects[o]; const String &meshName = shape->names[object.nameIndex]; if (object.numMeshes <= detail.objectDetailNum) continue; // No mesh, a flat bounds, or no verts.... nothing to do. TSMesh *mesh = shape->meshes[object.startMeshIndex + detail.objectDetailNum]; if (!mesh || mesh->getBounds().isEmpty() || mesh->mNumVerts == 0) continue; // We need the default mesh transform. MatrixF localXfm; shape->getNodeWorldTransform(object.nodeIndex, &localXfm); // We have some sort of collision shape... so allocate it. if (!colShape) colShape = PHYSICSMGR->createCollision(); // Any other mesh name we assume as a generic convex hull. // // Collect the verts using the vertex polylist which will // filter out duplicates. This is importaint as the convex // generators can sometimes fail with duplicate verts. // VertexPolyList polyList; MatrixF meshMat(localXfm); Point3F t = meshMat.getPosition(); t.convolve(mOwner->getScale()); meshMat.setPosition(t); polyList.setTransform(&MatrixF::Identity, mOwner->getScale()); mesh->buildPolyList(0, &polyList, surfaceKey, NULL); colShape->addConvex(polyList.getVertexList().address(), polyList.getVertexList().size(), meshMat); } // objects } // details } return colShape; }