//--------------------------------------------------------------------------- void Terrain::geometry (void) { //--------------------------------------------------------------------- leastZ = 1.0f;leastW = 1.0f; mostZ = -1.0f; mostW = -1.0; leastWY = 0.0f; mostWY = 0.0f; //----------------------------------- // Transform entire list of vertices VertexPtr currentVertex = vertexList; Stuff::Vector3D cameraPos; cameraPos.x = -eye->getCameraOrigin().x; cameraPos.y = eye->getCameraOrigin().z; cameraPos.z = eye->getCameraOrigin().y; float vClipConstant = eye->verticalSphereClipConstant; float hClipConstant = eye->horizontalSphereClipConstant; long i=0; for (i=0;i<numberVertices;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 = false; //----------------------------------------------------------------- // Find angle between lookVector of Camera and vector from camPos // to Target. If angle is less then halfFOV, object is visible. if (eye->usePerspective) { //------------------------------------------------------------------- //NEW METHOD from the WAY BACK Days onScreen = true; Stuff::Vector3D vPosition; vPosition.x = currentVertex->vx; vPosition.y = currentVertex->vy; vPosition.z = currentVertex->pVertex->elevation; Stuff::Vector3D objectCenter; objectCenter.Subtract(vPosition,cameraPos); Camera::cameraFrame.trans_to_frame(objectCenter); float distanceToEye = objectCenter.GetApproximateLength(); Stuff::Vector3D clipVector = objectCenter; clipVector.z = 0.0f; float distanceToClip = clipVector.GetApproximateLength(); float clip_distance = fabs(1.0f / objectCenter.y); if (distanceToClip > CLIP_THRESHOLD_DISTANCE) { //Is vertex on Screen OR close enough to screen that its triangle MAY be visible? // WE have removed the atans here by simply taking the tan of the angle we want above. float object_angle = fabs(objectCenter.z) * clip_distance; float extent_angle = VERTEX_EXTENT_RADIUS / distanceToEye; if (object_angle > (vClipConstant + extent_angle)) { //In theory, we would return here. Object is NOT on screen. onScreen = false; } else { object_angle = fabs(objectCenter.x) * clip_distance; if (object_angle > (hClipConstant + extent_angle)) { //In theory, we would return here. Object is NOT on screen. onScreen = false; } } } if (onScreen) { if (distanceToEye > Camera::MaxClipDistance) { currentVertex->hazeFactor = 1.0f; } else if (distanceToEye > Camera::MinHazeDistance) { currentVertex->hazeFactor = (distanceToEye - Camera::MinHazeDistance) * Camera::DistanceFactor; } else { currentVertex->hazeFactor = 0.0f; } //--------------------------------------- // Vertex is at edge of world or beyond. Stuff::Vector3D vPos(currentVertex->vx,currentVertex->vy,currentVertex->pVertex->elevation); bool isVisible = Terrain::IsGameSelectTerrainPosition(vPos) || drawTerrainGrid; if (!isVisible) { currentVertex->hazeFactor = 1.0f; onScreen = true; } } else { currentVertex->hazeFactor = 1.0f; } } else { currentVertex->hazeFactor = 0.0f; onScreen = true; } bool inView = false; Stuff::Vector4D screenPos(-10000.0f,-10000.0f,-10000.0f,-10000.0f); if (onScreen) { Stuff::Vector3D vertex3D(currentVertex->vx,currentVertex->vy,currentVertex->pVertex->elevation); inView = eye->projectZ(vertex3D,screenPos); currentVertex->px = screenPos.x; currentVertex->py = screenPos.y; currentVertex->pz = screenPos.z; currentVertex->pw = screenPos.w; //---------------------------------------------------------------------------------- //We must transform these but should NOT draw any face where all three are fogged. // if (currentVertex->hazeFactor == 1.0f) // onScreen = false; } else { currentVertex->px = currentVertex->py = 10000.0f; currentVertex->pz = -0.5f; currentVertex->pw = 0.5f; currentVertex->hazeFactor = 0.0f; } //------------------------------------------------------------ // Fix clip. Vertices can all be off screen and triangle // still needs to be drawn! if (eye->usePerspective && Environment.Renderer != 3) { currentVertex->clipInfo = onScreen; } else currentVertex->clipInfo = inView; if (currentVertex->clipInfo) //ONLY set TRUE ones. Otherwise we just reset the FLAG each vertex! { setObjBlockActive(currentVertex->getBlockNumber(), true); setObjVertexActive(currentVertex->vertexNum,true); if (inView) { if (screenPos.z < leastZ) { leastZ = screenPos.z; } if (screenPos.z > mostZ) { mostZ = screenPos.z; } if (screenPos.w < leastW) { leastW = screenPos.w; leastWY = screenPos.y; } if (screenPos.w > mostW) { mostW = screenPos.w; mostWY = screenPos.y; } } } currentVertex++; } //----------------------------------- // setup terrain quad textures // Also sets up mine data. TerrainQuadPtr currentQuad = quadList; for (i=0;i<numberQuads;i++) { currentQuad->setupTextures(); currentQuad++; } float ywRange = 0.0f, yzRange = 0.0f; if (fabs(mostWY - leastWY) > Stuff::SMALL) { ywRange = (mostW - leastW) / (mostWY - leastWY); yzRange = (mostZ - leastZ) / (mostWY - leastWY); } eye->setInverseProject(mostZ,leastW,yzRange,ywRange); //----------------------------------- // update the cloud layer if (Terrain::cloudLayer) Terrain::cloudLayer->update(); }
//--------------------------------------------------------------------------- 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); } } } } }