~holger-seelig/cobweb.js/1.4

« back to all changes in this revision

Viewing changes to cobweb.js/cobweb/Components/ParticleSystems/SurfaceEmitter.js

  • Committer: Holger Seelig
  • Date: 2016-04-30 05:14:33 UTC
  • Revision ID: holger.seelig@yahoo.de-20160430051433-i69hy9l7hqfcmef0
Added SurfaceEmitter.

Show diffs side-by-side

added added

removed removed

Lines of Context:
6
6
        "cobweb/Basic/FieldDefinitionArray",
7
7
        "cobweb/Components/ParticleSystems/X3DParticleEmitterNode",
8
8
        "cobweb/Bits/X3DConstants",
 
9
        "cobweb/Bits/X3DCast",
 
10
        "standard/Math/Geometry/Triangle3",
 
11
        "standard/Math/Numbers/Vector3",
 
12
        "standard/Math/Algorithm",
9
13
],
10
14
function ($,
11
15
          Fields,
12
16
          X3DFieldDefinition,
13
17
          FieldDefinitionArray,
14
18
          X3DParticleEmitterNode, 
15
 
          X3DConstants)
 
19
          X3DConstants,
 
20
          X3DCast,
 
21
          Triangle3,
 
22
          Vector3,
 
23
          Algorithm)
