void fxRenderImage::findCameraAxis(TSRenderContext &rc) { TMat3F wCamMat = rc.getCamera()->getTCW(); camAxis = transform.p; camAxis -= wCamMat.p; camDist = m_dot(camAxis,camAxis); if (IsEqual(camDist,0.0f)) camAxis.set(0,1,0); // camAxis.len()==0, just use standard axes else { camDist = m_sqrtf(camDist); camAxis *= 1/camDist; } }
/** return square root of a */ template <> inline float CMath<float>::sqrt(float a) { return m_sqrtf(a); }
// decide where to place and then add to the manager void SimExplosionCloud::lightFuse(SimExplosion * explosion, Point3F & cameraPos, bool igniteNow) { // decide when to detonate if (!igniteNow) explosion->setDetonationTime(g_expRand.getFloat(0,detonationMax)); Point3F pos; Point3F vec(0, 0, 0); Point3F worldPos,worldVec; switch (form) { case Sphere : { // try to make sure explosions no closer together than 1m in z int maxZ = (int) radius; if (maxZ) { if (topOnly) vec.z = g_expRand.getInt(0,maxZ); else vec.z = g_expRand.getInt(-maxZ,maxZ); } // don't break, fall through to circle } case Circle : { float angle = g_expRand.getFloat(0,float(M_2PI)); float circleRad = m_sqrtf(radius*radius - vec.z *vec.z); vec.x = circleRad * m_cos(angle); vec.y = circleRad * m_sin(angle); pos = center; pos += vec; break; } case Screen: { if (radius>0.1f) // if radius==0, skip some work { vec=cameraPos; vec -= center; vec.normalize(); Point3F dirX,dirZ; if (fabs(vec.z) < 0.95) { // vec is not near vector (0,0,1), so we can // use it as the pivot vector m_cross(vec, Point3F(0,0,1), &dirX); dirX.normalize(); m_cross(dirX, vec, &dirZ); } else { // dirY is near vector (0,0,1), so use // pivot Point3F(1,0,0) instead m_cross(Point3F(1,0,0), vec, &dirZ); dirZ.normalize(); m_cross(vec, dirZ, &dirX); } dirX *= g_expRand.getFloat(-radius,radius); dirZ *= g_expRand.getFloat(-radius,radius); vec *= radius; vec += dirX; vec += dirZ; } pos = center; pos += vec; break; } case Box : { int side; if (topOnly) side = g_expRand.getInt(1,5); else side = g_expRand.getInt(0,5); pos = box.fMax; switch (side) { case 0: pos.z = box.fMin.z; case 1: pos.x = g_expRand.getFloat(box.fMin.x,box.fMax.x); pos.y = g_expRand.getFloat(box.fMin.y,box.fMax.y); break; case 2: pos.y = box.fMin.y; case 3: pos.x = g_expRand.getFloat(box.fMin.x,box.fMax.x); pos.z = g_expRand.getFloat(box.fMin.z,box.fMax.z); break; case 4: pos.x = box.fMin.x; case 5: pos.y = g_expRand.getFloat(box.fMin.y,box.fMax.y); pos.z = g_expRand.getFloat(box.fMin.z,box.fMax.z); break; } switch (side) { case 0: vec.set(0,0,box.fMin.z-box.fMax.z); break; case 1: vec.set(0,0,box.fMax.z-box.fMin.z); break; case 2: vec.set(0,box.fMin.y-box.fMax.y,0); break; case 3: vec.set(0,box.fMax.y-box.fMin.y,0); break; case 4: vec.set(box.fMin.x-box.fMax.x,0,0); break; case 5: vec.set(box.fMax.x-box.fMin.x,0,0); break; } break; } } // now put into world coords if (hasTransform) { m_mul(pos,transform,&worldPos); m_mul(vec,(RMat3F&)transform,&worldVec); } else { worldPos=pos; worldVec=vec; } Point3F camAxis = worldPos; camAxis -= cameraPos; if (m_dot(camAxis,worldVec)>0.0f) { worldPos -= worldVec; worldPos -= worldVec; } explosion->setPosition(worldPos); explosion->setAxis(worldVec); // move away from the building... ;-> explosion->setSound(false); manager->addObject(explosion); }