bool BMaxObject::UpdateModel(SceneState * sceneState /*= NULL*/) { if (!m_pAnimatedMesh) return false; int nIndex = (sceneState && IsLODEnabled()) ? m_pAnimatedMesh->GetLodIndex(sceneState->GetCameraToCurObjectDistance()/*, GetScaling()*/) : 0; CParaXModel* pModel = m_pAnimatedMesh->GetModel(nIndex); if (pModel == NULL) return false; // just a single standing animation is supported now and looped. if (!m_CurrentAnim.IsValid()) m_CurrentAnim = pModel->GetAnimIndexByID(0); if (m_CurrentAnim.IsValid() && IsAnimEnabled()) { int nAnimLength = std::max(1, m_CurrentAnim.nEndFrame - m_CurrentAnim.nStartFrame); int nToDoFrame = (m_CurrentAnim.nCurrentFrame + (int)(sceneState->dTimeDelta * 1000)) % nAnimLength; m_CurrentAnim.nCurrentFrame = nToDoFrame; } pModel->m_CurrentAnim = m_CurrentAnim; pModel->m_NextAnim.nIndex = 0; pModel->m_BlendingAnim.MakeInvalid(); pModel->blendingFactor = 0; pModel->animate(sceneState, NULL, GetAnimInstanceFields()); return true; }
Matrix4* BMaxObject::GetAttachmentMatrix(Matrix4& matOut, int nAttachmentID /*= 0*/, int nRenderNumber /*= 0*/) { if (m_pAnimatedMesh && m_pAnimatedMesh->IsLoaded()) { CParaXModel* pModel = m_pAnimatedMesh->GetModel(); if (pModel) { Matrix4* pOut = &matOut; if (pModel->GetAttachmentMatrix(pOut, nAttachmentID, m_CurrentAnim, AnimIndex(), 0.f)) { Matrix4 matScale; float fScaling = GetScaling(); if (fabs(fScaling - 1.0f) > FLT_TOLERANCE) { ParaMatrixScaling(&matScale, fScaling, fScaling, fScaling); (*pOut) = (*pOut)*matScale; } return pOut; } } } return NULL; }
bool CBoneAnimProvider::LoadAsset() { if(m_bLoaded) return true; ParaXEntity* pAsset = m_asset.get(); if(pAsset && pAsset->GetPrimaryTechniqueHandle() > 0) { CParaXModel* pModel = pAsset->GetModel(); if(pModel) { m_asset.reset(); m_bLoaded = true; // copy bone look up table memcpy(m_boneLookup, pModel->m_boneLookup, sizeof(m_boneLookup)); // copy bones int nBones = pModel->GetObjectNum().nBones; m_bones.resize(nBones); for (int i=0;i<nBones;++i) { m_bones[i] = pModel->bones[i]; } // copy animation sequence info int nAnimations = pModel->GetObjectNum().nAnimations; m_anims.resize(nAnimations); for (int i=0;i<nAnimations ;++i) { m_anims[i] = pModel->anims[i]; } return true; } } return m_bLoaded; }
void BMaxObject::LoadPhysics() { if (m_dwPhysicsMethod > 0 && IsPhysicsEnabled() && (GetStaticActorCount() == 0)) { if (m_pAnimatedMesh && m_pAnimatedMesh->IsLoaded()) { CParaXModel* ppMesh = m_pAnimatedMesh->GetModel(); if (ppMesh == 0 || ppMesh->GetHeader().maxExtent.x <= 0.f) { EnablePhysics(false); // disable physics forever, if failed loading physics data return; } // get world transform matrix Matrix4 mxWorld; GetWorldTransform(mxWorld); IParaPhysicsActor* pActor = CGlobals::GetPhysicsWorld()->CreateStaticMesh(m_pAnimatedMesh.get(), mxWorld, m_nPhysicsGroup, &m_staticActors, this); if (m_staticActors.empty()) { // disable physics forever, if no physics actors are loaded. EnablePhysics(false); } } } }
HRESULT BMaxObject::Draw(SceneState * sceneState) { if (!m_pAnimatedMesh) return E_FAIL; if (GetPrimaryTechniqueHandle() < 0) { // try loading the asset if it has not been done before. m_pAnimatedMesh->LoadAsset(); if (m_pAnimatedMesh->IsLoaded()) { SetPrimaryTechniqueHandle(m_pAnimatedMesh->GetPrimaryTechniqueHandle()); UpdateGeometry(); } return E_FAIL; } if (!CGlobals::GetEffectManager()->IsCurrentEffectValid()) { return E_FAIL; } sceneState->SetCurrentSceneObject(this); int nIndex = (sceneState && sceneState->IsLODEnabled()) ? m_pAnimatedMesh->GetLodIndex(sceneState->GetCameraToCurObjectDistance()/*, GetScaling()*/) : 0; CParaXModel* pModel = m_pAnimatedMesh->GetModel(nIndex); if (pModel == NULL) return E_FAIL; int nRestoreSpecialTextures = -1; for (auto const & tex : mReplaceTextures) { if(pModel->specialTextures[tex.first] >= 0) pModel->replaceTextures[pModel->specialTextures[tex.first]] = tex.second; else { // if there is only one texture, we will force replace it even there is no special replaceable id redefined. if (pModel->GetObjectNum().nTextures <= 1 && nRestoreSpecialTextures<0) { nRestoreSpecialTextures = tex.first; pModel->specialTextures[tex.first] = tex.first; pModel->replaceTextures[pModel->specialTextures[tex.first]] = tex.second; break; } } } sceneState->SetCurrentSceneObject(this); SetFrameNumber(sceneState->m_nRenderCount); // get world transform matrix Matrix4 mxWorld; GetRenderMatrix(mxWorld); RenderDevicePtr pd3dDevice = sceneState->m_pd3dDevice; EffectManager* pEffectManager = CGlobals::GetEffectManager(); pEffectManager->applyObjectLocalLighting(this); CEffectFile* pEffectFile = pEffectManager->GetCurrentEffectFile(); CGlobals::GetWorldMatrixStack().push(mxWorld); ApplyBlockLighting(sceneState); CApplyObjectLevelParamBlock p(GetEffectParamBlock()); if (pEffectFile == 0) { // TODO: Fixed Function. } else { bool bUsePointTextureFilter = false; // apply block space lighting for object whose size is comparable to a single block size if (CheckAttribute(MESH_USE_LIGHT) && !(sceneState->IsShadowPass())) { BlockWorldClient* pBlockWorldClient = BlockWorldClient::GetInstance(); if (pBlockWorldClient && pBlockWorldClient->IsInBlockWorld()) { Vector3 vPos = GetPosition(); vPos.y += 0.1f; Uint16x3 blockId_ws(0, 0, 0); BlockCommon::ConvertToBlockIndex(vPos.x, vPos.y, vPos.z, blockId_ws.x, blockId_ws.y, blockId_ws.z); DWORD dwPositionHash = blockId_ws.GetHashCode(); uint8_t brightness[2]; pBlockWorldClient->GetBlockMeshBrightness(blockId_ws, brightness, 2); // block light float fBlockLightness = Math::Max(pBlockWorldClient->GetLightBrightnessLinearFloat(brightness[0]), 0.1f); sceneState->GetCurrentLightStrength().y = fBlockLightness; // sun light float fSunLightness = Math::Max(pBlockWorldClient->GetLightBrightnessLinearFloat(brightness[1]), 0.1f); sceneState->GetCurrentLightStrength().x = fSunLightness; float fLightness = Math::Max(fBlockLightness, fSunLightness*pBlockWorldClient->GetSunIntensity()); if (m_fLastBlockLight != fLightness) { float fMaxStep = (float)(sceneState->dTimeDelta*0.5f); if (dwPositionHash == m_dwLastBlockHash || m_dwLastBlockHash == 0) m_fLastBlockLight = fLightness; else Math::SmoothMoveFloat1(m_fLastBlockLight, fLightness, fMaxStep); fLightness = m_fLastBlockLight; } else { m_dwLastBlockHash = dwPositionHash; } sceneState->GetLocalMaterial().Ambient = (LinearColor(fLightness*0.7f, fLightness*0.7f, fLightness*0.7f, 1.f)); sceneState->GetLocalMaterial().Diffuse = (LinearColor(fLightness*0.4f, fLightness*0.4f, fLightness*0.4f, 1.f)); sceneState->EnableLocalMaterial(true); bUsePointTextureFilter = bUsePointTextureFilter || pBlockWorldClient->GetUsePointTextureFiltering(); } } if (bUsePointTextureFilter) { pEffectManager->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); pEffectManager->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); } else { pEffectManager->SetSamplerState(0, D3DSAMP_MINFILTER, pEffectManager->GetDefaultSamplerState(0, D3DSAMP_MINFILTER)); pEffectManager->SetSamplerState(0, D3DSAMP_MAGFILTER, pEffectManager->GetDefaultSamplerState(0, D3DSAMP_MAGFILTER)); } // just a single standing animation is supported now and looped. UpdateModel(sceneState); pModel->draw(sceneState, p.GetParamsBlock()); } if (nRestoreSpecialTextures >= 0) { pModel->specialTextures[nRestoreSpecialTextures] = -1; pModel->replaceTextures[nRestoreSpecialTextures] = nullptr; } CGlobals::GetWorldMatrixStack().pop(); return S_OK; }
HRESULT ParaEngine::CLightObject::RenderMesh(SceneState * sceneState) { if (!m_pAnimatedMesh) return E_FAIL; if (GetPrimaryTechniqueHandle() < 0) { // try loading the asset if it has not been done before. m_pAnimatedMesh->LoadAsset(); if (m_pAnimatedMesh->IsLoaded()) { SetPrimaryTechniqueHandle(m_pAnimatedMesh->GetPrimaryTechniqueHandle()); UpdateGeometry(); } return E_FAIL; } if (!CGlobals::GetEffectManager()->IsCurrentEffectValid()) { return E_FAIL; } CParaXModel* pModel = m_pAnimatedMesh->GetModel(0); if (pModel == NULL) return E_FAIL; sceneState->SetCurrentSceneObject(this); SetFrameNumber(sceneState->m_nRenderCount); // get world transform matrix Matrix4 mxWorld; GetRenderMatrix(mxWorld); RenderDevicePtr pd3dDevice = sceneState->m_pd3dDevice; EffectManager* pEffectManager = CGlobals::GetEffectManager(); pEffectManager->applyObjectLocalLighting(this); CEffectFile* pEffectFile = pEffectManager->GetCurrentEffectFile(); CGlobals::GetWorldMatrixStack().push(mxWorld); if (pEffectFile == 0) { // TODO: Fixed Function. } else { // apply block space lighting for object whose size is comparable to a single block size BlockWorldClient* pBlockWorldClient = BlockWorldClient::GetInstance(); if (pBlockWorldClient && pBlockWorldClient->IsInBlockWorld()) { uint8_t brightness[2]; Uint16x3 blockId_ws(0, 0, 0); Vector3 vPos = GetPosition(); BlockCommon::ConvertToBlockIndex(vPos.x, vPos.y + 0.1f, vPos.z, blockId_ws.x, blockId_ws.y, blockId_ws.z); float fLightness; pBlockWorldClient->GetBlockMeshBrightness(blockId_ws, brightness); // block light float fBlockLightness = Math::Max(pBlockWorldClient->GetLightBrightnessFloat(brightness[0]), 0.1f); sceneState->GetCurrentLightStrength().y = fBlockLightness; // sun light fLightness = Math::Max(pBlockWorldClient->GetLightBrightnessFloat(brightness[1]), 0.1f); sceneState->GetCurrentLightStrength().x = fLightness; fLightness *= pBlockWorldClient->GetSunIntensity(); fLightness = Math::Max(fLightness, fBlockLightness); sceneState->GetLocalMaterial().Ambient = (LinearColor(fLightness*0.7f, fLightness*0.7f, fLightness*0.7f, 1.f)); sceneState->GetLocalMaterial().Diffuse = (LinearColor(fLightness*0.4f, fLightness*0.4f, fLightness*0.4f, 1.f)); sceneState->EnableLocalMaterial(true); } // just a single standing animation is supported now and looped. if (!m_CurrentAnim.IsValid()) m_CurrentAnim = pModel->GetAnimIndexByID(0); if (m_CurrentAnim.IsValid()) { int nAnimLength = std::max(1, m_CurrentAnim.nEndFrame - m_CurrentAnim.nStartFrame); int nToDoFrame = (m_CurrentAnim.nCurrentFrame + (int)(sceneState->dTimeDelta * 1000)) % nAnimLength; m_CurrentAnim.nCurrentFrame = nToDoFrame; } pModel->m_CurrentAnim = m_CurrentAnim; pModel->m_NextAnim.nIndex = 0; pModel->m_BlendingAnim.MakeInvalid(); pModel->blendingFactor = 0; pModel->animate(sceneState, NULL); // force CParaXModel::BMAX_MODEL? pModel->draw(sceneState, NULL); } CGlobals::GetWorldMatrixStack().pop(); return S_OK; }