1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010-2015 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/>.
20 #include "nel/misc/aabbox.h"
21 #include "nel/misc/matrix.h"
23 #include "nel/3d/ps_util.h"
24 #include "nel/3d/particle_system.h"
25 #include "nel/3d/driver.h"
26 #include "nel/3d/vertex_buffer.h"
27 #include "nel/3d/index_buffer.h"
28 #include "nel/3d/material.h"
29 #include "nel/3d/nelu.h"
30 #include "nel/3d/font_generator.h"
31 #include "nel/3d/font_manager.h"
32 #include "nel/3d/computed_string.h"
33 #include "nel/3d/dru.h"
34 #include "nel/3d/ps_located.h"
35 #include "nel/3d/ps_sound.h"
36 #include "nel/3d/ps_light.h"
39 #include "nel/3d/particle_system_shape.h"
49 using NLMISC::CVector
;
53 bool CPSUtil::_CosTableInitialized
= false;
54 bool CPSUtil::_PerlinNoiseTableInitialized
= false;
57 float CPSUtil::_CosTable
[256];
58 float CPSUtil::_SinTable
[256];
59 float CPSUtil::_PerlinNoiseTab
[1024];
64 //==========================================================================
65 void CPSUtil::initPerlinNoiseTable(void)
67 NL_PS_FUNC(CPSUtil_initPerlinNoiseTable
)
68 for (uint32 k
= 0; k
< 1024; ++k
)
70 _PerlinNoiseTab
[k
] = (rand() % 30000) / 30000.f
;
73 _PerlinNoiseTableInitialized
= true;
77 //==========================================================================
78 void CPSUtil::initFastCosNSinTable(void)
80 NL_PS_FUNC(CPSUtil_initFastCosNSinTable
)
81 for (uint32 k
= 0; k
< 256; k
++)
83 const float angle
= k
/ 256.0f
* 2.0f
* float(NLMISC::Pi
);
84 _CosTable
[k
] = (float) cos( angle
);
85 _SinTable
[k
] = (float) sin( angle
);
88 _CosTableInitialized
= true;
92 //==========================================================================
93 void CPSUtil::registerSerialParticleSystem(void)
95 NL_PS_FUNC(CPSUtil_registerSerialParticleSystem
)
96 NLMISC_REGISTER_CLASS(CPSLocated
);
97 NLMISC_REGISTER_CLASS(CParticleSystemShape
);
98 NLMISC_REGISTER_CLASS(CPSSound
);
99 NLMISC_REGISTER_CLASS(CPSLight
);
109 // while we are here, we perform some important inits
110 initFastCosNSinTable(); // init fast cosine lookup table
111 initPerlinNoiseTable(); // init perlin noise table
114 //==========================================================================
115 void CPSUtil::displayBBox(NL3D::IDriver
*driver
, const NLMISC::CAABBox
&box
, NLMISC::CRGBA col
/* = NLMISC::CRGBA::White */)
117 NL_PS_FUNC(CPSUtil_displayBBox
)
118 CVector max
= box
.getMax()
121 vb
.setVertexFormat(CVertexBuffer::PositionFlag
);
122 vb
.setNumVertices(8);
125 CVertexBufferReadWrite vba
;
127 vba
.setVertexCoord(0, min
);
128 vba
.setVertexCoord(1, CVector(max
.x
, min
.y
, min
.z
));
129 vba
.setVertexCoord(2, CVector(min
.x
, max
.y
, min
.z
));
130 vba
.setVertexCoord(3, CVector(max
.x
, max
.y
, min
.z
));
131 vba
.setVertexCoord(4, CVector(min
.x
, min
.y
, max
.z
));
132 vba
.setVertexCoord(5, CVector(max
.x
, min
.y
, max
.z
));
133 vba
.setVertexCoord(6, CVector(min
.x
, max
.y
, max
.z
));
134 vba
.setVertexCoord(7, max
);
140 material
.setColor(col
);
141 material
.setLighting(false);
142 material
.setBlendFunc(CMaterial::one
, CMaterial::one
);
143 material
.setZWrite(false);
144 material
.setBlend(true);
149 pb
.setFormat(NL_DEFAULT_INDEX_BUFFER_FORMAT
);
150 pb
.setNumIndexes(2*12);
152 CIndexBufferReadWrite ibaWrite
;
154 ibaWrite
.setLine(0, 0, 1);
155 ibaWrite
.setLine(2, 1, 5);
156 ibaWrite
.setLine(4, 5, 4);
157 ibaWrite
.setLine(6, 4, 0);
158 ibaWrite
.setLine(8, 0, 2);
159 ibaWrite
.setLine(10, 1, 3);
160 ibaWrite
.setLine(12, 4, 6);
161 ibaWrite
.setLine(14, 5, 7);
162 ibaWrite
.setLine(16, 6, 7);
163 ibaWrite
.setLine(18, 7, 3);
164 ibaWrite
.setLine(20, 3, 2);
165 ibaWrite
.setLine(22, 2, 6);
170 driver
->activeVertexBuffer(vb
);
171 driver
->activeIndexBuffer(pb
);
172 driver
->renderLines(material
, 0, pb
.getNumIndexes()/2);
176 //==========================================================================
177 void CPSUtil::displayArrow(IDriver
*driver
, const CVector
&start
, const CVector
&v
, float size
, CRGBA col1
, CRGBA col2
)
180 NL_PS_FUNC(CPSUtil_displayArrow
)
182 const float coneSize
= size
* 0.1f
;
184 static CIndexBuffer vTab
;
185 static const TIndexType vTabIndexes
[] =
192 vTab
.setFormat(NL_DEFAULT_INDEX_BUFFER_FORMAT
);
194 if (vTab
.getNumIndexes()==0)
196 vTab
.setNumIndexes (sizeofarray(vTabIndexes
));
197 CIndexBufferReadWrite iba
;
199 memcpy (iba
.getPtr(), vTabIndexes
, sizeof(vTabIndexes
));
203 CVector end
= start
+ size
* v
;
204 CDRU::drawLine(start
, end
, col1
, *driver
);
206 buildSchmidtBasis(v
, m
);
210 vb
.setVertexFormat(CVertexBuffer::PositionFlag
);
211 vb
.setNumVertices(5);
215 CVertexBufferReadWrite vba
;
217 vba
.setVertexCoord(0, end
+ m
* CVector(0, 0, 3.0f
* coneSize
) );
218 vba
.setVertexCoord(1, end
+ m
* CVector(-coneSize
, -coneSize
, 0) );
219 vba
.setVertexCoord(2, end
+ m
* CVector(coneSize
, -coneSize
, 0) );
220 vba
.setVertexCoord(3, end
+ m
* CVector(coneSize
, coneSize
, 0) );
221 vba
.setVertexCoord(4, end
+ m
* CVector(-coneSize
, coneSize
, 0) );
227 material
.setColor(col2
);
228 material
.setLighting(false);
229 material
.setBlendFunc(CMaterial::one
, CMaterial::one
);
230 material
.setZWrite(false);
231 material
.setBlend(true);
232 material
.setDoubleSided(true);
236 driver
->activeVertexBuffer(vb
);
237 driver
->activeIndexBuffer(vTab
);
238 driver
->renderTriangles(material
, 0, 6);
243 //==========================================================================
244 void CPSUtil::displayBasis(IDriver
*driver
, const CMatrix
&modelMat
, const NLMISC::CMatrix
&m
, float size
, CFontGenerator
&fg
, CFontManager
&fm
)
246 NL_PS_FUNC(CPSUtil_displayBasis
)
250 driver
->setupModelMatrix(modelMat
);
255 displayArrow(driver
, m
.getPos(), m
.getI(), size
, CRGBA(127, 127, 127), CRGBA(0, 0, 80));
257 displayArrow(driver
, m
.getPos(), m
.getJ(), size
, CRGBA(127, 127, 127), CRGBA(0, 0, 80));
259 displayArrow(driver
, m
.getPos(), m
.getK(), size
, CRGBA(127, 127, 127), CRGBA(200, 0, 80));
264 CPSUtil::print(driver
, std::string("x"), fg
, fm
, modelMat
* m
* CVector(1.4f
* size
, 0, 0), 15.0f
* size
);
266 CPSUtil::print(driver
, std::string("y"), fg
, fm
, modelMat
* m
* CVector(0, 1.4f
* size
, 0), 15.0f
* size
);
268 CPSUtil::print(driver
, std::string("z"), fg
, fm
, modelMat
* m
* CVector(0, 0, 1.4f
* size
), 15.0f
* size
);
273 //==========================================================================
274 void CPSUtil::print(IDriver
*driver
, const std::string
&text
, CFontGenerator
&fg
, CFontManager
&fm
, const CVector
&pos
, float size
, NLMISC::CRGBA col
/*= NLMISC::CRGBA::White*/)
276 NL_PS_FUNC(CPSUtil_print
)
277 CComputedString cptedString
;
278 fm
.computeString ( text
,
288 CMatrix mat
= driver
->getViewMatrix();
289 mat
.setPos(CVector::Null
);
290 mat
.scale(CVector(size
, size
, size
));
293 cptedString
.render3D(*driver
, mat
);
297 //==========================================================================
298 void CPSUtil::buildSchmidtBasis(const CVector
&k_
, NLMISC::CMatrix
&result
)
300 NL_PS_FUNC(CPSUtil_buildSchmidtBasis
)
301 const float epsilon
= 10E-4f
;
305 if ((1.0f
- fabsf(k
* CVector::I
)) > epsilon
)
310 if ((1.0f
- fabs(k
* CVector::J
)) > epsilon
)
321 result
.setRot(i
, k
^ i
, k
, true);
325 //==========================================================================
326 void CPSUtil::displaySphere(IDriver
&driver
, float radius
, const CVector
¢er
, uint nbSubdiv
, CRGBA color
)
328 NL_PS_FUNC(CPSUtil_displaySphere
)
332 static const CVector lK
[] = { CVector::I
, -CVector::I
333 ,CVector::J
, -CVector::J
334 ,CVector::K
, -CVector::K
};
336 /* static const CVector lI = { CVector::J, -CVector::J
337 ,CVector::K, -CVector::K
338 ,CVector::I, -CVector::I };*/
342 for (k
= 0; k
< 6; ++k
)
344 const CVector
&I
= lK
[(k
+ 2) % 6];
345 const CVector
&K
= lK
[k
];
346 const CVector J
= K
^ I
;
348 for (x
= 0; x
< nbSubdiv
; ++x
)
350 for (y
= 0; y
< nbSubdiv
; ++y
)
352 p
= ((2.f
* x
/ float(nbSubdiv
) ) - 1.f
) * I
+ ((2.f
* y
/ float(nbSubdiv
) ) - 1.f
) * J
+ K
;
353 p1
= p
+ 2.f
/ float(nbSubdiv
) * I
;
354 p2
= p
+ 2.f
/ float(nbSubdiv
) * J
;
360 p
= center
+ radius
* p
;
361 p1
= center
+ radius
* p1
;
362 p2
= center
+ radius
* p2
;
364 CDRU::drawLine(p
, p1
, color
, driver
);
365 CDRU::drawLine(p
, p2
, color
, driver
);
372 //==========================================================================
373 void CPSUtil::displayDisc(IDriver
&driver
, float radius
, const CVector
¢er
, const CMatrix
&mat
, uint nbSubdiv
, CRGBA color
)
375 NL_PS_FUNC(CPSUtil_displayDisc
)
376 // not optimized, but for edition only
377 float thetaDelta
= (float) NLMISC::Pi
* 2.f
/ nbSubdiv
;
379 const CVector
&I
= mat
.getI();
380 const CVector
&J
= mat
.getJ();
381 for (uint k
= 0; k
< nbSubdiv
; ++k
)
384 CDRU::drawLine(center
+ radius
* ((float) cos(theta
) * I
+ (float) sin(theta
) * J
)
385 , center
+ radius
* ((float) cos(theta
+ thetaDelta
) * I
+ (float) sin(theta
+ thetaDelta
) * J
)
392 //==========================================================================
393 void CPSUtil::displayCylinder(IDriver
&driver
, const CVector
¢er
, const CMatrix
&mat
, const CVector
&dim
, uint nbSubdiv
, CRGBA color
)
395 NL_PS_FUNC(CPSUtil_displayCylinder
)
396 // not optimized, but for edition only
397 float thetaDelta
= (float) NLMISC::Pi
* 2.f
/ nbSubdiv
;
399 const CVector
&I
= mat
.getI();
400 const CVector
&J
= mat
.getJ();
401 const CVector
&K
= mat
.getK();
403 for (uint k
= 0; k
< nbSubdiv
; ++k
)
406 CDRU::drawLine(center
+ dim
.z
* K
+ dim
.x
* cosf(theta
) * I
+ dim
.y
* sinf(theta
) * J
407 , center
+ dim
.z
* K
+ dim
.x
* cosf(theta
+ thetaDelta
) * I
+ dim
.y
* sinf(theta
+ thetaDelta
) * J
410 CDRU::drawLine(center
- dim
.z
* K
+ dim
.x
* cosf(theta
) * I
+ dim
.y
* sinf(theta
) * J
411 , center
- dim
.z
* K
+ dim
.x
* cosf(theta
+ thetaDelta
) * I
+ dim
.y
* sinf(theta
+ thetaDelta
) * J
414 CDRU::drawLine(center
+ dim
.z
* K
+ dim
.x
* cosf(theta
) * I
+ dim
.y
* sinf(theta
) * J
415 , center
- dim
.z
* K
+ dim
.x
* cosf(theta
) * I
+ dim
.y
* sinf(theta
) * J
425 //==========================================================================
426 void CPSUtil::display3DQuad(IDriver
&driver
, const CVector
&c1
, const CVector
&c2
427 ,const CVector
&c3
, const CVector
&c4
, CRGBA color
)
429 NL_PS_FUNC(CPSUtil_display3DQuad
)
430 CDRU::drawLine(c1
, c2
, color
, driver
);
431 CDRU::drawLine(c2
, c3
, color
, driver
);
432 CDRU::drawLine(c3
, c4
, color
, driver
);
433 CDRU::drawLine(c4
, c1
, color
, driver
);