-
Notifications
You must be signed in to change notification settings - Fork 0
/
scene_node.js
184 lines (150 loc) · 6.59 KB
/
scene_node.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/*
* JavaScript / Canvas teaching framwork
* (C)opyright Hartmut Schirmacher, hschirmacher.beuth-hochschule.de
*
* Module: SceneNode V2
*
* A SceneNode is a container for a transformation, a program,
* and a list of drawable objects.
*
* The drawable objects can themselves be SceneNodes, so that
* hierarchical modeling is supported.
*
* The node has a public attribute "visible" that determines whether
* the node and its children will actually be drawn or not.
*
* The program and the transformation are optional; however
* at a minimum you must specify a program for the root node.
*
* - the transformation associated with the node can be
* accessed directly via the attribute "transformation".
*
* - the program associated with the node can be accessed
* directly via the attribute "program".
*
* - drawable objects can be added via the addObjects() method,
* and can be removed again using the removeObjects() method.
*
* - the draw() method
* - multiplies the model-view matrix passed as an argument
* with its own model-view matrix from the right
* - calculates the normal matrix from the model-view matrix
* - for each drawable object it refers to:
* - activates the program to be used
* (either the node's own program, or if that is not
* defined, the program passed as an argument)
* - sets the uniforms "modelViewMAtrix" and "normalMatrix"
* in the active program
* - calls the object's draw() method using the current
* program and matrix
*
*/
/* requireJS module definition */
define(["util", "gl-matrix"],
(function(util, dummy) {
"use strict";
/*
* SceneNode constructor
* A SceneNode holds a collection of things to be drawn,
* plus an associated transformation and program (both optional).
*
* The constructor takes the following arguments:
* - name : string defining the name of the SceneNode for UI/debugging purposes,
* - objects : array of objects to be contained in this SceneNode
* - program : a Program object (see program.js)
* - transform : local transformation matrix (of type mat4, see lib/gl-matrix.js)
* - visible : if false, draw() to this node and all children is simply ignored.
*
* The three attributes SceneNode.program, SceneNode.transformation, and
* SceneNode.visible can be safely modified from the outside.
*
*/
var SceneNode = function(name, objects, program, transform, visible) {
// name for UI / debugging
this.name = name;
// optional list of objects contained in this node
this.drawableObjects = objects || [];
// optional GPU program for this node
this.program = program || null;
// optional transformation for this node
this.transformation = transform || mat4.identity();
// flag: draw this node and its children, or not?
this.visible = visible===undefined? true : visible;
window.console.log("created " + (visible? "invisible " : "") + "node " + this.name +
" with " + this.drawableObjects.length + " children.");
};
/*
* draw() simply calls the draw() method of each object,
* in the order they were added to the SceneNode. Before that,
* the SceneNode node's own model-view matrix is chained
* with the model-view matrix passed as an argument,
* and the shader variable "modelViewMatrix" is set;
* also the inverse-transpose of MV-Matrix is calculated and
* set as the shader variable "normalMatrix".
* - gl : the WebGL rendering context
* - progam : the (WebGL) Program to be used
* - modelViewMatrix : the current modelview matrix
*/
SceneNode.prototype.draw = function(gl, program, modelViewMatrix) {
if(!this.visible)
return;
if(!gl) {
throw "no WebGL context specified in scene node " + this.name;
return;
};
// take program passed as a parameter, or the program from the constructor
var newProgram = this.program || program;
if(!newProgram) {
throw "no program specified in scene node " + this.name;
return;
};
// copy the matrix passed as a parameter, or identity if undefined
var newMatrix = mat4.create(modelViewMatrix || mat4.identity());
// multiply the local transformation from the right so it will be executed FIRST
mat4.multiply(newMatrix, this.transformation);
// calculate the normal matrix from the model-view matrix
var normalMatrix = mat4.toInverseMat3(newMatrix);
mat3.transpose(normalMatrix,normalMatrix);
// loop over all drawable objects and call their draw() methods
for(var i=0; i<this.drawableObjects.length; ++i) {
// set new program and new model view matrix for each child
newProgram.use();
newProgram.setUniform("modelViewMatrix", "mat4", newMatrix);
newProgram.setUniform("normalMatrix", "mat3", normalMatrix, false);
// child may manipulate the program and/or matrix!
this.drawableObjects[i].draw(gl, newProgram, newMatrix);
};
};
/*
* add multiple objects to the SceneNode, in drawing order
* - objects: ARRAY of objects to be added
*/
SceneNode.prototype.addObjects = function(objects) {
for(var i=0; i<objects.length; i++) {
var o = objects[i];
if(!o.draw) {
throw "addObjects(): object " + i + " has no draw() method.";
} else {
this.drawableObjects.push(o);
}
};
window.console.log("added " + objects.length + " objects to SceneNode " + this.name + ".");
};
/*
* remove drawable objects from the SceneNode (provided in an array)
*/
SceneNode.prototype.removeObjects = function(objects) {
for(var i=0; i<objects.length; i++) {
// find obj in array
var idx = this.drawableObjects.indexOf(objects[i]);
if(idx === -1) {
// window.console.log("warning: SceneNode.remove(): object not found.");
} else {
// remove obj from array
this.drawableObjects.splice(idx,1);
};
};
};
// this module only exports the constructor for SceneNode objects
return SceneNode;
})); // define