1 /************************************************************************
3 * Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
6 * voxelands - 3d voxel world sandbox game
7 * Copyright (C) Lisa 'darkrose' Milne 2014 <lisa@ltmnet.com>
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 * See the GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>
22 * License updated from GPLv2 or later to GPLv3 or later by Lisa Milne
24 ************************************************************************/
32 #include <IAnimatedMesh.h>
33 #include <SAnimatedMesh.h>
34 #include <ICameraSceneNode.h>
35 #include "constants.h"
37 #include <IMeshLoader.h>
38 #include <IMeshCache.h>
42 // In Irrlicht 1.8 the signature of ITexture::lock was changed from
43 // (bool, u32) to (E_TEXTURE_LOCK_MODE, u32).
44 #if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR <= 7
45 #define MY_ETLM_READ_ONLY true
47 #define MY_ETLM_READ_ONLY video::ETLM_READ_ONLY
50 scene::IAnimatedMesh
* createNodeBoxMesh(std::vector
<NodeBox
> nodeboxes
, v3f scale
)
52 video::SColor
c(255,255,255,255);
54 scene::SMesh
*mesh
= new scene::SMesh();
55 for (std::vector
<NodeBox
>::const_iterator n
= nodeboxes
.begin(); n
!= nodeboxes
.end(); n
++) {
57 v3f min
= box
.m_box
.MinEdge
;
58 v3f max
= box
.m_box
.MaxEdge
;
59 // Compute texture coords
60 f32 tx1
= (box
.m_box
.MinEdge
.X
/BS
)+0.5;
61 f32 ty1
= (box
.m_box
.MinEdge
.Y
/BS
)+0.5;
62 f32 tz1
= (box
.m_box
.MinEdge
.Z
/BS
)+0.5;
63 f32 tx2
= (box
.m_box
.MaxEdge
.X
/BS
)+0.5;
64 f32 ty2
= (box
.m_box
.MaxEdge
.Y
/BS
)+0.5;
65 f32 tz2
= (box
.m_box
.MaxEdge
.Z
/BS
)+0.5;
68 tx1
, 1-tz2
, tx2
, 1-tz1
,
72 tz1
, 1-ty2
, tz2
, 1-ty1
,
74 1-tz2
, 1-ty2
, 1-tz1
, 1-ty1
,
76 1-tx2
, 1-ty2
, 1-tx1
, 1-ty1
,
78 tx1
, 1-ty2
, tx2
, 1-ty1
,
80 video::S3DVertex vertices
[24] = {
82 video::S3DVertex(min
.X
/BS
,max
.Y
/BS
,max
.Z
/BS
, 0,1,0, c
, txc
[0],txc
[1]),
83 video::S3DVertex(max
.X
/BS
,max
.Y
/BS
,max
.Z
/BS
, 0,1,0, c
, txc
[2],txc
[1]),
84 video::S3DVertex(max
.X
/BS
,max
.Y
/BS
,min
.Z
/BS
, 0,1,0, c
, txc
[2],txc
[3]),
85 video::S3DVertex(min
.X
/BS
,max
.Y
/BS
,min
.Z
/BS
, 0,1,0, c
, txc
[0],txc
[3]),
87 video::S3DVertex(min
.X
/BS
,min
.Y
/BS
,min
.Z
/BS
, 0,-1,0, c
, txc
[4],txc
[5]),
88 video::S3DVertex(max
.X
/BS
,min
.Y
/BS
,min
.Z
/BS
, 0,-1,0, c
, txc
[6],txc
[5]),
89 video::S3DVertex(max
.X
/BS
,min
.Y
/BS
,max
.Z
/BS
, 0,-1,0, c
, txc
[6],txc
[7]),
90 video::S3DVertex(min
.X
/BS
,min
.Y
/BS
,max
.Z
/BS
, 0,-1,0, c
, txc
[4],txc
[7]),
92 video::S3DVertex(max
.X
/BS
,max
.Y
/BS
,min
.Z
/BS
, 1,0,0, c
, txc
[ 8],txc
[9]),
93 video::S3DVertex(max
.X
/BS
,max
.Y
/BS
,max
.Z
/BS
, 1,0,0, c
, txc
[10],txc
[9]),
94 video::S3DVertex(max
.X
/BS
,min
.Y
/BS
,max
.Z
/BS
, 1,0,0, c
, txc
[10],txc
[11]),
95 video::S3DVertex(max
.X
/BS
,min
.Y
/BS
,min
.Z
/BS
, 1,0,0, c
, txc
[ 8],txc
[11]),
97 video::S3DVertex(min
.X
/BS
,max
.Y
/BS
,max
.Z
/BS
, -1,0,0, c
, txc
[12],txc
[13]),
98 video::S3DVertex(min
.X
/BS
,max
.Y
/BS
,min
.Z
/BS
, -1,0,0, c
, txc
[14],txc
[13]),
99 video::S3DVertex(min
.X
/BS
,min
.Y
/BS
,min
.Z
/BS
, -1,0,0, c
, txc
[14],txc
[15]),
100 video::S3DVertex(min
.X
/BS
,min
.Y
/BS
,max
.Z
/BS
, -1,0,0, c
, txc
[12],txc
[15]),
102 video::S3DVertex(max
.X
/BS
,max
.Y
/BS
,max
.Z
/BS
, 0,0,1, c
, txc
[16],txc
[17]),
103 video::S3DVertex(min
.X
/BS
,max
.Y
/BS
,max
.Z
/BS
, 0,0,1, c
, txc
[18],txc
[17]),
104 video::S3DVertex(min
.X
/BS
,min
.Y
/BS
,max
.Z
/BS
, 0,0,1, c
, txc
[18],txc
[19]),
105 video::S3DVertex(max
.X
/BS
,min
.Y
/BS
,max
.Z
/BS
, 0,0,1, c
, txc
[16],txc
[19]),
107 video::S3DVertex(min
.X
/BS
,max
.Y
/BS
,min
.Z
/BS
, 0,0,-1, c
, txc
[20],txc
[21]),
108 video::S3DVertex(max
.X
/BS
,max
.Y
/BS
,min
.Z
/BS
, 0,0,-1, c
, txc
[22],txc
[21]),
109 video::S3DVertex(max
.X
/BS
,min
.Y
/BS
,min
.Z
/BS
, 0,0,-1, c
, txc
[22],txc
[23]),
110 video::S3DVertex(min
.X
/BS
,min
.Y
/BS
,min
.Z
/BS
, 0,0,-1, c
, txc
[20],txc
[23]),
113 if (box
.m_angle
!= v3s16(0,0,0)) {
114 for (s32 j
=0; j
<24; j
++) {
116 vertices
[j
].Pos
.rotateXZBy(box
.m_angle
.Y
);
118 vertices
[j
].Pos
.rotateYZBy(box
.m_angle
.X
);
120 vertices
[j
].Pos
.rotateXYBy(box
.m_angle
.Z
);
124 u16 indices
[6] = {0,1,2,2,3,0};
125 for (u32 i
=0; i
<6; ++i
) {
126 scene::IMeshBuffer
*buf
= new scene::SMeshBuffer();
127 buf
->append(vertices
+ 4 * i
, 4, indices
, 6);
128 // Set default material
129 buf
->getMaterial().setFlag(video::EMF_LIGHTING
, false);
130 buf
->getMaterial().setFlag(video::EMF_BILINEAR_FILTER
, false);
131 buf
->getMaterial().MaterialType
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF
;
132 // Add mesh buffer to mesh
133 mesh
->addMeshBuffer(buf
);
138 scene::SAnimatedMesh
*anim_mesh
= new scene::SAnimatedMesh(mesh
);
140 scaleMesh(anim_mesh
, scale
); // also recalculates bounding box
144 scene::IAnimatedMesh
* createCubeMesh(v3f scale
)
146 std::vector
<NodeBox
> nodeboxes
;
148 nodeboxes
.push_back(NodeBox(
157 return createNodeBoxMesh(nodeboxes
,scale
);
161 scene::IAnimatedMesh
* createModelMesh(scene::ISceneManager
* smgr
, std::string model
, bool unique
)
163 std::string model_path
= getModelPath(model
);
164 scene::IAnimatedMesh
* mesh
= smgr
->getMesh(model_path
.c_str());
167 #if (IRRLICHT_VERSION_MAJOR >= 1 && IRRLICHT_VERSION_MINOR >= 8) || IRRLICHT_VERSION_MAJOR >= 2
168 // irrlicht 1.8+ we just manually load the mesh
169 scene::IMeshLoader
*loader
;
170 u32 lc
= smgr
->getMeshLoaderCount();
171 io::IReadFile
* file
= smgr
->getFileSystem()->createAndOpenFile(model_path
.c_str());
174 for (u32 i
=0; i
<lc
; i
++) {
175 loader
= smgr
->getMeshLoader(i
);
177 if (loader
->isALoadableFileExtension(model
.c_str())) {
178 mesh
= loader
->createMesh(file
);
184 // irrlicht 1.7 doesn't have a meshloader interface, so rename
185 // the previous mesh from this file to force scenemanager to
187 scene::IMeshCache
*mc
= smgr
->getMeshCache();
191 mp
= model_path
+ "-" + itos(i
++);
192 } while (mc
->getMeshByName(mp
.c_str()));
194 mc
->renameMesh(mesh
,mp
.c_str());
196 mesh
= smgr
->getMesh(model_path
.c_str());
202 static scene::IAnimatedMesh
* extrudeARGB(u32 twidth
, u32 theight
, u8
*data
)
204 const s32 argb_wstep
= 4 * twidth
;
205 const s32 alpha_threshold
= 64;
207 scene::IMeshBuffer
*buf
= new scene::SMeshBuffer();
208 video::SColor
c(255,255,255,255);
212 video::S3DVertex vertices
[8] = {
213 video::S3DVertex(-0.5,-0.5,-0.5, 0,0,-1, c
, 0,1),
214 video::S3DVertex(-0.5,+0.5,-0.5, 0,0,-1, c
, 0,0),
215 video::S3DVertex(+0.5,+0.5,-0.5, 0,0,-1, c
, 1,0),
216 video::S3DVertex(+0.5,-0.5,-0.5, 0,0,-1, c
, 1,1),
217 video::S3DVertex(+0.5,-0.5,+0.5, 0,0,+1, c
, 1,1),
218 video::S3DVertex(+0.5,+0.5,+0.5, 0,0,+1, c
, 1,0),
219 video::S3DVertex(-0.5,+0.5,+0.5, 0,0,+1, c
, 0,0),
220 video::S3DVertex(-0.5,-0.5,+0.5, 0,0,+1, c
, 0,1),
222 u16 indices
[12] = {0,1,2,2,3,0,4,5,6,6,7,4};
223 buf
->append(vertices
, 8, indices
, 12);
227 // (add faces where a solid pixel is next to a transparent one)
228 u8
*solidity
= new u8
[(twidth
+2) * (theight
+2)];
229 u32 wstep
= twidth
+ 2;
230 for (u32 y
= 0; y
< theight
+ 2; ++y
) {
231 u8
*scanline
= solidity
+ y
* wstep
;
232 if (y
== 0 || y
== theight
+ 1) {
233 for (u32 x
= 0; x
< twidth
+ 2; ++x
) {
238 u8
*argb_scanline
= data
+ (y
- 1) * argb_wstep
;
239 for (u32 x
= 0; x
< twidth
; ++x
) {
240 scanline
[x
+1] = (argb_scanline
[x
*4+3] >= alpha_threshold
);
242 scanline
[twidth
+ 1] = 0;
246 // without this, there would be occasional "holes" in the mesh
249 for (u32 y
= 0; y
<= theight
; ++y
) {
250 u8
*scanline
= solidity
+ y
* wstep
+ 1;
251 for (u32 x
= 0; x
<= twidth
; ++x
) {
252 if (scanline
[x
] && !scanline
[x
+ wstep
]) {
254 while (scanline
[xx
] && !scanline
[xx
+ wstep
]) {
257 f32 vx1
= (x
- eps
) / (f32
) twidth
- 0.5;
258 f32 vx2
= (xx
+ eps
) / (f32
) twidth
- 0.5;
259 f32 vy
= 0.5 - (y
- eps
) / (f32
) theight
;
260 f32 tx1
= x
/ (f32
) twidth
;
261 f32 tx2
= xx
/ (f32
) twidth
;
262 f32 ty
= (y
- 0.5) / (f32
) theight
;
263 video::S3DVertex vertices
[8] = {
264 video::S3DVertex(vx1
,vy
,-0.5, 0,-1,0, c
, tx1
,ty
),
265 video::S3DVertex(vx2
,vy
,-0.5, 0,-1,0, c
, tx2
,ty
),
266 video::S3DVertex(vx2
,vy
,+0.5, 0,-1,0, c
, tx2
,ty
),
267 video::S3DVertex(vx1
,vy
,+0.5, 0,-1,0, c
, tx1
,ty
),
269 u16 indices
[6] = {0,1,2,2,3,0};
270 buf
->append(vertices
, 4, indices
, 6);
273 if (!scanline
[x
] && scanline
[x
+ wstep
]) {
275 while (!scanline
[xx
] && scanline
[xx
+ wstep
]) {
278 f32 vx1
= (x
- eps
) / (f32
) twidth
- 0.5;
279 f32 vx2
= (xx
+ eps
) / (f32
) twidth
- 0.5;
280 f32 vy
= 0.5 - (y
+ eps
) / (f32
) theight
;
281 f32 tx1
= x
/ (f32
) twidth
;
282 f32 tx2
= xx
/ (f32
) twidth
;
283 f32 ty
= (y
+ 0.5) / (f32
) theight
;
284 video::S3DVertex vertices
[8] = {
285 video::S3DVertex(vx1
,vy
,-0.5, 0,1,0, c
, tx1
,ty
),
286 video::S3DVertex(vx1
,vy
,+0.5, 0,1,0, c
, tx1
,ty
),
287 video::S3DVertex(vx2
,vy
,+0.5, 0,1,0, c
, tx2
,ty
),
288 video::S3DVertex(vx2
,vy
,-0.5, 0,1,0, c
, tx2
,ty
),
290 u16 indices
[6] = {0,1,2,2,3,0};
291 buf
->append(vertices
, 4, indices
, 6);
297 for (u32 x
= 0; x
<= twidth
; ++x
) {
298 u8
*scancol
= solidity
+ x
+ wstep
;
299 for (u32 y
= 0; y
<= theight
; ++y
) {
300 if (scancol
[y
* wstep
] && !scancol
[y
* wstep
+ 1]) {
302 while (scancol
[yy
* wstep
] && !scancol
[yy
* wstep
+ 1]) {
305 f32 vx
= (x
- eps
) / (f32
) twidth
- 0.5;
306 f32 vy1
= 0.5 - (y
- eps
) / (f32
) theight
;
307 f32 vy2
= 0.5 - (yy
+ eps
) / (f32
) theight
;
308 f32 tx
= (x
- 0.5) / (f32
) twidth
;
309 f32 ty1
= y
/ (f32
) theight
;
310 f32 ty2
= yy
/ (f32
) theight
;
311 video::S3DVertex vertices
[8] = {
312 video::S3DVertex(vx
,vy1
,-0.5, 1,0,0, c
, tx
,ty1
),
313 video::S3DVertex(vx
,vy1
,+0.5, 1,0,0, c
, tx
,ty1
),
314 video::S3DVertex(vx
,vy2
,+0.5, 1,0,0, c
, tx
,ty2
),
315 video::S3DVertex(vx
,vy2
,-0.5, 1,0,0, c
, tx
,ty2
),
317 u16 indices
[6] = {0,1,2,2,3,0};
318 buf
->append(vertices
, 4, indices
, 6);
321 if (!scancol
[y
* wstep
] && scancol
[y
* wstep
+ 1]) {
323 while (!scancol
[yy
* wstep
] && scancol
[yy
* wstep
+ 1]) {
326 f32 vx
= (x
+ eps
) / (f32
) twidth
- 0.5;
327 f32 vy1
= 0.5 - (y
- eps
) / (f32
) theight
;
328 f32 vy2
= 0.5 - (yy
+ eps
) / (f32
) theight
;
329 f32 tx
= (x
+ 0.5) / (f32
) twidth
;
330 f32 ty1
= y
/ (f32
) theight
;
331 f32 ty2
= yy
/ (f32
) theight
;
332 video::S3DVertex vertices
[8] = {
333 video::S3DVertex(vx
,vy1
,-0.5, -1,0,0, c
, tx
,ty1
),
334 video::S3DVertex(vx
,vy2
,-0.5, -1,0,0, c
, tx
,ty2
),
335 video::S3DVertex(vx
,vy2
,+0.5, -1,0,0, c
, tx
,ty2
),
336 video::S3DVertex(vx
,vy1
,+0.5, -1,0,0, c
, tx
,ty1
),
338 u16 indices
[6] = {0,1,2,2,3,0};
339 buf
->append(vertices
, 4, indices
, 6);
348 scene::SMesh
*mesh
= new scene::SMesh();
349 mesh
->addMeshBuffer(buf
);
351 scene::SAnimatedMesh
*anim_mesh
= new scene::SAnimatedMesh(mesh
);
356 scene::IAnimatedMesh
* createExtrudedMesh(video::ITexture
*texture
,
357 video::IVideoDriver
*driver
, v3f scale
)
359 scene::IAnimatedMesh
*mesh
= NULL
;
360 core::dimension2d
<u32
> size
= texture
->getSize();
361 video::ECOLOR_FORMAT format
= texture
->getColorFormat();
362 if (format
== video::ECF_A8R8G8B8
) {
363 // Texture is in the correct color format, we can pass it
364 // to extrudeARGB right away.
365 void *data
= texture
->lock(MY_ETLM_READ_ONLY
);
368 mesh
= extrudeARGB(size
.Width
, size
.Height
, (u8
*) data
);
371 video::IImage
*img1
= driver
->createImageFromData(format
, size
, texture
->lock(MY_ETLM_READ_ONLY
));
375 // img1 is in the texture's color format, convert to 8-bit ARGB
376 video::IImage
*img2
= driver
->createImage(video::ECF_A8R8G8B8
, size
);
380 mesh
= extrudeARGB(size
.Width
, size
.Height
, (u8
*) img2
->lock());
387 // Set default material
388 if (mesh
&& mesh
->getMeshBufferCount() > 0) {
389 scene::IMeshBuffer
*buf
= mesh
->getMeshBuffer(0);
391 buf
->getMaterial().setTexture(0, texture
);
392 buf
->getMaterial().setFlag(video::EMF_LIGHTING
, false);
393 buf
->getMaterial().setFlag(video::EMF_BILINEAR_FILTER
, false);
394 buf
->getMaterial().MaterialType
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF
;
398 scaleMesh(mesh
, scale
); // also recalculates bounding box
402 void scaleMesh(scene::IMesh
*mesh
, v3f scale
)
407 core::aabbox3d
<f32
> bbox
;
410 u16 mc
= mesh
->getMeshBufferCount();
411 for (u16 j
=0; j
<mc
; j
++) {
412 scene::IMeshBuffer
*buf
= mesh
->getMeshBuffer(j
);
415 u16 vc
= buf
->getVertexCount();
418 video::S3DVertex
*vertices
= (video::S3DVertex
*)buf
->getVertices();
421 for (u16 i
=0; i
<vc
; i
++) {
422 vertices
[i
].Pos
*= scale
;
424 buf
->recalculateBoundingBox();
426 // calculate total bounding box
428 bbox
= buf
->getBoundingBox();
430 bbox
.addInternalBox(buf
->getBoundingBox());
433 mesh
->setBoundingBox(bbox
);
436 void translateMesh(scene::IMesh
*mesh
, v3f vec
)
441 core::aabbox3d
<f32
> bbox
;
444 u16 mc
= mesh
->getMeshBufferCount();
445 for (u16 j
=0; j
<mc
; j
++) {
446 scene::IMeshBuffer
*buf
= mesh
->getMeshBuffer(j
);
449 u16 vc
= buf
->getVertexCount();
452 video::S3DVertex
*vertices
= (video::S3DVertex
*)buf
->getVertices();
455 for (u16 i
=0; i
<vc
; i
++) {
456 vertices
[i
].Pos
+= vec
;
458 buf
->recalculateBoundingBox();
460 // calculate total bounding box
462 bbox
= buf
->getBoundingBox();
464 bbox
.addInternalBox(buf
->getBoundingBox());
467 mesh
->setBoundingBox(bbox
);
470 void setMeshColor(scene::IMesh
*mesh
, const video::SColor
&color
)
475 u16 mc
= mesh
->getMeshBufferCount();
476 for (u16 j
=0; j
<mc
; j
++) {
477 scene::IMeshBuffer
*buf
= mesh
->getMeshBuffer(j
);
480 u16 vc
= buf
->getVertexCount();
483 video::S3DVertex
*vertices
= (video::S3DVertex
*)buf
->getVertices();
486 for (u16 i
=0; i
<vc
; i
++) {
487 vertices
[i
].Color
= color
;
492 void setMeshColorByNormalXYZ(scene::IMesh
*mesh
,
493 const video::SColor
&colorX
,
494 const video::SColor
&colorY
,
495 const video::SColor
&colorZ
)
500 u16 mc
= mesh
->getMeshBufferCount();
501 for (u16 j
=0; j
<mc
; j
++) {
502 scene::IMeshBuffer
*buf
= mesh
->getMeshBuffer(j
);
505 u16 vc
= buf
->getVertexCount();
508 video::S3DVertex
*vertices
= (video::S3DVertex
*)buf
->getVertices();
511 for (u16 i
=0; i
<vc
; i
++) {
512 f32 x
= fabs(vertices
[i
].Normal
.X
);
513 f32 y
= fabs(vertices
[i
].Normal
.Y
);
514 f32 z
= fabs(vertices
[i
].Normal
.Z
);
515 if (x
>= y
&& x
>= z
) {
516 vertices
[i
].Color
= colorX
;
518 vertices
[i
].Color
= colorY
;
520 vertices
[i
].Color
= colorZ
;
526 video::ITexture
*generateTextureFromMesh(scene::IMesh
*mesh
,
527 IrrlichtDevice
*device
,
528 core::dimension2d
<u32
> dim
,
529 std::string texture_name
,
532 core::CMatrix4
<f32
> camera_projection_matrix
,
533 video::SColorf ambient_light
,
535 video::SColorf light_color
,
538 video::IVideoDriver
*driver
= device
->getVideoDriver();
539 if(driver
->queryFeature(video::EVDF_RENDER_TO_TARGET
) == false)
541 static bool warned
= false;
544 errorstream
<<"generateTextureFromMesh(): EVDF_RENDER_TO_TARGET"
545 " not supported."<<std::endl
;
551 // Create render target texture
552 video::ITexture
*rtt
= driver
->addRenderTargetTexture(
553 dim
, texture_name
.c_str(), video::ECF_A8R8G8B8
);
556 errorstream
<<"generateTextureFromMesh(): addRenderTargetTexture"
557 " returned NULL."<<std::endl
;
562 driver
->setRenderTarget(rtt
, false, true, video::SColor(0,0,0,0));
564 // Get a scene manager
565 scene::ISceneManager
*smgr_main
= device
->getSceneManager();
567 scene::ISceneManager
*smgr
= smgr_main
->createNewSceneManager();
570 scene::IMeshSceneNode
* meshnode
= smgr
->addMeshSceneNode(mesh
, NULL
, -1, v3f(0,0,0), v3f(0,0,0), v3f(1,1,1), true);
571 meshnode
->setMaterialFlag(video::EMF_LIGHTING
, true);
572 meshnode
->setMaterialFlag(video::EMF_ANTI_ALIASING
, true);
573 meshnode
->setMaterialFlag(video::EMF_BILINEAR_FILTER
, true);
575 scene::ICameraSceneNode
* camera
= smgr
->addCameraSceneNode(0,
576 camera_position
, camera_lookat
);
577 // second parameter of setProjectionMatrix (isOrthogonal) is ignored
578 camera
->setProjectionMatrix(camera_projection_matrix
, false);
580 smgr
->setAmbientLight(ambient_light
);
581 smgr
->addLightSceneNode(0, light_position
, light_color
, light_radius
);
584 driver
->beginScene(true, true, video::SColor(0,0,0,0));
588 // NOTE: The scene nodes should not be dropped, otherwise
589 // smgr->drop() segfaults
593 // Drop scene manager
596 // Unset render target
597 driver
->setRenderTarget(0, false, true, 0);
602 ExtrudedSpriteSceneNode::ExtrudedSpriteSceneNode(
603 scene::ISceneNode
* parent
,
604 scene::ISceneManager
* mgr
,
610 ISceneNode(parent
, mgr
, id
, position
, rotation
, scale
)
612 m_meshnode
= mgr
->addMeshSceneNode(NULL
, this, -1, v3f(0,0,0), v3f(0,0,0), v3f(1,1,1), true);
619 ExtrudedSpriteSceneNode::~ExtrudedSpriteSceneNode()
621 removeChild(m_meshnode
);
626 void ExtrudedSpriteSceneNode::setSprite(video::ITexture
* texture
)
628 const v3f
sprite_scale(1.0,1.0, 1.0); // width, height, thickness
630 if (texture
== NULL
) {
631 m_meshnode
->setVisible(false);
635 io::path name
= getExtrudedName(texture
);
636 scene::IMeshCache
* cache
= SceneManager
->getMeshCache();
637 scene::IAnimatedMesh
* mesh
= cache
->getMeshByName(name
);
640 // Extruded texture has been found in cache.
641 m_meshnode
->setMesh(mesh
);
645 // Texture was not yet extruded, do it now and save in cache
646 mesh
= createExtrudedMesh(texture
, SceneManager
->getVideoDriver(), sprite_scale
);
649 dstream
<< "Warning: failed to extrude sprite" << std::endl
;
650 m_meshnode
->setVisible(false);
653 cache
->addMesh(name
, mesh
);
654 m_meshnode
->setMesh(mesh
);
658 m_meshnode
->setScale(v3f(1, 1, m_thickness
));
659 m_meshnode
->getMaterial(0).setTexture(0, texture
);
660 m_meshnode
->getMaterial(0).setFlag(video::EMF_LIGHTING
, false);
661 m_meshnode
->getMaterial(0).setFlag(video::EMF_BILINEAR_FILTER
, false);
662 m_meshnode
->getMaterial(0).MaterialType
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF
;
663 m_meshnode
->setVisible(true);
665 updateLight(m_light
);
668 void ExtrudedSpriteSceneNode::setCube(const TileSpec tiles
[6])
670 const v3f
cube_scale(1.0, 1.0, 1.0);
674 m_cubemesh
= createCubeMesh(cube_scale
);
676 m_meshnode
->setMesh(m_cubemesh
);
677 m_meshnode
->setScale(v3f(1));
678 for (int i
= 0; i
< 6; ++i
)
680 // Get the tile texture and atlas transformation
681 video::ITexture
* atlas
= tiles
[i
].texture
.atlas
;
682 v2f pos
= tiles
[i
].texture
.pos
;
683 v2f size
= tiles
[i
].texture
.size
;
685 // Set material flags and texture
686 video::SMaterial
& material
= m_meshnode
->getMaterial(i
);
687 material
.setFlag(video::EMF_LIGHTING
, false);
688 material
.setFlag(video::EMF_BILINEAR_FILTER
, false);
689 tiles
[i
].applyMaterialOptions(material
);
690 material
.setTexture(0, atlas
);
691 material
.getTextureMatrix(0).setTextureTranslate(pos
.X
, pos
.Y
);
692 material
.getTextureMatrix(0).setTextureScale(size
.X
, size
.Y
);
694 m_meshnode
->setVisible(true);
696 updateLight(m_light
);
699 void ExtrudedSpriteSceneNode::setNodeBox(content_t c
)
701 const v3f
cube_scale(1.0, 1.0, 1.0);
705 std::vector
<NodeBox
> boxes
= content_features(c
).getWieldNodeBoxes();
706 m_cubemesh
= createNodeBoxMesh(boxes
,cube_scale
);
708 for (u16 i
=0; i
< boxes
.size(); i
++) {
709 for (int t
=0; t
<6; t
++) {
710 video::ITexture
* atlas
= content_features(c
).tiles
[t
].texture
.atlas
;
711 v2f pos
= content_features(c
).tiles
[t
].texture
.pos
;
712 v2f size
= content_features(c
).tiles
[t
].texture
.size
;
713 video::SMaterial
& material
= m_cubemesh
->getMeshBuffer((i
*6)+t
)->getMaterial();
714 material
.setFlag(video::EMF_LIGHTING
, false);
715 material
.setFlag(video::EMF_BILINEAR_FILTER
, false);
716 content_features(c
).tiles
[i
].applyMaterialOptions(material
);
717 material
.setTexture(0, atlas
);
718 material
.getTextureMatrix(0).setTextureTranslate(pos
.X
, pos
.Y
);
719 material
.getTextureMatrix(0).setTextureScale(size
.X
, size
.Y
);
723 m_meshnode
->setMesh(m_cubemesh
);
724 m_meshnode
->setScale(v3f(1));
726 m_meshnode
->setVisible(true);
728 updateLight(m_light
);
731 void ExtrudedSpriteSceneNode::setArm(video::ITexture
*texture
)
733 const v3f
cube_scale(0.3, 1.0, 0.3);
737 m_cubemesh
= createCubeMesh(cube_scale
);
739 m_meshnode
->setMesh(m_cubemesh
);
740 m_meshnode
->setScale(v3f(1));
742 // Get the tile texture and atlas transformation
744 texture
= g_texturesource
->getTextureRaw("character.png");
746 v2f
size(0.0625,0.125);
748 // Set material flags and texture
749 video::SMaterial
& material
= m_meshnode
->getMaterial(0);
750 material
.setFlag(video::EMF_LIGHTING
, false);
751 material
.setFlag(video::EMF_BILINEAR_FILTER
, false);
752 material
.MaterialType
= video::EMT_SOLID
;
753 material
.BackfaceCulling
= true;
754 material
.setTexture(0, texture
);
755 material
.getTextureMatrix(0).setTextureTranslate(pos
.X
, pos
.Y
);
756 material
.getTextureMatrix(0).setTextureScale(size
.X
, size
.Y
);
758 for (int i
= 1; i
< 6; ++i
) {
759 // Get the tile texture and atlas transformation
761 v2f
size(0.0625,-0.375);
763 // Set material flags and texture
764 video::SMaterial
& material
= m_meshnode
->getMaterial(i
);
765 material
.setFlag(video::EMF_LIGHTING
, false);
766 material
.setFlag(video::EMF_BILINEAR_FILTER
, false);
767 material
.MaterialType
= video::EMT_SOLID
;
768 material
.BackfaceCulling
= true;
769 material
.setTexture(0, texture
);
770 material
.getTextureMatrix(0).setTextureTranslate(pos
.X
, pos
.Y
);
771 material
.getTextureMatrix(0).setTextureScale(size
.X
, size
.Y
);
773 m_meshnode
->setVisible(true);
775 updateLight(m_light
);
778 void ExtrudedSpriteSceneNode::updateLight(u8 light
)
781 video::SColor
color(255,light
,light
,light
);
782 setMeshVerticesColor(m_meshnode
->getMesh(), color
);
785 void ExtrudedSpriteSceneNode::removeSpriteFromCache(video::ITexture
* texture
)
787 scene::IMeshCache
* cache
= SceneManager
->getMeshCache();
788 scene::IAnimatedMesh
* mesh
= cache
->getMeshByName(getExtrudedName(texture
));
790 cache
->removeMesh(mesh
);
793 void ExtrudedSpriteSceneNode::setSpriteThickness(f32 thickness
)
795 m_thickness
= thickness
;
797 m_meshnode
->setScale(v3f(1, 1, thickness
));
800 const core::aabbox3d
<f32
>& ExtrudedSpriteSceneNode::getBoundingBox() const
802 return m_meshnode
->getBoundingBox();
805 void ExtrudedSpriteSceneNode::OnRegisterSceneNode()
808 SceneManager
->registerNodeForRendering(this);
809 ISceneNode::OnRegisterSceneNode();
812 void ExtrudedSpriteSceneNode::render()
817 io::path
ExtrudedSpriteSceneNode::getExtrudedName(video::ITexture
* texture
)
819 io::path path
= texture
->getName();
820 path
.append("/[extruded]");