void VCoronaManager::RenderCorona (VCoronaCandidate& coronaCandidate, VTextureObject*& pTexture) { #ifdef SUPPORTS_CORONAS VCoronaComponent *pCorona = coronaCandidate.m_pCorona; VisRenderContext_cl* pContext = VisRenderContext_cl::GetCurrentContext(); VisLightSource_cl* pLight = (VisLightSource_cl*)pCorona->GetOwner(); hkvVec3 vLightPos(hkvNoInitialization); pLight->GetVirtualPosition(vLightPos, pContext); hkvVec3 vEyePos(hkvNoInitialization); pContext->GetCamera()->GetPosition(vEyePos); hkvVec3 vDir = pContext->GetCamera()->GetDirection(); // Corona texture VTextureObject *pTex = pCorona->GetCoronaTexture(); if (pTex == NULL) return; if (pTexture != pTex) { pTexture = pTex; Vision::RenderLoopHelper.BindMeshTexture(pTexture,0); } // Get light color VColorRef color = pLight->GetColor(); hkvVec3 vDist = vLightPos - vEyePos; float fEyeDist = vDir.dot(vDist); //determine if camera is in light cone if the light is directional float fDirectionalDampening = 1.0f; if ( pLight->GetType() == VIS_LIGHT_SPOTLIGHT && pCorona->GetOnlyVisibleInSpotLight() ) { fDirectionalDampening = 0.0f; float fConeAngle = pLight->GetProjectionAngle(); float fConeLength = pLight->GetRadius(); hkvVec3 fConeDirection = pLight->GetDirection(); fConeDirection.normalize(); hkvVec3 vLightEyeDist = vEyePos - vLightPos; //#2 check if the camera is inside the angle of the cone float cosinusAngle = (vLightEyeDist/vLightEyeDist.getLength()).dot(fConeDirection); float fDegree = hkvMath::acosDeg(cosinusAngle); float normRadius = fDegree / (fConeAngle/2.0f); if (normRadius < 1.0f) { //hardcoded falloff. For better performance, we avoid sampling the projection texture here. const float fEpsilon = 64.0f/256.0f; const float fQuadFactor = 1.0f/fEpsilon - 1.0f; fDirectionalDampening = 1.0f / (1.0f + fQuadFactor*normRadius*normRadius); // scale the function so that the value is exactly 0.0 at the edge and 1.0 in the center fDirectionalDampening = (fDirectionalDampening - fEpsilon) / (1.0f - fEpsilon); } } // Fog params float fFogDampening = 1.0f; if (pLight->GetType() != VIS_LIGHT_DIRECTED && Vision::World.IsLinearDepthFogEnabled()) { const VFogParameters &fog = Vision::World.GetFogParameters(); float fFogStart = fog.fDepthStart; float fFogEnd = fog.fDepthEnd; float fFogFactor = (fFogEnd > fFogStart) ? ((fEyeDist - fFogStart) / (fFogEnd - fFogStart)) : 0.f; fFogDampening = 1.0f - hkvMath::clamp(fFogFactor, 0.0f, 1.0f); } // Get corona rotation float fRotation = 0.0f; hkvVec4 vRotation(1.0f, 0.0f, 0.0f, 1.0f); if (pCorona->CoronaFlags & VIS_CORONASCALE_ROTATING) { fRotation = hkvMath::mod (fEyeDist * 0.5f, 360.f); vRotation.x = hkvMath::cosDeg (fRotation); vRotation.y = -hkvMath::sinDeg (fRotation); vRotation.z = -vRotation.y; vRotation.w = vRotation.x; } // Texture dimensions int iSizeX, iSizeY, depth; pTex->GetTextureDimensions(iSizeX, iSizeY, depth); hkvVec4 vScale(0.0f, 0.0f, 0.0f, 0.0f); int iMainWidth, iMainHeight, iWidth, iHeight; pContext->GetSize(iWidth, iHeight); VisRenderContext_cl::GetMainRenderContext()->GetSize(iMainWidth, iMainHeight); // Preserve texture aspect ratio int iTexHeight = pTex->GetTextureHeight(); int iTexWidth = pTex->GetTextureWidth(); // Perspective scaling // This scaling ensures roughly the same size on 720p as the old implementation. vScale.z = iTexWidth * pCorona->CoronaScaling * 0.25f; vScale.w = iTexHeight * pCorona->CoronaScaling * 0.25f; // Screen-space scaling // This scaling ensures roughly the same size on 720p as the old implementation. const float fScaleFactor = pCorona->CoronaScaling * iMainHeight / 11.0f; vScale.x = ((float)iTexWidth / 128.0f) * fScaleFactor * (float(iWidth) / float(iMainWidth)); vScale.y = ((float)iTexHeight / 128.0f) * fScaleFactor * (float(iHeight) / float(iMainHeight)); vScale.x *= 2.0f / iWidth; vScale.y *= 2.0f / iHeight; // Scale by visibility if (pCorona->CoronaFlags & VIS_CORONASCALE_VISIBLEAREA) { vScale.x *= coronaCandidate.m_fCurrentVisibility; vScale.y *= coronaCandidate.m_fCurrentVisibility; vScale.z *= coronaCandidate.m_fCurrentVisibility; vScale.w *= coronaCandidate.m_fCurrentVisibility; } VCompiledShaderPass* pShader = m_spCoronaTechnique->GetShader(0); VShaderConstantBuffer *pVertexConstBuffer = pShader->GetConstantBuffer(VSS_VertexShader); // xyz = worldspace position, w = 1.0 if VIS_CORONASCALE_DISTANCE is true, otherwise zero. pVertexConstBuffer->SetSingleParameterF("coronaPosition", vLightPos.x, vLightPos.y, vLightPos.z, (pCorona->CoronaFlags & VIS_CORONASCALE_DISTANCE) ? 1.0f : 0.0f); // xyz = light color, w = corona visibility. pVertexConstBuffer->SetSingleParameterF("coronaColor", color.r/255.0f, color.g/255.0f, color.b/255.0f, coronaCandidate.m_fCurrentVisibility * fFogDampening * fDirectionalDampening); // xyzw = 2x2 rotation matrix. float2x2 is not supported in shader model 2, so a float4 is used and multiplication is done manually in the shader. pVertexConstBuffer->SetSingleParameterF("coronaRotation", vRotation.x, vRotation.y, vRotation.z, vRotation.w); // xy = screen-space scaling. zw = view-space scaling. pVertexConstBuffer->SetSingleParameterF("coronaScale", vScale.x, vScale.y, vScale.z, vScale.w); Vision::RenderLoopHelper.RenderMeshes(pShader, VisMeshBuffer_cl::MB_PRIMTYPE_TRILIST, 0, 2, 6); #endif }
// load a file if we recognize the type. DWORD CXMLWorldLoader::OnLoadWorldFile(DWORD size, void *params) { CHashString oldVersion = _T(""); CREATEOBJECTPARAMS cop; INITOBJECTPARAMS iop; SERIALIZEOBJECTPARAMS sop; DWORD retVal; IXMLArchive *Archive = NULL; DWORD currNode = 0; LOADINGUPDATEPARAMS pbp; VERIFY_MESSAGE_SIZE(size, sizeof(TCHAR *)); TCHAR *pFileName = (TCHAR *)params; // use both a hashstring and a pointer so that the first iteration of the loop // will pass SetParentName a NULL instead of an address of a hashstring // hashed to "" CHashString hszParentType(_T("CWorld")); CHashString hszParentName(_T("World")); CHashString hszName(_T("")); CHashString hszTypeName(_T("")); CHashString streamType(_T("File")); // delete previous world root DELETEOBJECTPARAMS dop; dop.name = &hszParentName; static DWORD msgHash_DeleteObject = CHashString(_T("DeleteObject")).GetUniqueID(); EngineGetToolBox()->SendMessage(msgHash_DeleteObject, sizeof(dop), &dop ); // delete is ok to fail if no world has been created yet // create new world root cop.name = &hszParentName; cop.parentName = NULL; cop.typeName = &hszParentType; static DWORD msgHash_CreateObject = CHashString(_T("CreateObject")).GetUniqueID(); DWORD returnValue = EngineGetToolBox()->SendMessage(msgHash_CreateObject, sizeof(cop), &cop ); if (returnValue != MSG_HANDLED) { EngineGetToolBox()->Log(LOGERROR, _T("Failed to create World Root Object\n")); return MSG_ERROR; } CREATEARCHIVE ca; ca.streamData = (void *)pFileName; ca.mode = STREAM_MODE_READ; ca.streamType = &streamType; #ifdef USEXMLFILESTREAMS // call the Archive factory to create an XML archive static DWORD msgHash_CreateXMLArchiveStream = CHashString(_T("CreateXMLArchiveStream")).GetUniqueID(); if (retVal = m_ToolBox->SendMessage(msgHash_CreateXMLArchiveStream, sizeof(CREATEARCHIVE), &ca) != MSG_HANDLED) #else // call the Archive factory to create an XML archive static DWORD msgHash_CreateXMLArchive = CHashString(_T("CreateXMLArchive")).GetUniqueID(); if (retVal = m_ToolBox->SendMessage(msgHash_CreateXMLArchive, sizeof(CREATEARCHIVE), &ca) != MSG_HANDLED) #endif { return retVal; } Archive = dynamic_cast<IXMLArchive *>(ca.archive); DWORD numNodes = Archive->GetNumberOfNodes(); // Deteriminte World Version int iWorldNumAttrib = Archive->GetNumAttributes(); StdString szNodeName; Archive->GetNode(szNodeName); pbp.currentPosition = Archive->GetCurrentNodePosition(); pbp.totalSize = numNodes; // update progress bar static DWORD msgHash_LoadingUpdate = CHashString(_T("LoadingUpdate")).GetUniqueID(); m_ToolBox->SendMessage(msgHash_LoadingUpdate, sizeof(LOADINGUPDATEPARAMS), &pbp); // must start with <World> if (szNodeName != _T("CWorld")) { EngineGetToolBox()->SetErrorValue(WARN_INVALID_FILE); EngineGetToolBox()->Log(LOGWARNING, _T("Invalid world file %s\n"), pFileName); Archive->Close(); return MSG_ERROR; } // Version 1.0 if( iWorldNumAttrib == 1 ) { // read the name of the world StdString szName; Archive->Read( szName, _T("Name") ); m_WorldFileVersion = 1.0f; static DWORD msgHash_GetFileVersion = CHashString(_T("GetFileVersion")).GetUniqueID(); DWORD retval = m_ToolBox->SendMessage(msgHash_GetFileVersion, sizeof(IHashString), &oldVersion); if (retval != MSG_HANDLED) { m_ToolBox->Log(LOGERROR, _T("Could not get world version!")); return MSG_ERROR; } CHashString hszNewVersion = _T("1.0"); static DWORD msgHash_SetFileVersion = CHashString(_T("SetFileVersion")).GetUniqueID(); retval = m_ToolBox->SendMessage(msgHash_SetFileVersion, sizeof(IHashString), &hszNewVersion); if (retval != MSG_HANDLED) { m_ToolBox->Log(LOGERROR, _T("Could not set world version!")); return MSG_ERROR; } } // Version 1.5 else if( iWorldNumAttrib == 2 ) { StdString szName; Archive->Read( szName, _T("Name") ); float fileVersion = 0; Archive->Read( m_WorldFileVersion, _T("Version") ); static DWORD msgHash_GetFileVersion = CHashString(_T("GetFileVersion")).GetUniqueID(); DWORD retval = m_ToolBox->SendMessage(msgHash_GetFileVersion, sizeof(IHashString), &oldVersion); if (retval != MSG_HANDLED) { m_ToolBox->Log(LOGERROR, _T("Could not get world version!")); return MSG_ERROR; } TCHAR buf[50]; _stprintf(buf, "%.1f", m_WorldFileVersion); CHashString hszNewVersion(buf); static DWORD msgHash_SetFileVersion = CHashString(_T("SetFileVersion")).GetUniqueID(); retval = m_ToolBox->SendMessage(msgHash_SetFileVersion, sizeof(IHashString), &hszNewVersion); if (retval != MSG_HANDLED) { m_ToolBox->Log(LOGERROR, _T("Could not set world version!")); return MSG_ERROR; } } // Unknown Version else { EngineGetToolBox()->SetErrorValue(WARN_INVALID_FILE); EngineGetToolBox()->Log(LOGWARNING, _T("Invalid world file %s\n"), pFileName); Archive->Close(); static DWORD msgHash_SetFileVersion = CHashString(_T("SetFileVersion")).GetUniqueID(); m_ToolBox->SendMessage(msgHash_SetFileVersion, sizeof(IHashString), &oldVersion); return MSG_ERROR; } // failure checks bool componentFailed = false; int failedDepth = 0; float secondsPerFrame = 1 / m_fLoadingUpdateFPS; ITimer *timer = EngineGetToolBox()->GetTimer(); float lastLoadTime = timer->GetRealTime(); float elapsedTime = 0.0f; while (Archive->GetNode(szNodeName)) { int currDepth = Archive->GetDepth(); if (componentFailed == true) { // current node is child of failed if (currDepth > failedDepth) { continue; } // if sibling or uncle, reset comp failed flag else { componentFailed = false; } } hszTypeName.Init( szNodeName.c_str() ); StdString parentName; StdString parentType; StdString childType; Archive->GotoParentNode( parentType ); Archive->Read( parentName, _T("Name") ); if ( parentName != _T("") ) { hszParentName = parentName; } Archive->ReturnToChildNode( childType ); if( hszTypeName.GetString() != childType ) { assert( hszTypeName.GetString() == childType ); static DWORD msgHash_SetFileVersion = CHashString(_T("SetFileVersion")).GetUniqueID(); m_ToolBox->SendMessage(msgHash_SetFileVersion, sizeof(IHashString), &oldVersion); return MSG_ERROR; } //parentName = Archive->GetParentName(); StdString szName; Archive->Read( szName, _T("Name") ); hszName.Init( szName.c_str() ); cop.parentName = &hszParentName; cop.typeName = &hszTypeName; cop.name = &hszName; static DWORD msgHash_CreateObject = CHashString(_T("CreateObject")).GetUniqueID(); DWORD retval = m_ToolBox->SendMessage(msgHash_CreateObject, sizeof(CREATEOBJECTPARAMS), &cop, NULL, NULL); if (retval != MSG_HANDLED) { m_ToolBox->Log(LOGINFORMATION, _T("World loader: could not create component; skipping children!\n")); componentFailed = true; failedDepth = Archive->GetDepth(); continue; } // 1.0 -> 1.5 Readjusted scale and position on object by 1000/898 if( m_WorldFileVersion == 1.0 ) { float fConvert = 1000.0f/898.0f; if( hszTypeName.GetUniqueID() == CHashString(_T("CV3ORenderObject")).GetUniqueID() ) { StdString szFileName; Vec3 vPosition(0,0,0); Vec3 vRotation(0,0,0); Vec3 vScaling(0,0,0); Archive->Read( szFileName, _T("FileName") ); Archive->Read( vPosition, _T("Position") ); vPosition.x = ( vPosition.x * fConvert ); vPosition.y = ( vPosition.y * fConvert ); vPosition.z = ( vPosition.z * fConvert ); Archive->Read( vRotation, _T("Rotation") ); Archive->Read( vScaling, _T("Scaling") ); vScaling.x = ( vScaling.x * fConvert ); vScaling.y = ( vScaling.y * fConvert ); vScaling.z = ( vScaling.z * fConvert ); IArchive *MemArchive; CHashString memType(_T("Memory")); CREATEARCHIVE caOut; caOut.mode = STREAM_MODE_WRITE; caOut.streamData = NULL; caOut.streamSize = 0; caOut.streamType = &memType; static DWORD msgHash_CreateArchive = CHashString(_T("CreateArchive")).GetUniqueID(); if (m_ToolBox->SendMessage(msgHash_CreateArchive, sizeof(CREATEARCHIVE), &caOut) != MSG_HANDLED) { static DWORD msgHash_SetFileVersion = CHashString(_T("SetFileVersion")).GetUniqueID(); m_ToolBox->SendMessage(msgHash_SetFileVersion, sizeof(IHashString), &oldVersion); return true; } MemArchive = caOut.archive; MemArchive->Write( szFileName, _T("FileName") ); MemArchive->Write( vPosition, _T("Position") ); MemArchive->Write( vRotation, _T("Rotation") ); MemArchive->Write( vScaling, _T("Scaling") ); CREATESTREAM cs; cs.streamData = caOut.streamData; cs.streamSize = caOut.streamSize; cs.mode = STREAM_MODE_READ; static DWORD msgHash_CreateStream_Memory = CHashString(_T("CreateStream_Memory")).GetUniqueID(); if (m_ToolBox->SendMessage(msgHash_CreateStream_Memory, sizeof(CREATESTREAM), &cs) != MSG_HANDLED) { static DWORD msgHash_SetFileVersion = CHashString(_T("SetFileVersion")).GetUniqueID(); m_ToolBox->SendMessage(msgHash_SetFileVersion, sizeof(IHashString), &oldVersion); return true; } MemArchive->Init(cs.openStream); sop.name = &hszName; sop.archive = MemArchive; static DWORD msgHash_SerializeObject = CHashString(_T("SerializeObject")).GetUniqueID(); m_ToolBox->SendMessage(msgHash_SerializeObject, sizeof(SERIALIZEOBJECTPARAMS), &sop, NULL, NULL); MemArchive->Close(); } else if( hszTypeName.GetUniqueID() == CHashString(_T("CPhysicsObject")).GetUniqueID() ) { //StdString szDynamics; StdString szType; StdString szShapeFileName; //float fMass; //Vec3 vPosition; //Vec3 vRotation; //Vec3 vScaling; //Archive->Read( vPosition, _T("pos") ); //vPosition.SetX( vPosition.GetX() * fConvert ); //vPosition.SetY( vPosition.GetY() * fConvert ); //vPosition.SetZ( vPosition.GetZ() * fConvert ); //Archive->Read( vRotation, _T("rot") ); //Archive->Read( vScaling, _T("scale") ); //vScaling.SetX( vScaling.GetX() * fConvert ); //vScaling.SetY( vScaling.GetY() * fConvert ); //vScaling.SetZ( vScaling.GetZ() * fConvert ); //Archive->Read( fMass, _T("mass") ); Archive->Read( szType, _T("Type") ); Archive->Read( szShapeFileName, _T("filename") ); IArchive *MemArchive; CHashString memType(_T("Memory")); //int size = sizeof(char) * 256 * 2 + sizeof(float) + sizeof(Vec3) * 3 + 256; CREATEARCHIVE caOut; caOut.mode = STREAM_MODE_WRITE; caOut.streamData = NULL; caOut.streamSize = 0; caOut.streamType = &memType; static DWORD msgHash_CreateArchive = CHashString(_T("CreateArchive")).GetUniqueID(); if (m_ToolBox->SendMessage(msgHash_CreateArchive, sizeof(CREATEARCHIVE), &caOut) != MSG_HANDLED) { static DWORD msgHash_SetFileVersion = CHashString(_T("SetFileVersion")).GetUniqueID(); m_ToolBox->SendMessage(msgHash_SetFileVersion, sizeof(IHashString), &oldVersion); return true; } MemArchive = caOut.archive; //MemArchive->Write( vPosition, _T("pos") ); //MemArchive->Write( vRotation, _T("rot") ); //MemArchive->Write( vScaling, _T("scale") ); //MemArchive->Write( fMass, _T("mass") ); //MemArchive->Write( szDynamics, _T("dynamics") ); //MemArchive->Write( szShapeFileName, _T("shapeFile") ); MemArchive->Write( szType, _T("Type") ); MemArchive->Write( szShapeFileName, _T("filename") ); CREATESTREAM cs; cs.streamData = caOut.streamData; cs.streamSize = caOut.streamSize; cs.mode = STREAM_MODE_READ; static DWORD msgHash_CreateStream_Memory = CHashString(_T("CreateStream_Memory")).GetUniqueID(); if (m_ToolBox->SendMessage(msgHash_CreateStream_Memory, sizeof(CREATESTREAM), &cs) != MSG_HANDLED) { static DWORD msgHash_SetFileVersion = CHashString(_T("SetFileVersion")).GetUniqueID(); m_ToolBox->SendMessage(msgHash_SetFileVersion, sizeof(IHashString), &oldVersion); return true; } MemArchive->Init(cs.openStream); sop.name = &hszName; sop.archive = MemArchive; static DWORD msgHash_SerializeObject = CHashString(_T("SerializeObject")).GetUniqueID(); m_ToolBox->SendMessage(msgHash_SerializeObject, sizeof(SERIALIZEOBJECTPARAMS), &sop, NULL, NULL); MemArchive->Close(); } else if( hszTypeName.GetUniqueID() == CHashString(_T("CTerrainConfig")).GetUniqueID() ) { StdString szTerShaderLib; StdString szTerShaderEff; int iSectorRes; float fSectorSize; float fZScale; float fLODDistance; Archive->Read( szTerShaderLib, _T("TerrainShaderLibrary") ); Archive->Read( szTerShaderEff, _T("TerrainShaderEffect") ); Archive->Read( iSectorRes, _T("SectorResolution") ); Archive->Read( fSectorSize, _T("SectorSize") ); fSectorSize = fSectorSize * fConvert; Archive->Read( fZScale, _T("ZScale") ); fZScale = fZScale * fConvert; Archive->Read( fLODDistance, _T("LODDistance") ); IArchive *MemArchive; CHashString memType(_T("Memory")); CREATEARCHIVE caOut; caOut.mode = STREAM_MODE_WRITE; caOut.streamData = NULL; caOut.streamSize = 0; caOut.streamType = &memType; static DWORD msgHash_CreateArchive = CHashString(_T("CreateArchive")).GetUniqueID(); if (m_ToolBox->SendMessage(msgHash_CreateArchive, sizeof(CREATEARCHIVE), &caOut) != MSG_HANDLED) { static DWORD msgHash_SetFileVersion = CHashString(_T("SetFileVersion")).GetUniqueID(); m_ToolBox->SendMessage(msgHash_SetFileVersion, sizeof(IHashString), &oldVersion); return true; } MemArchive = caOut.archive; MemArchive->Write( szTerShaderLib, _T("TerrainShaderLibrary") ); MemArchive->Write( szTerShaderEff, _T("TerrainShaderEffect") ); MemArchive->Write( iSectorRes, _T("SectorResolution") ); MemArchive->Write( fSectorSize, _T("SectorSize") ); MemArchive->Write( fZScale, _T("ZScale") ); MemArchive->Write( fLODDistance, _T("LODDistance") ); CREATESTREAM cs; cs.streamData = caOut.streamData; cs.streamSize = caOut.streamSize; cs.mode = STREAM_MODE_READ; static DWORD msgHash_CreateStream_Memory = CHashString(_T("CreateStream_Memory")).GetUniqueID(); if (m_ToolBox->SendMessage(msgHash_CreateStream_Memory, sizeof(CREATESTREAM), &cs) != MSG_HANDLED) { static DWORD msgHash_SetFileVersion = CHashString(_T("SetFileVersion")).GetUniqueID(); m_ToolBox->SendMessage(msgHash_SetFileVersion, sizeof(IHashString), &oldVersion); return true; } MemArchive->Init(cs.openStream); sop.name = &hszName; sop.archive = MemArchive; static DWORD msgHash_SerializeObject = CHashString(_T("SerializeObject")).GetUniqueID(); m_ToolBox->SendMessage(msgHash_SerializeObject, sizeof(SERIALIZEOBJECTPARAMS), &sop, NULL, NULL); MemArchive->Close(); } else { sop.name = &hszName; sop.archive = Archive; static DWORD msgHash_SerializeObject = CHashString(_T("SerializeObject")).GetUniqueID(); m_ToolBox->SendMessage(msgHash_SerializeObject, sizeof(SERIALIZEOBJECTPARAMS), &sop, NULL, NULL); } } else { sop.name = &hszName; sop.archive = Archive; static DWORD msgHash_SerializeObject = CHashString(_T("SerializeObject")).GetUniqueID(); m_ToolBox->SendMessage(msgHash_SerializeObject, sizeof(SERIALIZEOBJECTPARAMS), &sop, NULL, NULL); } iop.name = &hszName; static DWORD msgHash_InitObject = CHashString(_T("InitObject")).GetUniqueID(); m_ToolBox->SendMessage(msgHash_InitObject, sizeof(INITOBJECTPARAMS), &iop, NULL, NULL); elapsedTime += timer->GetRealTime() - lastLoadTime; lastLoadTime = timer->GetRealTime(); if (elapsedTime > secondsPerFrame) { elapsedTime = 0.0f; pbp.currentPosition = Archive->GetCurrentNodePosition(); pbp.totalSize = numNodes; m_ToolBox->SendMessage(msgHash_LoadingUpdate, sizeof(LOADINGUPDATEPARAMS), &pbp); } } pbp.currentPosition = 0; pbp.totalSize = 0; m_ToolBox->SendMessage(msgHash_LoadingUpdate, sizeof(LOADINGUPDATEPARAMS), &pbp); Archive->Close(); static DWORD msgHash_SetFileVersion = CHashString(_T("SetFileVersion")).GetUniqueID(); m_ToolBox->SendMessage(msgHash_SetFileVersion, sizeof(IHashString), &oldVersion); return MSG_HANDLED_STOP; }
void CIFXMotionDecoder::ProcessMotionCompressedX( IFXDataBlockX &rDataBlockX ) { if(NULL == m_pCoreServices) { IFXCHECKX(IFX_E_NOT_INITIALIZED); } // Get the scene graph IFXDECLARELOCAL(IFXSceneGraph,pSceneGraph); IFXCHECKX(m_pCoreServices->GetSceneGraph( IID_IFXSceneGraph,( void** )&pSceneGraph )); // Process the motion description data block // The motion description block has the following sections: // 1. MotionName // 2. TrackCount // 3. InverseQuantTime // 4. InverseQuantRotation // 5. TrackName // 6. TimeCount // 7. InverseQuantDisplacement // 8. InverseQuantScale // 9. Time // 10. Displacement // 11. Rotation // 12. Scale // set metadata IFXDECLARELOCAL(IFXMetaDataX, pBlockMD); IFXDECLARELOCAL(IFXMetaDataX, pObjectMD); rDataBlockX.QueryInterface(IID_IFXMetaDataX, (void**)&pBlockMD); m_pObject->QueryInterface(IID_IFXMetaDataX, (void**)&pObjectMD); pObjectMD->AppendX(pBlockMD); // Create a bitstream component and initialize it to decode the block IFXDECLARELOCAL(IFXBitStreamCompressedX,pBitStreamX); IFXCHECKX(IFXCreateComponent( CID_IFXBitStreamX, IID_IFXBitStreamCompressedX, ( void** )&pBitStreamX )); IFXDECLARELOCAL(IFXNameMap, pNameMap); m_pCoreServices->GetNameMap(IID_IFXNameMap, (void**)&pNameMap); U32 uProfile; pNameMap->GetProfile(m_uLoadId, uProfile); pBitStreamX->SetNoCompressionMode((uProfile & IFXPROFILE_NOCOMPRESSION) ? TRUE : FALSE); U32 uBlockType = 0; rDataBlockX.GetBlockTypeX(uBlockType); pBitStreamX->SetDataBlockX( rDataBlockX ); // 1. MotionName IFXString stringMotionName; // read the motion name pBitStreamX->ReadIFXStringX( stringMotionName ); IFXCHECKX(pNameMap->Map(m_uLoadId, IFXSceneGraph::MOTION, stringMotionName)); // Access the appropriate interface of the shader that was handed in via SetObject(). IFXDECLARELOCAL(IFXMotionResource,pMotionResource); IFXCHECKX(m_pObject->QueryInterface( IID_IFXMotionResource, (void**)&pMotionResource )); pMotionResource->GetMotionRef()->SetName(stringMotionName); // 2. TrackCount U32 uTrackCount = 0; pBitStreamX->ReadU32X( uTrackCount ); // 3. InverseQuantTime F32 fInverseQuantTime = 1.0; pBitStreamX->ReadF32X( fInverseQuantTime ); // 4. InverseQuantRotation F32 fInverseQuantRotation = 1.0; pBitStreamX->ReadF32X( fInverseQuantRotation ); U32 i = 0; for( i=0; i < uTrackCount; i++ ) { // 5. TrackName IFXString trackName; pBitStreamX->ReadIFXStringX( trackName ); IFXDECLARELOCAL(IFXNameMap, pNameMap); m_pCoreServices->GetNameMap(IID_IFXNameMap, (void**)&pNameMap); IFXCHECKX(pNameMap->Map(m_uLoadId, IFXSceneGraph::MOTION, trackName)); // Find the track id from the track name U32 uTrackID = 0; IFXRESULT iFindResult = pMotionResource->FindTrack( &trackName, &uTrackID ); if( IFXFAILURE( iFindResult ) ) { IFXCHECKX(pMotionResource->AddTrack( &trackName, &uTrackID )); } // 6. TimeCount U32 uTimeCount = 0; pBitStreamX->ReadU32X( uTimeCount ); IFXKeyFrame *pKeyFrameArray = NULL; pKeyFrameArray = new IFXKeyFrame[uTimeCount]; if( NULL == pKeyFrameArray ) { IFXCHECKX(IFX_E_OUT_OF_MEMORY); } // 7. InverseQuantDisplacement F32 fInverseQuantDisplacement = 1.0; pBitStreamX->ReadF32X(fInverseQuantDisplacement); // 8. InverseQuantScale F32 fInverseQuantScale = 1.0; pBitStreamX->ReadF32X(fInverseQuantScale); IFXKeyFrame thePredictedKeyFrame; U32 j = 0; for( j=0; j < uTimeCount; j++ ) { // 9. Time F32 fDiffTime = 0.0f; if(0==j || (uTimeCount-1) == j) { pBitStreamX->ReadF32X(fDiffTime); } else { U32 uDiffTime = 0; U8 u8SignTime = 0; pBitStreamX->ReadCompressedU8X(uACContextMotionSignTime,u8SignTime); pBitStreamX->ReadCompressedU32X(uACContextMotionDiffTime, uDiffTime ); fDiffTime = (fInverseQuantTime*uDiffTime); if(u8SignTime & 1) { fDiffTime *= -1.0f; } } F32 fPredictedTime = thePredictedKeyFrame.Time(); F32 fTime = fDiffTime + fPredictedTime; pKeyFrameArray[j].SetTime( fTime ); // 10. Displacement F32 fdX=0.0f, fdY=0.0f, fdZ=0.0f; if(0==j || ((uTimeCount-1) == j && BlockType_ResourceMotionU3D == uBlockType )) { pBitStreamX->ReadF32X(fdX); pBitStreamX->ReadF32X(fdY); pBitStreamX->ReadF32X(fdZ); } else { U8 u8SignDisplacement = 0; U32 udX = 0; U32 udY = 0; U32 udZ = 0; pBitStreamX->ReadCompressedU8X(uACContextMotionSignDisplacement, u8SignDisplacement); pBitStreamX->ReadCompressedU32X(uACContextMotionDiffDisplacement, udX ); pBitStreamX->ReadCompressedU32X(uACContextMotionDiffDisplacement, udY ); pBitStreamX->ReadCompressedU32X(uACContextMotionDiffDisplacement, udZ ); fdX = fInverseQuantDisplacement*udX; fdY = fInverseQuantDisplacement*udY; fdZ = fInverseQuantDisplacement*udZ; if(u8SignDisplacement & 1) { fdX *= -1.0; } if(u8SignDisplacement & 2) { fdY *= -1.0; } if(u8SignDisplacement & 4) { fdZ *= -1.0; } } IFXVector3 vDisplacement(0.0f,0.0f,0.0f); IFXVector3 vPredictedDisplacement = thePredictedKeyFrame.Location(); IFXVector3 vDiffDisplacement(fdX,fdY,fdZ); vDisplacement.Add(vDiffDisplacement,vPredictedDisplacement); pKeyFrameArray[j].Location() = vDisplacement; // 11. Rotation U8 u8SignRot = 0; U32 uB=0,uC=0,uD=0; if(0==j || ((uTimeCount-1) == j && BlockType_ResourceMotionU3D == uBlockType )) { F32 fao,fbo,fco,fdo; pBitStreamX->ReadF32X(fao); pBitStreamX->ReadF32X(fbo); pBitStreamX->ReadF32X(fco); pBitStreamX->ReadF32X(fdo); IFXQuaternion vRotation(1.0f,0.0f,0.0f,0.0f); vRotation.Set(fao,fbo,fco,fdo); pKeyFrameArray[j].Rotation() = vRotation; } else { pBitStreamX->ReadCompressedU8X(uACContextMotionSignRotation,u8SignRot); pBitStreamX->ReadCompressedU32X(uACContextMotionDiffRotation, uB ); pBitStreamX->ReadCompressedU32X(uACContextMotionDiffRotation, uC ); pBitStreamX->ReadCompressedU32X(uACContextMotionDiffRotation, uD ); F32 fb = fInverseQuantRotation*uB; F32 fc = fInverseQuantRotation*uC; F32 fd = fInverseQuantRotation*uD; if(fb > 1.0f) fb = 1.0f; if(fc > 1.0f) fc = 1.0f; if(fd > 1.0f) fd = 1.0f; F32 fa = (F32) sqrt(fabs(1.0 - ((F64)fb)*((F64)fb) - ((F64)fc)*((F64)fc) - ((F64)fd)*((F64)fd))); if(u8SignRot & 1) { fa *= -1.0; } if(u8SignRot & 2) { fb *= -1.0; } if(u8SignRot & 4) { fc *= -1.0; } if(u8SignRot & 8) { fd *= -1.0; } // Set the key frame values IFXQuaternion vDiffRotation( fa,fb,fc,fd ); IFXQuaternion vPredictedRotation = thePredictedKeyFrame.Rotation(); IFXQuaternion vRotationQ(1.0f,0.0f,0.0f,0.0f); vRotationQ.Multiply(vPredictedRotation,vDiffRotation); pKeyFrameArray[j].Rotation() = vRotationQ; } // 12. Scale F32 fdsX=0.0f, fdsY=0.0f, fdsZ=0.0f; if(0==j || ((uTimeCount-1) == j && BlockType_ResourceMotionU3D == uBlockType )) { pBitStreamX->ReadF32X(fdsX); pBitStreamX->ReadF32X(fdsY); pBitStreamX->ReadF32X(fdsZ); } else { U8 u8SignScale = 0; U32 udsX = 0; U32 udsY = 0; U32 udsZ = 0; pBitStreamX->ReadCompressedU8X(uACContextMotionSignScale, u8SignScale); pBitStreamX->ReadCompressedU32X(uACContextMotionDiffScale, udsX ); pBitStreamX->ReadCompressedU32X(uACContextMotionDiffScale, udsY ); pBitStreamX->ReadCompressedU32X(uACContextMotionDiffScale, udsZ ); fdsX = fInverseQuantScale*udsX; fdsY = fInverseQuantScale*udsY; fdsZ = fInverseQuantScale*udsZ; if(u8SignScale & 1) { fdsX *= -1.0; } if(u8SignScale & 2) { fdsY *= -1.0; } if(u8SignScale & 4) { fdsZ *= -1.0; } } IFXVector3 vScaleQ(0.0f,0.0f,0.0f); IFXVector3 vPredictedScaleQ = thePredictedKeyFrame.Scale(); IFXVector3 vDiffScaleQ(fdsX,fdsY,fdsZ); vScaleQ.Add(vDiffScaleQ,vPredictedScaleQ); pKeyFrameArray[j].Scale() = vScaleQ; // Set the predicted frame for the next key frame thePredictedKeyFrame = pKeyFrameArray[j]; } // Set the key frame array to the motion resource IFXCHECKX(pMotionResource->ClearTrack( uTrackID )); IFXCHECKX(pMotionResource->InsertKeyFrames( uTrackID,uTimeCount,pKeyFrameArray )); IFXDELETE_ARRAY( pKeyFrameArray ); } // Now, add a fully-mapped mixer to the mixer palette for this motion { U32 uMixerID = 0; IFXDECLARELOCAL(IFXPalette,pMixerPalette); IFXCHECKX(pSceneGraph->GetPalette( IFXSceneGraph::MIXER, &pMixerPalette )); IFXRESULT iFindResult = pMixerPalette->Find( &stringMotionName,&uMixerID ); // if not found, add it to the palette if ( IFXFAILURE( iFindResult ) ) { IFXCHECKX(pMixerPalette->Add( &stringMotionName,&uMixerID )); } // now, try to get the motion resource pointer IFXDECLARELOCAL(IFXMixerConstruct, pMixerConstruct ); IFXRESULT iGetResourceResult = pMixerPalette->GetResourcePtr(uMixerID,IID_IFXMixerConstruct,(void**)&pMixerConstruct); // if there was no resource pointer, then create one if (IFXFAILURE(iGetResourceResult)) { IFXCHECKX(IFXCreateComponent( CID_IFXMixerConstruct, IID_IFXMixerConstruct,( void** )&pMixerConstruct )); IFXASSERT(pMotionResource); pMixerConstruct->SetMotionResource(pMotionResource); // Set the scenegraph IFXCHECKX(pMixerConstruct->SetSceneGraph( pSceneGraph )); pMixerConstruct->SetExternalFlag(m_bExternal); pMixerConstruct->SetPriority(rDataBlockX.GetPriorityX(), FALSE, FALSE); // set the resource pointer in the palette IFXDECLARELOCAL(IFXUnknown,pUnknown); IFXCHECKX(pMixerConstruct->QueryInterface(IID_IFXUnknown, (void**)&pUnknown)); IFXCHECKX(pMixerPalette->SetResourcePtr( uMixerID,pUnknown )); } } }