16
24
{
17
25
"use strict";
18
26
 
 
27
        var
 
28
                vertex1  = new Vector3 (0, 0, 0),
 
29
                vertex2  = new Vector3 (0, 0, 0),
 
30
                vertex3  = new Vector3 (0, 0, 0),
 
31
                direction = new Vector3 (0, 0, 0);
 
32
 
19
33
        function SurfaceEmitter (executionContext)
20
34
        {
21
35
                X3DParticleEmitterNode .call (this, executionContext);
22
36
 
23
37
                this .addType (X3DConstants .SurfaceEmitter);
 
38
 
 
39
                this .surfaceNode    = null;
 
40
                this .areaSoFarArray = [ 0 ];
24
41
        }
25
42
 
26
43
        SurfaceEmitter .prototype = $.extend (Object .create (X3DParticleEmitterNode .prototype),
46
63
                {
47
64
                        return "emitter";
48
65
                },
 
66
                initialize: function ()
 
67
                {
 
68
                        X3DParticleEmitterNode .prototype .initialize .call (this);
 
69
 
 
70
                        this .surface_ .addInterest (this, "set_surface__");
 
71
 
 
72
                        this .set_surface__ ();
 
73
                },
 
74
                set_surface__: function ()
 
75
                {
 
76
                        if (this .surfaceNode)
 
77
                                this .surfaceNode .removeInterest (this, "set_geometry__");
 
78
 
 
79
                        this .surfaceNode = X3DCast (X3DConstants .X3DGeometryNode, this .surface_);
 
80
 
 
81
                        if (this .surfaceNode)
 
82
                                this .surfaceNode .addInterest (this, "set_geometry__");
 
83
 
 
84
                        this .set_geometry__ ();
 
85
                },
 
86
                set_geometry__: function ()
 
87
                {
 
88
                        if (this .surfaceNode)
 
89
                        {               
 
90
                                delete this .getRandomPosition;
 
91
                                delete this .getRandomVelocity;
 
92
 
 
93
                                var
 
94
                                        areaSoFar      = 0,
 
95
                                        areaSoFarArray = this .areaSoFarArray,
 
96
                                        vertices       = this .surfaceNode .getVertices ();
 
97
                
 
98
                                areaSoFarArray .length = 1;
 
99
 
 
100
                                for (var i = 0, length = vertices .length; i < length; i += 12)
 
101
                                {
 
102
                                        vertex1 .set (vertices [i + 0], vertices [i + 1], vertices [i + 2]);
 
103
                                        vertex2 .set (vertices [i + 4], vertices [i + 5], vertices [i + 6]);
 
104
                                        vertex3 .set (vertices [i + 8], vertices [i + 9], vertices [i + 10]);
 
105
 
 
106
                                        areaSoFar += Triangle3 .area (vertex1, vertex2, vertex3);
 
107
                                        areaSoFarArray .push (areaSoFar);
 
108
                                }
 
109
                        }
 
110
                        else
 
111
                        {
 
112
                                this .getRandomPosition = getPosition;
 
113
                                this .getRandomVelocity = this .getSphericalRandomVelocity;
 
114
 
 
115
                                direction .set (0, 0, 0);
 
116
                        }
 
117
                },
 
118
                getRandomPosition: function (position)
 
119
                {
 
120
                        // Determine index0 and weight.
 
121
 
 
122
                        var
 
123
                                areaSoFarArray = this .areaSoFarArray,
 
124
                                length         = areaSoFarArray .length,
 
125
                                fraction       = Math .random () * areaSoFarArray [length - 1],
 
126
                                index0         = 0,
 
127
                                index1         = 0,
 
128
                                weight         = 0;
 
129
 
 
130
                        if (length == 1 || fraction <= areaSoFarArray [0])
 
131
                        {
 
132
                                index0 = 0;
 
133
                                weight = 0;
 
134
                        }
 
135
                        else if (fraction >= areaSoFarArray [length - 1])
 
136
                        {
 
137
                                index0 = length - 2;
 
138
                                weight = 1;
 
139
                        }
 
140
                        else
 
141
                        {
 
142
                                var index = Algorithm .upperBound (areaSoFarArray, 0, length, fraction, Algorithm .less);
 
143
 
 
144
                                if (index < length)
 
145
                                {
 
146
                                        index1 = index;
 
147
                                        index0 = index - 1;
 
148
                        
 
149
                                        var
 
150
                                                key0 = areaSoFarArray [index0],
 
151
                                                key1 = areaSoFarArray [index1];
 
152
                        
 
153
                                        weight = Algorithm .clamp ((fraction - key0) / (key1 - key0), 0, 1);
 
154
                                }
 
155
                                else
 
156
                                {
 
157
                                        index0 = 0;
 
158
                                        weight = 0;
 
159
                                }
 
160
                        }
 
161
 
 
162
                        // Interpolate and set position.
 
163
 
 
164
                        var
 
165
                                i        = index0 * 12,
 
166
                                vertices = this .surfaceNode .getVertices ();
 
167
 
 
168
                        // Random barycentric coordinates.
 
169
 
 
170
                        var
 
171
                                u = Math .random (),
 
172
                                v = Math .random ();
 
173
                
 
174
                        if (u + v > 1)
 
175
                        {
 
176
                                u = 1 - u;
 
177
                                v = 1 - v;
 
178
                        }
 
179
 
 
180
                        var t = 1 - u - v;
 
181
 
 
182
                        position .x = u * vertices [i + 0] + v * vertices [i + 4] + t * vertices [i + 8];
 
183
                        position .y = u * vertices [i + 1] + v * vertices [i + 5] + t * vertices [i + 9];
 
184
                        position .z = u * vertices [i + 2] + v * vertices [i + 6] + t * vertices [i + 10];
 
185
 
 
186
                        var
 
187
                                i       = index0 * 9,
 
188
                                normals = this .surfaceNode .getNormals ();
 
189
 
 
190
                        direction .x = u * normals [i + 0] + v * normals [i + 3] + t * normals [i + 6];
 
191
                        direction .y = u * normals [i + 1] + v * normals [i + 4] + t * normals [i + 7];
 
192
                        direction .z = u * normals [i + 2] + v * normals [i + 5] + t * normals [i + 8];
 
193
 
 
194
                        return position;
 
195
                },
 
196
                getRandomVelocity: function (velocity)
 
197
                {
 
198
                        var speed = this .getRandomSpeed ();
 
199
 
 
200
                        velocity .x = direction .x * speed;
 
201
                        velocity .y = direction .y * speed;
 
202
                        velocity .z = direction .z * speed;
 
203
 
 
204
                        return velocity;
 
205
                },
49
206
        });
50
207
 
 
208
        function getPosition (position)
 
209
        {
 
210
                return this .position .set (0, 0, 0);
 
211
        }
 
212
 
51
213
        return SurfaceEmitter;
52
214
});
53
215