~holger-seelig/cobweb.js/trunk

« back to all changes in this revision

Viewing changes to src/cobweb/Components/Rendering/X3DComposedGeometryNode.js

  • Committer: Holger Seelig
  • Date: 2017-08-22 04:53:24 UTC
  • Revision ID: holger.seelig@yahoo.de-20170822045324-4of4xxgt79669gbt
Switched to npm.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: JavaScript; coding: utf-8; tab-width: 3; indent-tabs-mode: tab; c-basic-offset: 3 -*-
 
2
 *******************************************************************************
 
3
 *
 
4
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
5
 *
 
6
 * Copyright create3000, Scheffelstraße 31a, Leipzig, Germany 2011.
 
7
 *
 
8
 * All rights reserved. Holger Seelig <holger.seelig@yahoo.de>.
 
9
 *
 
10
 * The copyright notice above does not evidence any actual of intended
 
11
 * publication of such source code, and is an unpublished work by create3000.
 
12
 * This material contains CONFIDENTIAL INFORMATION that is the property of
 
13
 * create3000.
 
14
 *
 
15
 * No permission is granted to copy, distribute, or create derivative works from
 
16
 * the contents of this software, in whole or in part, without the prior written
 
17
 * permission of create3000.
 
18
 *
 
19
 * NON-MILITARY USE ONLY
 
20
 *
 
21
 * All create3000 software are effectively free software with a non-military use
 
22
 * restriction. It is free. Well commented source is provided. You may reuse the
 
23
 * source in any way you please with the exception anything that uses it must be
 
24
 * marked to indicate is contains 'non-military use only' components.
 
25
 *
 
26
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
27
 *
 
28
 * Copyright 2015, 2016 Holger Seelig <holger.seelig@yahoo.de>.
 
29
 *
 
30
 * This file is part of the Cobweb Project.
 
31
 *
 
32
 * Cobweb is free software: you can redistribute it and/or modify it under the
 
33
 * terms of the GNU General Public License version 3 only, as published by the
 
34
 * Free Software Foundation.
 
35
 *
 
36
 * Cobweb is distributed in the hope that it will be useful, but WITHOUT ANY
 
37
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 
38
 * A PARTICULAR PURPOSE. See the GNU General Public License version 3 for more
 
39
 * details (a copy is included in the LICENSE file that accompanied this code).
 
40
 *
 
41
 * You should have received a copy of the GNU General Public License version 3
 
42
 * along with Cobweb.  If not, see <http://www.gnu.org/licenses/gpl.html> for a
 
43
 * copy of the GPLv3 License.
 
44
 *
 
45
 * For Silvio, Joy and Adi.
 
46
 *
 
47
 ******************************************************************************/
 
