rev |
line source |
nuclear@0
|
1 #include <string>
|
nuclear@0
|
2 #include "3dscene.h"
|
nuclear@0
|
3
|
nuclear@0
|
4 using std::string;
|
nuclear@0
|
5
|
nuclear@0
|
6 Scene::Scene(GraphicsContext *gc) {
|
nuclear@0
|
7 this->gc = gc;
|
nuclear@0
|
8
|
nuclear@0
|
9 ActiveCamera = 0;
|
nuclear@0
|
10 Shadows = false;
|
nuclear@0
|
11 LightHalos = false;
|
nuclear@0
|
12 HaloSize = 10.0f;
|
nuclear@0
|
13 UseFog = false;
|
nuclear@0
|
14
|
nuclear@0
|
15 memset(lights, 0, 8 * sizeof(Light*));
|
nuclear@0
|
16
|
nuclear@0
|
17 AmbientLight = Color(0.0f, 0.0f, 0.0f);
|
nuclear@0
|
18 ManageData = true;
|
nuclear@0
|
19 }
|
nuclear@0
|
20
|
nuclear@0
|
21 Scene::~Scene() {
|
nuclear@0
|
22
|
nuclear@0
|
23 if(ManageData) {
|
nuclear@0
|
24 std::list<Object*>::iterator obj = objects.begin();
|
nuclear@0
|
25 while(obj != objects.end()) {
|
nuclear@0
|
26 delete *obj++;
|
nuclear@0
|
27 }
|
nuclear@0
|
28
|
nuclear@0
|
29 std::list<Camera*>::iterator cam = cameras.begin();
|
nuclear@0
|
30 while(cam != cameras.end()) {
|
nuclear@0
|
31 delete *cam++;
|
nuclear@0
|
32 }
|
nuclear@0
|
33
|
nuclear@0
|
34 for(int i=0; i<8; i++) {
|
nuclear@0
|
35 delete lights[i];
|
nuclear@0
|
36 }
|
nuclear@0
|
37
|
nuclear@0
|
38 std::list<Curve*>::iterator citer = curves.begin();
|
nuclear@0
|
39 while(citer != curves.end()) {
|
nuclear@0
|
40 delete *citer++;
|
nuclear@0
|
41 }
|
nuclear@0
|
42
|
nuclear@0
|
43 std::list<ShadowVolume>::iterator sv = StaticShadowVolumes.begin();
|
nuclear@0
|
44 while(sv != StaticShadowVolumes.end()) {
|
nuclear@0
|
45 delete (*sv++).shadow_mesh;
|
nuclear@0
|
46 }
|
nuclear@0
|
47 }
|
nuclear@0
|
48
|
nuclear@0
|
49 }
|
nuclear@0
|
50
|
nuclear@0
|
51 void Scene::SetGraphicsContext(GraphicsContext *gc) {
|
nuclear@0
|
52 this->gc = gc;
|
nuclear@0
|
53 }
|
nuclear@0
|
54
|
nuclear@0
|
55 void Scene::AddCamera(Camera *cam) {
|
nuclear@0
|
56 cameras.push_back(cam);
|
nuclear@0
|
57 if(!ActiveCamera) ActiveCamera = cam;
|
nuclear@0
|
58 }
|
nuclear@0
|
59
|
nuclear@0
|
60 void Scene::AddLight(Light *light) {
|
nuclear@0
|
61 for(int i=0; i<8; i++) {
|
nuclear@0
|
62 if(!lights[i]) {
|
nuclear@0
|
63 lights[i] = light;
|
nuclear@0
|
64 break;
|
nuclear@0
|
65 }
|
nuclear@0
|
66 }
|
nuclear@0
|
67 }
|
nuclear@0
|
68
|
nuclear@0
|
69 void Scene::AddObject(Object *obj) {
|
nuclear@0
|
70 if(obj->material.Alpha < 1.0f) {
|
nuclear@0
|
71 objects.push_back(obj);
|
nuclear@0
|
72 } else {
|
nuclear@0
|
73 objects.push_front(obj);
|
nuclear@0
|
74 }
|
nuclear@0
|
75 }
|
nuclear@0
|
76
|
nuclear@0
|
77 void Scene::AddStaticShadowVolume(TriMesh *mesh, const Light *light) {
|
nuclear@0
|
78 ShadowVolume svol;
|
nuclear@0
|
79 svol.shadow_mesh = mesh;
|
nuclear@0
|
80 svol.light = light;
|
nuclear@0
|
81 StaticShadowVolumes.push_back(svol);
|
nuclear@0
|
82 }
|
nuclear@0
|
83
|
nuclear@0
|
84 void Scene::AddCurve(Curve *curve) {
|
nuclear@0
|
85 curves.push_back(curve);
|
nuclear@0
|
86 }
|
nuclear@0
|
87
|
nuclear@0
|
88
|
nuclear@0
|
89 void Scene::RemoveObject(const Object *obj) {
|
nuclear@0
|
90 std::list<Object *>::iterator iter = objects.begin();
|
nuclear@0
|
91 while(iter != objects.end()) {
|
nuclear@0
|
92 if(obj == *iter) {
|
nuclear@0
|
93 objects.erase(iter);
|
nuclear@0
|
94 return;
|
nuclear@0
|
95 }
|
nuclear@0
|
96 iter++;
|
nuclear@0
|
97 }
|
nuclear@0
|
98 }
|
nuclear@0
|
99
|
nuclear@0
|
100 void Scene::RemoveLight(const Light *light) {
|
nuclear@0
|
101 for(int i=0; i<8; i++) {
|
nuclear@0
|
102 if(light = lights[i]) {
|
nuclear@0
|
103 lights[i] = 0;
|
nuclear@0
|
104 return;
|
nuclear@0
|
105 }
|
nuclear@0
|
106 }
|
nuclear@0
|
107 }
|
nuclear@0
|
108
|
nuclear@0
|
109
|
nuclear@0
|
110 Camera *Scene::GetCamera(const char *name) {
|
nuclear@0
|
111 std::list<Camera *>::iterator iter = cameras.begin();
|
nuclear@0
|
112 while(iter != cameras.end()) {
|
nuclear@0
|
113 if(!strcmp((*iter)->name.c_str(), name)) return *iter;
|
nuclear@0
|
114 iter++;
|
nuclear@0
|
115 }
|
nuclear@0
|
116 return 0;
|
nuclear@0
|
117 }
|
nuclear@0
|
118
|
nuclear@0
|
119 Light *Scene::GetLight(const char *name) {
|
nuclear@0
|
120 for(int i=0; i<8; i++) {
|
nuclear@0
|
121 if(!strcmp(lights[i]->name.c_str(), name)) return lights[i];
|
nuclear@0
|
122 }
|
nuclear@0
|
123 return 0;
|
nuclear@0
|
124 }
|
nuclear@0
|
125
|
nuclear@0
|
126 Object *Scene::GetObject(const char *name) {
|
nuclear@0
|
127 std::list<Object *>::iterator iter = objects.begin();
|
nuclear@0
|
128 while(iter != objects.end()) {
|
nuclear@0
|
129 if(!strcmp((*iter)->name.c_str(), name)) return *iter;
|
nuclear@0
|
130 iter++;
|
nuclear@0
|
131 }
|
nuclear@0
|
132 return 0;
|
nuclear@0
|
133 }
|
nuclear@0
|
134
|
nuclear@0
|
135 Curve *Scene::GetCurve(const char *name) {
|
nuclear@0
|
136 std::list<Curve *>::iterator iter = curves.begin();
|
nuclear@0
|
137 while(iter != curves.end()) {
|
nuclear@0
|
138 if(!strcmp((*iter)->name.c_str(), name)) return *iter;
|
nuclear@0
|
139 iter++;
|
nuclear@0
|
140 }
|
nuclear@0
|
141 return 0;
|
nuclear@0
|
142 }
|
nuclear@0
|
143
|
nuclear@0
|
144
|
nuclear@0
|
145 std::list<Object*> *Scene::GetObjectsList() {
|
nuclear@0
|
146 return &objects;
|
nuclear@0
|
147 }
|
nuclear@0
|
148
|
nuclear@0
|
149
|
nuclear@0
|
150 void Scene::SetActiveCamera(Camera *cam) {
|
nuclear@0
|
151 ActiveCamera = cam;
|
nuclear@0
|
152 }
|
nuclear@0
|
153
|
nuclear@0
|
154 Camera *Scene::GetActiveCamera() const {
|
nuclear@0
|
155 return ActiveCamera;
|
nuclear@0
|
156 }
|
nuclear@0
|
157
|
nuclear@0
|
158 void Scene::SetShadows(bool enable) {
|
nuclear@0
|
159 Shadows = enable;
|
nuclear@0
|
160 }
|
nuclear@0
|
161
|
nuclear@0
|
162 void Scene::SetHaloDrawing(bool enable) {
|
nuclear@0
|
163 LightHalos = enable;
|
nuclear@0
|
164 }
|
nuclear@0
|
165
|
nuclear@0
|
166 void Scene::SetHaloSize(float size) {
|
nuclear@0
|
167 HaloSize = size;
|
nuclear@0
|
168 }
|
nuclear@0
|
169
|
nuclear@0
|
170 void Scene::SetAmbientLight(Color ambient) {
|
nuclear@0
|
171 AmbientLight = ambient;
|
nuclear@0
|
172 }
|
nuclear@0
|
173
|
nuclear@0
|
174 Color Scene::GetAmbientLight() const {
|
nuclear@0
|
175 return AmbientLight;
|
nuclear@0
|
176 }
|
nuclear@0
|
177
|
nuclear@0
|
178 void Scene::SetFog(bool enable, Color FogColor, float Near, float Far) {
|
nuclear@0
|
179 UseFog = enable;
|
nuclear@0
|
180 if(enable) {
|
nuclear@0
|
181 this->FogColor = FogColor;
|
nuclear@0
|
182 NearFogRange = Near;
|
nuclear@0
|
183 FarFogRange = Far;
|
nuclear@0
|
184 }
|
nuclear@0
|
185 }
|
nuclear@0
|
186
|
nuclear@0
|
187
|
nuclear@0
|
188 void Scene::SetupLights() const {
|
nuclear@0
|
189 int LightIndex = 0;
|
nuclear@0
|
190 for(int i=0; i<8; i++) {
|
nuclear@0
|
191 if(lights[i]) {
|
nuclear@0
|
192 lights[i]->SetLight(LightIndex++, gc);
|
nuclear@0
|
193 }
|
nuclear@0
|
194 }
|
nuclear@0
|
195 gc->D3DDevice->LightEnable(LightIndex, false);
|
nuclear@0
|
196 }
|
nuclear@0
|
197
|
nuclear@0
|
198
|
nuclear@0
|
199 void Scene::RenderShadows() const {
|
nuclear@0
|
200
|
nuclear@0
|
201 for(int i=0, slight=0; i<8; i++) {
|
nuclear@0
|
202 if(!lights[i] || !lights[i]->GetShadowCasting()) continue;
|
nuclear@0
|
203
|
nuclear@0
|
204 // disable shadow casting light and render the scene (first pass)
|
nuclear@0
|
205 gc->SetAlphaBlending(true);
|
nuclear@0
|
206 gc->D3DDevice->LightEnable(i, false);
|
nuclear@0
|
207 std::list<Object*>::const_iterator iter = objects.begin();
|
nuclear@0
|
208 while(iter != objects.end()) {
|
nuclear@0
|
209 Object *obj = *iter++;
|
nuclear@0
|
210 obj->Render();
|
nuclear@0
|
211 }
|
nuclear@0
|
212 gc->D3DDevice->LightEnable(i, true);
|
nuclear@0
|
213 gc->SetAlphaBlending(false);
|
nuclear@0
|
214
|
nuclear@0
|
215 // shadow volume front faces
|
nuclear@0
|
216 gc->SetZWrite(false);
|
nuclear@0
|
217 gc->SetColorWrite(false, false, false, false);
|
nuclear@0
|
218 gc->SetLighting(false);
|
nuclear@0
|
219
|
nuclear@0
|
220 gc->SetStencilBuffering(true);
|
nuclear@0
|
221 gc->SetStencilFunc(CMP_ALWAYS);
|
nuclear@0
|
222 gc->SetStencilOp(SOP_KEEP, SOP_KEEP, SOP_INC);
|
nuclear@0
|
223
|
nuclear@0
|
224 iter = objects.begin();
|
nuclear@0
|
225 while(iter != objects.end()) {
|
nuclear@0
|
226 Object *obj = *iter++;
|
nuclear@0
|
227 TriMesh *mesh = obj->GetShadowVolume(slight);
|
nuclear@0
|
228 if(mesh) {
|
nuclear@0
|
229 gc->SetWorldMatrix(obj->GetWorldTransform());
|
nuclear@0
|
230 gc->Draw(const_cast<Vertex*>(mesh->GetVertexArray()), mesh->GetVertexCount());
|
nuclear@0
|
231
|
nuclear@0
|
232 // back faces pass
|
nuclear@0
|
233 //gc->SetFrontFace(CounterClockwise);
|
nuclear@0
|
234 //gc->SetStencilOp(SOP_KEEP, SOP_KEEP, SOP_DEC);
|
nuclear@0
|
235
|
nuclear@0
|
236 //gc->Draw(const_cast<Vertex*>(mesh->GetVertexArray()), mesh->GetVertexCount());
|
nuclear@0
|
237 }
|
nuclear@0
|
238 }
|
nuclear@0
|
239
|
nuclear@0
|
240 // static shadow volumes
|
nuclear@0
|
241 gc->SetWorldMatrix(Matrix4x4());
|
nuclear@0
|
242 std::list<ShadowVolume>::const_iterator shadow_iter = StaticShadowVolumes.begin();
|
nuclear@0
|
243 while(shadow_iter != StaticShadowVolumes.end()) {
|
nuclear@0
|
244 if(shadow_iter->light == lights[i]) {
|
nuclear@0
|
245 gc->Draw(const_cast<Vertex*>(shadow_iter->shadow_mesh->GetVertexArray()), shadow_iter->shadow_mesh->GetVertexCount());
|
nuclear@0
|
246 }
|
nuclear@0
|
247 shadow_iter++;
|
nuclear@0
|
248 }
|
nuclear@0
|
249
|
nuclear@0
|
250 // back faces pass
|
nuclear@0
|
251 gc->SetFrontFace(CounterClockwise);
|
nuclear@0
|
252 gc->SetStencilOp(SOP_KEEP, SOP_KEEP, SOP_DEC);
|
nuclear@0
|
253
|
nuclear@0
|
254 iter = objects.begin();
|
nuclear@0
|
255 while(iter != objects.end()) {
|
nuclear@0
|
256 Object *obj = *iter++;
|
nuclear@0
|
257 TriMesh *mesh = obj->GetShadowVolume(slight);
|
nuclear@0
|
258 if(mesh) {
|
nuclear@0
|
259 gc->SetWorldMatrix(obj->GetWorldTransform());
|
nuclear@0
|
260 gc->Draw(const_cast<Vertex*>(mesh->GetVertexArray()), mesh->GetVertexCount());
|
nuclear@0
|
261 }
|
nuclear@0
|
262 }
|
nuclear@0
|
263
|
nuclear@0
|
264 // static shadow volumes
|
nuclear@0
|
265 gc->SetWorldMatrix(Matrix4x4());
|
nuclear@0
|
266 shadow_iter = StaticShadowVolumes.begin();
|
nuclear@0
|
267 while(shadow_iter != StaticShadowVolumes.end()) {
|
nuclear@0
|
268 if(shadow_iter->light == lights[i]) {
|
nuclear@0
|
269 gc->Draw(const_cast<Vertex*>(shadow_iter->shadow_mesh->GetVertexArray()), shadow_iter->shadow_mesh->GetVertexCount());
|
nuclear@0
|
270 }
|
nuclear@0
|
271 shadow_iter++;
|
nuclear@0
|
272 }
|
nuclear@0
|
273
|
nuclear@0
|
274 gc->SetFrontFace(Clockwise);
|
nuclear@0
|
275
|
nuclear@0
|
276 gc->SetLighting(true);
|
nuclear@0
|
277 gc->SetZWrite(true);
|
nuclear@0
|
278 gc->SetColorWrite(true, true, true, true);
|
nuclear@0
|
279
|
nuclear@0
|
280 gc->SetStencilOp(SOP_KEEP, SOP_KEEP, SOP_KEEP);
|
nuclear@0
|
281 gc->SetStencilFunc(CMP_EQUAL);
|
nuclear@0
|
282 gc->SetStencilReference(0);
|
nuclear@0
|
283
|
nuclear@0
|
284 gc->SetLighting(true);
|
nuclear@0
|
285 //SetupLights();
|
nuclear@0
|
286
|
nuclear@0
|
287 slight++;
|
nuclear@0
|
288 }
|
nuclear@0
|
289 }
|
nuclear@0
|
290
|
nuclear@0
|
291 void Scene::Render() const {
|
nuclear@0
|
292 gc->SetAmbientLight(AmbientLight);
|
nuclear@0
|
293
|
nuclear@0
|
294 // set camera
|
nuclear@0
|
295 if(!ActiveCamera) return;
|
nuclear@0
|
296 ActiveCamera->CreateCameraMatrix();
|
nuclear@0
|
297 gc->SetViewMatrix(ActiveCamera->GetCameraMatrix());
|
nuclear@0
|
298
|
nuclear@0
|
299 // set projection matrix
|
nuclear@0
|
300 float NearClip, FarClip;
|
nuclear@0
|
301 Matrix4x4 ProjMat;
|
nuclear@0
|
302 ActiveCamera->GetClippingPlanes(&NearClip, &FarClip);
|
nuclear@0
|
303 CreateProjectionMatrix(&ProjMat, ActiveCamera->GetFOV(), 1.3333333f, NearClip, FarClip);
|
nuclear@0
|
304 gc->SetProjectionMatrix(ProjMat);
|
nuclear@0
|
305
|
nuclear@0
|
306 SetupLights();
|
nuclear@0
|
307
|
nuclear@0
|
308 // render shadows
|
nuclear@0
|
309 if(Shadows) {
|
nuclear@0
|
310
|
nuclear@0
|
311 // make array of shadow-casting lights
|
nuclear@0
|
312 Light *ShadowCasters[8];
|
nuclear@0
|
313 Light **lptr = ShadowCasters;
|
nuclear@0
|
314 for(int i=0; i<8; i++) {
|
nuclear@0
|
315 if(lights[i] && lights[i]->GetShadowCasting()) {
|
nuclear@0
|
316 *lptr++ = lights[i];
|
nuclear@0
|
317 }
|
nuclear@0
|
318 }
|
nuclear@0
|
319 int ShadowCasterCount = (int)(lptr - ShadowCasters);
|
nuclear@0
|
320
|
nuclear@0
|
321 std::list<Object *>::const_iterator iter = objects.begin();
|
nuclear@0
|
322 while(iter != objects.end()) {
|
nuclear@0
|
323 Object *obj = *iter++;
|
nuclear@0
|
324
|
nuclear@0
|
325 if(obj->GetShadowCasting()) {
|
nuclear@0
|
326 obj->CalculateShadows((const Light**)ShadowCasters, ShadowCasterCount);
|
nuclear@0
|
327 }
|
nuclear@0
|
328 }
|
nuclear@0
|
329
|
nuclear@0
|
330 RenderShadows();
|
nuclear@0
|
331 }
|
nuclear@0
|
332
|
nuclear@0
|
333 // render objects
|
nuclear@0
|
334 std::list<Object *>::const_iterator iter = objects.begin();
|
nuclear@0
|
335 while(iter != objects.end()) {
|
nuclear@0
|
336 Object *obj = *iter++;
|
nuclear@0
|
337
|
nuclear@0
|
338 obj->Render();
|
nuclear@0
|
339 }
|
nuclear@0
|
340
|
nuclear@0
|
341 if(Shadows) {
|
nuclear@0
|
342 gc->SetStencilBuffering(false);
|
nuclear@0
|
343 gc->SetStencilFunc(CMP_ALWAYS);
|
nuclear@0
|
344 }
|
nuclear@0
|
345
|
nuclear@0
|
346 if(LightHalos) {
|
nuclear@0
|
347 for(int i=0; i<8; i++) {
|
nuclear@0
|
348 if(lights[i]) lights[i]->Draw(gc, HaloSize);
|
nuclear@0
|
349 }
|
nuclear@0
|
350 }
|
nuclear@0
|
351 } |