Linux multi-monitor fullscreen support
[ryzomcore.git] / nel / src / 3d / transform_shape.cpp
blob014e997abae958ff4f92e3ddf796225ecf8804ab
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/misc/hierarchical_timer.h"
20 #include "nel/misc/debug.h"
21 #include "nel/3d/driver.h"
22 #include "nel/3d/transform_shape.h"
23 #include "nel/3d/skeleton_model.h"
24 #include "nel/3d/mesh_base_instance.h"
25 #include "nel/3d/clip_trav.h"
26 #include "nel/3d/render_trav.h"
27 #include "nel/3d/load_balancing_trav.h"
28 #include "nel/3d/quad_grid_clip_cluster.h"
29 #include "nel/3d/scene.h"
32 using namespace NLMISC;
34 #ifdef DEBUG_NEW
35 #define new DEBUG_NEW
36 #endif
38 namespace NL3D
42 // ***************************************************************************
43 void CTransformShape::registerBasic()
45 CScene::registerModel(TransformShapeId, TransformId, CTransformShape::creator);
49 // ***************************************************************************
50 CTransformShape::CTransformShape()
52 _NumTrianglesAfterLoadBalancing= 100;
53 _CurrentLightContribution= NULL;
54 _CurrentUseLocalAttenuation= false;
55 _DistMax = -1.f;
56 // By default all transformShape are LoadBalancable
57 CTransform::setIsLoadbalancable(true);
59 // The model is renderable
60 CTransform::setIsRenderable(true);
62 // I am a CTransformShape
63 CTransform::setIsTransformShape(true);
67 // ***************************************************************************
68 float CTransformShape::getNumTriangles (float distance)
70 // Call shape method
71 return Shape->getNumTriangles (distance);
75 // ***************************************************************************
76 void CTransformShape::getAABBox(NLMISC::CAABBox &bbox) const
78 if(Shape)
80 Shape->getAABBox(bbox);
82 else
84 bbox.setCenter(CVector::Null);
85 bbox.setHalfSize(CVector::Null);
90 // ***************************************************************************
91 void CTransformShape::setupCurrentLightContribution(CLightContribution *lightContrib, bool useLocalAtt)
93 _CurrentLightContribution= lightContrib;
94 _CurrentUseLocalAttenuation= useLocalAtt;
97 // ***************************************************************************
98 void CTransformShape::changeLightSetup(CRenderTrav *rdrTrav)
100 // setup the instance lighting.
101 rdrTrav->changeLightSetup(_CurrentLightContribution, _CurrentUseLocalAttenuation);
105 // ***************************************************************************
106 uint CTransformShape::getNumMaterial () const
108 return 0;
112 // ***************************************************************************
113 const CMaterial *CTransformShape::getMaterial (uint /* materialId */) const
115 return NULL;
119 // ***************************************************************************
120 CMaterial *CTransformShape::getMaterial (uint /* materialId */)
122 return NULL;
125 // ***************************************************************************
126 void CTransformShape::unlinkFromQuadCluster()
128 // if linked to a quadGridClipCluster, unlink it
129 _QuadClusterListNode.unlink();
133 // ***************************************************************************
134 bool CTransformShape::clip()
136 H_AUTO( NL3D_TrShape_Clip );
138 CClipTrav &clipTrav= getOwnerScene()->getClipTrav();
140 if(Shape)
142 // first test DistMax (faster).
143 float maxDist = getDistMax();
144 // if DistMax test enabled
145 if(maxDist!=-1)
147 // Calc the distance
148 float sqrDist = (clipTrav.CamPos - getWorldMatrix().getPos()).sqrnorm ();
149 maxDist*=maxDist;
151 // if dist > maxDist, skip
152 if (sqrDist > maxDist)
154 // Ok, not shown
155 return false;
159 // Else finer clip with pyramid, only if needed
160 if(clipTrav.ForceNoFrustumClip)
161 return true;
162 else
163 return Shape->clip(clipTrav.WorldPyramid, getWorldMatrix());
165 else
166 return false;
170 // ***************************************************************************
171 void CTransformShape::traverseRender()
173 H_AUTO( NL3D_TrShape_Render );
176 // Compute the current lighting setup for this instance
177 //===================
180 // if the transform is lightable (ie not a fully lightmaped model), setup lighting
181 if(isLightable())
183 // useLocalAttenuation for this shape ??
184 if(Shape)
185 _CurrentUseLocalAttenuation= Shape->useLightingLocalAttenuation ();
186 else
187 _CurrentUseLocalAttenuation= false;
189 // the std case is to take my model lightContribution
190 if(_AncestorSkeletonModel==NULL)
191 _CurrentLightContribution= &getLightContribution();
192 // but if skinned/sticked (directly or not) to a skeleton, take its.
193 else
194 _CurrentLightContribution= &((CTransformShape*)_AncestorSkeletonModel)->getLightContribution();
196 // else must disable the lightSetup
197 else
199 // setting NULL will disable all lights
200 _CurrentLightContribution= NULL;
201 _CurrentUseLocalAttenuation= false;
205 // render the shape.
206 //=================
207 if(Shape)
209 CRenderTrav &rdrTrav= getOwnerScene()->getRenderTrav();
210 bool currentPassOpaque= rdrTrav.isCurrentPassOpaque();
212 // shape must be rendered in a CMeshBlockManager ??
213 float polygonCount = 0.f;
214 IMeshGeom *meshGeom= NULL;
215 // true only if in pass opaque
216 if( currentPassOpaque )
217 meshGeom= Shape->supportMeshBlockRendering(this, polygonCount);
219 // if ok, add the meshgeom to the block manager.
220 if(meshGeom)
222 CMeshBaseInstance *inst= safe_cast<CMeshBaseInstance*>(this);
223 rdrTrav.MeshBlockManager.addInstance(meshGeom, inst, polygonCount);
225 // else render it.
226 else
228 // setup the lighting
229 changeLightSetup( &rdrTrav );
231 // render the shape.
232 IDriver *drv= rdrTrav.getDriver();
233 Shape->render( drv, this, currentPassOpaque );
239 // ***************************************************************************
240 void CTransformShape::profileRender()
242 // profile the shape.
243 if(Shape)
245 CRenderTrav &rdrTrav= getOwnerScene()->getRenderTrav();
246 bool currentPassOpaque= rdrTrav.isCurrentPassOpaque();
248 Shape->profileSceneRender( &rdrTrav, this, currentPassOpaque );
253 // ***************************************************************************
254 void CTransformShape::traverseLoadBalancing()
256 CLoadBalancingTrav &loadTrav= getOwnerScene()->getLoadBalancingTrav();
257 if(loadTrav.getLoadPass()==0)
258 traverseLoadBalancingPass0();
259 else
260 traverseLoadBalancingPass1();
265 // ***************************************************************************
266 void CTransformShape::traverseLoadBalancingPass0()
268 CLoadBalancingTrav &loadTrav= getOwnerScene()->getLoadBalancingTrav();
269 CSkeletonModel *skeleton= getSkeletonModel();
271 // World Model position
272 const CVector *modelPos;
274 // If this isntance is binded or skinned to a skeleton, take the world matrix of this one as
275 // center for LoadBalancing Resolution.
276 if(skeleton)
278 // Take the root bone of the skeleton as reference (bone 0)
279 // And so get our position.
280 modelPos= &skeleton->Bones[0].getWorldMatrix().getPos();
282 else
284 // get our position from
285 modelPos= &getWorldMatrix().getPos();
289 // Then compute distance from camera.
290 float modelDist= ( loadTrav.CamPos - *modelPos).norm();
293 // Get the number of triangles this model use now.
294 _FaceCount= getNumTriangles(modelDist);
295 _LoadBalancingGroup->addNbFacesPass0(_FaceCount);
299 // ***************************************************************************
300 void CTransformShape::traverseLoadBalancingPass1()
302 // Show more polygons for upscaled shapes to preserve visual quality
303 float factor = 1.0f;
304 if (getTransformMode() == RotEuler || getTransformMode() == RotQuat)
306 factor = std::max(1.0f, std::max(getScale().x, std::max(getScale().y, getScale().z)));
307 if (factor > 1)
309 _FaceCount = factor * std::max(_FaceCount, factor * 200.0f);
313 // Set the result into the instance.
314 _NumTrianglesAfterLoadBalancing= _LoadBalancingGroup->computeModelNbFace(_FaceCount);
318 // ***************************************************************************
319 void CTransformShape::getLightHotSpotInWorld(CVector &modelPos, float &modelRadius) const
322 // get the untransformed bbox from the model.
323 CAABBox bbox;
324 getAABBox(bbox);
325 // get transformed center pos of bbox
326 modelPos= getWorldMatrix() * bbox.getCenter();
327 // If the model is a big lightable, must take radius from aabbox, else suppose 0 radius.
328 if(isBigLightable())
330 // get size of the bbox (bounding sphere)
331 modelRadius= bbox.getRadius();
333 else
335 // Assume 0 radius => faster computeLinearAttenuation()
336 modelRadius= 0;
340 // This method works well for Big Trees.
341 // TODO: generalize, saving a LightHotSpot per shape.
343 // get pos of object. Ie the hotSpot is the pivot.
344 modelPos= getWorldMatrix().getPos();
345 // If the model is a big lightable, must take radius from aabbox, else suppose 0 radius.
346 if(isBigLightable())
348 // get the untransformed bbox from the model.
349 CAABBox bbox;
350 getAABBox(bbox);
351 // get size of the bbox (bounding sphere)
352 modelRadius= bbox.getRadius();
354 else
356 // Assume 0 radius => faster computeLinearAttenuation()
357 modelRadius= 0;
363 } // NL3D