48
 
 
49
 
 
50
define ([
 
51
        "jquery",
 
52
        "cobweb/Components/Rendering/X3DGeometryNode",
 
53
        "cobweb/Bits/X3DCast",
 
54
        "cobweb/Bits/X3DConstants",
 
55
        "standard/Math/Numbers/Vector3",
 
56
],
 
57
function ($,
 
58
          X3DGeometryNode,
 
59
          X3DCast,
 
60
          X3DConstants,
 
61
          Vector3)
 
62
{
 
63
"use strict";
 
64
 
 
65
        function X3DComposedGeometryNode (executionContext)
 
66
        {
 
67
                X3DGeometryNode .call (this, executionContext);
 
68
 
 
69
                this .addType (X3DConstants .X3DComposedGeometryNode);
 
70
 
 
71
                this .colorNode    = null;
 
72
                this .texCoordNode = null;
 
73
                this .normalNode   = null;
 
74
                this .coordNode    = null;
 
75
        }
 
76
 
 
77
        X3DComposedGeometryNode .prototype = $.extend (Object .create (X3DGeometryNode .prototype),
 
78
        {
 
79
                constructor: X3DComposedGeometryNode,
 
80
                initialize: function ()
 
81
                {
 
82
                        X3DGeometryNode .prototype .initialize .call (this);
 
83
 
 
84
                        this .attrib_   .addInterest ("set_attrib__", this);
 
85
                        this .color_    .addInterest ("set_color__", this);
 
86
                        this .texCoord_ .addInterest ("set_texCoord__", this);
 
87
                        this .normal_   .addInterest ("set_normal__", this);
 
88
                        this .coord_    .addInterest ("set_coord__", this);
 
89
 
 
90
                        this .set_attrib__ ();
 
91
                        this .set_color__ ();
 
92
                        this .set_texCoord__ ();
 
93
                        this .set_normal__ ();
 
94
                        this .set_coord__ ();
 
95
                },
 
96
                getColor: function ()
 
97
                {
 
98
                        return this .colorNode;
 
99
                },
 
100
                getTexCoord: function ()
 
101
                {
 
102
                        return this .texCoordNode;
 
103
                },
 
104
                getNormal: function ()
 
105
                {
 
106
                        return this .normalNode;
 
107
                },
 
108
                getCoord: function ()
 
109
                {
 
110
                        return this .coordNode;
 
111
                },
 
112
                set_attrib__: function ()
 
113
                {
 
114
                        var attribNodes = this .getAttrib ();
 
115
 
 
116
                        for (var i = 0, length = attribNodes .length; i < length; ++ i)
 
117
                                attribNodes [i] .removeInterest ("addNodeEvent", this);
 
118
 
 
119
                        attribNodes .length = 0;
 
120
 
 
121
                        for (var i = 0, length = this .attrib_ .length; i < length; ++ i)
 
122
                        {
 
123
                                var attribNode = X3DCast (X3DConstants .X3DVertexAttributeNode, this .attrib_ [i]);
 
124
 
 
125
                                if (attribNode)
 
126
                                        attribNodes .push (attribNode);
 
127
                        }
 
128
 
 
129
                        for (var i = 0; i < this .attribNodes .length; ++ i)
 
130
                                attribNodes [i] .addInterest ("addNodeEvent", this);
 
131
                },
 
132
                set_color__: function ()
 
133
                {
 
134
                        if (this .colorNode)
 
135
                        {
 
136
                                this .colorNode .removeInterest ("addNodeEvent", this);
 
137
                                this .colorNode .removeInterest ("set_transparent__", this);
 
138
                        }
 
139
 
 
140
                        this .colorNode = X3DCast (X3DConstants .X3DColorNode, this .color_);
 
141
 
 
142
                        if (this .colorNode)
 
143
                        {
 
144
                                this .colorNode .addInterest ("addNodeEvent", this);
 
145
                                this .colorNode .addInterest ("set_transparent__", this);
 
146
 
 
147
                                this .set_transparent__ ();
 
148
                        }
 
149
                        else
 
150
                                this .transparent_ = false;
 
151
                },
 
152
                set_transparent__: function ()
 
153
                {
 
154
                        this .transparent_ = this .colorNode .isTransparent ();
 
155
                },
 
156
                set_texCoord__: function ()
 
157
                {
 
158
                        if (this .texCoordNode)
 
159
                                this .texCoordNode .removeInterest ("addNodeEvent", this);
 
160
 
 
161
                        this .texCoordNode = X3DCast (X3DConstants .X3DTextureCoordinateNode, this .texCoord_);
 
162
 
 
163
                        if (this .texCoordNode)
 
164
                                this .texCoordNode .addInterest ("addNodeEvent", this);
 
165
 
 
166
                        this .setCurrentTexCoord (this .texCoordNode);
 
167
                },
 
168
                set_normal__: function ()
 
169
                {
 
170
                        if (this .normalNode)
 
171
                                this .normalNode .removeInterest ("addNodeEvent", this);
 
172
 
 
173
                        this .normalNode = X3DCast (X3DConstants .X3DNormalNode, this .normal_);
 
174
 
 
175
                        if (this .normalNode)
 
176
                                this .normalNode .addInterest ("addNodeEvent", this);
 
177
                },
 
178
                set_coord__: function ()
 
179
                {
 
180
                        if (this .coordNode)
 
181
                                this .coordNode .removeInterest ("addNodeEvent", this);
 
182
 
 
183
                        this .coordNode = X3DCast (X3DConstants .X3DCoordinateNode, this .coord_);
 
184
 
 
185
                        if (this .coordNode)
 
186
                                this .coordNode .addInterest ("addNodeEvent", this);
 
187
                },
 
188
                getPolygonIndex: function (index)
 
189
                {
 
190
                        return index;
 
191
                },
 
192
                getTriangleIndex: function (index)
 
193
                {
 
194
                        return index;
 
195
                },
 
196
                build: function (verticesPerPolygon, polygonsSize, verticesPerFace, trianglesSize)
 
197
                {
 
198
                        if (! this .coordNode || this .coordNode .isEmpty ())
 
199
                                return;
 
200
 
 
201
                        // Set size to a multiple of verticesPerPolygon.
 
202
 
 
203
                        polygonsSize  -= polygonsSize % verticesPerPolygon;
 
204
                        trianglesSize -= trianglesSize % verticesPerFace;
 
205
 
 
206
                        var
 
207
                                colorPerVertex  = this .colorPerVertex_ .getValue (),
 
208
                                normalPerVertex = this .normalPerVertex_ .getValue (),
 
209
                                attribNodes     = this .getAttrib (),
 
210
                                numAttrib       = attribNodes .length,
 
211
                                attribs         = this .getAttribs (),
 
212
                                colorNode       = this .getColor (),
 
213
                                texCoordNode    = this .getTexCoord (),
 
214
                                normalNode      = this .getNormal (),
 
215
                                coordNode       = this .getCoord (),
 
216
                                textCoords      = this .getTexCoords (),
 
217
                                face            = 0;
 
218
 
 
219
                        if (texCoordNode)
 
220
                                texCoordNode .init (textCoords);
 
221
                
 
222
                        // Fill GeometryNode
 
223
                
 
224
                        for (var i = 0; i < trianglesSize; ++ i)
 
225
                        {
 
226
                                face = Math .floor (i / verticesPerFace);
 
227
 
 
228
                                var index = this .getPolygonIndex (this .getTriangleIndex (i));
 
229
 
 
230
                                for (var a = 0; a < numAttrib; ++ a)
 
231
                                        attrib [a] .addValue (attribs [a], index);
 
232
 
 
233
                                if (colorNode)
 
234
                                {
 
235
                                        if (colorPerVertex)
 
236
                                                this .addColor (colorNode .get1Color (index));
 
237
                                        else
 
238
                                                this .addColor (colorNode .get1Color (face));
 
239
                                }
 
240
 
 
241
                                if (texCoordNode)
 
242
                                        texCoordNode .addTexCoord (textCoords, index);
 
243
        
 
244
                                if (normalNode)
 
245
                                {
 
246
                                        if (normalPerVertex)
 
247
                                                this .addNormal (normalNode .get1Vector (index));
 
248
 
 
249
                                        else
 
250
                                                this .addNormal (normalNode .get1Vector (face));
 
251
                                }
 
252
 
 
253
                                this .addVertex (coordNode .get1Point (index));
 
254
                        }
 
255
                
 
256
                        // Autogenerate normal if not specified.
 
257
 
 
258
                        if (! this .getNormal ())
 
259
                                this .buildNormals (verticesPerPolygon, polygonsSize, trianglesSize);
 
260
 
 
261
                        this .setSolid (this .solid_ .getValue ());
 
262
                        this .setCCW (this .ccw_ .getValue ());
 
263
                },
 
264
                buildNormals: function (verticesPerPolygon, polygonsSize, trianglesSize)
 
265
                {
 
266
                        var normals = this .createNormals (verticesPerPolygon, polygonsSize);
 
267
 
 
268
                        for (var i = 0; i < trianglesSize; ++ i)
 
269
                                this .addNormal (normals [this .getTriangleIndex (i)]);
 
270
                },
 
271
                createNormals: function (verticesPerPolygon, polygonsSize)
 
272
                {
 
273
                        var normals = this .createFaceNormals (verticesPerPolygon, polygonsSize);
 
274
                
 
275
                        if (this .normalPerVertex_ .getValue ())
 
276
                        {
 
277
                                var normalIndex = [ ];
 
278
                
 
279
                                for (var i = 0; i < polygonsSize; ++ i)
 
280
                                {
 
281
                                        var index = this .getPolygonIndex (i);
 
282
 
 
283
                                        if (! normalIndex [index])
 
284
                                                normalIndex [index] = [ ];
 
285
 
 
286
                                        normalIndex [index] .push (i);
 
287
                                }
 
288
 
 
289
                                return this .refineNormals (normalIndex, normals, Math .PI);
 
290
                        }
 
291
                
 
292
                        return normals;
 
293
                },
 
294
                createFaceNormals: function (verticesPerPolygon, polygonsSize)
 
295
                {
 
296
                        var
 
297
                                cw      = ! this .ccw_ .getValue (),
 
298
                                coord   = this .coordNode,
 
299
                                normals = [ ];
 
300
 
 
301
                        for (var i = 0; i < polygonsSize; i += verticesPerPolygon)
 
302
                        {
 
303
                                var normal = this .getPolygonNormal (verticesPerPolygon, coord);
 
304
 
 
305
                                if (cw)
 
306
                                        normal .negate ();
 
307
 
 
308
                                for (var n = 0; n < verticesPerPolygon; ++ n)
 
309
                                        normals .push (normal);
 
310
                        }
 
311
 
 
312
                        return normals;
 
313
                },
 
314
                getPolygonNormal: function (verticesPerPolygon, coord)
 
315
                {
 
316
                        // Determine polygon normal.
 
317
                        // We use Newell's method https://www.opengl.org/wiki/Calculating_a_Surface_Normal here:
 
318
 
 
319
                        var
 
320
                                normal = new Vector3 (0, 0, 0),
 
321
                                next   = coord .get1Point (this .getPolygonIndex (0));
 
322
 
 
323
                        for (var i = 0; i < verticesPerPolygon; ++ i)
 
324
                        {
 
325
                                var
 
326
                                        current = next,
 
327
                                        next    = coord .get1Point (this .getPolygonIndex ((i + 1) % verticesPerPolygon));
 
328
 
 
329
                                normal .x += (current .y - next .y) * (current .z + next .z);
 
330
                                normal .y += (current .z - next .z) * (current .x + next .x);
 
331
                                normal .z += (current .x - next .x) * (current .y + next .y);
 
332
                        }
 
333
 
 
334
                        return normal .normalize ();
 
335
                },
 
336
        });
 
337
 
 
338
        return X3DComposedGeometryNode;
 
339
});
 
340
 
 
341