int PhysicsServer::GetObjectID( const char* name, JObject* context ) { int nObj = m_Objects.size(); for (int i = 0; i < nObj; i++) { JObject* pObject = m_Objects[i]; if (!pObject) continue; if (!stricmp( name, pObject->GetName() ) && (!context || pObject->GetParent() == context )) return i; } if (context == NULL) { context = this; } PhysObject* pObj = g_pObjectServer->FindObject<PhysObject>( name, context ); if (pObj) { m_Objects.push_back( pObj ); int id = m_Objects.size() - 1; pObj->SetID( id ); return id; } return -1; } // PhysicsServer::GetObjectID
int JLuaServer::FnSet( lua_State* pLua ) { if (lua_gettop( pLua ) < 3 || lua_gettop( pLua ) > 4) { rlog.err( "LUA: Incorrect command usage: <set>. " "Function takes 3 or 4 arguments (<objectRef>|<objectName>, <propName>, <val>, [tag]), but %d is provided", lua_gettop( pLua ) ); lua_settop( pLua, 0 ); lua_pushnil( pLua ); return 1; } JObject* pObj = NULL; const char* pPath = lua_tostring( pLua, 1 ); if (pPath) { JLuaThread* pThread = reinterpret_cast<JLuaThread*>( pLua->userdata ); assert( pThread->m_pLua == pLua ); JObject* pRootObj = pThread->m_pRootObj; pObj = g_pObjectServer->FindObject( pPath, NULL, pRootObj ); } else { pObj = reinterpret_cast<JObject*>( lua_touserdata( pLua, 1 ) ); } const char* pPropName = lua_tostring( pLua, 2 ); const char* pPropVal = lua_tostring( pLua, 3 ); if (!pPropVal && lua_isboolean( pLua, 3 )) { bool bVal = lua_toboolean( pLua, 3 ) == 0 ? false : true; pPropVal = bVal ? "true" : "false"; } int tag = -1; if (lua_isnumber( pLua, 4 )) { tag = (int)lua_tonumber( pLua, 4 ); } if (!pObj) { rlog.warn( "LUA: Trying to call <set> for the nil object." ); return 0; } bool bRes = pObj->SetProperty( pPropName, pPropVal, tag ); if (!bRes) { rlog.err( "LUA: Could not set property '%s' for object '%s' of type '%s'.", pPropName, pObj->GetName(), pObj->ClassName() ); } return 0; } // JLuaServer::FnSet
int JLuaServer::FnCall( lua_State* pLua ) { if (lua_gettop( pLua ) < 2 || lua_gettop( pLua ) > 3) { rlog.err( "LUA: Incorrect command usage: <call>. " "Function takes 2 to 3 arguments (object|objectName, funcName, [tag]), but %d is provided", lua_gettop( pLua ) ); lua_settop( pLua, 0 ); return 0; } JObject* pObj = NULL; const char* pPath = lua_tostring( pLua, 1 ); if (pPath) { JLuaThread* pThread = reinterpret_cast<JLuaThread*>( pLua->userdata ); assert( pThread->m_pLua == pLua ); JObject* pRootObj = pThread->m_pRootObj; pObj = g_pObjectServer->FindObject( pPath, NULL, pRootObj ); if (!pObj) { rlog.warn( "LUA: Method <call> refers to non-existing object: %s", pPath ); return NULL; } } else { pObj = reinterpret_cast<JObject*>( lua_touserdata( pLua, 1 ) ); if (!pObj) { rlog.warn( "LUA: Trying to call <call> for the nil object" ); return NULL; } } const char* pMethodName = lua_tostring( pLua, 2 ); int tag = -1; if (lua_isnumber( pLua, 3 )) { tag = (int)lua_tonumber( pLua, 3 ); } bool bRes = pObj->CallMethod( pMethodName, tag ); if (!bRes) { rlog.err( "LUA: Could not call method '%s' for object '%s' of type '%s'.", pMethodName, pObj->GetName(), pObj->ClassName() ); } return 0; } // JLuaServer::FnCall
int JLuaServer::FnGet( lua_State* pLua ) { if (lua_gettop( pLua ) < 2 || lua_gettop( pLua ) > 3) { rlog.err( "LUA: Incorrect command usage: <get>. " "Function takes 2 or 3 arguments (<objectRef>|<objectName>, <propName>, [tag]), but %d is provided", lua_gettop( pLua ) ); lua_settop( pLua, 0 ); lua_pushnil( pLua ); return 1; } JObject* pObj = NULL; const char* pPath = lua_tostring( pLua, 1 ); if (pPath) { JLuaThread* pThread = reinterpret_cast<JLuaThread*>( pLua->userdata ); assert( pThread->m_pLua == pLua ); JObject* pRootObj = pThread->m_pRootObj; pObj = g_pObjectServer->FindObject( pPath, NULL, pRootObj ); } else { pObj = reinterpret_cast<JObject*>( lua_touserdata( pLua, 1 ) ); } const char* pPropName = lua_tostring( pLua, 2 ); int tag = -1; if (lua_isnumber( pLua, 3 )) { tag = (int)lua_tonumber( pLua, 3 ); } if (!pObj) { rlog.warn( "LUA: Trying to call <get> for the nil object. Nil is returned." ); lua_pushnil( pLua ); return 1; } static JString val; bool bRes = pObj->GetProperty( pPropName, val, tag ); if (!bRes) { rlog.err( "LUA: Could not get property '%s' for object '%s' of type '%s'.", pPropName, pObj->GetName(), pObj->ClassName() ); } lua_pushstring( pLua, val.c_str() ); return 1; } // JLuaServer::FnGet
JObject* RBExport::ProcessPhysicsObject( INode* node ) { ObjectState os = node->EvalWorldState( m_CurTime ); Object* pObj = os.obj; const char* pNodeName = node->GetName(); if (!pObj) { Warn( "Physics node %s is invalid.", pNodeName ); } JObject* pPhysObj = NULL; Mat4 objTM = Convert( GetLocalTM( node, m_CurTime ) ); JString hostName = ""; ExpNode* pExportedParent = GetExportedNode( node->GetParentNode() ); if (pExportedParent && pExportedParent->m_pObject) { JObject* pParentObj = pExportedParent->m_pObject; if (obj_cast<PhysBody>( pParentObj )) { hostName = pParentObj->GetName(); } else if (obj_cast<JBone>( pParentObj )) { hostName = pParentObj->GetName(); } } // check for joint type DWORD scID = pObj->SuperClassID(); if (scID == HELPER_CLASS_ID) { PhysJoint* pJoint = new PhysJoint(); pJoint->SetHostBone( hostName.c_str() ); pPhysObj = pJoint; } else { CStr className; pObj->GetClassName( className ); IParamArray* pParam = pObj->GetParamBlock(); IParamBlock* pParamBlock = NULL; if (pParam) pParamBlock = pParam->GetParamBlock(); if (!stricmp( className, "sphere" )) { ColSphere* pSphere = new ColSphere(); pPhysObj = pSphere; float radius = 0.0f; pParamBlock->GetValue( SPHERE_RADIUS, 0, radius, FOREVER ); pSphere->SetRadius( radius ); pSphere->SetHost( hostName.c_str() ); pSphere->SetOffsetTM( objTM ); } if (!stricmp( className, "box" )) { ColBox* pBox = new ColBox(); pPhysObj = pBox; Vec3 ext; pParamBlock->GetValue( BOXOBJ_LENGTH, 0, ext.x, FOREVER ); pParamBlock->GetValue( BOXOBJ_WIDTH, 0, ext.y, FOREVER ); pParamBlock->GetValue( BOXOBJ_HEIGHT, 0, ext.z, FOREVER ); pBox->SetExtents( ext ); pBox->SetHost( hostName.c_str() ); pBox->SetOffsetTM( objTM ); } if (!stricmp( className, "capsule" )) { ColCapsule* pCapsule = new ColCapsule(); pPhysObj = pCapsule; int bCenters = 0; float radius = 0.0f; float height = 0.0f; pParamBlock->GetValue( PB_RADIUS, 0, radius, FOREVER ); pParamBlock->GetValue( PB_HEIGHT, 0, height, FOREVER ); pParamBlock->GetValue( PB_CENTERS, 0, bCenters, FOREVER ); pCapsule->SetRadius( radius ); pCapsule->SetHeight( height ); pCapsule->SetHost( hostName.c_str() ); pCapsule->SetOffsetTM( objTM ); } if (!stricmp( className, "cylinder" )) { ColCylinder* pCylinder = new ColCylinder(); pPhysObj = pCylinder; int bCenters = 0; float radius = 0.0f; float height = 0.0f; pParamBlock->GetValue( PB_RADIUS, 0, radius, FOREVER ); pParamBlock->GetValue( PB_HEIGHT, 0, height, FOREVER ); pParamBlock->GetValue( PB_CENTERS, 0, bCenters, FOREVER ); pCylinder->SetRadius( radius ); pCylinder->SetHeight( height ); pCylinder->SetHost( hostName.c_str() ); pCylinder->SetOffsetTM( objTM ); } if (!stricmp( className, "teapot" )) { // by teapot we represent physical body (point of mass) PhysBody* pBody = new PhysBody(); pBody->SetHostBone( hostName.c_str() ); pPhysObj = pBody; pBody->SetOffsetTM( objTM ); } // if none of above, try to export as trimesh collision primitive if (pPhysObj == NULL && scID == GEOMOBJECT_CLASS_ID) { ColMesh* pMesh = GetColMesh( node ); if (pMesh) { pPhysObj = pMesh; pMesh->SetHost( hostName.c_str() ); pMesh->SetOffsetTM( objTM ); } } } if (pPhysObj) { if (!m_pPhysicsGroup) { m_pPhysicsGroup = new JGroup(); m_pPhysicsGroup->SetName( "physics" ); } pPhysObj->SetName( pNodeName ); m_pPhysicsGroup->AddChild( pPhysObj ); } else { Warn( "Unrecognized physics object type in node %s", pNodeName ); return NULL; } return pPhysObj; } // RBExport::ProcessPhysicsObject
void RBExport::AddMesh( int meshID, int startVByte, int startVert, int nVert, int startFace, int nFaces ) { if (nVert == 0) return; // create mesh JMesh* pMesh = new JMesh(); char nameBuf[_MAX_PATH]; const char* nodeName = m_Nodes[m_Vertices[startVert]->nodeID].m_pNode->GetName(); sprintf( nameBuf, "%s_mesh", nodeName ); // create skin bone list std::vector<int> boneReindex; boneReindex.resize( m_Nodes.size() ); std::fill( boneReindex.begin(), boneReindex.end(), -1 ); int nMeshBones = 0; for (int i = 0; i < nVert; i++) { ExpVertex& v = *m_Vertices[startVert + i]; for (int j = 0; j < v.nBones; j++) { int boneIdx = v.boneIdx[j]; if (boneIdx == -1) continue; if (boneReindex[boneIdx] == -1) { pMesh->AddBone( m_Nodes[boneIdx].m_pNode->GetName() ); boneReindex[boneIdx] = nMeshBones; nMeshBones++; } v.boneIdx[j] = boneReindex[boneIdx]; } } if (pMesh->GetNSkinBones() > c_MaxBonesPerSkin) { Err( "Mesh %s exceeds bone limit. Number of ones is %d, maximum allowed is %d.", nodeName, pMesh->GetNSkinBones(), c_MaxBonesPerSkin ); } // check whether all the references to bones within indices are in correct range for (int i = 0; i < nVert; i++) { const ExpVertex& v = *(m_Vertices[startVert + i]); for (int j = 0; j < v.nBones; j++) { if (v.boneIdx[j] >= 0 && v.boneIdx[j] < pMesh->GetNSkinBones()) { continue; } Err( "Skin of mesh %s has incorrect bone reference: %d.", nodeName, v.boneIdx[j] ); } } // create vertex declaration VertexDeclaration vertexDecl = GetVDecl( startVert, nVert ); int vertexStride = vertexDecl.m_VertexSize; // create vertex buffer int nVertBytes = nVert*vertexStride; Buffer vbuf( nVertBytes ); FillVertexBuffer( vbuf.GetData(), vertexDecl, startVert, nVert ); // add vertices to model m_pModel->AddVertices( vbuf.GetData(), nVertBytes ); int mtlID = m_Vertices[startVert]->mtlID; const char* mtlName = ""; if (mtlID >= 0) mtlName = m_Materials[mtlID]->GetName(); int nodeID = m_Vertices[startVert]->nodeID; JObject* pHostBone = m_Nodes[nodeID].m_pObject; pMesh->SetName ( nameBuf ); pMesh->SetVisible ( true ); pMesh->SetVertexRange( startVByte, nVert ); pMesh->SetIndexRange ( startFace*3, nFaces*3 ); pMesh->SetVDecl ( vertexDecl ); pMesh->SetMaterial ( mtlName ); pMesh->SetHostBone ( pHostBone->GetName() ); // add faces to model std::vector<WORD> idx; int nIdx = 3*nFaces; idx.resize( nIdx ); for (int j = 0; j < nIdx; j += 3) { ExpFace& face = m_Faces[startFace + j/3]; idx[j + 0] = face.pV0->index - startVert; idx[j + 1] = face.pV1->index - startVert; idx[j + 2] = face.pV2->index - startVert; } m_pModel->AddIndices( &idx[0], nIdx ); m_pModel->AddChild( pMesh ); } // RBExport::AddMeshData