/* * Ray++ - Object-oriented ray tracing library * Copyright (C) 1998-2001 Martin Reinecke and others. * See the AUTHORS file for more information. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * See the README file for more information. */ #include "worlds/scene.h" namespace RAYPP { //virtual void SCENE::Init () { if (initialized) return; uint4 m; for (m=0; mInit(); if (HMaker) { HMaker->Init(); HMaker->Build_Hierarchy (Object); } else { if (Object.size() > 10) { warning ("SCENE: You should probably use a HMAKER."); } } objects_ready = true; for (m=0; mInit(); initialized = true; } //virtual void SCENE::Deinit () { if (!initialized) return; warning ("SCENE::Deinit() called. This may cause trouble."); uint4 m; for (m=0; mDeinit(); if (HMaker) HMaker->Deinit(); objects_ready = false; for (m=0; mDeinit(); initialized = false; } //virtual void SCENE::Get_Surrounding_Volume (const VECTOR &Loc, INSIDE_INFO &result) const { coi(); INSIDE_INFO TempIns; result.Priority = -1; result.Vol = 0; for (vector >::const_iterator i=Object.begin(); iInside_Volume (Loc, result, TempIns)) result = TempIns; } //virtual bool SCENE::Get_Next_Intersection (const RAY &Ray, float8 &dist, SHADING_INFO &result) const { ci(); bool Hit = false; RAY Local_Ray = Ray; INTERSECT_INFO Inter, TmpInter; OBJECT_QUEUE Queue; TMPHANDLE ActObject; float8 ActDist; for (vector >::const_iterator i=Object.begin(); iTest (Local_Ray, dist)) Queue.push (oqentry (dist, *i)); } while (!Queue.empty()) { ActDist = Queue.top().first; ActObject = Queue.top().second; Queue.pop(); if (ActDist > Local_Ray.maxdist) break; if (ActObject->Intersect (Local_Ray, Queue, TmpInter)) { Hit = true; Local_Ray.maxdist = TmpInter.depth; Inter = TmpInter; } } if (!Hit) return false; dist = Inter.depth; result.Intersect_Point = Ray.eval(Inter.depth); result.Incident_Dir = Ray.dir; result.Normal = (Dot(Inter.Normal, Ray.dir) < 0) ? Inter.Normal : -Inter.Normal; result.Surf = Inter.Surf; // if (Ins.Priority > Inter.Ins.Priority) // internal ("Error in intersection algorithm"); result.Ins1 = Local_Ray.Inside; if (!Inter.Has_Volume) result.Ins2 = Local_Ray.Inside; else { if (Local_Ray.Inside.Priority == Inter.Ins.Priority) { VECTOR tmp = Ray.eval(Inter.depth + Small_dist); Get_Surrounding_Volume (tmp, result.Ins2); } else result.Ins2 = Inter.Ins; } return true; } //virtual void SCENE::Get_Lights (const VECTOR &Loc, LIGHT_ARRAY &result) const { for (vector >::const_iterator j=Light.begin(); jCast_Light (Loc, result); } //virtual COLOUR SCENE::Get_Background (const VECTOR &Dir) const { if (!BackgroundPigment) return COLOUR(0,0,0); SHADING_INFO BackgroundInfo; BackgroundInfo.Intersect_Point = Dir; // This is very sloppy, I know. // The rest of BackgroundInfo should also be initialized. return BackgroundPigment->Get_Colour(BackgroundInfo); } void SCENE::Add (const HANDLE &Obj) { cni(); if (!Obj) error ("SCENE::Add: Invalid Handle"); Object.push_back (Obj); } void SCENE::Add (const HANDLE &Lgt) { cni(); if (!Lgt) error ("SCENE::Add: Invalid Handle"); Light.push_back (Lgt); } void SCENE::Set_HMaker (const HANDLE &Hm) { cni(); if (!Hm) error ("SCENE::Set_HMaker: Invalid Handle"); HMaker = Hm; } void SCENE::Set_Background(const HANDLE &Pigment) { cni(); if (!Pigment) error("SCENE::Set_Background: Invalid Handle"); BackgroundPigment = Pigment; } } // namespace RAYPP