Bonjour,
Je débute sur irrlicht.
J'ai dérivé un ISceneNode pour créer un objet personnalisé (TubeSceneNode) et j'aimerais le texturer. J'ai essayé de modifier "m_material" sans succès.
J'aimerais de votre aide svp pour m'expliquer comment je pourrais faire.
Mon programme affiche un tube formé à partir de quelques points, le chemin du tube est calculé par l'interpolation de Hermite. Vous pouvez vous déplacer avec la caméra FPS standard.
Voici le code complet :
Code c++ :
#include <irrlicht.h>
#include <cmath>
using namespace irr;class Path3D
{public: Path3D
(double tension
= 0, double bias
= 0) : m_tension
(tension
), m_bias
(bias
) { } void push
(const core::vector3df
& v
) { m_array
.push_back
(v
); } int size
() const { return m_array
.size
(); } core::vector3df getPoint
(double mu
) const { core::vector3df v1
, v2
, v3
, v4
; int index
; double mu_interval
, intpart
; mu_interval
= modf
(mu
, &intpart
); index
= (int)intpart
; return getPoint
(index
, mu_interval
); } core::vector3df getPoint
(int index
, double mu
) const { core::vector3df v1
, v2
, v3
, v4
; v1
= getVectorById
(index
- 1); v2
= getVectorById
(index
); v3
= getVectorById
(index
+ 1); v4
= getVectorById
(index
+ 2); return HermiteInterpolateVector
(v1
, v2
, v3
, v4
, mu
); }private: core::vector3df getVectorById
(int id
) const { if (m_array
.empty
()) return core::vector3df
(0, 0, 0); else return m_array
[id
% m_array
.size
()]; } core::vector3df HermiteInterpolateVector
( const core::vector3df
& v1
, const core::vector3df
& v2
, const core::vector3df
& v3
, const core::vector3df
& v4
, double mu
) const { core::vector3df w
; w
.X
= HermiteInterpolate
(v1
.X
, v2
.X
, v3
.X
, v4
.X
, mu
); w
.Y
= HermiteInterpolate
(v1
.Y
, v2
.Y
, v3
.Y
, v4
.Y
, mu
); w
.Z
= HermiteInterpolate
(v1
.Z
, v2
.Z
, v3
.Z
, v4
.Z
, mu
); return w
; } double HermiteInterpolate
(double y0
, double y1
, double y2
, double y3
, double mu
) const { double m0
, m1
, mu2
, mu3
; double a0
, a1
, a2
, a3
; mu2
= mu
* mu
; mu3
= mu2
* mu
; m0
= (y1
- y0
)*(1 + m_bias
)*(1 - m_tension
)/2; m0
+= (y2
- y1
)*(1 - m_bias
)*(1 - m_tension
)/2; m1
= (y2
- y1
)*(1 + m_bias
)*(1 - m_tension
)/2; m1
+= (y3
- y2
)*(1 - m_bias
)*(1 - m_tension
)/2; a0
= 2*mu3
- 3*mu2
+ 1; a1
= mu3
- 2*mu2
+ mu
; a2
= mu3
- mu2
; a3
= -2*mu3
+ 3*mu2
; return (a0
*y1
+ a1
*m0
+ a2
*m1
+ a3
*y2
); }private: double m_tension
; double m_bias
; core::array
<core::vector3df
> m_array
;};class TubeSceneNode
: public scene::ISceneNode{public: TubeSceneNode
(scene::ISceneNode *parent
, scene::ISceneManager *mgr
, s32 id
, const Path3D
& path
, int radius
, int pathDivide
= 16, int ringDivide
= 16) : scene::ISceneNode(parent
, mgr
, id
) { core::vector3df u
, v
, A
, B
, dir
, pt
; m_material
.Wireframe
= false; m_material
.Lighting
= false; m_material
.BackfaceCulling
= false; m_ringDivide
= ringDivide
; m_verticesCount
= path
.size
() * pathDivide
* m_ringDivide
; m_vertices
= new video::S3DVertex[m_verticesCount
]; for (int i
= 0; i
< path
.size
(); i
++) { for (int j
= 0; j
< pathDivide
; j
++) { A
= path
.getPoint
(f64
(i
) + ( f64
(j
) / f64
(pathDivide
) )); B
= path
.getPoint
(f64
(i
) + ( f64
(j
+ 1) / f64
(pathDivide
) )); dir
= (B
- A
).normalize
(); u
= (core::vector3df
(dir
.Y
, -dir
.X
, 0)).normalize
(); v
= (dir
.crossProduct
(u
)).normalize
(); int indexRef
= i
* pathDivide
* m_ringDivide
+ j
* m_ringDivide
; for (int k
= 0; k
< m_ringDivide
; k
++) { double teta
= k
* 2.0 * M_PI
/ m_ringDivide
; pt
= A
+ ( radius
* cos
(teta
) ) * u
+ ( radius
* sin
(teta
) ) * v
; m_vertices
[indexRef
+ k
] = video::S3DVertex(pt
, core::vector3df
(0, 0, 0), video::SColor(128, 128, 255, 255), core::vector2d< f32
>(0, 0)); } } } } virtual void OnRegisterSceneNode
() { if (IsVisible
) SceneManager
->registerNodeForRendering
(this); ISceneNode::OnRegisterSceneNode
(); } virtual void render
() { u16 indices
[6*m_verticesCount
]; video::IVideoDriver* driver
; for (int i
= 0; i
< m_verticesCount
; i
++) { indices
[3*i
] = i
% m_verticesCount
; indices
[3*i
+ 1] = ( i
+ 1 ) % m_verticesCount
; indices
[3*i
+ 2] = ( i
+ m_ringDivide
) % m_verticesCount
; } int j
= m_verticesCount
* 3; for (int i
= 0; i
< m_verticesCount
; i
++) { indices
[j
+ 3*i
] = ( i
+ 1 ) % m_verticesCount
; indices
[j
+ 3*i
+ 1] = ( i
+ m_ringDivide
) % m_verticesCount
; indices
[j
+ 3*i
+ 2] = ( i
+ m_ringDivide
+ 1 ) % m_verticesCount
; } driver
= SceneManager
->getVideoDriver
(); driver
->setMaterial
(m_material
); driver
->setTransform
(video::ETS_WORLD
, AbsoluteTransformation
); driver
->drawIndexedTriangleList
(m_vertices
, m_verticesCount
, &indices
[0], m_verticesCount
*2); } virtual const
core::aabbox3d<f32
>& getBoundingBox
() const { return m_box
; } virtual u32 getMaterialCount
() const { return 1; } virtual video::SMaterial& getMaterial
(u32 i
) { return m_material
; }private: core::aabbox3d<irr::f32
> m_box
; video::SMaterial m_material
; video::S3DVertex *m_vertices
; int m_verticesCount
; int m_pathDivide
; int m_ringDivide
;};void drawTubeLines
(video::IVideoDriver *driver
, const Path3D
&path
, int precision
){ core::vector3df w1
, w2
; core::vector3df u
, v
, w
; for (int i
= 0; i
< path
.size
(); i
++) { for (int j
= 0; j
<= precision
- 1; j
++) { w1
= path
.getPoint
(i
, f64
(j
) / f64
(precision
)); w2
= path
.getPoint
(i
, f64
(j
+ 1) / f64
(precision
)); driver
->draw3DLine
(w1
, w2
, video::SColor(0, 255*( f64
(j
) / f64
(precision
) ), 255*( f64
(j
) / f64
(precision
) ), 0 )); u
= (w2
- w1
).normalize
(); v
= (core::vector3df
(u
.Y
, -u
.X
, 0)).normalize
(); w
= (u
.crossProduct
(v
)).normalize
(); driver
->draw3DLine
(w1
, w1
+ 40 * u
, video::SColor(0, 128, 0, 0 )); driver
->draw3DLine
(w1
, w1
+ 40 * v
, video::SColor(0, 0, 128, 0 )); driver
->draw3DLine
(w1
, w1
+ 40 * w
, video::SColor(0, 0, 0, 128 )); int radius
= 80; int circleDetail
= 16; for (int k
= 0; k
< circleDetail
; k
++) { double teta
= k
* 2 * M_PI
/ circleDetail
; double teta2
= (k
+ 1) * 2 * M_PI
/ circleDetail
; core::vector3df u1
, u2
; u1
= w1
+ radius
* cos
(teta
) * v
+ radius
* sin
(teta
) * w
; u2
= w1
+ radius
* cos
(teta2
) * v
+ radius
* sin
(teta2
) * w
; driver
->draw3DLine
(u1
, u2
, video::SColor(0, 0, 128, 128 )); } } }}int main
(void){ IrrlichtDevice *device
; video::IVideoDriver *driver
; scene::ISceneManager *sceneManager
; gui::IGUIEnvironment
*gui; scene::ICameraSceneNode *camera
; gui::IGUIStaticText
*coordText
; Path3D path
; device
= createDevice
(video::EDT_OPENGL
, core::dimension2d<u32
>(800, 600), 32, false, false, false, 0); driver
= device
->getVideoDriver
(); sceneManager
= device
->getSceneManager
(); gui = device
->getGUIEnvironment
(); camera
= sceneManager
->addCameraSceneNodeFPS
(); coordText
= gui->addStaticText
(L
"Coordonnees", core::rect<s32
>(10, 10, 100, 45), true, true, 0, -1, true); path
.push
(core::vector3df
(80, 80, 80)); path
.push
(core::vector3df
(500, 200, 200)); path
.push
(core::vector3df
(500, 1000, 0)); path
.push
(core::vector3df
(200, 1000, 600)); TubeSceneNode
*tube
= new TubeSceneNode
(sceneManager
->getRootSceneNode
(), sceneManager
, 666, path
, 80); tube
->drop
(); core::vector3df posCam
; wchar_t buffer
[128]; video::SMaterial material
; material
.Lighting
= false; while (device
->run
()) { driver
->beginScene
(true, true, video::SColor(255, 255, 255, 255)); sceneManager
->drawAll
(); gui->drawAll
(); driver
->setMaterial
(material
); driver
->draw3DLine
(core::vector3df
(0, 0, 0), core::vector3df
(100, 0, 0), video::SColor(0, 255, 0, 0)); driver
->draw3DLine
(core::vector3df
(0, 0, 0), core::vector3df
(0, 100, 0), video::SColor(0, 0, 255, 0)); driver
->draw3DLine
(core::vector3df
(0, 0, 0), core::vector3df
(0, 0, 100), video::SColor(0, 0, 0, 255)); drawTubeLines
(driver
, path
, 16); driver
->endScene
(); posCam
= camera
->getPosition
(); swprintf
(buffer
, 128, L
"X : %f\nY : %f\nZ : %f", posCam
.X
, posCam
.Y
, posCam
.Z
); coordText
->setText
(buffer
); } device
->drop
(); return 0;}
Merci.
Cordialement, Charly