absence_thelab
diff 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 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/3deng/3dscene.cpp Thu Oct 23 01:46:07 2014 +0300 1.3 @@ -0,0 +1,351 @@ 1.4 +#include <string> 1.5 +#include "3dscene.h" 1.6 + 1.7 +using std::string; 1.8 + 1.9 +Scene::Scene(GraphicsContext *gc) { 1.10 + this->gc = gc; 1.11 + 1.12 + ActiveCamera = 0; 1.13 + Shadows = false; 1.14 + LightHalos = false; 1.15 + HaloSize = 10.0f; 1.16 + UseFog = false; 1.17 + 1.18 + memset(lights, 0, 8 * sizeof(Light*)); 1.19 + 1.20 + AmbientLight = Color(0.0f, 0.0f, 0.0f); 1.21 + ManageData = true; 1.22 +} 1.23 + 1.24 +Scene::~Scene() { 1.25 + 1.26 + if(ManageData) { 1.27 + std::list<Object*>::iterator obj = objects.begin(); 1.28 + while(obj != objects.end()) { 1.29 + delete *obj++; 1.30 + } 1.31 + 1.32 + std::list<Camera*>::iterator cam = cameras.begin(); 1.33 + while(cam != cameras.end()) { 1.34 + delete *cam++; 1.35 + } 1.36 + 1.37 + for(int i=0; i<8; i++) { 1.38 + delete lights[i]; 1.39 + } 1.40 + 1.41 + std::list<Curve*>::iterator citer = curves.begin(); 1.42 + while(citer != curves.end()) { 1.43 + delete *citer++; 1.44 + } 1.45 + 1.46 + std::list<ShadowVolume>::iterator sv = StaticShadowVolumes.begin(); 1.47 + while(sv != StaticShadowVolumes.end()) { 1.48 + delete (*sv++).shadow_mesh; 1.49 + } 1.50 + } 1.51 + 1.52 +} 1.53 + 1.54 +void Scene::SetGraphicsContext(GraphicsContext *gc) { 1.55 + this->gc = gc; 1.56 +} 1.57 + 1.58 +void Scene::AddCamera(Camera *cam) { 1.59 + cameras.push_back(cam); 1.60 + if(!ActiveCamera) ActiveCamera = cam; 1.61 +} 1.62 + 1.63 +void Scene::AddLight(Light *light) { 1.64 + for(int i=0; i<8; i++) { 1.65 + if(!lights[i]) { 1.66 + lights[i] = light; 1.67 + break; 1.68 + } 1.69 + } 1.70 +} 1.71 + 1.72 +void Scene::AddObject(Object *obj) { 1.73 + if(obj->material.Alpha < 1.0f) { 1.74 + objects.push_back(obj); 1.75 + } else { 1.76 + objects.push_front(obj); 1.77 + } 1.78 +} 1.79 + 1.80 +void Scene::AddStaticShadowVolume(TriMesh *mesh, const Light *light) { 1.81 + ShadowVolume svol; 1.82 + svol.shadow_mesh = mesh; 1.83 + svol.light = light; 1.84 + StaticShadowVolumes.push_back(svol); 1.85 +} 1.86 + 1.87 +void Scene::AddCurve(Curve *curve) { 1.88 + curves.push_back(curve); 1.89 +} 1.90 + 1.91 + 1.92 +void Scene::RemoveObject(const Object *obj) { 1.93 + std::list<Object *>::iterator iter = objects.begin(); 1.94 + while(iter != objects.end()) { 1.95 + if(obj == *iter) { 1.96 + objects.erase(iter); 1.97 + return; 1.98 + } 1.99 + iter++; 1.100 + } 1.101 +} 1.102 + 1.103 +void Scene::RemoveLight(const Light *light) { 1.104 + for(int i=0; i<8; i++) { 1.105 + if(light = lights[i]) { 1.106 + lights[i] = 0; 1.107 + return; 1.108 + } 1.109 + } 1.110 +} 1.111 + 1.112 + 1.113 +Camera *Scene::GetCamera(const char *name) { 1.114 + std::list<Camera *>::iterator iter = cameras.begin(); 1.115 + while(iter != cameras.end()) { 1.116 + if(!strcmp((*iter)->name.c_str(), name)) return *iter; 1.117 + iter++; 1.118 + } 1.119 + return 0; 1.120 +} 1.121 + 1.122 +Light *Scene::GetLight(const char *name) { 1.123 + for(int i=0; i<8; i++) { 1.124 + if(!strcmp(lights[i]->name.c_str(), name)) return lights[i]; 1.125 + } 1.126 + return 0; 1.127 +} 1.128 + 1.129 +Object *Scene::GetObject(const char *name) { 1.130 + std::list<Object *>::iterator iter = objects.begin(); 1.131 + while(iter != objects.end()) { 1.132 + if(!strcmp((*iter)->name.c_str(), name)) return *iter; 1.133 + iter++; 1.134 + } 1.135 + return 0; 1.136 +} 1.137 + 1.138 +Curve *Scene::GetCurve(const char *name) { 1.139 + std::list<Curve *>::iterator iter = curves.begin(); 1.140 + while(iter != curves.end()) { 1.141 + if(!strcmp((*iter)->name.c_str(), name)) return *iter; 1.142 + iter++; 1.143 + } 1.144 + return 0; 1.145 +} 1.146 + 1.147 + 1.148 +std::list<Object*> *Scene::GetObjectsList() { 1.149 + return &objects; 1.150 +} 1.151 + 1.152 + 1.153 +void Scene::SetActiveCamera(Camera *cam) { 1.154 + ActiveCamera = cam; 1.155 +} 1.156 + 1.157 +Camera *Scene::GetActiveCamera() const { 1.158 + return ActiveCamera; 1.159 +} 1.160 + 1.161 +void Scene::SetShadows(bool enable) { 1.162 + Shadows = enable; 1.163 +} 1.164 + 1.165 +void Scene::SetHaloDrawing(bool enable) { 1.166 + LightHalos = enable; 1.167 +} 1.168 + 1.169 +void Scene::SetHaloSize(float size) { 1.170 + HaloSize = size; 1.171 +} 1.172 + 1.173 +void Scene::SetAmbientLight(Color ambient) { 1.174 + AmbientLight = ambient; 1.175 +} 1.176 + 1.177 +Color Scene::GetAmbientLight() const { 1.178 + return AmbientLight; 1.179 +} 1.180 + 1.181 +void Scene::SetFog(bool enable, Color FogColor, float Near, float Far) { 1.182 + UseFog = enable; 1.183 + if(enable) { 1.184 + this->FogColor = FogColor; 1.185 + NearFogRange = Near; 1.186 + FarFogRange = Far; 1.187 + } 1.188 +} 1.189 + 1.190 + 1.191 +void Scene::SetupLights() const { 1.192 + int LightIndex = 0; 1.193 + for(int i=0; i<8; i++) { 1.194 + if(lights[i]) { 1.195 + lights[i]->SetLight(LightIndex++, gc); 1.196 + } 1.197 + } 1.198 + gc->D3DDevice->LightEnable(LightIndex, false); 1.199 +} 1.200 + 1.201 + 1.202 +void Scene::RenderShadows() const { 1.203 + 1.204 + for(int i=0, slight=0; i<8; i++) { 1.205 + if(!lights[i] || !lights[i]->GetShadowCasting()) continue; 1.206 + 1.207 + // disable shadow casting light and render the scene (first pass) 1.208 + gc->SetAlphaBlending(true); 1.209 + gc->D3DDevice->LightEnable(i, false); 1.210 + std::list<Object*>::const_iterator iter = objects.begin(); 1.211 + while(iter != objects.end()) { 1.212 + Object *obj = *iter++; 1.213 + obj->Render(); 1.214 + } 1.215 + gc->D3DDevice->LightEnable(i, true); 1.216 + gc->SetAlphaBlending(false); 1.217 + 1.218 + // shadow volume front faces 1.219 + gc->SetZWrite(false); 1.220 + gc->SetColorWrite(false, false, false, false); 1.221 + gc->SetLighting(false); 1.222 + 1.223 + gc->SetStencilBuffering(true); 1.224 + gc->SetStencilFunc(CMP_ALWAYS); 1.225 + gc->SetStencilOp(SOP_KEEP, SOP_KEEP, SOP_INC); 1.226 + 1.227 + iter = objects.begin(); 1.228 + while(iter != objects.end()) { 1.229 + Object *obj = *iter++; 1.230 + TriMesh *mesh = obj->GetShadowVolume(slight); 1.231 + if(mesh) { 1.232 + gc->SetWorldMatrix(obj->GetWorldTransform()); 1.233 + gc->Draw(const_cast<Vertex*>(mesh->GetVertexArray()), mesh->GetVertexCount()); 1.234 + 1.235 + // back faces pass 1.236 + //gc->SetFrontFace(CounterClockwise); 1.237 + //gc->SetStencilOp(SOP_KEEP, SOP_KEEP, SOP_DEC); 1.238 + 1.239 + //gc->Draw(const_cast<Vertex*>(mesh->GetVertexArray()), mesh->GetVertexCount()); 1.240 + } 1.241 + } 1.242 + 1.243 + // static shadow volumes 1.244 + gc->SetWorldMatrix(Matrix4x4()); 1.245 + std::list<ShadowVolume>::const_iterator shadow_iter = StaticShadowVolumes.begin(); 1.246 + while(shadow_iter != StaticShadowVolumes.end()) { 1.247 + if(shadow_iter->light == lights[i]) { 1.248 + gc->Draw(const_cast<Vertex*>(shadow_iter->shadow_mesh->GetVertexArray()), shadow_iter->shadow_mesh->GetVertexCount()); 1.249 + } 1.250 + shadow_iter++; 1.251 + } 1.252 + 1.253 + // back faces pass 1.254 + gc->SetFrontFace(CounterClockwise); 1.255 + gc->SetStencilOp(SOP_KEEP, SOP_KEEP, SOP_DEC); 1.256 + 1.257 + iter = objects.begin(); 1.258 + while(iter != objects.end()) { 1.259 + Object *obj = *iter++; 1.260 + TriMesh *mesh = obj->GetShadowVolume(slight); 1.261 + if(mesh) { 1.262 + gc->SetWorldMatrix(obj->GetWorldTransform()); 1.263 + gc->Draw(const_cast<Vertex*>(mesh->GetVertexArray()), mesh->GetVertexCount()); 1.264 + } 1.265 + } 1.266 + 1.267 + // static shadow volumes 1.268 + gc->SetWorldMatrix(Matrix4x4()); 1.269 + shadow_iter = StaticShadowVolumes.begin(); 1.270 + while(shadow_iter != StaticShadowVolumes.end()) { 1.271 + if(shadow_iter->light == lights[i]) { 1.272 + gc->Draw(const_cast<Vertex*>(shadow_iter->shadow_mesh->GetVertexArray()), shadow_iter->shadow_mesh->GetVertexCount()); 1.273 + } 1.274 + shadow_iter++; 1.275 + } 1.276 + 1.277 + gc->SetFrontFace(Clockwise); 1.278 + 1.279 + gc->SetLighting(true); 1.280 + gc->SetZWrite(true); 1.281 + gc->SetColorWrite(true, true, true, true); 1.282 + 1.283 + gc->SetStencilOp(SOP_KEEP, SOP_KEEP, SOP_KEEP); 1.284 + gc->SetStencilFunc(CMP_EQUAL); 1.285 + gc->SetStencilReference(0); 1.286 + 1.287 + gc->SetLighting(true); 1.288 + //SetupLights(); 1.289 + 1.290 + slight++; 1.291 + } 1.292 +} 1.293 + 1.294 +void Scene::Render() const { 1.295 + gc->SetAmbientLight(AmbientLight); 1.296 + 1.297 + // set camera 1.298 + if(!ActiveCamera) return; 1.299 + ActiveCamera->CreateCameraMatrix(); 1.300 + gc->SetViewMatrix(ActiveCamera->GetCameraMatrix()); 1.301 + 1.302 + // set projection matrix 1.303 + float NearClip, FarClip; 1.304 + Matrix4x4 ProjMat; 1.305 + ActiveCamera->GetClippingPlanes(&NearClip, &FarClip); 1.306 + CreateProjectionMatrix(&ProjMat, ActiveCamera->GetFOV(), 1.3333333f, NearClip, FarClip); 1.307 + gc->SetProjectionMatrix(ProjMat); 1.308 + 1.309 + SetupLights(); 1.310 + 1.311 + // render shadows 1.312 + if(Shadows) { 1.313 + 1.314 + // make array of shadow-casting lights 1.315 + Light *ShadowCasters[8]; 1.316 + Light **lptr = ShadowCasters; 1.317 + for(int i=0; i<8; i++) { 1.318 + if(lights[i] && lights[i]->GetShadowCasting()) { 1.319 + *lptr++ = lights[i]; 1.320 + } 1.321 + } 1.322 + int ShadowCasterCount = (int)(lptr - ShadowCasters); 1.323 + 1.324 + std::list<Object *>::const_iterator iter = objects.begin(); 1.325 + while(iter != objects.end()) { 1.326 + Object *obj = *iter++; 1.327 + 1.328 + if(obj->GetShadowCasting()) { 1.329 + obj->CalculateShadows((const Light**)ShadowCasters, ShadowCasterCount); 1.330 + } 1.331 + } 1.332 + 1.333 + RenderShadows(); 1.334 + } 1.335 + 1.336 + // render objects 1.337 + std::list<Object *>::const_iterator iter = objects.begin(); 1.338 + while(iter != objects.end()) { 1.339 + Object *obj = *iter++; 1.340 + 1.341 + obj->Render(); 1.342 + } 1.343 + 1.344 + if(Shadows) { 1.345 + gc->SetStencilBuffering(false); 1.346 + gc->SetStencilFunc(CMP_ALWAYS); 1.347 + } 1.348 + 1.349 + if(LightHalos) { 1.350 + for(int i=0; i<8; i++) { 1.351 + if(lights[i]) lights[i]->Draw(gc, HaloSize); 1.352 + } 1.353 + } 1.354 +} 1.355 \ No newline at end of file