| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694 |
- /*
- ** Command & Conquer Generals(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- ////////////////////////////////////////////////////////////////////////////////
- // //
- // (c) 2001-2003 Electronic Arts Inc. //
- // //
- ////////////////////////////////////////////////////////////////////////////////
- // FILE: W3DTreeBuffer.cpp ////////////////////////////////////////////////
- //-----------------------------------------------------------------------------
- //
- // Westwood Studios Pacific.
- //
- // Confidential Information
- // Copyright (C) 2001 - All Rights Reserved
- //
- //-----------------------------------------------------------------------------
- //
- // Project: RTS3
- //
- // File name: W3DTreeBuffer.cpp
- //
- // Created: John Ahlquist, May 2001
- //
- // Desc: Draw buffer to handle all the trees in a scene.
- //
- //-----------------------------------------------------------------------------
- //-----------------------------------------------------------------------------
- // Includes
- //-----------------------------------------------------------------------------
- #include "W3DDevice/GameClient/W3DTreeBuffer.h"
- #include <stdio.h>
- #include <string.h>
- #include <assetmgr.h>
- #include <texture.h>
- #include "common/GlobalData.h"
- #include "GameClient/ClientRandomValue.h"
- #include "W3DDevice/GameClient/TerrainTex.h"
- #include "W3DDevice/GameClient/HeightMap.h"
- #include "W3DDevice/GameClient/W3DDynamicLight.h"
- #include "WW3D2/Camera.h"
- #include "WW3D2/DX8Wrapper.h"
- #include "WW3D2/DX8Renderer.h"
- #include "WW3D2/Mesh.h"
- #include "WW3D2/MeshMdl.h"
- //-----------------------------------------------------------------------------
- // Private Data
- //-----------------------------------------------------------------------------
- // A W3D shader that does alpha, texturing, tests zbuffer, doesn't update zbuffer.
- #define SC_ALPHA_DETAIL ( SHADE_CNST(ShaderClass::PASS_LEQUAL, ShaderClass::DEPTH_WRITE_DISABLE, ShaderClass::COLOR_WRITE_ENABLE, ShaderClass::SRCBLEND_SRC_ALPHA, \
- ShaderClass::DSTBLEND_ONE_MINUS_SRC_ALPHA, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_MODULATE, ShaderClass::SECONDARY_GRADIENT_DISABLE, ShaderClass::TEXTURING_ENABLE, \
- ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_DISABLE, \
- ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE) )
- static ShaderClass detailAlphaShader(SC_ALPHA_DETAIL);
- /*
- #define SC_ALPHA_MIRROR ( SHADE_CNST(ShaderClass::PASS_LEQUAL, ShaderClass::DEPTH_WRITE_DISABLE, ShaderClass::COLOR_WRITE_ENABLE, ShaderClass::SRCBLEND_SRC_ALPHA, \
- ShaderClass::DSTBLEND_ONE_MINUS_SRC_ALPHA, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_MODULATE, ShaderClass::SECONDARY_GRADIENT_DISABLE, ShaderClass::TEXTURING_ENABLE, \
- ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE, ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_DISABLE, \
- ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE) )
- static ShaderClass mirrorAlphaShader(SC_ALPHA_DETAIL);
- // ShaderClass::PASS_ALWAYS,
- #define SC_ALPHA_2D ( SHADE_CNST(PASS_ALWAYS, DEPTH_WRITE_DISABLE, COLOR_WRITE_ENABLE, \
- SRCBLEND_SRC_ALPHA, DSTBLEND_ONE_MINUS_SRC_ALPHA, FOG_DISABLE, GRADIENT_DISABLE, \
- SECONDARY_GRADIENT_DISABLE, TEXTURING_ENABLE, DETAILCOLOR_DISABLE, DETAILALPHA_DISABLE, \
- ALPHATEST_DISABLE, CULL_MODE_ENABLE, DETAILCOLOR_DISABLE, DETAILALPHA_DISABLE) )
- ShaderClass ShaderClass::_PresetAlpha2DShader(SC_ALPHA_2D);
- */
- //-----------------------------------------------------------------------------
- // Private Functions
- //-----------------------------------------------------------------------------
- //=============================================================================
- // W3DTreeBuffer::cull
- //=============================================================================
- /** Culls the trees, marking the visible flag. If a tree becomes visible, it sets
- it's sortKey */
- //=============================================================================
- void W3DTreeBuffer::cull(CameraClass * camera)
- {
- Int curTree;
- m_anythingChanged = false;
- // Calulate the vector direction that the camera is looking at.
- Matrix3D camera_matrix = camera->Get_Transform();
- float zmod = -1;
- float x = zmod * camera_matrix[0][2] ;
- float y = zmod * camera_matrix[1][2] ;
- float z = zmod * camera_matrix[2][2] ;
- m_cameraLookAtVector.Set(x,y,z);
- for (curTree=0; curTree<m_numTrees; curTree++) {
- Bool doKey = false; // We calculate the key when a tree becomes visible.
- Bool visible = !camera->Cull_Sphere(m_trees[curTree].bounds);
- if (visible!=m_trees[curTree].visible) {
- m_trees[curTree].visible=visible;
- m_anythingChanged = true;
- if (visible) {
- doKey = true;
- }
- }
- // Also calculate sort key if a tree is visible, and the view changed setting m_updateAllKeys to true.
- if (doKey || (visible&&m_updateAllKeys)) {
- // The sort key is essentially the distance of location in the direction of the
- // camera look at.
- m_trees[curTree].sortKey = Vector3::Dot_Product(m_trees[curTree].location, m_cameraLookAtVector);
- }
- }
- m_updateAllKeys = false;
- }
- //=============================================================================
- // W3DTreeBuffer::cullMirror
- //=============================================================================
- /** Culls the trees, marking the visible flag for the mirror view. Unlike cull(),
- doesn't update anything except the visible flag. */
- //=============================================================================
- void W3DTreeBuffer::cullMirror(CameraClass * camera)
- {
- Int curTree;
- m_anythingChanged = false;
- for (curTree=0; curTree<m_numTrees; curTree++) {
- if (!m_trees[curTree].mirrorVisible) {
- if (m_trees[curTree].visible) {
- m_anythingChanged = true;
- }
- m_trees[curTree].visible = false;
- continue;
- }
- Bool visible = !camera->Cull_Sphere(m_trees[curTree].bounds);
- m_trees[curTree].visible=visible;
- }
- }
- //=============================================================================
- // W3DTreeBuffer::sort
- //=============================================================================
- /** Sorts the trees. Does num_iterations of a bubble sort. This is good because
- it ends immediately if the trees are already sorted (which is most of the time)
- and will perform a fixed amount of work each frame until it becomes sorted. */
- //=============================================================================
- void W3DTreeBuffer::sort(Int numIterations)
- {
- // sort in descending order.
- Int iter;
- Bool swap = false;
- for (iter = 0; iter<numIterations; iter++) {
- Int cur = 0;
- // Note - only sorts the visible trees.
- while (cur<m_numTrees-iter && !m_trees[cur].visible) {
- cur++;
- }
- Int i;
- for (i=cur+1; i<m_numTrees-iter; i++) {
- if (m_trees[i].visible) {
- if (m_trees[cur].sortKey > m_trees[i].sortKey) {
- TTree tmp = m_trees[cur];
- m_trees[cur] = m_trees[i];
- m_trees[i] = tmp;
- swap = true;
- }
- cur = i;
- }
- }
- if (!swap) {
- return;
- }
- m_anythingChanged = true;
- }
- }
- //=============================================================================
- // W3DTreeBuffer::doLighting
- //=============================================================================
- /** Calculates the diffuse lighting as affected by dynamic lighting. */
- //=============================================================================
- Int W3DTreeBuffer::doLighting(Vector3 *loc, Real r, Real g, Real b, SphereClass &bounds, RefRenderObjListIterator *pDynamicLightsIterator)
- {
- if (pDynamicLightsIterator == NULL) {
- return(REAL_TO_INT(b) | (REAL_TO_INT(g) << 8) | (REAL_TO_INT(r) << 16) | (255 << 24));
- }
- Real shadeR, shadeG, shadeB;
- shadeR = r;
- shadeG = g;
- shadeB = b;
- Bool didLight = false;
- for (pDynamicLightsIterator->First(); !pDynamicLightsIterator->Is_Done(); pDynamicLightsIterator->Next())
- {
- W3DDynamicLight *pLight = (W3DDynamicLight*)pDynamicLightsIterator->Peek_Obj();
- if (!pLight->isEnabled()) {
- continue; // he is turned off.
- }
- if (CollisionMath::Overlap_Test(bounds, pLight->Get_Bounding_Sphere()) == CollisionMath::OUTSIDE) {
- continue; // this tree is outside of the light's influence.
- }
- Vector3 lightDirection = *loc;
- Real factor;
- switch(pLight->Get_Type()) {
- case LightClass::POINT:
- case LightClass::SPOT: {
- Vector3 lightLoc = pLight->Get_Position();
- lightDirection -= lightLoc;
- double range, midRange;
- pLight->Get_Far_Attenuation_Range(midRange, range);
- Real dist = lightDirection.Length();
- if (dist >= range) continue;
- if (midRange < 0.1) continue;
- factor = 1.0f - (dist - midRange) / (range - midRange);
- factor = WWMath::Clamp(factor,0.0f,1.0f);
- }
- break;
- case LightClass::DIRECTIONAL:
- pLight->Get_Spot_Direction(lightDirection);
- factor = 1.0;
- break;
- };
- Real shade = 0.5f * factor; // Assume adjustment for diffuse.
- Vector3 vDiffuse;
- pLight->Get_Diffuse(&vDiffuse);
- Vector3 ambient;
- pLight->Get_Ambient(&ambient);
- if (shade > 1.0) shade = 1.0;
- if(shade < 0.0f) shade = 0.0f;
- shadeR += shade*vDiffuse.X;
- shadeG += shade*vDiffuse.Y;
- shadeB += shade*vDiffuse.Z;
- shadeR += factor*ambient.X;
- shadeG += factor*ambient.Y;
- shadeB += factor*ambient.Z;
- didLight = true;
- }
- if (!didLight) {
- return(REAL_TO_INT(b) | (REAL_TO_INT(g) << 8) | (REAL_TO_INT(r) << 16) | (255 << 24));
- }
- if (shadeR > 1.0) shadeR = 1.0;
- if(shadeR < 0.0f) shadeR = 0.0f;
- if (shadeG > 1.0) shadeG = 1.0;
- if(shadeG < 0.0f) shadeG = 0.0f;
- if (shadeB > 1.0) shadeB = 1.0;
- if(shadeB < 0.0f) shadeB = 0.0f;
- shadeR*=255.0f;
- shadeG*=255.0f;
- shadeB*=255.0f;
- return(REAL_TO_INT(shadeB) | (REAL_TO_INT(shadeG) << 8) | (REAL_TO_INT(shadeR) << 16) | (255 << 24));
- }
- //=============================================================================
- // W3DTreeBuffer::loadTreesInVertexAndIndexBuffers
- //=============================================================================
- /** Loads the trees into the vertex buffer for drawing. */
- //=============================================================================
- void W3DTreeBuffer::loadTreesInVertexAndIndexBuffers(RefRenderObjListIterator *pDynamicLightsIterator)
- {
- if (!m_indexTree || !m_vertexTree || !m_initialized) {
- return;
- }
- if (!m_anythingChanged) {
- //return;
- }
- m_curNumTreeVertices = 0;
- m_curNumTreeIndices = 0;
- VertexFormatXYZDUV1 *vb;
- UnsignedShort *ib;
- // Lock the buffers.
- DX8IndexBufferClass::WriteLockClass lockIdxBuffer(m_indexTree);
- DX8VertexBufferClass::WriteLockClass lockVtxBuffer(m_vertexTree);
- vb=(VertexFormatXYZDUV1*)lockVtxBuffer.Get_Vertex_Array();
- ib = lockIdxBuffer.Get_Index_Array();
- // Add to the index buffer & vertex buffer.
- Vector2 lookAtVector(m_cameraLookAtVector.X, m_cameraLookAtVector.Y);
- lookAtVector.Normalize();
- // We draw from back to front, so we put the indexes in the buffer
- // from back to front.
- UnsignedShort *curIb = ib+MAX_TREE_INDEX;
- VertexFormatXYZDUV1 *curVb = vb;
- Int curTree;
- // Calculate a static lighting value to use for all the trees.
- Real shadeR, shadeG, shadeB;
- shadeR = TheGlobalData->m_terrainAmbient[0].red;
- shadeG = TheGlobalData->m_terrainAmbient[0].green;
- shadeB = TheGlobalData->m_terrainAmbient[0].blue;
- shadeR += TheGlobalData->m_terrainDiffuse[0].red;
- shadeG += TheGlobalData->m_terrainDiffuse[0].green;
- shadeB += TheGlobalData->m_terrainDiffuse[0].blue;
- if (shadeR>1.0f) shadeR=1.0f;
- if (shadeG>1.0f) shadeG=1.0f;
- if (shadeB>1.0f) shadeB=1.0f;
- shadeR*=255.0f;
- shadeG*=255.0f;
- shadeB*=255.0f;
- for (curTree=0; curTree<m_numTrees; curTree++) {
- if (!m_trees[curTree].visible) continue;
- Real scale = m_trees[curTree].scale;
- Vector3 loc = m_trees[curTree].location;
- Int type = m_trees[curTree].treeType;
- Real theSin = m_trees[curTree].sin;
- Real theCos = m_trees[curTree].cos;
- if (type<0 || m_typeMesh[type] == 0) {
- type = 0;
- }
- Bool doVertexLighting = false;
- #if 0 // no dynamic lighting.
- for (pDynamicLightsIterator->First(); !pDynamicLightsIterator->Is_Done(); pDynamicLightsIterator->Next())
- {
- W3DDynamicLight *pLight = (W3DDynamicLight*)pDynamicLightsIterator->Peek_Obj();
- if (!pLight->isEnabled()) {
- continue; // he is turned off.
- }
- if (CollisionMath::Overlap_Test(m_trees[curTree].bounds, pLight->Get_Bounding_Sphere()) == CollisionMath::OUTSIDE) {
- continue; // this tree is outside of the light's influence.
- }
- doVertexLighting = true;
- }
- #endif
- Int diffuse = 0;
- if (!doVertexLighting) {
- diffuse = doLighting(&loc, shadeR, shadeG, shadeB, m_trees[curTree].bounds, NULL);
- }
- Real typeOffset = type*0.5;
- Int startVertex = m_curNumTreeVertices;
- Int i, j;
- Int numVertex = m_typeMesh[type]->Peek_Model()->Get_Vertex_Count();
- Vector3 *pVert = m_typeMesh[type]->Peek_Model()->Get_Vertex_Array();
- // If we happen to have too many trees, stop.
- if (m_curNumTreeVertices+numVertex+2>= MAX_TREE_VERTEX) {
- break;
- }
- Int numIndex = m_typeMesh[type]->Get_Model()->Get_Polygon_Count();
- const Vector3i *pPoly = m_typeMesh[type]->Get_Model()->Get_Polygon_Array();
- if (m_curNumTreeIndices+3*numIndex+6 >= MAX_TREE_INDEX) {
- break;
- }
- const Vector2*uvs=m_typeMesh[type]->Get_Model()->Get_UV_Array_By_Index(0);
- // If we are doing reduced resolution terrain, do reduced
- // poly trees.
- Bool doPanel = (TheGlobalData->m_useHalfHeightMap || TheGlobalData->m_stretchTerrain);
- if (doPanel) {
- if (m_trees[curTree].rotates) {
- theSin = -lookAtVector.X;
- theCos = lookAtVector.Y;
- }
- // panel start is index offset, there are 3 index per triangle.
- if (m_trees[curTree].panelStart/3 + 2 > numIndex) {
- continue; // not enought polygons for the offset. jba.
- }
- for (j=0; j<6; j++) {
- i = ((Int *)pPoly)[j+m_trees[curTree].panelStart];
- if (m_curNumTreeVertices >= MAX_TREE_VERTEX)
- break;
- // Update the uv values. The W3D models each have their own texture, and
- // we use one texture with all images in one, so we have to change the uvs to
- // match.
- Real U, V;
- if (type==SHRUB) {
- // shrub texture is tucked in the corner
- U = ((512-64)+uvs[i].U*64.0f)/512.0f;
- V = ((256-64)+uvs[i].V*64.0f)/256.0f;
- } else if (type==FENCE) {
- U = uvs[i].U*0.5f;
- V = 1.0f + uvs[i].V;
- } else {
- U = typeOffset+uvs[i].U*0.5f;
- V = uvs[i].V;
- }
- curVb->u1 = U;
- curVb->v1 = V/2.0;
- Vector3 vLoc;
- vLoc.X = pVert[i].X*scale*theCos - pVert[i].Z*scale*theSin;
- vLoc.Y = pVert[i].Z*scale*theCos + pVert[i].X*scale*theSin;
- vLoc.X += loc.X;
- vLoc.Y += loc.Y;
- vLoc.Z = loc.Z + pVert[i].Y*scale; // In W3D z is up, in 3dMax y is up.
- curVb->x = vLoc.X;
- curVb->y = vLoc.Y;
- curVb->z = vLoc.Z;
- if (doVertexLighting) {
- curVb->diffuse = doLighting(&vLoc, shadeR, shadeG, shadeB, m_trees[curTree].bounds, pDynamicLightsIterator);
- } else {
- curVb->diffuse = diffuse;
- }
- curVb++;
- m_curNumTreeVertices++;
- }
- for (i=0; i<6; i++) {
- if (m_curNumTreeIndices+4 > MAX_TREE_INDEX)
- break;
- curIb--;
- *curIb = startVertex + i;
- m_curNumTreeIndices++;
- }
- } else {
- for (i=0; i<numVertex; i++) {
- if (m_curNumTreeVertices >= MAX_TREE_VERTEX)
- break;
- // Update the uv values. The W3D models each have their own texture, and
- // we use one texture with all images in one, so we have to change the uvs to
- // match.
- Real U, V;
- if (type==SHRUB) {
- // shrub texture is tucked in the corner
- U = ((512-64)+uvs[i].U*64.0f)/512.0f;
- V = ((256-64)+uvs[i].V*64.0f)/256.0f;
- } else if (type==FENCE) {
- U = uvs[i].U*0.5f;
- V = 1.0f + uvs[i].V;
- } else {
- U = typeOffset+uvs[i].U*0.5f;
- V = uvs[i].V;
- }
- curVb->u1 = U;
- curVb->v1 = V/2.0;
- Vector3 vLoc;
- vLoc.X = pVert[i].X*scale*theCos - pVert[i].Z*scale*theSin;
- vLoc.Y = pVert[i].Z*scale*theCos + pVert[i].X*scale*theSin;
- vLoc.X += loc.X;
- vLoc.Y += loc.Y;
- vLoc.Z = loc.Z + pVert[i].Y*scale; // In W3D z is up, in 3dMax y is up.
- curVb->x = vLoc.X;
- curVb->y = vLoc.Y;
- curVb->z = vLoc.Z;
- if (doVertexLighting) {
- curVb->diffuse = doLighting(&vLoc, shadeR, shadeG, shadeB, m_trees[curTree].bounds, pDynamicLightsIterator);
- } else {
- curVb->diffuse = diffuse;
- }
- curVb++;
- m_curNumTreeVertices++;
- }
- for (i=0; i<numIndex; i++) {
- if (m_curNumTreeIndices+4 > MAX_TREE_INDEX)
- break;
- curIb-=3;
- *curIb++ = startVertex + pPoly[i].I;
- *curIb++ = startVertex + pPoly[i].J;
- *curIb++ = startVertex + pPoly[i].K;
- curIb-=3;
- m_curNumTreeIndices+=3;
- }
- }
- }
- m_curTreeIndexOffset = curIb - ib;
- }
- //-----------------------------------------------------------------------------
- // Public Functions
- //-----------------------------------------------------------------------------
- //=============================================================================
- // W3DTreeBuffer::~W3DTreeBuffer
- //=============================================================================
- /** Destructor. Releases w3d assets. */
- //=============================================================================
- W3DTreeBuffer::~W3DTreeBuffer(void)
- {
- freeTreeBuffers();
- REF_PTR_RELEASE(m_treeTexture);
- Int i;
- for (i=0; i<MAX_TYPES; i++) {
- REF_PTR_RELEASE(m_typeMesh[i]);
- }
- }
- //=============================================================================
- // W3DTreeBuffer::W3DTreeBuffer
- //=============================================================================
- /** Constructor. Sets m_initialized to true if it finds the w3d models it needs
- for the trees. */
- //=============================================================================
- W3DTreeBuffer::W3DTreeBuffer(void)
- {
- m_initialized = false;
- ///@toto - reactivate this optimization if useful. jba.
- return;
- m_vertexTree = NULL;
- m_indexTree = NULL;
- m_treeTexture = NULL;
- m_curNumTreeVertices=0;
- m_curNumTreeIndices=0;
- clearAllTrees();
- allocateTreeBuffers();
- Int i;
- for (i=0; i<MAX_TYPES; i++) {
- m_typeMesh[i] = 0;
- }
- if (WW3DAssetManager::Get_Instance()==NULL)
- return; // WorldBuilderTool doesn't initialize the asset manager. jba.
- m_treeTexture = NEW_REF(TextureClass, ("trees.tga"));
- m_treeTexture->Set_U_Addr_Mode(TextureClass::TEXTURE_ADDRESS_CLAMP);
- m_treeTexture->Set_V_Addr_Mode(TextureClass::TEXTURE_ADDRESS_CLAMP);
- for (i=0; i<MAX_TYPES; i++) {
- switch(i) {
- case 0:
- m_typeMesh[i] = (MeshClass*)WW3DAssetManager::Get_Instance()->Create_Render_Obj("ALPINETREE.TREE 1" );
- break;
- case 1:
- m_typeMesh[i] = (MeshClass*)WW3DAssetManager::Get_Instance()->Create_Render_Obj("DECIDUOUS.TREE 1" );
- break;
- case 2:
- m_typeMesh[i] = (MeshClass*)WW3DAssetManager::Get_Instance()->Create_Render_Obj("SHRUB.TREE 1" );
- break;
- case 3:
- m_typeMesh[i] = (MeshClass*)WW3DAssetManager::Get_Instance()->Create_Render_Obj("FENCE.PLANE09" );
- break;
- }
- if (m_typeMesh[i] == NULL) continue;
- Int numVertex = m_typeMesh[i]->Peek_Model()->Get_Vertex_Count();
- Vector3 *pVert = m_typeMesh[i]->Peek_Model()->Get_Vertex_Array();
- const Matrix3D xfm = m_typeMesh[i]->Get_Transform();
- SphereClass bounds(pVert, numVertex);
- // Model is in y up format, so swap y and z.
- Real tmp;
- tmp = bounds.Center.Y;
- bounds.Center.Y = bounds.Center.Z;
- bounds.Center.Z = tmp;
- m_typeBounds[i] = bounds;
- }
- if (m_typeMesh[0] == NULL) {
- //DEBUG_LOG("!!!!!!!!!!!!*************** W3DTreeBuffer failed to initialize.\n");
- return; // didn't initialize.
- }
- m_initialized = true;
- }
- //=============================================================================
- // W3DTreeBuffer::freeTreeBuffers
- //=============================================================================
- /** Frees the index and vertex buffers. */
- //=============================================================================
- void W3DTreeBuffer::freeTreeBuffers(void)
- {
- REF_PTR_RELEASE(m_vertexTree);
- REF_PTR_RELEASE(m_indexTree);
- }
- //=============================================================================
- // W3DTreeBuffer::allocateTreeBuffers
- //=============================================================================
- /** Allocates the index and vertex buffers. */
- //=============================================================================
- void W3DTreeBuffer::allocateTreeBuffers(void)
- {
- m_vertexTree=NEW_REF(DX8VertexBufferClass,(DX8_FVF_XYZDUV1,MAX_TREE_VERTEX+4,DX8VertexBufferClass::USAGE_DYNAMIC));
- m_indexTree=NEW_REF(DX8IndexBufferClass,(2*MAX_TREE_INDEX+4, DX8IndexBufferClass::USAGE_DYNAMIC));
- m_curNumTreeVertices=0;
- m_curNumTreeIndices=0;
- }
- //=============================================================================
- // W3DTreeBuffer::clearAllTrees
- //=============================================================================
- /** Removes all trees. */
- //=============================================================================
- void W3DTreeBuffer::clearAllTrees(void)
- {
- m_numTrees=0;
- }
- //=============================================================================
- // W3DTreeBuffer::addTree
- //=============================================================================
- /** Adds a tree. Name is the W3D model name, supported models are
- ALPINE, DECIDUOUS and SHRUB. */
- //=============================================================================
- void W3DTreeBuffer::addTree(Coord3D loc, Real scale, Real angle, AsciiString name, Bool mirrorVisible)
- {
- if (m_numTrees >= MAX_TREES) {
- return;
- }
- if (!m_initialized) {
- return;
- }
- TTreeType treeType = ALPINE_TREE;
- if (!name.compare("DECIDUOUS")) {
- treeType = DECIDUOUS_TREE;
- } else if (!name.compare("SHRUB")) {
- treeType = SHRUB;
- } else if (!name.compare("FENCE")) {
- treeType = FENCE;
- }
- m_trees[m_numTrees].panelStart = 0;
- Real randomScale = GameClientRandomValueReal( 0.7f, 1.3f );
- if (treeType == FENCE) {
- // Fences don't randomly scale & orient
- m_trees[m_numTrees].sin = WWMath::Sin(angle);
- m_trees[m_numTrees].scale = scale;
- m_trees[m_numTrees].cos = WWMath::Cos(angle);
- m_trees[m_numTrees].rotates = false;
- m_trees[m_numTrees].panelStart = 48;
- } else {
- // Randomizes the scale and orientation of trees.
- m_trees[m_numTrees].sin = GameClientRandomValueReal( -1.0f, 1.0f );
- m_trees[m_numTrees].scale = scale*randomScale;
- m_trees[m_numTrees].cos = WWMath::Sqrt(1.0 - m_trees[m_numTrees].sin*m_trees[m_numTrees].sin);
- m_trees[m_numTrees].rotates = true;
- }
- m_trees[m_numTrees].location = Vector3(loc.x, loc.y, loc.z);
- m_trees[m_numTrees].treeType = treeType;
- // Translate the bounding sphere of the model.
- m_trees[m_numTrees].bounds = m_typeBounds[treeType];
- m_trees[m_numTrees].bounds.Center *= scale;
- m_trees[m_numTrees].bounds.Radius *= scale;
- m_trees[m_numTrees].bounds.Center += m_trees[m_numTrees].location;
- // Initially set it invisible. cull will update it's visiblity flag.
- m_trees[m_numTrees].visible = false;
- m_trees[m_numTrees].mirrorVisible = mirrorVisible;
- m_numTrees++;
- }
- //=============================================================================
- // W3DTreeBuffer::drawTrees
- //=============================================================================
- /** Draws the trees. Uses camera to cull. */
- //=============================================================================
- void W3DTreeBuffer::drawTrees(CameraClass * camera, RefRenderObjListIterator *pDynamicLightsIterator)
- {
- if (!m_isTerrainPass) {
- return;
- }
- m_isTerrainPass = false;
- if (ShaderClass::Is_Backface_Culling_Inverted()) {
- // Mirror inverts backface culling.
- cullMirror(camera);
- } else {
- // Normal draw.
- cull(camera);
- // Only sort once per frame.
- sort(SORT_ITERATIONS_PER_FRAME);
- }
- loadTreesInVertexAndIndexBuffers(pDynamicLightsIterator);
- if (m_curNumTreeIndices == 0) {
- return;
- }
- // Setup the vertex buffer, shader & texture.
- DX8Wrapper::Set_Index_Buffer(m_indexTree,0);
- DX8Wrapper::Set_Vertex_Buffer(m_vertexTree);
- DX8Wrapper::Set_Shader(detailAlphaShader);
- DX8Wrapper::Set_Texture(0,m_treeTexture);
- // Draw all the trees.
- DX8Wrapper::Draw_Triangles( m_curTreeIndexOffset, m_curNumTreeIndices/3, 0, m_curNumTreeVertices);
- }
|