1 /**
  2  * Copyright (C) 2009-2012 Klaus Reimer <k@ailis.de>
  3  * See LICENSE.txt for licensing information
  4  * 
  5  * @require threedee.js
  6  * @require threedee/Color.js
  7  * @use threedee/rendering/PolygonBuffer.js
  8  */
  9 
 10 /**
 11  * Constructs a new scene.
 12  *            
 13  * @constructor
 14  * @class
 15  * A scene.
 16  */
 17 threedee.Scene = function()
 18 {
 19     this.buffer = new threedee.PolygonBuffer();
 20 };
 21 
 22 /** 
 23  * The root node of the scene.
 24  * @private 
 25  * @type {?threedee.SceneNode} 
 26  */
 27 threedee.Scene.prototype.rootNode = null;
 28 
 29 /** 
 30  * The polygon buffer. 
 31  * @private 
 32  * @type {!threedee.PolygonBuffer} 
 33  */
 34 threedee.Scene.prototype.buffer;
 35 
 36 /** 
 37  * The global ambient color. 
 38  * @private 
 39  * @type {!threedee.Color} 
 40  */
 41 threedee.Scene.prototype.globalAmbient = threedee.Color.DARK_GRAY;
 42 
 43 /** 
 44  * The last update timestamp. 
 45  * @private 
 46  * @type {number} 
 47  */
 48 threedee.Scene.prototype.lastUpdate = 0;
 49 
 50 /**
 51  * Sets the root node.
 52  * 
 53  * @param {?threedee.SceneNode} rootNode
 54  *            The root node to set. Null to unset.
 55  */
 56 threedee.Scene.prototype.setRootNode = function(rootNode)
 57 {
 58     this.rootNode = rootNode;
 59 };
 60 
 61 /**
 62  * Returns the current root node.
 63  * 
 64  * @return {?threedee.SceneNode}
 65  *            The current root node. Null if none set.
 66  */
 67 threedee.Scene.prototype.getRootNode = function()
 68 {
 69     return this.rootNode;
 70 };
 71 
 72 /**
 73  * Sets the global ambient color.
 74  * 
 75  * @param {!threedee.Color} globalAmbient
 76  *            The global ambient color to set
 77  */
 78 threedee.Scene.prototype.setGlobalAmbient = function(globalAmbient)
 79 {
 80     this.globalAmbient = globalAmbient;
 81 };
 82 
 83 /**
 84  * Returns the global ambient color.
 85  * 
 86  * @return {!threedee.Color} The global ambient color
 87  */
 88 threedee.Scene.prototype.getGlobalAmbient = function()
 89 {
 90     return this.globalAmbient;
 91 };
 92 
 93 /**
 94  * Updates the scene with the specified time delta (milliseconds);
 95  * 
 96  * @param {number} delta
 97  *            The time elapsed since the last call to this method measured
 98  *            in milliseconds. This is optional. If not specified then
 99  *            it is calculated automatically
100  */
101 threedee.Scene.prototype.update = function(delta)
102 {
103     var now;
104     
105     if (!this.rootNode) return;
106 
107     if (delta === undefined)
108     {
109         now = new Date().getTime();
110         delta = now - this.lastUpdate;
111         this.lastUpdate = now;
112         
113         // If delta is too large then ignore this update
114         if (delta > 10000) return;
115     }
116     
117     // Update the root node
118     this.rootNode.update(delta);  
119 };
120 
121 
122 /**
123  * Renders the scene.
124  * 
125  * @param {!CanvasRenderingContext2D} g
126  *            The graphics context
127  * @param {number} width
128  *            The output width in pixels
129  * @param {number} height
130  *            The output height in pixels
131  * @param {?threedee.RenderOptions=} renderOptions
132  *            The render options. If not set then the default options
133  *            are used.
134  * @param {?threedee.CameraNode=} camera
135  *            The camera node to use. If it is null then a fixed default
136  *            camera at position 0,0,0 looking in direction 0,0,1 is used
137  */
138 threedee.Scene.prototype.render = function(g, width, height, renderOptions,
139     camera)
140 {
141     var rootTransform;
142     
143     // If no root node is set yet then do nothing
144     if (!this.rootNode) return;
145 
146     // Calculate the root transformation
147     rootTransform = this.rootNode.getTransform();
148     if (camera)
149     {
150         rootTransform =
151             camera.getTransform().copy().invert()
152                 .transform(rootTransform);
153     }
154 
155     // Initialize the polygon buffer and recursively render the scene
156     // nodes into it
157     this.buffer.prepare(width, height);
158     this.buffer.setGlobalAmbient(this.globalAmbient);
159     if (renderOptions) this.buffer.setRenderOptions(renderOptions);
160     this.rootNode.render(this.buffer, rootTransform);
161 
162     // Render the polygon buffer onto the screen
163     this.buffer.render(g);
164 };
165 
166 /**
167  * Returns debugging info. The debugInfo flag in the rendering options must
168  * be set to true to get up-to-date debug info.
169  * 
170  * @return {string} The debug info
171  */
172 threedee.Scene.prototype.getDebugInfo = function()
173 {
174     return this.buffer.getDebugInfo();
175 };
176