00001 #ifndef SCENE_H 00002 #define SCENE_H 00003 00004 00005 #include <vector> 00006 #include <cassert> 00007 00008 #include "Object.h" 00009 #include "Light.h" 00010 #include "Texture.h" 00011 #include "Primitive.h" 00012 #include "BilliardPhysics.h" 00013 00014 00015 class Shader; 00016 class Animator; 00017 00018 00024 class Scene 00025 { 00026 public: 00029 Scene(); 00030 00033 ~Scene(); 00034 00037 bool castShadows() const 00038 { 00039 return mCastShadows; 00040 } 00041 00044 void setCastShadows(bool cs) 00045 { 00046 mCastShadows = cs; 00047 } 00048 00051 const Object * getObject(int i) const 00052 { 00053 assert(i>=0); 00054 return mObjects.at(i); 00055 } 00056 00061 void addObject( Object * obj ) 00062 { 00063 assert(obj); 00064 mObjects.push_back(obj); 00065 if (obj->applyPhysics()) 00066 mPhysics.add(obj); 00067 } 00068 00071 void removeObject(Object * obj); 00072 00075 const Light * getLight(int i) const 00076 { 00077 assert(i>=0); 00078 return mLights.at(i); 00079 } 00080 00083 void addLight(Light * light) 00084 { 00085 assert(light); 00086 light->setScene(this); 00087 mLights.push_back(light); 00088 } 00089 00092 void removeLight(Light * light); 00093 00096 unsigned int lightsCount() const 00097 { 00098 return mLights.size(); 00099 } 00100 00103 void addTexture(Texture* tex) 00104 { 00105 assert(tex); 00106 mTextures.push_back(tex); 00107 } 00108 00111 const Texture * getTexture(int i) const 00112 { 00113 assert(i>=0); 00114 return mTextures.at(i); 00115 } 00116 00119 void addShader(Shader* sh) 00120 { 00121 assert(sh); 00122 mShaders.push_back(sh); 00123 } 00124 00127 const Shader * getShader(int i) const 00128 { 00129 assert(i>=0); 00130 return mShaders.at(i); 00131 } 00132 00135 void setBgColor(const RGBAColor & c) 00136 { 00137 mBgColor = c; 00138 mBgColor.setA(1); 00139 } 00140 00143 const RGBAColor & bgColor() const 00144 { 00145 return mBgColor; 00146 } 00147 00153 RGBAColor rayTrace(Ray & ray) const 00154 { 00155 // we use this value to manage maximal possible tracing depth 00156 // FIXME maybe kick maxBounce and only use ray.recDeep() 00157 // FIXME test if ray.recDeep() method works with multithreading 00158 static __thread int maxBounce = 400; 00159 00160 // here we store the result 00161 RGBAColor result = mBgColor; 00162 00163 // only shoot another ray if the maximum recursion depth is not exceeded 00164 if (maxBounce > 0 && ray.recDeep() < MAX_RECURSION_DEEP && intersect(ray)) 00165 { 00166 maxBounce --; 00167 assert( ray.hit()->shader() ); 00168 result = ray.hit()->shade(ray); // shade the primitive 00169 maxBounce ++; 00170 } 00171 #ifdef DEBUG 00172 // some stats 00173 if (maxBounce <= 0 || ray.recDeep() >= MAX_RECURSION_DEEP) 00174 { 00175 mBounced++; 00176 // LOG("bounced"); 00177 // return RGBAColor(0, 1, 0); // FIXME DEBUG 00178 } 00179 #endif 00180 00181 return result; 00182 } 00183 00186 bool intersect(Ray & ray) const 00187 { 00188 bool hit = false; 00189 for (unsigned int i=0; i < mObjects.size(); i++) 00190 { 00191 hit |= mObjects[i]->intersect(ray); 00192 } 00193 return hit; 00194 } 00195 00198 void clear(); 00199 00202 void addAnimator(Animator * ani) 00203 { 00204 assert(ani); 00205 mAnimators.push_back(ani); 00206 } 00207 00210 void step(); 00211 00216 void physicsDump(const std::string & file) 00217 { 00218 mPhysics.dumpToFile(file); 00219 } 00220 00225 void physicsLoad(const std::string & file) 00226 { 00227 mPhysics.loadFromFile(file); 00228 } 00229 00230 private: 00232 std::vector<Object *> mObjects; 00233 00235 std::vector<Light *> mLights; 00236 00238 std::vector<Texture *> mTextures; 00239 00241 std::vector<Shader *> mShaders; 00242 00244 std::vector<Animator *> mAnimators; 00245 00247 RGBAColor mBgColor; 00248 00250 bool mCastShadows; 00251 00253 BilliardPhysics mPhysics; 00254 00256 int mFrameNr; 00257 00258 #ifdef DEBUG 00260 static __thread long long int mBounced; 00261 #endif 00262 }; 00263 00264 #endif 00265