Merge branch 'main/rendor-staging' into fixes
[ryzomcore.git] / nel / src / 3d / mesh_multi_lod_instance.cpp
blobcf7805788e391208964410abe7b033a0c099420f
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "std3d.h"
19 #include "nel/3d/mesh_multi_lod_instance.h"
20 #include "nel/3d/mesh_multi_lod.h"
21 #include "nel/3d/coarse_mesh_manager.h"
22 #include "nel/3d/scene.h"
24 #include "nel/misc/debug.h"
26 using namespace NLMISC;
28 #ifdef DEBUG_NEW
29 #define new DEBUG_NEW
30 #endif
32 namespace NL3D
35 // ***************************************************************************
37 CMeshMultiLodInstance::CMeshMultiLodInstance ()
39 // No flags
40 Flags=0;
41 _CoarseMeshDistance = -1.f;
42 _LastCoarseMesh= NULL;
43 _LastCoarseMeshNumVertices= 0;
46 // ***************************************************************************
48 CMeshMultiLodInstance::~CMeshMultiLodInstance ()
53 // ***************************************************************************
55 void CMeshMultiLodInstance::registerBasic()
57 CScene::registerModel (MeshMultiLodInstanceId, MeshBaseInstanceId, CMeshMultiLodInstance::creator);
61 // ***************************************************************************
62 CRGBA CMeshMultiLodInstance::getCoarseMeshLighting()
64 CScene *scene= getOwnerScene();
65 nlassert(scene);
67 // compute his sun contribution result, and update
68 CRGBA sunContrib= scene->getSunDiffuse();
69 // simulate/average diffuse lighting over the mesh by dividing diffuse by 2.
70 sunContrib.modulateFromuiRGBOnly(sunContrib, getLightContribution().SunContribution/2 );
71 // Add Ambient
72 sunContrib.addRGBOnly(sunContrib, scene->getSunAmbient());
73 sunContrib.A= 255;
75 return sunContrib;
79 // ***************************************************************************
81 void CMeshMultiLodInstance::traverseLoadBalancing()
83 // Call previous
84 CMeshBaseInstance::traverseLoadBalancing ();
86 // If this is the second pass of LoadBalancing, choose the Lods, according to getNumTrianglesAfterLoadBalancing()
87 CLoadBalancingTrav &loadTrav= getOwnerScene()->getLoadBalancingTrav();
88 if(loadTrav.getLoadPass()==1)
90 // Get a pointer on the shape
91 CMeshMultiLod *shape=safe_cast<CMeshMultiLod*> ((IShape*)Shape);
93 // Reset render pass
94 if (!getBypassLODOpacityFlag())
96 setTransparency(false);
97 setOpacity(false);
100 // Get the wanted number of polygons
101 float polygonCount= getNumTrianglesAfterLoadBalancing ();
103 // Look for the good slot
104 uint meshCount=(uint)shape->_MeshVector.size();
105 Lod0=0;
106 if (meshCount>1)
108 // Look for good i
109 while ( polygonCount < shape->_MeshVector[Lod0].EndPolygonCount )
111 Lod0++;
112 if (Lod0==meshCount-1)
113 break;
117 // The slot
118 CMeshMultiLod::CMeshSlot &slot=shape->_MeshVector[Lod0];
120 // Get the distance with polygon count
121 float distance=(polygonCount-slot.B)/slot.A;
123 // Get the final polygon count
124 if (slot.MeshGeom)
125 PolygonCountLod0=slot.MeshGeom->getNumTriangles (distance);
127 // Second slot in use ?
128 Lod1=0xffffffff;
130 // The next slot
131 CMeshMultiLod::CMeshSlot *nextSlot=NULL;
133 // Next slot exist ?
134 if (Lod0!=meshCount-1)
136 nextSlot=&(shape->_MeshVector[Lod0+1]);
139 // Max dist before blend
140 float startBlend;
141 if (nextSlot)
142 startBlend=slot.DistMax-nextSlot->BlendLength;
143 else
144 startBlend=slot.DistMax-slot.BlendLength;
146 // In blend zone ?
147 if ( startBlend < distance )
149 // Alpha factor for main Lod
150 BlendFactor = (slot.DistMax-distance)/(slot.DistMax-startBlend);
151 if (BlendFactor<0)
152 BlendFactor=0;
153 nlassert (BlendFactor<=1);
155 // Render this mesh
156 if (slot.MeshGeom)
158 if (slot.Flags&CMeshMultiLod::CMeshSlot::BlendOut)
160 // Render the geom mesh with alpha blending with goodPolyCount
161 if (!getBypassLODOpacityFlag()) setTransparency(true);
162 Flags|=CMeshMultiLodInstance::Lod0Blend;
164 else
166 // Render the geom mesh without alpha blending with goodPolyCount
167 if (!getBypassLODOpacityFlag()) setTransparency (slot.isTransparent());
168 setOpacity (slot.isOpaque());
169 Flags&=~CMeshMultiLodInstance::Lod0Blend;
172 else
173 Lod0=0xffffffff;
175 // Next mesh, BlendIn actived ?
176 if (nextSlot && shape->_MeshVector[Lod0+1].MeshGeom && (nextSlot->Flags&CMeshMultiLod::CMeshSlot::BlendIn))
178 // Render the geom mesh with alpha blending with nextSlot->BeginPolygonCount
179 PolygonCountLod1=nextSlot->MeshGeom->getNumTriangles (distance);
180 Lod1=Lod0+1;
181 if (!getBypassLODOpacityFlag()) setTransparency(true);
184 else
186 if (slot.MeshGeom)
188 // Render without blend with goodPolyCount
189 if (!getBypassLODOpacityFlag())
191 setTransparency (slot.isTransparent());
192 setOpacity (slot.isOpaque());
194 Flags&=~CMeshMultiLodInstance::Lod0Blend;
196 else
197 Lod0=0xffffffff;
204 // ***************************************************************************
205 void CMeshMultiLodInstance::changeMRMDistanceSetup(float distanceFinest, float distanceMiddle, float distanceCoarsest)
207 if(Shape)
209 // Get a pointer on the shape.
210 CMeshMultiLod *pMesh =safe_cast<CMeshMultiLod*> ((IShape*)Shape);
211 // Affect the mesh directly.
212 pMesh->changeMRMDistanceSetup(distanceFinest, distanceMiddle, distanceCoarsest);
217 // ***************************************************************************
218 float CMeshMultiLodInstance::getNumTriangles (float distance)
220 CMeshMultiLod *shape = safe_cast<CMeshMultiLod*> ((IShape*)Shape);
221 return shape->getNumTrianglesWithCoarsestDist(distance, _CoarseMeshDistance);
225 // ***************************************************************************
226 void CMeshMultiLodInstance::initRenderFilterType()
228 if(Shape)
230 CMeshMultiLod *shape = safe_cast<CMeshMultiLod*> ((IShape*)Shape);
232 // Look only the First LOD to know if it has a VP or not
233 bool hasVP= false;
234 bool coarseMesh;
235 if(shape->getNumSlotMesh()>0 && shape->getSlotMesh(0, coarseMesh))
237 IMeshGeom *meshGeom= shape->getSlotMesh(0, coarseMesh);
238 // hasVP possible only if not a coarseMesh.
239 if(!coarseMesh)
240 hasVP= meshGeom->hasMeshVertexProgram();
243 if(hasVP)
244 _RenderFilterType= UScene::FilterMeshLodVP;
245 else
246 _RenderFilterType= UScene::FilterMeshLodNoVP;
251 // ***************************************************************************
252 void CMeshMultiLodInstance::setUVCoarseMesh( CMeshGeom &geom, uint vtDstSize, uint dstUvOff )
254 // *** Copy UVs to the vertices
256 // Src vertex buffer
257 const CVertexBuffer &vbSrc=geom.getVertexBuffer();
258 CVertexBufferRead vba;
259 vbSrc.lock (vba);
261 // Check the vertex format and src Vertices
262 nlassert (vbSrc.getVertexFormat() & (CVertexBuffer::PositionFlag|CVertexBuffer::TexCoord0Flag) );
263 nlassert (vbSrc.getNumVertices()==_LastCoarseMeshNumVertices);
265 // src Vertex size
266 uint vtSrcSize=vbSrc.getVertexSize ();
268 // Copy vector
269 const uint8 *vSrc = (const uint8 *)vba.getTexCoordPointer(0,0);
270 uint8 *vDest = &_CoarseMeshVB[0];
271 vDest+= dstUvOff;
273 // Transform it
274 for (uint i=0; i<_LastCoarseMeshNumVertices; i++)
276 // Transform position
277 *(CUV*)vDest = *(const CUV*)vSrc;
279 // Next point
280 vSrc+=vtSrcSize;
281 vDest+=vtDstSize;
284 // ***************************************************************************
285 void CMeshMultiLodInstance::setPosCoarseMesh( CMeshGeom &geom, const CMatrix &matrix, uint vtDstSize )
287 // *** Transform the vertices
289 // Src vertex buffer
290 const CVertexBuffer &vbSrc=geom.getVertexBuffer();
291 CVertexBufferRead vba;
292 vbSrc.lock (vba);
294 // Check the vertex format and src Vertices
295 nlassert (vbSrc.getVertexFormat() & (CVertexBuffer::PositionFlag|CVertexBuffer::TexCoord0Flag) );
296 nlassert (vbSrc.getNumVertices()==_LastCoarseMeshNumVertices);
298 // src Vertex size
299 uint vtSrcSize=vbSrc.getVertexSize ();
301 // Copy vector
302 const uint8 *vSrc = (const uint8 *)vba.getVertexCoordPointer (0);
303 uint8 *vDest = &_CoarseMeshVB[0];
305 // Transform it
306 for (uint i=0; i<_LastCoarseMeshNumVertices; i++)
308 // Transform position
309 *(CVector*)vDest = matrix.mulPoint (*(const CVector*)vSrc);
311 // Next point
312 vSrc+=vtSrcSize;
313 vDest+=vtDstSize;
316 // ***************************************************************************
317 void CMeshMultiLodInstance::setColorCoarseMesh( CRGBA color, uint vtDstSize, uint dstColorOff )
319 // *** Copy color to vertices
321 // Copy vector
322 uint8 *vDest = &_CoarseMeshVB[0];
323 vDest+= dstColorOff;
325 // Transform it
326 for (uint i=0; i<_LastCoarseMeshNumVertices; i++)
328 // Transform position
329 *(CRGBA*)vDest = color;
331 // Next point
332 vDest+=vtDstSize;
337 } // NL3D