1 /*
  2   Copyright (c) 2008 Seneca College
  3   Licenced under the MIT License (http://www.c3dl.org/index.php/mit-license/)
  4 */
  5 
  6 				
  7 /**
  8 	@private
  9 
 10 	@class c3dl.SceneNode
 11 */
 12 c3dl.SceneNode = c3dl.inherit(c3dl.Primitive, function()
 13 {
 14 	c3dl._superc(this);
 15 
 16 	// An array of c3dl.Actors
 17 	this.children = [];
 18 });
 19 
 20 /**
 21 	@private
 22 
 23 	Get a copy of this node and all its children.
 24 */
 25 c3dl.SceneNode.prototype.getCopy = function()
 26 {
 27 	var sceneNode = new c3dl.SceneNode();
 28 	sceneNode.clone(this);
 29 	return sceneNode;
 30 }
 31 
 32 /**
 33 	@private
 34 */
 35 c3dl.SceneNode.prototype.clone = function(other)
 36 {
 37 	c3dl._super(this, arguments, "clone");
 38 
 39 	// copy all the children
 40 	for (var i = 0; i < other.children.length; i++)
 41 	{
 42 		this.addChild(other.children[i].getCopy());
 43 	}
 44 }
 45 
 46 
 47 /**
 48 	@private
 49 
 50 	Add a child to this node
 51 
 52 	@param child
 53 */
 54 c3dl.SceneNode.prototype.addChild = function(child)
 55 {
 56 	this.children.push(child);
 57 }
 58 
 59 
 60 /**
 61 	@private
 62 	
 63 	private until function is tested.
 64 	
 65 	Ask every child node if they are named 'nodeName'.
 66 	
 67 	@param nodeName
 68 */
 69 c3dl.SceneNode.prototype.findNode = function(nodeName)
 70 {
 71 	var child = null;
 72 
 73 	// check first if this node is the one user is looking for.
 74 	if(nodeName == this.name)
 75 	{
 76 		child = this;
 77 	}
 78 
 79 	// otherwise check the children
 80 	else
 81 	{
 82 		for (var i=0; i < this.children.length; i++)
 83 		{
 84 			//
 85 			if(this.children[i] instanceof c3dl.SceneNode)
 86 			{
 87 				child = this.children[i].findNode(nodeName);
 88 
 89 				// if we found something it wont be null, so we can
 90 				// skip checking the other nodes
 91 				if (child != null)
 92 				{
 93 					break;
 94 				}
 95 			}
 96 		}
 97 	}
 98 	return child;
 99 }
100 
101 
102 /**
103 	@private
104 	
105 	Called automatically.
106 
107 	Update animations, etc.
108 
109 	@param {float} timeStep
110 */
111 c3dl.SceneNode.prototype.update = function(timeStep)
112 {
113 	c3dl._super(this, arguments, "update");
114 
115 	for (var i=0; i < this.children.length; i++)
116 	{
117 		this.children[i].update(timeStep);
118 	}
119 }
120 
121 
122 /**
123 	@private
124 	
125 	Called automatically.
126 
127 	When scene nodes are rendered, they first push on their matrix 
128 	onto the stack, and render their children.  By doing this, all 
129 	children will be rendered relative to their parent which is this node.
130 */
131 c3dl.SceneNode.prototype.render = function(glCanvas3D, scene)
132 {
133 	c3dl.pushMatrix();
134 	c3dl.multMatrix(this.getTransform());
135 
136 	for (var i = 0; i < this.children.length; i++)
137 	{
138 		this.children[i].render(glCanvas3D, scene);
139 	}
140 
141 	c3dl.popMatrix();
142 }	
143 
144 
145 /**
146 	@private
147 
148 	Set the texture for all the geometry leaves in the scenegraph.
149 	This should be used when a Collada file has many meshes and each
150 	mesh uses the same texture file.
151 
152 	@param {String} textureName
153 */
154 c3dl.SceneNode.prototype.setTexture = function(textureName)
155 {
156 	for (var i = 0; i < this.children.length; i++)
157 	{
158 		this.children[i].setTexture(textureName);
159 	}
160 }
161 
162 /**
163 	@private
164 
165 */
166 c3dl.SceneNode.prototype.setMaterial = function(material)
167 {
168 	for (var i = 0; i < this.children.length; i++)
169 	{
170 		this.children[i].setMaterial(material);
171 	}
172 }
173 
174 /**
175 */
176 c3dl.SceneNode.prototype.setEffect = function(effect)
177 {
178 	for (var i = 0; i < this.children.length; i++)
179 	{
180 		this.children[i].setEffect(effect);
181 	}	
182 }
183 
184 /**
185 	@private
186 	
187 	Called automatically
188 
189 	Do any of the triangles in any of the geometry child nodes of this node intersect
190 	with the given ray?
191 
192 	@param {Array} rayOrigin
193 	@param {Array} rayDir
194 
195 	@returns {bool} true if any child geometry node has intersected the ray.
196 */
197 c3dl.SceneNode.prototype.rayIntersectsTriangles = function(rayOrigin, rayDir)
198 {
199 	c3dl.pushMatrix();
200 	c3dl.multMatrix(this.getTransform());
201 	
202 	var passed = false;
203 
204 	for (var i = 0; i < this.children.length; i++)
205 	{
206 		// found a node which passed, we don't have to test the rest of the nodes.
207 		if(this.children[i].rayIntersectsTriangles(rayOrigin, rayDir))
208 		{
209 			passed = true;
210 			break;
211 		}
212 	}
213 
214 	c3dl.popMatrix();
215 	return passed;
216 }
217 
218 /**
219 	@private
220 
221 	Called automatically.
222 
223 	Do any of the geometry child nodes of this node intersect with the given ray?
224 
225 	@param {Array} rayOrigin
226 	@param {Array} rayDir
227 
228 	@returns {bool} true if any child geometry node has intersected the ray.
229 */
230 c3dl.SceneNode.prototype.rayIntersectsEnclosures = function(rayOrigin, rayDir)
231 {
232 	c3dl.pushMatrix();
233 	c3dl.multMatrix(this.getTransform());
234 	
235 	var passed = false;
236 
237 	// iterate over each child or stop until we find one which has passed the Bounding
238 	// sphere test.
239 	for (var i = 0; i < this.children.length; i++)
240 	{
241 		// found a node which passed, we don't have to test the rest of the nodes.
242 		if(this.children[i].rayIntersectsEnclosures(rayOrigin, rayDir))
243 		{
244 			passed = true;		
245 			break;
246 		}
247 	}
248 	
249 	c3dl.popMatrix();
250 	return passed;
251 }
252