// // 影响粒子 // 注意: 只影响从KeepLocal=TRUE 到 KeepLocal=FALSE // VOID CAffectorKeepLocal::Affect(CParticle *pParticle, FLOAT deltaTime) { if (IsCanAffect(pParticle)) { if (pParticle->bKeepLocal && m_bKeepLocal == FALSE) { const VEC3 *parentWorldScale = pParticle->pEmitter->GetWorldScale(); const VEC3 *parentWorldPosition = pParticle->pEmitter->GetWorldPosition(); const QUAT *parentWorldOrientation = pParticle->pEmitter->GetWorldOrientation(); QuatMul(&pParticle->localOrientation, &pParticle->localOrientation, parentWorldOrientation); VEC3 scalePosition; VEC3 scaleOrientationPosition; Vec3Mul(&scalePosition, &pParticle->localPosition, parentWorldScale); Vec3MulQuat(&scaleOrientationPosition, &scalePosition, parentWorldOrientation); Vec3Add(&pParticle->localPosition, &scaleOrientationPosition, parentWorldPosition); FLOAT velocity = Vec3Normalize(&pParticle->localVelocity); VEC3 localDirection; Vec3Set(&localDirection, 0.0f, 0.0f, 1.0f); Vec3MulQuat(&pParticle->localVelocity, &localDirection, &pParticle->localOrientation); Vec3Normalize(&pParticle->localVelocity); Vec3Scale(&pParticle->localVelocity, &pParticle->localVelocity, velocity); Vec3Mul(&pParticle->localVelocity, &pParticle->localVelocity, parentWorldScale); pParticle->bKeepLocal = FALSE; } } }
/*! @brief 直接照明計算 @param[o] out: 出力輝度 @param[i] v: 着目点 @param[i] mtrl: マテリアル */ void Renderer::DirectLighting(Color& out, const Ray& ray, const Vertex& v, const Material& mtrl) { // 自己遮蔽で引っかかるため法線方向に押し出す const float epsilon = 0.001f; Ray to_lig; ColorSet(&out, 0.0f, 0.0f, 0.0f); const LightList& list = scene->GetLightList(); for(LightList::const_iterator it = list.begin(); it != list.end(); it++) { // occlusion test #ifdef USE_OCCLUSION_TEST if((*it)->type == Light::Type_Point) { Vec3Subtract(&to_lig.dir, &(*it)->pos, &v.p); float d = sqrtf(Vec3InnerProduct(&to_lig.dir, &to_lig.dir)); if(d < FLT_EPSILON) continue; Vec3Scale(&to_lig.dir, &to_lig.dir, 1.0f/d); Vec3Scale(&to_lig.org, &to_lig.dir, epsilon); Vec3Add(&to_lig.org, &v.p, &to_lig.org); float t; if(FindOccluder(t, to_lig) && (t <= (d + epsilon))) continue; } else { to_lig.dir = -(*it)->dir; Vec3Scale(&to_lig.org, &to_lig.dir, epsilon); Vec3Add(&to_lig.org, &v.p, &to_lig.org); float t; if(FindOccluder(t, to_lig)) continue; } #endif // USE_OCCLUSION_TEST // lighting Color col; (*it)->Lighting(col, ray, v, mtrl); ColorAdd3(&out, &out, &col); } }
// // 更新 // 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); }