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(); }
TSMesh* AppMesh::constructTSMesh() { TSMesh* tsmesh; if (isSkin()) { TSSkinMesh* tsskin = new TSSkinMesh(); tsmesh = tsskin; // Copy skin elements tsskin->weight = weight; tsskin->boneIndex = boneIndex; tsskin->vertexIndex = vertexIndex; tsskin->batchData.nodeIndex = nodeIndex; tsskin->batchData.initialTransforms = initialTransforms; tsskin->batchData.initialVerts = initialVerts; tsskin->batchData.initialNorms = initialNorms; } else { tsmesh = new TSMesh(); } // Copy mesh elements tsmesh->verts = points; tsmesh->norms = normals; tsmesh->tverts = uvs; tsmesh->primitives = primitives; tsmesh->indices = indices; tsmesh->colors = colors; tsmesh->tverts2 = uv2s; // Finish initializing the shape tsmesh->setFlags(flags); tsmesh->computeBounds(); tsmesh->numFrames = numFrames; tsmesh->numMatFrames = numMatFrames; tsmesh->vertsPerFrame = vertsPerFrame; tsmesh->createTangents(tsmesh->verts, tsmesh->norms); tsmesh->encodedNorms.set(NULL,0); return tsmesh; }
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; }
void SoftBody::prepBatchRender(SceneRenderState* state, S32 mountedImageIndex ) { if (!m_physShapeSoft || m_physShapeSoft->getNodesNum()==0 || gFreezeSim || m_stopSimulation) { Parent::prepBatchRender(state,mountedImageIndex); return; } TSShapeInstance* shapeInst = getShapeInstance(); S32 dl = 0; const TSShape* shape = getShape(); const TSDetail * detail = &shape->details[dl]; S32 ss = detail->subShapeNum; S32 od = detail->objectDetailNum; U32 vertexStride = shape->getVertexSize(); S32 start = shape->subShapeFirstObject[ss]; S32 end = shape->subShapeNumObjects[ss] + start; int physVertexIdx = 0; for (S32 i=start; i<end; i++) { TSShapeInstance::MeshObjectInstance* meshOI = &shapeInst->mMeshObjects[i]; if (od >= meshOI->object->numMeshes) continue; TSMesh* mesh = meshOI->getMesh(od); if (mesh) { mesh->setManualDynamic(true); TSVertexBufferHandle& vb = meshOI->mVertexBuffer; if (vb == NULL) mesh->createVBIB(vb); U8 *vertData = (U8*)vb.lock(); for(size_t i = 0;i<mesh->mNumVerts;i++) { Point3F physVertex = m_physShapeSoft->getNodePos(m_vertexBindingVec[physVertexIdx++]); //transform into local coordinates mRenderWorldToObj.mulP(physVertex); physVertex.convolveInverse(mObjScale); *((Point3F*)vertData) = physVertex; vertData += vertexStride; } vb.unlock(); } } Parent::prepBatchRender(state,mountedImageIndex); for (S32 i=start; i<end; i++) { TSShapeInstance::MeshObjectInstance* meshOI = &shapeInst->mMeshObjects[i]; if (od >= meshOI->object->numMeshes) continue; TSMesh* mesh = meshOI->getMesh(od); if (mesh) mesh->setManualDynamic(false); } }