absence_thelab

annotate src/3deng/3dscene.cpp @ 0:1cffe3409164

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 23 Oct 2014 01:46:07 +0300
parents
children
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 }