diff options
Diffstat (limited to 'libraries/irrlicht-1.8/source/Irrlicht/CShadowVolumeSceneNode.cpp')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/CShadowVolumeSceneNode.cpp | 838 |
1 files changed, 419 insertions, 419 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CShadowVolumeSceneNode.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CShadowVolumeSceneNode.cpp index 55c802a..0134edd 100644 --- a/libraries/irrlicht-1.8/source/Irrlicht/CShadowVolumeSceneNode.cpp +++ b/libraries/irrlicht-1.8/source/Irrlicht/CShadowVolumeSceneNode.cpp | |||
@@ -1,419 +1,419 @@ | |||
1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt | 1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt |
2 | // This file is part of the "Irrlicht Engine". | 2 | // This file is part of the "Irrlicht Engine". |
3 | // For conditions of distribution and use, see copyright notice in irrlicht.h | 3 | // For conditions of distribution and use, see copyright notice in irrlicht.h |
4 | 4 | ||
5 | #include "CShadowVolumeSceneNode.h" | 5 | #include "CShadowVolumeSceneNode.h" |
6 | #include "ISceneManager.h" | 6 | #include "ISceneManager.h" |
7 | #include "IMesh.h" | 7 | #include "IMesh.h" |
8 | #include "IVideoDriver.h" | 8 | #include "IVideoDriver.h" |
9 | #include "ICameraSceneNode.h" | 9 | #include "ICameraSceneNode.h" |
10 | #include "SViewFrustum.h" | 10 | #include "SViewFrustum.h" |
11 | #include "SLight.h" | 11 | #include "SLight.h" |
12 | #include "os.h" | 12 | #include "os.h" |
13 | 13 | ||
14 | namespace irr | 14 | namespace irr |
15 | { | 15 | { |
16 | namespace scene | 16 | namespace scene |
17 | { | 17 | { |
18 | 18 | ||
19 | 19 | ||
20 | //! constructor | 20 | //! constructor |
21 | CShadowVolumeSceneNode::CShadowVolumeSceneNode(const IMesh* shadowMesh, ISceneNode* parent, | 21 | CShadowVolumeSceneNode::CShadowVolumeSceneNode(const IMesh* shadowMesh, ISceneNode* parent, |
22 | ISceneManager* mgr, s32 id, bool zfailmethod, f32 infinity) | 22 | ISceneManager* mgr, s32 id, bool zfailmethod, f32 infinity) |
23 | : IShadowVolumeSceneNode(parent, mgr, id), | 23 | : IShadowVolumeSceneNode(parent, mgr, id), |
24 | ShadowMesh(0), IndexCount(0), VertexCount(0), ShadowVolumesUsed(0), | 24 | ShadowMesh(0), IndexCount(0), VertexCount(0), ShadowVolumesUsed(0), |
25 | Infinity(infinity), UseZFailMethod(zfailmethod) | 25 | Infinity(infinity), UseZFailMethod(zfailmethod) |
26 | { | 26 | { |
27 | #ifdef _DEBUG | 27 | #ifdef _DEBUG |
28 | setDebugName("CShadowVolumeSceneNode"); | 28 | setDebugName("CShadowVolumeSceneNode"); |
29 | #endif | 29 | #endif |
30 | setShadowMesh(shadowMesh); | 30 | setShadowMesh(shadowMesh); |
31 | setAutomaticCulling(scene::EAC_OFF); | 31 | setAutomaticCulling(scene::EAC_OFF); |
32 | } | 32 | } |
33 | 33 | ||
34 | 34 | ||
35 | //! destructor | 35 | //! destructor |
36 | CShadowVolumeSceneNode::~CShadowVolumeSceneNode() | 36 | CShadowVolumeSceneNode::~CShadowVolumeSceneNode() |
37 | { | 37 | { |
38 | if (ShadowMesh) | 38 | if (ShadowMesh) |
39 | ShadowMesh->drop(); | 39 | ShadowMesh->drop(); |
40 | } | 40 | } |
41 | 41 | ||
42 | 42 | ||
43 | void CShadowVolumeSceneNode::createShadowVolume(const core::vector3df& light, bool isDirectional) | 43 | void CShadowVolumeSceneNode::createShadowVolume(const core::vector3df& light, bool isDirectional) |
44 | { | 44 | { |
45 | SShadowVolume* svp = 0; | 45 | SShadowVolume* svp = 0; |
46 | core::aabbox3d<f32>* bb = 0; | 46 | core::aabbox3d<f32>* bb = 0; |
47 | 47 | ||
48 | // builds the shadow volume and adds it to the shadow volume list. | 48 | // builds the shadow volume and adds it to the shadow volume list. |
49 | 49 | ||
50 | if (ShadowVolumes.size() > ShadowVolumesUsed) | 50 | if (ShadowVolumes.size() > ShadowVolumesUsed) |
51 | { | 51 | { |
52 | // get the next unused buffer | 52 | // get the next unused buffer |
53 | 53 | ||
54 | svp = &ShadowVolumes[ShadowVolumesUsed]; | 54 | svp = &ShadowVolumes[ShadowVolumesUsed]; |
55 | svp->set_used(0); | 55 | svp->set_used(0); |
56 | 56 | ||
57 | bb = &ShadowBBox[ShadowVolumesUsed]; | 57 | bb = &ShadowBBox[ShadowVolumesUsed]; |
58 | } | 58 | } |
59 | else | 59 | else |
60 | { | 60 | { |
61 | ShadowVolumes.push_back(SShadowVolume()); | 61 | ShadowVolumes.push_back(SShadowVolume()); |
62 | svp = &ShadowVolumes.getLast(); | 62 | svp = &ShadowVolumes.getLast(); |
63 | 63 | ||
64 | ShadowBBox.push_back(core::aabbox3d<f32>()); | 64 | ShadowBBox.push_back(core::aabbox3d<f32>()); |
65 | bb = &ShadowBBox.getLast(); | 65 | bb = &ShadowBBox.getLast(); |
66 | } | 66 | } |
67 | svp->reallocate(IndexCount*5); | 67 | svp->reallocate(IndexCount*5); |
68 | ++ShadowVolumesUsed; | 68 | ++ShadowVolumesUsed; |
69 | 69 | ||
70 | // We use triangle lists | 70 | // We use triangle lists |
71 | Edges.set_used(IndexCount*2); | 71 | Edges.set_used(IndexCount*2); |
72 | u32 numEdges = 0; | 72 | u32 numEdges = 0; |
73 | 73 | ||
74 | numEdges=createEdgesAndCaps(light, svp, bb); | 74 | numEdges=createEdgesAndCaps(light, svp, bb); |
75 | 75 | ||
76 | // for all edges add the near->far quads | 76 | // for all edges add the near->far quads |
77 | for (u32 i=0; i<numEdges; ++i) | 77 | for (u32 i=0; i<numEdges; ++i) |
78 | { | 78 | { |
79 | const core::vector3df &v1 = Vertices[Edges[2*i+0]]; | 79 | const core::vector3df &v1 = Vertices[Edges[2*i+0]]; |
80 | const core::vector3df &v2 = Vertices[Edges[2*i+1]]; | 80 | const core::vector3df &v2 = Vertices[Edges[2*i+1]]; |
81 | const core::vector3df v3(v1+(v1 - light).normalize()*Infinity); | 81 | const core::vector3df v3(v1+(v1 - light).normalize()*Infinity); |
82 | const core::vector3df v4(v2+(v2 - light).normalize()*Infinity); | 82 | const core::vector3df v4(v2+(v2 - light).normalize()*Infinity); |
83 | 83 | ||
84 | // Add a quad (two triangles) to the vertex list | 84 | // Add a quad (two triangles) to the vertex list |
85 | #ifdef _DEBUG | 85 | #ifdef _DEBUG |
86 | if (svp->size() >= svp->allocated_size()-5) | 86 | if (svp->size() >= svp->allocated_size()-5) |
87 | os::Printer::log("Allocation too small.", ELL_DEBUG); | 87 | os::Printer::log("Allocation too small.", ELL_DEBUG); |
88 | #endif | 88 | #endif |
89 | svp->push_back(v1); | 89 | svp->push_back(v1); |
90 | svp->push_back(v2); | 90 | svp->push_back(v2); |
91 | svp->push_back(v3); | 91 | svp->push_back(v3); |
92 | 92 | ||
93 | svp->push_back(v2); | 93 | svp->push_back(v2); |
94 | svp->push_back(v4); | 94 | svp->push_back(v4); |
95 | svp->push_back(v3); | 95 | svp->push_back(v3); |
96 | } | 96 | } |
97 | } | 97 | } |
98 | 98 | ||
99 | 99 | ||
100 | #define IRR_USE_ADJACENCY | 100 | #define IRR_USE_ADJACENCY |
101 | #define IRR_USE_REVERSE_EXTRUDED | 101 | #define IRR_USE_REVERSE_EXTRUDED |
102 | 102 | ||
103 | u32 CShadowVolumeSceneNode::createEdgesAndCaps(const core::vector3df& light, | 103 | u32 CShadowVolumeSceneNode::createEdgesAndCaps(const core::vector3df& light, |
104 | SShadowVolume* svp, core::aabbox3d<f32>* bb) | 104 | SShadowVolume* svp, core::aabbox3d<f32>* bb) |
105 | { | 105 | { |
106 | u32 numEdges=0; | 106 | u32 numEdges=0; |
107 | const u32 faceCount = IndexCount / 3; | 107 | const u32 faceCount = IndexCount / 3; |
108 | 108 | ||
109 | if(faceCount >= 1) | 109 | if(faceCount >= 1) |
110 | bb->reset(Vertices[Indices[0]]); | 110 | bb->reset(Vertices[Indices[0]]); |
111 | else | 111 | else |
112 | bb->reset(0,0,0); | 112 | bb->reset(0,0,0); |
113 | 113 | ||
114 | // Check every face if it is front or back facing the light. | 114 | // Check every face if it is front or back facing the light. |
115 | for (u32 i=0; i<faceCount; ++i) | 115 | for (u32 i=0; i<faceCount; ++i) |
116 | { | 116 | { |
117 | const core::vector3df v0 = Vertices[Indices[3*i+0]]; | 117 | const core::vector3df v0 = Vertices[Indices[3*i+0]]; |
118 | const core::vector3df v1 = Vertices[Indices[3*i+1]]; | 118 | const core::vector3df v1 = Vertices[Indices[3*i+1]]; |
119 | const core::vector3df v2 = Vertices[Indices[3*i+2]]; | 119 | const core::vector3df v2 = Vertices[Indices[3*i+2]]; |
120 | 120 | ||
121 | #ifdef IRR_USE_REVERSE_EXTRUDED | 121 | #ifdef IRR_USE_REVERSE_EXTRUDED |
122 | FaceData[i]=core::triangle3df(v0,v1,v2).isFrontFacing(light); | 122 | FaceData[i]=core::triangle3df(v0,v1,v2).isFrontFacing(light); |
123 | #else | 123 | #else |
124 | FaceData[i]=core::triangle3df(v2,v1,v0).isFrontFacing(light); | 124 | FaceData[i]=core::triangle3df(v2,v1,v0).isFrontFacing(light); |
125 | #endif | 125 | #endif |
126 | 126 | ||
127 | if (UseZFailMethod && FaceData[i]) | 127 | if (UseZFailMethod && FaceData[i]) |
128 | { | 128 | { |
129 | #ifdef _DEBUG | 129 | #ifdef _DEBUG |
130 | if (svp->size() >= svp->allocated_size()-5) | 130 | if (svp->size() >= svp->allocated_size()-5) |
131 | os::Printer::log("Allocation too small.", ELL_DEBUG); | 131 | os::Printer::log("Allocation too small.", ELL_DEBUG); |
132 | #endif | 132 | #endif |
133 | // add front cap from light-facing faces | 133 | // add front cap from light-facing faces |
134 | svp->push_back(v2); | 134 | svp->push_back(v2); |
135 | svp->push_back(v1); | 135 | svp->push_back(v1); |
136 | svp->push_back(v0); | 136 | svp->push_back(v0); |
137 | 137 | ||
138 | // add back cap | 138 | // add back cap |
139 | const core::vector3df i0 = v0+(v0-light).normalize()*Infinity; | 139 | const core::vector3df i0 = v0+(v0-light).normalize()*Infinity; |
140 | const core::vector3df i1 = v1+(v1-light).normalize()*Infinity; | 140 | const core::vector3df i1 = v1+(v1-light).normalize()*Infinity; |
141 | const core::vector3df i2 = v2+(v2-light).normalize()*Infinity; | 141 | const core::vector3df i2 = v2+(v2-light).normalize()*Infinity; |
142 | 142 | ||
143 | svp->push_back(i0); | 143 | svp->push_back(i0); |
144 | svp->push_back(i1); | 144 | svp->push_back(i1); |
145 | svp->push_back(i2); | 145 | svp->push_back(i2); |
146 | 146 | ||
147 | bb->addInternalPoint(i0); | 147 | bb->addInternalPoint(i0); |
148 | bb->addInternalPoint(i1); | 148 | bb->addInternalPoint(i1); |
149 | bb->addInternalPoint(i2); | 149 | bb->addInternalPoint(i2); |
150 | } | 150 | } |
151 | } | 151 | } |
152 | 152 | ||
153 | // Create edges | 153 | // Create edges |
154 | for (u32 i=0; i<faceCount; ++i) | 154 | for (u32 i=0; i<faceCount; ++i) |
155 | { | 155 | { |
156 | // check all front facing faces | 156 | // check all front facing faces |
157 | if (FaceData[i] == true) | 157 | if (FaceData[i] == true) |
158 | { | 158 | { |
159 | const u16 wFace0 = Indices[3*i+0]; | 159 | const u16 wFace0 = Indices[3*i+0]; |
160 | const u16 wFace1 = Indices[3*i+1]; | 160 | const u16 wFace1 = Indices[3*i+1]; |
161 | const u16 wFace2 = Indices[3*i+2]; | 161 | const u16 wFace2 = Indices[3*i+2]; |
162 | 162 | ||
163 | const u16 adj0 = Adjacency[3*i+0]; | 163 | const u16 adj0 = Adjacency[3*i+0]; |
164 | const u16 adj1 = Adjacency[3*i+1]; | 164 | const u16 adj1 = Adjacency[3*i+1]; |
165 | const u16 adj2 = Adjacency[3*i+2]; | 165 | const u16 adj2 = Adjacency[3*i+2]; |
166 | 166 | ||
167 | // add edges if face is adjacent to back-facing face | 167 | // add edges if face is adjacent to back-facing face |
168 | // or if no adjacent face was found | 168 | // or if no adjacent face was found |
169 | #ifdef IRR_USE_ADJACENCY | 169 | #ifdef IRR_USE_ADJACENCY |
170 | if (adj0 == i || FaceData[adj0] == false) | 170 | if (adj0 == i || FaceData[adj0] == false) |
171 | #endif | 171 | #endif |
172 | { | 172 | { |
173 | // add edge v0-v1 | 173 | // add edge v0-v1 |
174 | Edges[2*numEdges+0] = wFace0; | 174 | Edges[2*numEdges+0] = wFace0; |
175 | Edges[2*numEdges+1] = wFace1; | 175 | Edges[2*numEdges+1] = wFace1; |
176 | ++numEdges; | 176 | ++numEdges; |
177 | } | 177 | } |
178 | 178 | ||
179 | #ifdef IRR_USE_ADJACENCY | 179 | #ifdef IRR_USE_ADJACENCY |
180 | if (adj1 == i || FaceData[adj1] == false) | 180 | if (adj1 == i || FaceData[adj1] == false) |
181 | #endif | 181 | #endif |
182 | { | 182 | { |
183 | // add edge v1-v2 | 183 | // add edge v1-v2 |
184 | Edges[2*numEdges+0] = wFace1; | 184 | Edges[2*numEdges+0] = wFace1; |
185 | Edges[2*numEdges+1] = wFace2; | 185 | Edges[2*numEdges+1] = wFace2; |
186 | ++numEdges; | 186 | ++numEdges; |
187 | } | 187 | } |
188 | 188 | ||
189 | #ifdef IRR_USE_ADJACENCY | 189 | #ifdef IRR_USE_ADJACENCY |
190 | if (adj2 == i || FaceData[adj2] == false) | 190 | if (adj2 == i || FaceData[adj2] == false) |
191 | #endif | 191 | #endif |
192 | { | 192 | { |
193 | // add edge v2-v0 | 193 | // add edge v2-v0 |
194 | Edges[2*numEdges+0] = wFace2; | 194 | Edges[2*numEdges+0] = wFace2; |
195 | Edges[2*numEdges+1] = wFace0; | 195 | Edges[2*numEdges+1] = wFace0; |
196 | ++numEdges; | 196 | ++numEdges; |
197 | } | 197 | } |
198 | } | 198 | } |
199 | } | 199 | } |
200 | return numEdges; | 200 | return numEdges; |
201 | } | 201 | } |
202 | 202 | ||
203 | 203 | ||
204 | void CShadowVolumeSceneNode::setShadowMesh(const IMesh* mesh) | 204 | void CShadowVolumeSceneNode::setShadowMesh(const IMesh* mesh) |
205 | { | 205 | { |
206 | if (ShadowMesh == mesh) | 206 | if (ShadowMesh == mesh) |
207 | return; | 207 | return; |
208 | if (ShadowMesh) | 208 | if (ShadowMesh) |
209 | ShadowMesh->drop(); | 209 | ShadowMesh->drop(); |
210 | ShadowMesh = mesh; | 210 | ShadowMesh = mesh; |
211 | if (ShadowMesh) | 211 | if (ShadowMesh) |
212 | { | 212 | { |
213 | ShadowMesh->grab(); | 213 | ShadowMesh->grab(); |
214 | Box = ShadowMesh->getBoundingBox(); | 214 | Box = ShadowMesh->getBoundingBox(); |
215 | } | 215 | } |
216 | } | 216 | } |
217 | 217 | ||
218 | 218 | ||
219 | void CShadowVolumeSceneNode::updateShadowVolumes() | 219 | void CShadowVolumeSceneNode::updateShadowVolumes() |
220 | { | 220 | { |
221 | const u32 oldIndexCount = IndexCount; | 221 | const u32 oldIndexCount = IndexCount; |
222 | const u32 oldVertexCount = VertexCount; | 222 | const u32 oldVertexCount = VertexCount; |
223 | 223 | ||
224 | const IMesh* const mesh = ShadowMesh; | 224 | const IMesh* const mesh = ShadowMesh; |
225 | if (!mesh) | 225 | if (!mesh) |
226 | return; | 226 | return; |
227 | 227 | ||
228 | // create as much shadow volumes as there are lights but | 228 | // create as much shadow volumes as there are lights but |
229 | // do not ignore the max light settings. | 229 | // do not ignore the max light settings. |
230 | const u32 lightCount = SceneManager->getVideoDriver()->getDynamicLightCount(); | 230 | const u32 lightCount = SceneManager->getVideoDriver()->getDynamicLightCount(); |
231 | if (!lightCount) | 231 | if (!lightCount) |
232 | return; | 232 | return; |
233 | 233 | ||
234 | // calculate total amount of vertices and indices | 234 | // calculate total amount of vertices and indices |
235 | 235 | ||
236 | VertexCount = 0; | 236 | VertexCount = 0; |
237 | IndexCount = 0; | 237 | IndexCount = 0; |
238 | ShadowVolumesUsed = 0; | 238 | ShadowVolumesUsed = 0; |
239 | 239 | ||
240 | u32 i; | 240 | u32 i; |
241 | u32 totalVertices = 0; | 241 | u32 totalVertices = 0; |
242 | u32 totalIndices = 0; | 242 | u32 totalIndices = 0; |
243 | const u32 bufcnt = mesh->getMeshBufferCount(); | 243 | const u32 bufcnt = mesh->getMeshBufferCount(); |
244 | 244 | ||
245 | for (i=0; i<bufcnt; ++i) | 245 | for (i=0; i<bufcnt; ++i) |
246 | { | 246 | { |
247 | const IMeshBuffer* buf = mesh->getMeshBuffer(i); | 247 | const IMeshBuffer* buf = mesh->getMeshBuffer(i); |
248 | totalIndices += buf->getIndexCount(); | 248 | totalIndices += buf->getIndexCount(); |
249 | totalVertices += buf->getVertexCount(); | 249 | totalVertices += buf->getVertexCount(); |
250 | } | 250 | } |
251 | 251 | ||
252 | // allocate memory if necessary | 252 | // allocate memory if necessary |
253 | 253 | ||
254 | Vertices.set_used(totalVertices); | 254 | Vertices.set_used(totalVertices); |
255 | Indices.set_used(totalIndices); | 255 | Indices.set_used(totalIndices); |
256 | FaceData.set_used(totalIndices / 3); | 256 | FaceData.set_used(totalIndices / 3); |
257 | 257 | ||
258 | // copy mesh | 258 | // copy mesh |
259 | for (i=0; i<bufcnt; ++i) | 259 | for (i=0; i<bufcnt; ++i) |
260 | { | 260 | { |
261 | const IMeshBuffer* buf = mesh->getMeshBuffer(i); | 261 | const IMeshBuffer* buf = mesh->getMeshBuffer(i); |
262 | 262 | ||
263 | const u16* idxp = buf->getIndices(); | 263 | const u16* idxp = buf->getIndices(); |
264 | const u16* idxpend = idxp + buf->getIndexCount(); | 264 | const u16* idxpend = idxp + buf->getIndexCount(); |
265 | for (; idxp!=idxpend; ++idxp) | 265 | for (; idxp!=idxpend; ++idxp) |
266 | Indices[IndexCount++] = *idxp + VertexCount; | 266 | Indices[IndexCount++] = *idxp + VertexCount; |
267 | 267 | ||
268 | const u32 vtxcnt = buf->getVertexCount(); | 268 | const u32 vtxcnt = buf->getVertexCount(); |
269 | for (u32 j=0; j<vtxcnt; ++j) | 269 | for (u32 j=0; j<vtxcnt; ++j) |
270 | Vertices[VertexCount++] = buf->getPosition(j); | 270 | Vertices[VertexCount++] = buf->getPosition(j); |
271 | } | 271 | } |
272 | 272 | ||
273 | // recalculate adjacency if necessary | 273 | // recalculate adjacency if necessary |
274 | if (oldVertexCount != VertexCount || oldIndexCount != IndexCount) | 274 | if (oldVertexCount != VertexCount || oldIndexCount != IndexCount) |
275 | calculateAdjacency(); | 275 | calculateAdjacency(); |
276 | 276 | ||
277 | core::matrix4 mat = Parent->getAbsoluteTransformation(); | 277 | core::matrix4 mat = Parent->getAbsoluteTransformation(); |
278 | mat.makeInverse(); | 278 | mat.makeInverse(); |
279 | const core::vector3df parentpos = Parent->getAbsolutePosition(); | 279 | const core::vector3df parentpos = Parent->getAbsolutePosition(); |
280 | 280 | ||
281 | // TODO: Only correct for point lights. | 281 | // TODO: Only correct for point lights. |
282 | for (i=0; i<lightCount; ++i) | 282 | for (i=0; i<lightCount; ++i) |
283 | { | 283 | { |
284 | const video::SLight& dl = SceneManager->getVideoDriver()->getDynamicLight(i); | 284 | const video::SLight& dl = SceneManager->getVideoDriver()->getDynamicLight(i); |
285 | core::vector3df lpos = dl.Position; | 285 | core::vector3df lpos = dl.Position; |
286 | if (dl.CastShadows && | 286 | if (dl.CastShadows && |
287 | fabs((lpos - parentpos).getLengthSQ()) <= (dl.Radius*dl.Radius*4.0f)) | 287 | fabs((lpos - parentpos).getLengthSQ()) <= (dl.Radius*dl.Radius*4.0f)) |
288 | { | 288 | { |
289 | mat.transformVect(lpos); | 289 | mat.transformVect(lpos); |
290 | createShadowVolume(lpos); | 290 | createShadowVolume(lpos); |
291 | } | 291 | } |
292 | } | 292 | } |
293 | } | 293 | } |
294 | 294 | ||
295 | 295 | ||
296 | //! pre render method | 296 | //! pre render method |
297 | void CShadowVolumeSceneNode::OnRegisterSceneNode() | 297 | void CShadowVolumeSceneNode::OnRegisterSceneNode() |
298 | { | 298 | { |
299 | if (IsVisible) | 299 | if (IsVisible) |
300 | { | 300 | { |
301 | SceneManager->registerNodeForRendering(this, scene::ESNRP_SHADOW); | 301 | SceneManager->registerNodeForRendering(this, scene::ESNRP_SHADOW); |
302 | ISceneNode::OnRegisterSceneNode(); | 302 | ISceneNode::OnRegisterSceneNode(); |
303 | } | 303 | } |
304 | } | 304 | } |
305 | 305 | ||
306 | //! renders the node. | 306 | //! renders the node. |
307 | void CShadowVolumeSceneNode::render() | 307 | void CShadowVolumeSceneNode::render() |
308 | { | 308 | { |
309 | video::IVideoDriver* driver = SceneManager->getVideoDriver(); | 309 | video::IVideoDriver* driver = SceneManager->getVideoDriver(); |
310 | 310 | ||
311 | if (!ShadowVolumesUsed || !driver) | 311 | if (!ShadowVolumesUsed || !driver) |
312 | return; | 312 | return; |
313 | 313 | ||
314 | driver->setTransform(video::ETS_WORLD, Parent->getAbsoluteTransformation()); | 314 | driver->setTransform(video::ETS_WORLD, Parent->getAbsoluteTransformation()); |
315 | 315 | ||
316 | for (u32 i=0; i<ShadowVolumesUsed; ++i) | 316 | for (u32 i=0; i<ShadowVolumesUsed; ++i) |
317 | { | 317 | { |
318 | bool drawShadow = true; | 318 | bool drawShadow = true; |
319 | 319 | ||
320 | if (UseZFailMethod && SceneManager->getActiveCamera()) | 320 | if (UseZFailMethod && SceneManager->getActiveCamera()) |
321 | { | 321 | { |
322 | // Disable shadows drawing, when back cap is behind of ZFar plane. | 322 | // Disable shadows drawing, when back cap is behind of ZFar plane. |
323 | 323 | ||
324 | SViewFrustum frust = *SceneManager->getActiveCamera()->getViewFrustum(); | 324 | SViewFrustum frust = *SceneManager->getActiveCamera()->getViewFrustum(); |
325 | 325 | ||
326 | core::matrix4 invTrans(Parent->getAbsoluteTransformation(), core::matrix4::EM4CONST_INVERSE); | 326 | core::matrix4 invTrans(Parent->getAbsoluteTransformation(), core::matrix4::EM4CONST_INVERSE); |
327 | frust.transform(invTrans); | 327 | frust.transform(invTrans); |
328 | 328 | ||
329 | core::vector3df edges[8]; | 329 | core::vector3df edges[8]; |
330 | ShadowBBox[i].getEdges(edges); | 330 | ShadowBBox[i].getEdges(edges); |
331 | 331 | ||
332 | core::vector3df largestEdge = edges[0]; | 332 | core::vector3df largestEdge = edges[0]; |
333 | f32 maxDistance = core::vector3df(SceneManager->getActiveCamera()->getPosition() - edges[0]).getLength(); | 333 | f32 maxDistance = core::vector3df(SceneManager->getActiveCamera()->getPosition() - edges[0]).getLength(); |
334 | f32 curDistance = 0.f; | 334 | f32 curDistance = 0.f; |
335 | 335 | ||
336 | for(int j = 1; j < 8; ++j) | 336 | for(int j = 1; j < 8; ++j) |
337 | { | 337 | { |
338 | curDistance = core::vector3df(SceneManager->getActiveCamera()->getPosition() - edges[j]).getLength(); | 338 | curDistance = core::vector3df(SceneManager->getActiveCamera()->getPosition() - edges[j]).getLength(); |
339 | 339 | ||
340 | if(curDistance > maxDistance) | 340 | if(curDistance > maxDistance) |
341 | { | 341 | { |
342 | maxDistance = curDistance; | 342 | maxDistance = curDistance; |
343 | largestEdge = edges[j]; | 343 | largestEdge = edges[j]; |
344 | } | 344 | } |
345 | } | 345 | } |
346 | 346 | ||
347 | if (!(frust.planes[scene::SViewFrustum::VF_FAR_PLANE].classifyPointRelation(largestEdge) != core::ISREL3D_FRONT)) | 347 | if (!(frust.planes[scene::SViewFrustum::VF_FAR_PLANE].classifyPointRelation(largestEdge) != core::ISREL3D_FRONT)) |
348 | drawShadow = false; | 348 | drawShadow = false; |
349 | } | 349 | } |
350 | 350 | ||
351 | if(drawShadow) | 351 | if(drawShadow) |
352 | driver->drawStencilShadowVolume(ShadowVolumes[i], UseZFailMethod, DebugDataVisible); | 352 | driver->drawStencilShadowVolume(ShadowVolumes[i], UseZFailMethod, DebugDataVisible); |
353 | else | 353 | else |
354 | { | 354 | { |
355 | core::array<core::vector3df> triangles; | 355 | core::array<core::vector3df> triangles; |
356 | driver->drawStencilShadowVolume(triangles, UseZFailMethod, DebugDataVisible); | 356 | driver->drawStencilShadowVolume(triangles, UseZFailMethod, DebugDataVisible); |
357 | } | 357 | } |
358 | } | 358 | } |
359 | } | 359 | } |
360 | 360 | ||
361 | 361 | ||
362 | //! returns the axis aligned bounding box of this node | 362 | //! returns the axis aligned bounding box of this node |
363 | const core::aabbox3d<f32>& CShadowVolumeSceneNode::getBoundingBox() const | 363 | const core::aabbox3d<f32>& CShadowVolumeSceneNode::getBoundingBox() const |
364 | { | 364 | { |
365 | return Box; | 365 | return Box; |
366 | } | 366 | } |
367 | 367 | ||
368 | 368 | ||
369 | //! Generates adjacency information based on mesh indices. | 369 | //! Generates adjacency information based on mesh indices. |
370 | void CShadowVolumeSceneNode::calculateAdjacency() | 370 | void CShadowVolumeSceneNode::calculateAdjacency() |
371 | { | 371 | { |
372 | Adjacency.set_used(IndexCount); | 372 | Adjacency.set_used(IndexCount); |
373 | 373 | ||
374 | // go through all faces and fetch their three neighbours | 374 | // go through all faces and fetch their three neighbours |
375 | for (u32 f=0; f<IndexCount; f+=3) | 375 | for (u32 f=0; f<IndexCount; f+=3) |
376 | { | 376 | { |
377 | for (u32 edge = 0; edge<3; ++edge) | 377 | for (u32 edge = 0; edge<3; ++edge) |
378 | { | 378 | { |
379 | const core::vector3df& v1 = Vertices[Indices[f+edge]]; | 379 | const core::vector3df& v1 = Vertices[Indices[f+edge]]; |
380 | const core::vector3df& v2 = Vertices[Indices[f+((edge+1)%3)]]; | 380 | const core::vector3df& v2 = Vertices[Indices[f+((edge+1)%3)]]; |
381 | 381 | ||
382 | // now we search an_O_ther _F_ace with these two | 382 | // now we search an_O_ther _F_ace with these two |
383 | // vertices, which is not the current face. | 383 | // vertices, which is not the current face. |
384 | u32 of; | 384 | u32 of; |
385 | 385 | ||
386 | for (of=0; of<IndexCount; of+=3) | 386 | for (of=0; of<IndexCount; of+=3) |
387 | { | 387 | { |
388 | // only other faces | 388 | // only other faces |
389 | if (of != f) | 389 | if (of != f) |
390 | { | 390 | { |
391 | bool cnt1 = false; | 391 | bool cnt1 = false; |
392 | bool cnt2 = false; | 392 | bool cnt2 = false; |
393 | 393 | ||
394 | for (s32 e=0; e<3; ++e) | 394 | for (s32 e=0; e<3; ++e) |
395 | { | 395 | { |
396 | if (v1.equals(Vertices[Indices[of+e]])) | 396 | if (v1.equals(Vertices[Indices[of+e]])) |
397 | cnt1=true; | 397 | cnt1=true; |
398 | 398 | ||
399 | if (v2.equals(Vertices[Indices[of+e]])) | 399 | if (v2.equals(Vertices[Indices[of+e]])) |
400 | cnt2=true; | 400 | cnt2=true; |
401 | } | 401 | } |
402 | // one match for each vertex, i.e. edge is the same | 402 | // one match for each vertex, i.e. edge is the same |
403 | if (cnt1 && cnt2) | 403 | if (cnt1 && cnt2) |
404 | break; | 404 | break; |
405 | } | 405 | } |
406 | } | 406 | } |
407 | 407 | ||
408 | // no adjacent edges -> store face number, else store adjacent face | 408 | // no adjacent edges -> store face number, else store adjacent face |
409 | if (of >= IndexCount) | 409 | if (of >= IndexCount) |
410 | Adjacency[f + edge] = f/3; | 410 | Adjacency[f + edge] = f/3; |
411 | else | 411 | else |
412 | Adjacency[f + edge] = of/3; | 412 | Adjacency[f + edge] = of/3; |
413 | } | 413 | } |
414 | } | 414 | } |
415 | } | 415 | } |
416 | 416 | ||
417 | 417 | ||
418 | } // end namespace scene | 418 | } // end namespace scene |
419 | } // end namespace irr | 419 | } // end namespace irr |