1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
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.
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/>.
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
;
35 // ***************************************************************************
37 CMeshMultiLodInstance::CMeshMultiLodInstance ()
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();
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 );
72 sunContrib
.addRGBOnly(sunContrib
, scene
->getSunAmbient());
79 // ***************************************************************************
81 void CMeshMultiLodInstance::traverseLoadBalancing()
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
);
94 if (!getBypassLODOpacityFlag())
96 setTransparency(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();
109 while ( polygonCount
< shape
->_MeshVector
[Lod0
].EndPolygonCount
)
112 if (Lod0
==meshCount
-1)
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
125 PolygonCountLod0
=slot
.MeshGeom
->getNumTriangles (distance
);
127 // Second slot in use ?
131 CMeshMultiLod::CMeshSlot
*nextSlot
=NULL
;
134 if (Lod0
!=meshCount
-1)
136 nextSlot
=&(shape
->_MeshVector
[Lod0
+1]);
139 // Max dist before blend
142 startBlend
=slot
.DistMax
-nextSlot
->BlendLength
;
144 startBlend
=slot
.DistMax
-slot
.BlendLength
;
147 if ( startBlend
< distance
)
149 // Alpha factor for main Lod
150 BlendFactor
= (slot
.DistMax
-distance
)/(slot
.DistMax
-startBlend
);
153 nlassert (BlendFactor
<=1);
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
;
166 // Render the geom mesh without alpha blending with goodPolyCount
167 if (!getBypassLODOpacityFlag()) setTransparency (slot
.isTransparent());
168 setOpacity (slot
.isOpaque());
169 Flags
&=~CMeshMultiLodInstance::Lod0Blend
;
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
);
181 if (!getBypassLODOpacityFlag()) setTransparency(true);
188 // Render without blend with goodPolyCount
189 if (!getBypassLODOpacityFlag())
191 setTransparency (slot
.isTransparent());
192 setOpacity (slot
.isOpaque());
194 Flags
&=~CMeshMultiLodInstance::Lod0Blend
;
204 // ***************************************************************************
205 void CMeshMultiLodInstance::changeMRMDistanceSetup(float distanceFinest
, float distanceMiddle
, float distanceCoarsest
)
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()
230 CMeshMultiLod
*shape
= safe_cast
<CMeshMultiLod
*> ((IShape
*)Shape
);
232 // Look only the First LOD to know if it has a VP or not
235 if(shape
->getNumSlotMesh()>0 && shape
->getSlotMesh(0, coarseMesh
))
237 IMeshGeom
*meshGeom
= shape
->getSlotMesh(0, coarseMesh
);
238 // hasVP possible only if not a coarseMesh.
240 hasVP
= meshGeom
->hasMeshVertexProgram();
244 _RenderFilterType
= UScene::FilterMeshLodVP
;
246 _RenderFilterType
= UScene::FilterMeshLodNoVP
;
251 // ***************************************************************************
252 void CMeshMultiLodInstance::setUVCoarseMesh( CMeshGeom
&geom
, uint vtDstSize
, uint dstUvOff
)
254 // *** Copy UVs to the vertices
257 const CVertexBuffer
&vbSrc
=geom
.getVertexBuffer();
258 CVertexBufferRead vba
;
261 // Check the vertex format and src Vertices
262 nlassert (vbSrc
.getVertexFormat() & (CVertexBuffer::PositionFlag
|CVertexBuffer::TexCoord0Flag
) );
263 nlassert (vbSrc
.getNumVertices()==_LastCoarseMeshNumVertices
);
266 uint vtSrcSize
=vbSrc
.getVertexSize ();
269 const uint8
*vSrc
= (const uint8
*)vba
.getTexCoordPointer(0,0);
270 uint8
*vDest
= &_CoarseMeshVB
[0];
274 for (uint i
=0; i
<_LastCoarseMeshNumVertices
; i
++)
276 // Transform position
277 *(CUV
*)vDest
= *(const CUV
*)vSrc
;
284 // ***************************************************************************
285 void CMeshMultiLodInstance::setPosCoarseMesh( CMeshGeom
&geom
, const CMatrix
&matrix
, uint vtDstSize
)
287 // *** Transform the vertices
290 const CVertexBuffer
&vbSrc
=geom
.getVertexBuffer();
291 CVertexBufferRead vba
;
294 // Check the vertex format and src Vertices
295 nlassert (vbSrc
.getVertexFormat() & (CVertexBuffer::PositionFlag
|CVertexBuffer::TexCoord0Flag
) );
296 nlassert (vbSrc
.getNumVertices()==_LastCoarseMeshNumVertices
);
299 uint vtSrcSize
=vbSrc
.getVertexSize ();
302 const uint8
*vSrc
= (const uint8
*)vba
.getVertexCoordPointer (0);
303 uint8
*vDest
= &_CoarseMeshVB
[0];
306 for (uint i
=0; i
<_LastCoarseMeshNumVertices
; i
++)
308 // Transform position
309 *(CVector
*)vDest
= matrix
.mulPoint (*(const CVector
*)vSrc
);
316 // ***************************************************************************
317 void CMeshMultiLodInstance::setColorCoarseMesh( CRGBA color
, uint vtDstSize
, uint dstColorOff
)
319 // *** Copy color to vertices
322 uint8
*vDest
= &_CoarseMeshVB
[0];
326 for (uint i
=0; i
<_LastCoarseMeshNumVertices
; i
++)
328 // Transform position
329 *(CRGBA
*)vDest
= color
;