//--------------------------------------------------------------------------- void Clouds::update (void) { renderClouds = false; scrollU += frameLength * SCROLL_U_FACTOR; scrollV += frameLength * SCROLL_V_FACTOR; if (scrollU > 1.0f) scrollU -= 1.0f; if (scrollV > 1.0f) scrollV -= 1.0f; if (scrollU < -1.0f) scrollU += 1.0f; if (scrollV < -1.0f) scrollV += 1.0f; //--------------------------------------------------------------------- // If projectionAngle is less then some magic number, draw the clouds. // Otherwise, do not do anything! if (eye->active && eye->usePerspective && (eye->getProjectionAngle() < MAX_CLOUDS_ANGLE)) { //renderClouds = true; //------------------------------------------------------- // Create the cloud grid based on camera CENTER position. Stuff::Vector3D centerPosition(eye->getPosition()); //------------------------------------------------------- // Create a topLeft vertex float tLeftX = centerPosition.x + MAX_CLOUDS_SIZE; float tLeftY = centerPosition.y + MAX_CLOUDS_SIZE; //------------------------------------------------------- // Create the grid. long cloudInc = float2long(MAX_CLOUDS_SIZE * 2.0f / gridSize); float uvInc = MAX_UV_REPEAT / float(gridSize); for (long y=0;y<gridSize;y++) { for (long x=0;x<gridSize;x++) { cloudVertices[x + (y*gridSize)].vx = tLeftX - (cloudInc * x); cloudVertices[x + (y*gridSize)].vy = tLeftY - (cloudInc * y); cloudVertices[x + (y*gridSize)].pu = CLOUD_START_U + (uvInc * x); cloudVertices[x + (y*gridSize)].pv = CLOUD_START_V + (uvInc * y); } } //------------------------------------------------------- // Transform Grid long gridTotal = gridSize * gridSize; for (long i=0;i<gridTotal;i++) { //---------------------------------------------------------------------------------------- // Figure out if we are in front of camera or not. Should be faster then actual project! // Should weed out VAST overwhelming majority of vertices! bool onScreen = true; //----------------------------------------------------------------- // Find angle between lookVector of Camera and vector from camPos // to Target. If angle is less then halfFOV, object is visible. //------------------------------------------------------------------- // Then figure out if FarClipped. Should weed out a boatload more! float hazeFactor = 0.0f; Stuff::Point3D Distance; Stuff::Point3D vPosition; Stuff::Point3D eyePosition(eye->getPosition()); vPosition.x = cloudVertices[i].vx;; vPosition.y = cloudVertices[i].vy; vPosition.z = centerPosition.z; Distance.Subtract(eyePosition,vPosition); float eyeDistance = Distance.GetApproximateLength(); if (eyeDistance > Camera::MaxClipDistance) { hazeFactor = 1.0f; //onScreen = false; } else if (eyeDistance > Camera::MinHazeDistance) { hazeFactor = (eyeDistance - Camera::MinHazeDistance) * Camera::DistanceFactor; } else { hazeFactor = 0.0f; } //------------------------------------------------------------ // Calculate the HazeDWORD here if (hazeFactor != 0.0f) { float fogFactor = 1.0 - hazeFactor; DWORD distFog = float2long(fogFactor * 255.0f); cloudVertices[i].fogRGB = (distFog<<24) + (0xffffff); } else { cloudVertices[i].fogRGB = 0xffffffff; } if (onScreen) { Stuff::Vector3D Distance; Stuff::Point3D objPosition; Stuff::Point3D eyePosition(eye->getCameraOrigin()); objPosition.x = -cloudVertices[i].vx; objPosition.y = CLOUD_ALTITUDE; objPosition.z = cloudVertices[i].vy; Distance.Subtract(objPosition,eyePosition); Distance.Normalize(Distance); float cosine = Distance * eye->getLookVector(); if (cosine > eye->cosHalfFOV) onScreen = true; else onScreen = false; } else { hazeFactor = 1.0f; } Stuff::Vector3D vertex3D(cloudVertices[i].vx,cloudVertices[i].vy,(CLOUD_ALTITUDE+eye->getCameraOrigin().y)); Stuff::Vector4D screenPos; bool inView = eye->projectZ(vertex3D,screenPos); cloudVertices[i].px = screenPos.x; cloudVertices[i].py = screenPos.y; cloudVertices[i].pz = screenPos.z; cloudVertices[i].pw = screenPos.w; //------------------------------------------------------------ // Fix clip. Vertices can all be off screen and triangle // still needs to be drawn! cloudVertices[i].clipInfo = onScreen && inView; //------------------------------------------------------------ // Still need to scrollUVs here! cloudVertices[i].pu += scrollU; cloudVertices[i].pv += scrollV; } for (y=0;y<(gridSize-1);y++) { for (long x=0;x<(gridSize-1);x++) { CloudVertexPtr cloudVertex0 = &(cloudVertices[x + (y *gridSize)]); CloudVertexPtr cloudVertex1 = &(cloudVertices[(x+1) + (y *gridSize)]); CloudVertexPtr cloudVertex2 = &(cloudVertices[(x+1) + ((y+1)*gridSize)]); CloudVertexPtr cloudVertex3 = &(cloudVertices[x + ((y+1)*gridSize)]); bool clipCheck = (cloudVertex0->clipInfo || cloudVertex1->clipInfo || cloudVertex2->clipInfo); if (clipCheck && ((cloudVertex0->pz < 1.0f) && (cloudVertex0->pz > 0.0f) && (cloudVertex1->pz < 1.0f) && (cloudVertex1->pz > 0.0f) && (cloudVertex2->pz < 1.0f) && (cloudVertex2->pz > 0.0f))) { mcTextureManager->addTriangle(mcTextureNodeIndex,MC2_DRAWALPHA); } clipCheck = (cloudVertex0->clipInfo || cloudVertex2->clipInfo || cloudVertex3->clipInfo); if (clipCheck && ((cloudVertex0->pz < 1.0f) && (cloudVertex0->pz > 0.0f) && (cloudVertex2->pz < 1.0f) && (cloudVertex2->pz > 0.0f) && (cloudVertex3->pz < 1.0f) && (cloudVertex3->pz > 0.0f))) { mcTextureManager->addTriangle(mcTextureNodeIndex,MC2_DRAWALPHA); } } } } }
//------------------------------------------------------------------------------ // bool gosFX::PointCloud::AnimateParticle( uint32_t index, const Stuff::LinearMatrix4D* world_to_new_local, Stuff::Time till ) { Check_Object(this); // //----------------------------------------------------------------------- // If this cloud is unparented, we need to transform the point from local // space into world space and set the internal position/velocity pointers // to these temporary values //----------------------------------------------------------------------- // Particle* particle = GetParticle(index); Check_Object(particle); float age = particle->m_age; if(age >= 1.0f) return false; Set_Statistic(Point_Count, Point_Count + 1); Stuff::Vector3D* velocity = &particle->m_localLinearVelocity; Stuff::Point3D* translation = &m_P_localTranslation[index]; int32_t sim_mode = GetSimulationMode(); if(sim_mode == DynamicWorldSpaceSimulationMode) { Check_Object(translation); Check_Object(velocity); particle->m_worldLinearVelocity.Multiply(*velocity, m_localToWorld); particle->m_worldTranslation.Multiply(*translation, m_localToWorld); translation = &particle->m_worldTranslation; velocity = &particle->m_worldLinearVelocity; } Check_Object(translation); Check_Object(velocity); // //------------------------------------------------------------------ // First, calculate the drag on the particle. Drag can never assist // velocity //------------------------------------------------------------------ // float seed = particle->m_seed; Specification* spec = GetSpecification(); Check_Object(spec); Stuff::Vector3D ether; ether.x = spec->m_pEtherVelocityX.ComputeValue(age, seed); ether.y = spec->m_pEtherVelocityY.ComputeValue(age, seed); ether.z = spec->m_pEtherVelocityZ.ComputeValue(age, seed); Stuff::Vector3D accel(Stuff::Vector3D::Identity); // //------------------------------------------------------------------- // Deal with pseudo-world simulation. In this mode, we interpret the // forces as if they are already in worldspace, and we transform them // back to local space //------------------------------------------------------------------- // float drag = -spec->m_pDrag.ComputeValue(age, seed); Max_Clamp(drag, 0.0f); if(sim_mode == StaticWorldSpaceSimulationMode) { Stuff::LinearMatrix4D world_to_effect; world_to_effect.Invert(m_localToWorld); Stuff::Vector3D local_ether; local_ether.MultiplyByInverse(ether, world_to_effect); Stuff::Vector3D rel_vel; rel_vel.Subtract(*velocity, local_ether); accel.Multiply(rel_vel, drag); // //----------------------------------------- // Now, add in acceleration of the particle //----------------------------------------- // Stuff::Vector3D world_accel; world_accel.x = spec->m_pAccelerationX.ComputeValue(age, seed); world_accel.y = spec->m_pAccelerationY.ComputeValue(age, seed); world_accel.z = spec->m_pAccelerationZ.ComputeValue(age, seed); Stuff::Vector3D local_accel; local_accel.Multiply(world_accel, world_to_effect); accel += local_accel; } // //---------------------------------------------------------------------- // Otherwise, just add the forces in the same space the particles are in //---------------------------------------------------------------------- // else { Stuff::Vector3D rel_vel; rel_vel.Subtract(*velocity, ether); accel.Multiply(rel_vel, drag); // //----------------------------------------- // Now, add in acceleration of the particle //----------------------------------------- // accel.x += spec->m_pAccelerationX.ComputeValue(age, seed); accel.y += spec->m_pAccelerationY.ComputeValue(age, seed); accel.z += spec->m_pAccelerationZ.ComputeValue(age, seed); } // //------------------------------------------------- // Compute the particle's new velocity and position //------------------------------------------------- // float time_slice = static_cast<float>(till - m_lastRan); velocity->AddScaled(*velocity, accel, time_slice); translation->AddScaled(*translation, *velocity, time_slice); // //--------------------------------------------------------------------- // If we are unparented, we need to transform the velocity and position // data back into the NEW local space //--------------------------------------------------------------------- // if(sim_mode == DynamicWorldSpaceSimulationMode) { Check_Object(world_to_new_local); particle->m_localLinearVelocity.Multiply( particle->m_worldLinearVelocity, *world_to_new_local ); m_P_localTranslation[index].Multiply( particle->m_worldTranslation, *world_to_new_local ); } // //------------------ // Animate the color //------------------ // Check_Pointer(m_P_color); m_P_color[index].red = spec->m_pRed.ComputeValue(age, seed); m_P_color[index].green = spec->m_pGreen.ComputeValue(age, seed); m_P_color[index].blue = spec->m_pBlue.ComputeValue(age, seed); m_P_color[index].alpha = spec->m_pAlpha.ComputeValue(age, seed); return true; }
//--------------------------------------------------------------------- void CraterManager::render (void) { if (!useNonWeaponEffects) return; //----------------------------------------------------- // Run through all craters in list and render anything // which not clipped or an invalid_crater CraterDataPtr currCrater = craterList; for (long i=0;i<(long)maxCraters;i++,currCrater++) { if (currCrater->craterShapeId != -1) { long handleOffset = 1; float uvAdd = 0.125; if (currCrater->craterShapeId >= MAX_FOOTPRINTS) { handleOffset = 0; uvAdd = 0.50; } bool onScreen1 = eye->projectZ(currCrater->position[0],currCrater->screenPos[0]); bool onScreen2 = eye->projectZ(currCrater->position[1],currCrater->screenPos[1]); bool onScreen3 = eye->projectZ(currCrater->position[2],currCrater->screenPos[2]); bool onScreen4 = eye->projectZ(currCrater->position[3],currCrater->screenPos[3]); //-------------------------------------------------- // First, if we are using perspective, figure out // if object too far from camera. Far Clip Plane. float hazeFactor = 0.0f; if (eye->usePerspective) { Stuff::Point3D Distance; Stuff::Point3D objPosition; Stuff::Point3D eyePosition(eye->getCameraOrigin()); objPosition.x = -currCrater->position[0].x; objPosition.y = currCrater->position[0].z; objPosition.z = currCrater->position[0].y; Distance.Subtract(objPosition,eyePosition); float eyeDistance = Distance.GetApproximateLength(); if (eyeDistance > Camera::MaxClipDistance) { onScreen1 = false; onScreen2 = false; onScreen3 = false; onScreen4 = false; } else if (eyeDistance > Camera::MinHazeDistance) { hazeFactor = (eyeDistance - Camera::MinHazeDistance) * Camera::DistanceFactor; } else { hazeFactor = 0.0f; } } //---------------- // Check clipping if (onScreen1 || onScreen2 || onScreen3 || onScreen4) { DWORD lightRGB = 0xffffffff; DWORD specR = 0, specB = 0, specG = 0; unsigned char lightr = 0xff,lightg = 0xff,lightb = 0xff; lightr = eye->ambientRed; lightg = eye->ambientGreen; lightb = eye->ambientBlue; lightRGB = lightb + (lightr<<16) + (lightg << 8) + (0xff << 24); if (Terrain::terrainTextures2) { if (TerrainQuad::rainLightLevel < 1.0f) { lightr = (float)lightr * TerrainQuad::rainLightLevel; lightb = (float)lightb * TerrainQuad::rainLightLevel; lightg = (float)lightg * TerrainQuad::rainLightLevel; } if (TerrainQuad::lighteningLevel > 0x0) { specR = specG = specB = TerrainQuad::lighteningLevel; } lightRGB = lightb + (lightr<<16) + (lightg << 8) + (0xff << 24); } DWORD fogRGB = (0xff<<24) + (specR<<16) + (specG<<8) + specB; if (useFog) { DWORD fogValue = 0xff; float fogStart = eye->fogStart; float fogFull = eye->fogFull; if (currCrater->position[0].z < fogStart) { float fogFactor = fogStart - currCrater->position[0].z; if (fogFactor < 0.0) fogRGB = (0xff<<24) + (specR<<16) + (specG<<8) + specB; else { fogFactor /= (fogStart - fogFull); if (fogFactor <= 1.0) { fogFactor *= fogFactor; fogFactor = 1.0 - fogFactor; fogFactor *= 256.0; } else { fogFactor = 256.0; } unsigned char fogResult = fogFactor; fogValue = fogFactor; fogRGB = (fogResult << 24) + (specR<<16) + (specG<<8) + specB; } } else { fogRGB = (0xff<<24) + (specR<<16) + (specG<<8) + specB; } if (hazeFactor != 0.0f) { float fogFactor = 1.0 - hazeFactor; DWORD distFog = float2long(fogFactor * 255.0f); if (distFog < fogValue) fogValue = distFog; fogRGB = (fogValue << 24) + (specR << 16) + (specG << 8) + (specB); } } if (drawOldWay) { //------------------------------------ // Replace with Polygon Quad Elements gos_VERTEX gVertex[4]; gVertex[0].x = currCrater->screenPos[0].x; gVertex[0].y = currCrater->screenPos[0].y; gVertex[0].z = currCrater->screenPos[0].z; gVertex[0].rhw = currCrater->screenPos[0].w; gVertex[0].u = craterUVTable[(currCrater->craterShapeId*2)]; gVertex[0].v = craterUVTable[(currCrater->craterShapeId*2)+1]; gVertex[0].argb = lightRGB; gVertex[0].frgb = fogRGB; gVertex[1].x = currCrater->screenPos[1].x; gVertex[1].y = currCrater->screenPos[1].y; gVertex[1].z = currCrater->screenPos[1].z; gVertex[1].rhw = currCrater->screenPos[1].w; gVertex[1].u = gVertex[0].u + uvAdd; gVertex[1].v = gVertex[0].v; gVertex[1].argb = lightRGB; gVertex[1].frgb = fogRGB; gVertex[2].x = currCrater->screenPos[2].x; gVertex[2].y = currCrater->screenPos[2].y; gVertex[2].z = currCrater->screenPos[2].z; gVertex[2].rhw = currCrater->screenPos[2].w; gVertex[2].u = gVertex[1].u; gVertex[2].v = gVertex[0].v + uvAdd; gVertex[2].argb = lightRGB; gVertex[2].frgb = fogRGB; gVertex[3].x = currCrater->screenPos[3].x; gVertex[3].y = currCrater->screenPos[3].y; gVertex[3].z = currCrater->screenPos[3].z; gVertex[3].rhw = currCrater->screenPos[3].w; gVertex[3].u = gVertex[0].u; gVertex[3].v = gVertex[2].v; gVertex[3].argb = lightRGB; gVertex[3].frgb = fogRGB; TexturedPolygonQuadElement element; element.init(gVertex,craterTextureHandles[handleOffset],false,false); //----------------------------------------------------- // FOG time. Set Render state to FOG on! if (useFog) { DWORD fogColor = eye->fogColor; gos_SetRenderState( gos_State_Fog, (int)&fogColor); } else { gos_SetRenderState( gos_State_Fog, 0); } element.draw(); gos_SetRenderState( gos_State_Fog, 0); //ALWAYS SHUT FOG OFF WHEN DONE! } else { //------------------------------------ gos_VERTEX gVertex[3]; gos_VERTEX sVertex[3]; gVertex[0].x = sVertex[0].x = currCrater->screenPos[0].x; gVertex[0].y = sVertex[0].y = currCrater->screenPos[0].y; gVertex[0].z = sVertex[0].z = currCrater->screenPos[0].z; gVertex[0].rhw = sVertex[0].rhw = currCrater->screenPos[0].w; gVertex[0].u = sVertex[0].u = craterUVTable[(currCrater->craterShapeId*2)]; gVertex[0].v = sVertex[0].v = craterUVTable[(currCrater->craterShapeId*2)+1]; gVertex[0].argb = sVertex[0].argb = lightRGB; gVertex[0].frgb = sVertex[0].frgb = fogRGB; gVertex[1].x = currCrater->screenPos[1].x; gVertex[1].y = currCrater->screenPos[1].y; gVertex[1].z = currCrater->screenPos[1].z; gVertex[1].rhw = currCrater->screenPos[1].w; gVertex[1].u = gVertex[0].u + uvAdd; gVertex[1].v = gVertex[0].v; gVertex[1].argb = lightRGB; gVertex[1].frgb = fogRGB; gVertex[2].x = sVertex[1].x = currCrater->screenPos[2].x; gVertex[2].y = sVertex[1].y = currCrater->screenPos[2].y; gVertex[2].z = sVertex[1].z = currCrater->screenPos[2].z; gVertex[2].rhw = sVertex[1].rhw = currCrater->screenPos[2].w; gVertex[2].u = sVertex[1].u = gVertex[1].u; gVertex[2].v = sVertex[1].v = gVertex[0].v + uvAdd; gVertex[2].argb = sVertex[1].argb = lightRGB; gVertex[2].frgb = sVertex[1].frgb = fogRGB; sVertex[2].x = currCrater->screenPos[3].x; sVertex[2].y = currCrater->screenPos[3].y; sVertex[2].z = currCrater->screenPos[3].z; sVertex[2].rhw = currCrater->screenPos[3].w; sVertex[2].u = gVertex[0].u; sVertex[2].v = gVertex[2].v; sVertex[2].argb = lightRGB; sVertex[2].frgb = fogRGB; if (currCrater->craterShapeId > TURKINA_FOOTPRINT) //We are standard crater. { mcTextureManager->addVertices(craterTextureIndices[handleOffset],gVertex,MC2_ISCRATERS | MC2_DRAWALPHA | MC2_ISTERRAIN); mcTextureManager->addVertices(craterTextureIndices[handleOffset],sVertex,MC2_ISCRATERS | MC2_DRAWALPHA | MC2_ISTERRAIN); } else //We are a footprint { mcTextureManager->addVertices(craterTextureIndices[handleOffset],gVertex,MC2_ISCRATERS | MC2_DRAWALPHA); mcTextureManager->addVertices(craterTextureIndices[handleOffset],sVertex,MC2_ISCRATERS | MC2_DRAWALPHA); } } } } } }