void IgfxQBSP::_ModelTransformPlanes(gfxBSPModel *mdl) { Matrix InvTMtx; MtxInverse(&mdl->wrldMtx[FXMTX_NORMAL], &InvTMtx); MtxTranspose(&InvTMtx, &InvTMtx); // Loop through and tranform the brush side planes for(s32 i = 0; i < mdl->numOfBrushes; i++) _BrushTransormPlanes(&mdl->brushes[i], &InvTMtx); }
// // 设置世界位置 // VOID CSceneNode::SetWorldPosition(FLOAT x, FLOAT y, FLOAT z) { if (m_pParentNode) { // 算法: // worldPosition = localPosition * parentMatrix; // localPosition = worldPosition * parentMatrixInv; MATRIX4 mtxParentInv; MtxInverse(&mtxParentInv, m_pParentNode->GetWorldMatrix()); VEC3 localPosition; VEC3 worldPosition; Vec3Set(&worldPosition, x, y, z); Vec3MulMtx4x4(&localPosition, &worldPosition, &mtxParentInv); x = localPosition[0]; y = localPosition[1]; z = localPosition[2]; } SetLocalPosition(x, y, z); }
///////////////////////////////////// // Purpose: render the given model // Output: scene object added // Return: true ///////////////////////////////////// u32 IgfxQBSP::ModelRender(s32 modelInd, const Vec3D & camPos, u8 bShadow) { // model has to be enabled if(m_models[modelInd].numOfFaces > 0 && !TESTFLAGS(m_models[modelInd].status, QBSP_MODEL_FLAG_DISABLE)) { g_fragmentFrame++; Vec3D bbMin, bbMax; s32 f; RayModelGetBBoxMin(modelInd, &bbMin); RayModelGetBBoxMax(modelInd, &bbMax); u8 bOBJCulled = !FrustrumCheckBox(bbMin, bbMax); u8 bLightCulled = FALSE; //set the lights up. LightGetAllNearest(bbMin, bbMax, m_models[modelInd].lights); //our shadow light hLIGHT shL = _LightGetShadow(m_models[modelInd].lights); if(shL) bLightCulled = !FrustrumCheckPoint(shL->lDat.Position.x, shL->lDat.Position.y, shL->lDat.Position.z); // not within frustrum? if(bOBJCulled) { for(f = 0; f < m_models[modelInd].numOfFaces; f++) m_faces[f+m_models[modelInd].faceIndex].fragmentframe = g_fragmentFrame; } else { //Vec3D vCamObj(m_models[modelInd].wrldTrans.x-camPos.x, m_models[modelInd].wrldTrans.y-camPos.y, m_models[modelInd].wrldTrans.z-camPos.z); f32 lod_lvl = CameraGetBoundFarDistSq(m_models[modelInd].min, m_models[modelInd].max, &m_models[modelInd].wrldMtx[FXMTX_NORMAL]); //Vec3DDot(&vCamObj,&vCamObj); //calculate the matrices MtxInverse(&m_models[modelInd].wrldMtx[FXMTX_NORMAL], &m_models[modelInd].wrldMtx[FXMTX_INVERSE]); MtxTranspose(&m_models[modelInd].wrldMtx[FXMTX_NORMAL], &m_models[modelInd].wrldMtx[FXMTX_TRANSPOSE]); MtxTranspose(&m_models[modelInd].wrldMtx[FXMTX_INVERSE], &m_models[modelInd].wrldMtx[FXMTX_INVTRANSPOSE]); s32 faceInd; for(f = 0; f < m_models[modelInd].numOfFaces; f++) { faceInd = f+m_models[modelInd].faceIndex; if(m_textures[m_faces[faceInd].textureID].fx == m_dfltFX) //if we are using qbsp's default FX, then use the model technique _RenderFace(faceInd, m_models[modelInd].wrldMtx, 0, m_mdlFXTech, m_models[modelInd].lights, lod_lvl); else _RenderFace(faceInd, m_models[modelInd].wrldMtx, 0, 0, m_models[modelInd].lights, lod_lvl); } } //add shadowing if(shL && bShadow) { //FIXME!: check to see if vector: obj-light is intersecting frustrum!!!! // if bLightCulled is true if((!bLightCulled && !bOBJCulled) || (bLightCulled)) { ShadowDat shadow; //get the light position depending on type, for directional we only want direction. if(shL->lDat.Type == GFXLIGHT_DIRECTIONAL) { shadow.lPos = shL->lDat.Direction; shadow.flag = SHADOW_USE_DIR; } else { //Vec3DTransformCoord(&shL->lDat.Position, // &obj->wrldMtx[FXMTX_INVERSE], &shadow.lPos); shadow.lPos = shL->lDat.Position; shadow.flag = 0; } if(bOBJCulled) SETFLAG(shadow.flag, SHADOW_OCC_CULLED); //calculate the scissor area rect in 2d shadow.pWrldMtx = &m_models[modelInd].wrldMtx[FXMTX_NORMAL]; shadow.extrude = SHADOW_EXTRUDE;//shL->lDat.Range; // shadow.cb = QBSPMDLShadowCallback; shadow.usrDat = (void*)this; shadow.usrParam = modelInd; GFXShadowAdd(&shadow); } } } return TRUE; }