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