// // 更新变换 // 说明: 自上而下更新 // VOID CSceneNode::UpdateTransform(BOOL bParentUpdate) { BOOL bUpdate = bParentUpdate || m_bNeedUpdateTransform ? TRUE : FALSE; // // 1. 更新当前节点变换矩阵 // if (bUpdate) { if (m_bNeedUpdateTransform) { m_bNeedUpdateTransform = FALSE; MATRIX4 mtxScale; MATRIX4 mtxRotate; MATRIX4 mtxTranslate; MATRIX4 mtxScaleRotate; MtxDefScale(&mtxScale, m_localScale[0], m_localScale[1], m_localScale[2]); MtxDefTranslate(&mtxTranslate, m_localPosition[0], m_localPosition[1], m_localPosition[2]); QuatToMtxRotation(&mtxRotate, &m_localOrientation); // 级联顺序: scale * rotate * translate MtxMul(&mtxScaleRotate, &mtxScale, &mtxRotate); MtxMul(&m_mtxLocal, &mtxScaleRotate, &mtxTranslate); } if (m_pParentNode) { MtxMul(&m_mtxWorld, &m_mtxLocal, &m_pParentNode->m_mtxWorld); } else { MtxCopy(&m_mtxWorld, &m_mtxLocal); } MtxToScale(&m_worldScale, &m_mtxWorld); MtxToQuat(&m_worldOrientation, &m_mtxWorld); MtxToTranslate(&m_worldPosition, &m_mtxWorld); m_dwUpdateTransformCount++; m_dwParentUpdateTransformCount = m_pParentNode ? m_pParentNode->m_dwUpdateTransformCount : 0; } // // 2. 更新子节点变换 // if (CSceneNode *pNode = m_pNodeHead) { do { pNode->UpdateTransform(bUpdate); } while (pNode = pNode->pNext); } }
// // 立即更新变换 // 说明: 自下而上更新 // VOID CSceneNode::UpdateTransformImmediately(VOID) { // // 1. 更新父节点变换 // if (m_pParentNode) { m_pParentNode->UpdateTransformImmediately(); } // // 2. 更新当前节点变换矩阵 // if (m_bNeedUpdateTransform || (m_pParentNode && m_pParentNode->m_dwUpdateTransformCount != m_dwParentUpdateTransformCount)) { if (m_bNeedUpdateTransform) { m_bNeedUpdateTransform = FALSE; MATRIX4 mtxScale; MATRIX4 mtxRotate; MATRIX4 mtxTranslate; MATRIX4 mtxScaleRotate; MtxDefScale(&mtxScale, m_localScale[0], m_localScale[1], m_localScale[2]); MtxDefTranslate(&mtxTranslate, m_localPosition[0], m_localPosition[1], m_localPosition[2]); QuatToMtxRotation(&mtxRotate, &m_localOrientation); // 级联顺序: scale * rotate * translate MtxMul(&mtxScaleRotate, &mtxScale, &mtxRotate); MtxMul(&m_mtxLocal, &mtxScaleRotate, &mtxTranslate); } if (m_pParentNode) { MtxMul(&m_mtxWorld, &m_mtxLocal, &m_pParentNode->m_mtxWorld); } else { MtxCopy(&m_mtxWorld, &m_mtxLocal); } MtxToScale(&m_worldScale, &m_mtxWorld); MtxToQuat(&m_worldOrientation, &m_mtxWorld); MtxToTranslate(&m_worldPosition, &m_mtxWorld); m_dwUpdateTransformCount++; m_dwParentUpdateTransformCount = m_pParentNode ? m_pParentNode->m_dwUpdateTransformCount : 0; } }
/* m = m2 * m */ void MtxInvMult(matrix_t m, matrix_t m2) { matrix_t tmp; MtxCopy(tmp,m); MtxMult3(m, m2, tmp); }
// // 更新 // VOID CGfxBillboard::Update(const CEntityCamera *pCamera, CParticle *pParticleList, INT numParticles) { // // 1. 参数安全检查 // if (pCamera == NULL || pParticleList == NULL || numParticles <= 0) { return; } // // 2. 更新相机矩阵 // if (m_directionType == DIRECTION_CAMERA) { VEC3 direction; VEC3 position, up, target; Vec3Scale(&direction, pCamera->GetForwardDirection(), -1.0f); Vec3Set(&up, 0.0f, 1.0f, 0.0f); Vec3Set(&position, 0.0f, 0.0f, 0.0f); Vec3Ma(&target, &position, &direction, 1.0f); MtxDefLookAt(&m_mtxFaceToCamera, &position, &up, &target); } // // 3. 更新粒子数据 // VERTEX *vertices = (VERTEX *)SAFE_MALLOC(4 * numParticles * sizeof(*vertices), MEMTYPE_STACK); { // Billboard // 0 ___ 3 // | | // |___| // 1 2 INT indexVertex = 0; CParticle *pParticle = pParticleList; while (pParticle) { const VEC3 *parentWorldScale = pParticle->pEmitter->GetWorldScale(); const VEC3 *parentWorldPosition = pParticle->pEmitter->GetWorldPosition(); const QUAT *parentWorldOrientation = pParticle->pEmitter->GetWorldOrientation(); // // 1. 计算粒子位置与朝向 // VEC3 scale; VEC3 position; QUAT orientation; if (pParticle->bKeepLocal && pParticle->pEmitter) { Vec3Mul(&scale, &pParticle->localScale, parentWorldScale); if (m_directionType == DIRECTION_FIXED) { QuatMul(&orientation, &pParticle->localOrientation, parentWorldOrientation); } VEC3 scalePosition; VEC3 scaleOrientationPosition; Vec3Mul(&scalePosition, &pParticle->localPosition, parentWorldScale); Vec3MulQuat(&scaleOrientationPosition, &scalePosition, parentWorldOrientation); Vec3Add(&position, &scaleOrientationPosition, parentWorldPosition); } else { Vec3Copy(&scale, &pParticle->localScale); if (m_directionType == DIRECTION_FIXED) { QuatCopy(&orientation, &pParticle->localOrientation); } Vec3Copy(&position, &pParticle->localPosition); } // // 2. 粒子位置偏移量 // MATRIX4 mtxOrientation; if (m_directionType == DIRECTION_CAMERA) { MtxCopy(&mtxOrientation, &m_mtxFaceToCamera); if (m_offset < -EPSILON_E3 || m_offset > EPSILON_E3) { VEC3 offsetDirection; Vec3Sub(&offsetDirection, pCamera->GetPosition(), &position); Vec3Normalize(&offsetDirection); Vec3Ma(&position, &position, &offsetDirection, m_offset); } } else { QuatToMtxRotation(&mtxOrientation, &orientation); if (m_offset < -EPSILON_E3 || m_offset > EPSILON_E3) { VEC3 localDirection; VEC3 offsetDirection; Vec3Set(&localDirection, 0.0f, 0.0f, 1.0f); Vec3MulQuat(&offsetDirection, &localDirection, &orientation); Vec3Normalize(&offsetDirection); Vec3Ma(&position, &position, &offsetDirection, m_offset); } } // // 3. 计算粒子变换矩阵 // MATRIX4 mtxScale; MATRIX4 mtxRotate; MATRIX4 mtxRotateSelf; MATRIX4 mtxTranslate; MtxDefScale(&mtxScale, scale[0], scale[1], scale[2]); MtxDefTranslate(&mtxTranslate, position[0], position[1], position[2]); MtxDefRotateAxisAngle(&mtxRotateSelf, &axisz, pParticle->radian); MtxMul(&mtxRotate, &mtxRotateSelf, &mtxOrientation); MATRIX4 mtxSR; MATRIX4 mtxTransform; MtxMul(&mtxSR, &mtxScale, &mtxRotate); MtxMul(&mtxTransform, &mtxSR, &mtxTranslate); // // 4. 计算粒子纹理矩阵 // MATRIX4 mtxTexScale; MATRIX4 mtxTexTranslate; MATRIX4 mtxTexTransform; MtxDefScale(&mtxTexScale, pParticle->texSequenceScale[0], pParticle->texSequenceScale[1], 1.0f); MtxDefTranslate(&mtxTexTranslate, pParticle->texSequenceOffset[0] + pParticle->texScrollOffset[0], pParticle->texSequenceOffset[1] + pParticle->texScrollOffset[1], 0.0f); MtxMul(&mtxTexTransform, &mtxTexScale, &mtxTexTranslate); // // 5. 计算粒子顶点 // VEC3 desVertices[4]; VEC3 srcVertices[4] = { VEC3(-1.0f, 1.0f, 0.0f), VEC3(-1.0f, -1.0f, 0.0f), VEC3( 1.0f, -1.0f, 0.0f), VEC3( 1.0f, 1.0f, 0.0f), }; VEC2 texCoords[4] = { VEC2(pParticle->uvOffset[0] + 0.0f, pParticle->uvOffset[1] + 0.0f), VEC2(pParticle->uvOffset[0] + 0.0f, pParticle->uvOffset[1] + 1.0f), VEC2(pParticle->uvOffset[0] + 1.0f, pParticle->uvOffset[1] + 1.0f), VEC2(pParticle->uvOffset[0] + 1.0f, pParticle->uvOffset[1] + 0.0f), }; VEC3 localNormal, localBinormal; VEC3 worldNormal, worldBinormal; Vec3Set(&localNormal, 0.0f, 0.0f, 1.0f); Vec3Set(&localBinormal, 1.0f, 0.0f, 0.0f); Vec3MulMtx3x3(&worldNormal, &localNormal, &mtxTransform); Vec3MulMtx3x3(&worldBinormal, &localBinormal, &mtxTransform); Vec3MulMtx4x4(&desVertices[0], &srcVertices[0], &mtxTransform); Vec3MulMtx4x4(&desVertices[1], &srcVertices[1], &mtxTransform); Vec3MulMtx4x4(&desVertices[2], &srcVertices[2], &mtxTransform); Vec3MulMtx4x4(&desVertices[3], &srcVertices[3], &mtxTransform); Vec3Copy(&vertices[indexVertex].position, &desVertices[0]); Vec3Copy(&vertices[indexVertex].normal, &worldNormal); Vec3Copy(&vertices[indexVertex].binormal, &worldBinormal); Vec4Copy(&vertices[indexVertex].color, &pParticle->color); Vec2MulMtx4x4(&vertices[indexVertex].texCoordDiffuse, &texCoords[0], &mtxTexTransform); indexVertex++; Vec3Copy(&vertices[indexVertex].position, &desVertices[1]); Vec3Copy(&vertices[indexVertex].normal, &worldNormal); Vec3Copy(&vertices[indexVertex].binormal, &worldBinormal); Vec4Copy(&vertices[indexVertex].color, &pParticle->color); Vec2MulMtx4x4(&vertices[indexVertex].texCoordDiffuse, &texCoords[1], &mtxTexTransform); indexVertex++; Vec3Copy(&vertices[indexVertex].position, &desVertices[2]); Vec3Copy(&vertices[indexVertex].normal, &worldNormal); Vec3Copy(&vertices[indexVertex].binormal, &worldBinormal); Vec4Copy(&vertices[indexVertex].color, &pParticle->color); Vec2MulMtx4x4(&vertices[indexVertex].texCoordDiffuse, &texCoords[2], &mtxTexTransform); indexVertex++; Vec3Copy(&vertices[indexVertex].position, &desVertices[3]); Vec3Copy(&vertices[indexVertex].normal, &worldNormal); Vec3Copy(&vertices[indexVertex].binormal, &worldBinormal); Vec4Copy(&vertices[indexVertex].color, &pParticle->color); Vec2MulMtx4x4(&vertices[indexVertex].texCoordDiffuse, &texCoords[3], &mtxTexTransform); indexVertex++; pParticle = pParticle->pNext; } Renderer()->BindVBO(GL_ARRAY_BUFFER, m_vbo); Renderer()->UpdateVBO(GL_ARRAY_BUFFER, 0, 4 * numParticles * sizeof(*vertices), vertices); } SAFE_FREE(vertices); }