//--------------------------------------------------------------------------- // // Clouds.cpp -- File contains class definitions for the Clouds // // MechCommander 2 // //---------------------------------------------------------------------------// // Copyright (C) Microsoft Corporation. All rights reserved. // //===========================================================================// //--------------------------------------------------------------------------- // Include Files #ifndef CLOUDS_H #include "clouds.h" #endif #ifndef TXMMGR_H #include "txmmgr.h" #endif #ifndef CIDENT_H #include "cident.h" #endif #ifndef PATHS_H #include "paths.h" #endif #ifndef CAMERA_H #include "camera.h" #endif #ifndef CLIP_H #include "clip.h" #endif #ifndef TIMING_H #include "timing.h" #endif //--------------------------------------------------------------------------- // Macro Definitions #define MAX_CLOUDS_ANGLE 45.0f #define MAX_CLOUDS_SIZE 4500.0f #define MAX_UV_REPEAT 4.0f #define CLOUD_START_U -2.0f #define CLOUD_START_V -2.0f #define CLOUD_ALTITUDE 200.0f #define SCROLL_U_FACTOR 0.01f; #define SCROLL_V_FACTOR 0.01f; //---------------------------------------- // Externs extern bool useFog; extern bool hasGuardBand; //--------------------------------------------------------------------------- // Class Clouds void Clouds::init (char *textureName, long gSize) { FullPathFileName cloudName; cloudName.init(texturePath,textureName,".tga"); //------------------------------------- // Load Texture here. mcTextureNodeIndex = mcTextureManager->loadTexture(cloudName,gos_Texture_Alpha,/*gosHint_DisableMipmap |*/ gosHint_DontShrink); //------------------------------------- // Create the CloudVertices here. gridSize = gSize; long gridTotal = gridSize * gridSize; cloudVertices = (CloudVertexPtr)systemHeap->Malloc(sizeof(CloudVertex)*gridTotal); gosASSERT(cloudVertices != NULL); memset(cloudVertices,0,sizeof(CloudVertex)*gridTotal); } //--------------------------------------------------------------------------- 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;ygetPosition()); 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); } } } } } #define CLOUD_Z_VALUE 0.9900f //--------------------------------------------------------------------------- void Clouds::render (void) { if (!renderClouds) return; for (long 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)]); gos_VERTEX gVertex[3]; 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))) { //-------------------------- // Top Triangle gVertex[0].x = cloudVertex0->px; gVertex[0].y = cloudVertex0->py; gVertex[0].z = CLOUD_Z_VALUE; gVertex[0].rhw = cloudVertex0->pw; gVertex[0].u = cloudVertex0->pu; gVertex[0].v = cloudVertex0->pv; gVertex[0].argb = cloudVertex0->fogRGB; gVertex[0].frgb = 0xff000000; gVertex[1].x = cloudVertex1->px; gVertex[1].y = cloudVertex1->py; gVertex[1].z = CLOUD_Z_VALUE; gVertex[1].rhw = cloudVertex1->pw; gVertex[1].u = cloudVertex1->pu; gVertex[1].v = cloudVertex1->pv; gVertex[1].argb = cloudVertex1->fogRGB; gVertex[1].frgb = 0xff000000; gVertex[2].x = cloudVertex2->px; gVertex[2].y = cloudVertex2->py; gVertex[2].z = CLOUD_Z_VALUE; gVertex[2].rhw = cloudVertex2->pw; gVertex[2].u = cloudVertex2->pu; gVertex[2].v = cloudVertex2->pv; gVertex[2].argb = cloudVertex2->fogRGB; gVertex[2].frgb = 0xff000000; mcTextureManager->addVertices(mcTextureNodeIndex,gVertex,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))) { //-------------------------- //Bottom Triangle // // gVertex[0] same as above gVertex[0]. // gVertex[1] is same as above gVertex[2]. // gVertex[2] is calced from vertex[3]. gVertex[0].x = cloudVertex0->px; gVertex[0].y = cloudVertex0->py; gVertex[0].z = CLOUD_Z_VALUE; gVertex[0].rhw = cloudVertex0->pw; gVertex[0].u = cloudVertex0->pu; gVertex[0].v = cloudVertex0->pv; gVertex[0].argb = cloudVertex0->fogRGB; gVertex[0].frgb = 0xff000000; gVertex[1].x = cloudVertex2->px; gVertex[1].y = cloudVertex2->py; gVertex[1].z = CLOUD_Z_VALUE; gVertex[1].rhw = cloudVertex2->pw; gVertex[1].u = cloudVertex2->pu; gVertex[1].v = cloudVertex2->pv; gVertex[1].argb = cloudVertex2->fogRGB; gVertex[1].frgb = 0xff000000; gVertex[2].x = cloudVertex3->px; gVertex[2].y = cloudVertex3->py; gVertex[2].z = CLOUD_Z_VALUE; gVertex[2].rhw = cloudVertex3->pw; gVertex[2].u = cloudVertex3->pu; gVertex[2].v = cloudVertex3->pv; gVertex[2].argb = cloudVertex3->fogRGB; gVertex[2].frgb = 0xff000000; mcTextureManager->addVertices(mcTextureNodeIndex,gVertex,MC2_DRAWALPHA); } } } } //--------------------------------------------------------------------------- void Clouds::destroy (void) { systemHeap->Free(cloudVertices); cloudVertices = NULL; } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // // Edit Log // //---------------------------------------------------------------------------