matrix-engine-wgpu 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,454 @@
1
+ import {BALL_SHADER} from "../shaders/shaders";
2
+ import {mat4, vec3} from 'wgpu-matrix';
3
+ import {Position} from "./matrix-class";
4
+
5
+ var SphereLayout = {
6
+ vertexStride: 8 * 4,
7
+ positionsOffset: 0,
8
+ normalOffset: 3 * 4,
9
+ uvOffset: 6 * 4,
10
+ };
11
+
12
+ export default class MECube {
13
+
14
+ constructor(canvas, device, context, o) {
15
+ this.device = device;
16
+ this.context = context;
17
+
18
+ this.shaderModule = device.createShaderModule({
19
+ code: BALL_SHADER,
20
+ });
21
+
22
+ this.texturesPaths = [];
23
+
24
+ o.texturesPaths.forEach((t) => {
25
+ this.texturesPaths.push(t)
26
+ })
27
+
28
+ this.presentationFormat = navigator.gpu.getPreferredCanvasFormat();
29
+ this.position = new Position(o.position.x, o.position.y, o.position.z)
30
+ this.pipeline = device.createRenderPipeline({
31
+ layout: 'auto',
32
+ vertex: {
33
+ module: this.shaderModule,
34
+ entryPoint: 'vertexMain',
35
+ buffers: [
36
+ {
37
+ arrayStride: SphereLayout.vertexStride,
38
+ attributes: [
39
+ // position
40
+ {shaderLocation: 0, offset: SphereLayout.positionsOffset, format: 'float32x3'},
41
+ // normal
42
+ {shaderLocation: 1, offset: SphereLayout.normalOffset, format: 'float32x3'},
43
+ // uv
44
+ {shaderLocation: 2, offset: SphereLayout.uvOffset, format: 'float32x2', },
45
+ ],
46
+ },
47
+ ],
48
+ },
49
+ fragment: {
50
+ module: this.shaderModule,
51
+ entryPoint: 'fragmentMain',
52
+ targets: [{format: this.presentationFormat, },],
53
+ },
54
+ primitive: {
55
+ topology: 'triangle-list',
56
+ // Backface culling since the sphere is solid piece of geometry.
57
+ // Faces pointing away from the camera will be occluded by faces
58
+ // pointing toward the camera.
59
+ cullMode: 'back',
60
+ },
61
+ // Enable depth testing so that the fragment closest to the camera
62
+ // is rendered in front.
63
+ depthStencil: {
64
+ depthWriteEnabled: true,
65
+ depthCompare: 'less',
66
+ format: 'depth24plus',
67
+ },
68
+ });
69
+
70
+ this.depthTexture = device.createTexture({
71
+ size: [canvas.width, canvas.height],
72
+ format: 'depth24plus',
73
+ usage: GPUTextureUsage.RENDER_ATTACHMENT,
74
+ });
75
+
76
+ this.uniformBufferSize = 4 * 16; // 4x4 matrix
77
+ this.uniformBuffer = device.createBuffer({
78
+ size: this.uniformBufferSize,
79
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
80
+ });
81
+
82
+ // Fetch the images and upload them into a GPUTexture.
83
+ this.texture0 = null;
84
+ this.moonTexture = null;
85
+
86
+ this.settings = {
87
+ useRenderBundles: true,
88
+ asteroidCount: 15,
89
+ };
90
+
91
+ this.loadTex0(this.texturesPaths, device).then(() => {
92
+ this.loadTex1(device).then(() => {
93
+
94
+ this.sampler = device.createSampler({
95
+ magFilter: 'linear',
96
+ minFilter: 'linear',
97
+ });
98
+
99
+ this.transform = mat4.create();
100
+ mat4.identity(this.transform);
101
+
102
+ // Create one large central planet surrounded by a large ring of asteroids
103
+ this.planet = this.createSphereRenderable(1.0);
104
+ this.planet.bindGroup = this.createSphereBindGroup(this.texture0, this.transform);
105
+
106
+ var asteroids = [
107
+ this.createSphereRenderable(0.2, 8, 6, 0.15),
108
+ this.createSphereRenderable(0.13, 8, 6, 0.15)
109
+ ];
110
+
111
+ this.renderables = [this.planet];
112
+
113
+ // this.ensureEnoughAsteroids(asteroids, this.transform);
114
+
115
+ this.renderPassDescriptor = {
116
+ colorAttachments: [
117
+ {
118
+ view: undefined,
119
+ clearValue: {r: 0.0, g: 0.0, b: 0.0, a: 1.0},
120
+ loadOp: 'clear',
121
+ storeOp: 'store',
122
+ },
123
+ ],
124
+ depthStencilAttachment: {
125
+ view: this.depthTexture.createView(),
126
+ depthClearValue: 1.0,
127
+ depthLoadOp: 'clear',
128
+ depthStoreOp: 'store',
129
+ },
130
+ };
131
+
132
+ const aspect = canvas.width / canvas.height;
133
+ this.projectionMatrix = mat4.perspective((2 * Math.PI) / 5, aspect, 1, 100.0);
134
+ this.modelViewProjectionMatrix = mat4.create();
135
+
136
+ this.frameBindGroup = device.createBindGroup({
137
+ layout: this.pipeline.getBindGroupLayout(0),
138
+ entries: [
139
+ {
140
+ binding: 0,
141
+ resource: {buffer: this.uniformBuffer, },
142
+ },
143
+ ],
144
+ });
145
+
146
+ // The render bundle can be encoded once and re-used as many times as needed.
147
+ // Because it encodes all of the commands needed to render at the GPU level,
148
+ // those commands will not need to execute the associated JavaScript code upon
149
+ // execution or be re-validated, which can represent a significant time savings.
150
+ //
151
+ // However, because render bundles are immutable once created, they are only
152
+ // appropriate for rendering content where the same commands will be executed
153
+ // every time, with the only changes being the contents of the buffers and
154
+ // textures used. Cases where the executed commands differ from frame-to-frame,
155
+ // such as when using frustrum or occlusion culling, will not benefit from
156
+ // using render bundles as much.
157
+ this.renderBundle;
158
+ this.updateRenderBundle();
159
+ })
160
+ })
161
+ }
162
+
163
+ ensureEnoughAsteroids(asteroids, transform) {
164
+ for(let i = this.renderables.length;i <= this.settings.asteroidCount;++i) {
165
+ // Place copies of the asteroid in a ring.
166
+ const radius = Math.random() * 1.7 + 1.25;
167
+ const angle = Math.random() * Math.PI * 2;
168
+ const x = Math.sin(angle) * radius;
169
+ const y = (Math.random() - 0.5) * 0.015;
170
+ const z = Math.cos(angle) * radius;
171
+
172
+ mat4.identity(transform);
173
+ mat4.translate(transform, [x, y, z], transform);
174
+ mat4.rotateX(transform, Math.random() * Math.PI, transform);
175
+ mat4.rotateY(transform, Math.random() * Math.PI, transform);
176
+ this.renderables.push({
177
+ ...asteroids[i % asteroids.length],
178
+ bindGroup: this.createSphereBindGroup(this.moonTexture, transform),
179
+ });
180
+ }
181
+ }
182
+
183
+ updateRenderBundle() {
184
+ console.log('sss')
185
+ const renderBundleEncoder = this.device.createRenderBundleEncoder({
186
+ colorFormats: [this.presentationFormat],
187
+ depthStencilFormat: 'depth24plus',
188
+ });
189
+ this.renderScene(renderBundleEncoder);
190
+ this.renderBundle = renderBundleEncoder.finish();
191
+ }
192
+
193
+ createSphereRenderable(radius, widthSegments = 32, heightSegments = 16, randomness = 0) {
194
+
195
+ const sphereMesh = this.createCubeVertices();
196
+ // Create a vertex buffer from the sphere data.
197
+ const vertices = this.device.createBuffer({
198
+ size: sphereMesh.vertices.byteLength,
199
+ usage: GPUBufferUsage.VERTEX,
200
+ mappedAtCreation: true,
201
+ });
202
+ new Float32Array(vertices.getMappedRange()).set(sphereMesh.vertices);
203
+ vertices.unmap();
204
+
205
+ const indices = this.device.createBuffer({
206
+ size: sphereMesh.indices.byteLength,
207
+ usage: GPUBufferUsage.INDEX,
208
+ mappedAtCreation: true,
209
+ });
210
+ new Uint16Array(indices.getMappedRange()).set(sphereMesh.indices);
211
+ indices.unmap();
212
+
213
+ return {
214
+ vertices,
215
+ indices,
216
+ indexCount: sphereMesh.indices.length,
217
+ };
218
+ }
219
+
220
+ createSphereBindGroup(texture, transform) {
221
+
222
+ const uniformBufferSize = 4 * 16; // 4x4 matrix
223
+ const uniformBuffer = this.device.createBuffer({
224
+ size: uniformBufferSize,
225
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
226
+ mappedAtCreation: true,
227
+ });
228
+ new Float32Array(uniformBuffer.getMappedRange()).set(transform);
229
+ uniformBuffer.unmap();
230
+
231
+ const bindGroup = this.device.createBindGroup({
232
+ layout: this.pipeline.getBindGroupLayout(1),
233
+ entries: [
234
+ {
235
+ binding: 0,
236
+ resource: {
237
+ buffer: uniformBuffer,
238
+ },
239
+ },
240
+ {
241
+ binding: 1,
242
+ resource: this.sampler,
243
+ },
244
+ {
245
+ binding: 2,
246
+ resource: texture.createView(),
247
+ },
248
+ ],
249
+ });
250
+
251
+ return bindGroup;
252
+ }
253
+
254
+ getTransformationMatrix(pos) {
255
+ const viewMatrix = mat4.identity();
256
+ mat4.translate(viewMatrix, vec3.fromValues(pos.x, pos.y, pos.z), viewMatrix);
257
+ const now = Date.now() / 1000;
258
+ mat4.rotateZ(viewMatrix, Math.PI * 0, viewMatrix);
259
+ mat4.rotateX(viewMatrix, Math.PI * 0, viewMatrix);
260
+ mat4.rotateY(viewMatrix, -45, viewMatrix);
261
+ mat4.multiply(this.projectionMatrix, viewMatrix, this.modelViewProjectionMatrix);
262
+ return this.modelViewProjectionMatrix;
263
+ }
264
+
265
+ async loadTex1(device) {
266
+ return new Promise(async (resolve) => {
267
+ const response = await fetch('./res/textures/tex1.jpg');
268
+ const imageBitmap = await createImageBitmap(await response.blob());
269
+ this.moonTexture = device.createTexture({
270
+ size: [imageBitmap.width, imageBitmap.height, 1],
271
+ format: 'rgba8unorm',
272
+ usage:
273
+ GPUTextureUsage.TEXTURE_BINDING |
274
+ GPUTextureUsage.COPY_DST |
275
+ GPUTextureUsage.RENDER_ATTACHMENT,
276
+ });
277
+ var moonTexture = this.moonTexture
278
+ device.queue.copyExternalImageToTexture(
279
+ {source: imageBitmap},
280
+ {texture: moonTexture},
281
+ [imageBitmap.width, imageBitmap.height]
282
+ );
283
+ resolve()
284
+ })
285
+ }
286
+
287
+ async loadTex0(texturesPaths, device) {
288
+ return new Promise(async (resolve) => {
289
+ const response = await fetch(texturesPaths[0]);
290
+ const imageBitmap = await createImageBitmap(await response.blob());
291
+ console.log('WHAT IS THIS ', this)
292
+ this.texture0 = device.createTexture({
293
+ size: [imageBitmap.width, imageBitmap.height, 1],
294
+ format: 'rgba8unorm',
295
+ usage:
296
+ GPUTextureUsage.TEXTURE_BINDING |
297
+ GPUTextureUsage.COPY_DST |
298
+ GPUTextureUsage.RENDER_ATTACHMENT,
299
+ });
300
+ var texture0 = this.texture0
301
+ device.queue.copyExternalImageToTexture(
302
+ {source: imageBitmap},
303
+ {texture: texture0},
304
+ [imageBitmap.width, imageBitmap.height]
305
+ );
306
+ resolve()
307
+ })
308
+
309
+ }
310
+
311
+
312
+ // Render bundles function as partial, limited render passes, so we can use the
313
+ // same code both to render the scene normally and to build the render bundle.
314
+ renderScene(passEncoder) {
315
+
316
+ if(typeof this.renderables === 'undefined') return;
317
+
318
+ passEncoder.setPipeline(this.pipeline);
319
+ passEncoder.setBindGroup(0, this.frameBindGroup);
320
+
321
+ // Loop through every renderable object and draw them individually.
322
+ // (Because many of these meshes are repeated, with only the transforms
323
+ // differing, instancing would be highly effective here. This sample
324
+ // intentionally avoids using instancing in order to emulate a more complex
325
+ // scene, which helps demonstrate the potential time savings a render bundle
326
+ // can provide.)
327
+ let count = 0;
328
+ for(const renderable of this.renderables) {
329
+ passEncoder.setBindGroup(1, renderable.bindGroup);
330
+ passEncoder.setVertexBuffer(0, renderable.vertices);
331
+ passEncoder.setIndexBuffer(renderable.indices, 'uint16');
332
+ passEncoder.drawIndexed(renderable.indexCount);
333
+ if(++count > this.settings.asteroidCount) {
334
+ break;
335
+ }
336
+ }
337
+ }
338
+
339
+ createCubeVertices(options) {
340
+ if(typeof options === 'undefined') {
341
+ var options = {
342
+ scale: 1,
343
+ useUVShema4x2: false
344
+ }
345
+ }
346
+
347
+ let vertices;
348
+ if(options.useUVShema4x2 == true) {
349
+ vertices = new Float32Array([
350
+ // position | texture coordinate
351
+ //-------------+----------------------
352
+ // front face select the top left image 1, 0.5,
353
+ -1, 1, 1, 1, 0, 0, 0, 0,
354
+ -1, -1, 1, 1, 0, 0, 0, 0.5,
355
+ 1, 1, 1, 1, 0, 0, 0.25, 0,
356
+ 1, -1, 1, 1, 0, 0, 0.25, 0.5,
357
+ // right face select the top middle image
358
+ 1, 1, -1, 1, 0, 0, 0.25, 0,
359
+ 1, 1, 1, 1, 0, 0, 0.5, 0,
360
+ 1, -1, -1, 1, 0, 0, 0.25, 0.5,
361
+ 1, -1, 1, 1, 0, 0, 0.5, 0.5,
362
+ // back face select to top right image
363
+ 1, 1, -1, 1, 0, 0, 0.5, 0,
364
+ 1, -1, -1, 1, 0, 0, 0.5, 0.5,
365
+ -1, 1, -1, 1, 0, 0, 0.75, 0,
366
+ -1, -1, -1, 1, 0, 0, 0.75, 0.5,
367
+ // left face select the bottom left image
368
+ -1, 1, 1, 1, 0, 0, 0, 0.5,
369
+ -1, 1, -1, 1, 0, 0, 0.25, 0.5,
370
+ -1, -1, 1, 1, 0, 0, 0, 1,
371
+ -1, -1, -1, 1, 0, 0, 0.25, 1,
372
+ // bottom face select the bottom middle image
373
+ 1, -1, 1, 1, 0, 0, 0.25, 0.5,
374
+ -1, -1, 1, 1, 0, 0, 0.5, 0.5,
375
+ 1, -1, -1, 1, 0, 0, 0.25, 1,
376
+ -1, -1, -1, 1, 0, 0, 0.5, 1,
377
+ // top face select the bottom right image
378
+ -1, 1, 1, 1, 0, 0, 0.5, 0.5,
379
+ 1, 1, 1, 1, 0, 0, 0.75, 0.5,
380
+ -1, 1, -1, 1, 0, 0, 0.5, 1,
381
+ 1, 1, -1, 1, 0, 0, 0.75, 1,
382
+ ]);
383
+ } else {
384
+ vertices = new Float32Array([
385
+ // position | texture coordinate
386
+ //-------------+----------------------
387
+ // front face select the top left image 1, 0.5,
388
+ -1, 1, 1, 1, 0, 0, 0, 0,
389
+ -1, -1, 1, 1, 0, 0, 0, 1,
390
+ 1, 1, 1, 1, 0, 0, 1, 0,
391
+ 1, -1, 1, 1, 0, 0, 1, 1,
392
+ // right face select the top middle image
393
+ 1, 1, -1, 1, 0, 0, 0, 0,
394
+ 1, 1, 1, 1, 0, 0, 0, 1,
395
+ 1, -1, -1, 1, 0, 0, 1, 0,
396
+ 1, -1, 1, 1, 0, 0, 1, 1,
397
+ // back face select to top right image
398
+ 1, 1, -1, 1, 0, 0, 0, 0,
399
+ 1, -1, -1, 1, 0, 0, 0, 1,
400
+ -1, 1, -1, 1, 0, 0, 1, 0,
401
+ -1, -1, -1, 1, 0, 0, 1, 1,
402
+ // left face select the bottom left image
403
+ -1, 1, 1, 1, 0, 0, 0, 0,
404
+ -1, 1, -1, 1, 0, 0, 0, 1,
405
+ -1, -1, 1, 1, 0, 0, 1, 0,
406
+ -1, -1, -1, 1, 0, 0, 1, 1,
407
+ // bottom face select the bottom middle image
408
+ 1, -1, 1, 1, 0, 0, 0, 0,
409
+ -1, -1, 1, 1, 0, 0, 0, 1,
410
+ 1, -1, -1, 1, 0, 0, 1, 0,
411
+ -1, -1, -1, 1, 0, 0, 1, 1,
412
+ // top face select the bottom right image
413
+ -1, 1, 1, 1, 0, 0, 0, 0,
414
+ 1, 1, 1, 1, 0, 0, 0, 1,
415
+ -1, 1, -1, 1, 0, 0, 1, 0,
416
+ 1, 1, -1, 1, 0, 0, 1, 1,
417
+ ])
418
+ }
419
+
420
+
421
+ const indices = new Uint16Array([
422
+ 0, 1, 2, 2, 1, 3, // front
423
+ 4, 5, 6, 6, 5, 7, // right
424
+ 8, 9, 10, 10, 9, 11, // back
425
+ 12, 13, 14, 14, 13, 15, // left
426
+ 16, 17, 18, 18, 17, 19, // bottom
427
+ 20, 21, 22, 22, 21, 23, // top
428
+ ]);
429
+
430
+ return {
431
+ vertices,
432
+ indices,
433
+ numVertices: indices.length,
434
+ };
435
+ }
436
+
437
+ draw = () => {
438
+ if(this.moonTexture == null) {
439
+ console.log('not ready')
440
+ return;
441
+ }
442
+ const transformationMatrix = this.getTransformationMatrix(this.position);
443
+ this.device.queue.writeBuffer(
444
+ this.uniformBuffer,
445
+ 0,
446
+ transformationMatrix.buffer,
447
+ transformationMatrix.byteOffset,
448
+ transformationMatrix.byteLength
449
+ );
450
+ this.renderPassDescriptor.colorAttachments[0].view = this.context
451
+ .getCurrentTexture()
452
+ .createView();
453
+ }
454
+ }
@@ -0,0 +1,171 @@
1
+ // Sub classes for matrix-wgpu
2
+
3
+ /**
4
+ * @description Base class
5
+ * Position { x, y, z }
6
+ */
7
+
8
+ export class Position {
9
+
10
+ constructor(x, y, z) {
11
+
12
+ // Not in use for nwo this is from matrix-engine project [nameUniq]
13
+ this.nameUniq = null;
14
+
15
+ if(typeof x == 'undefined') x = 0;
16
+ if(typeof y == 'undefined') y = 0;
17
+ if(typeof z == 'undefined') z = 0;
18
+
19
+ this.x = x;
20
+ this.y = y;
21
+ this.z = z;
22
+
23
+ this.velY = 0;
24
+ this.velX = 0;
25
+ this.velZ = 0;
26
+ this.inMove = false;
27
+ this.targetX = x;
28
+ this.targetY = y;
29
+ this.targetZ = z;
30
+ this.thrust = 0.01;
31
+
32
+ return this;
33
+ }
34
+
35
+ setSpeed(n) {
36
+ if(typeof n === 'number') {
37
+ this.thrust = n;
38
+ } else {
39
+ console.log('Description: arguments (w, h) must be type of number.');
40
+ }
41
+ }
42
+
43
+ translateByX(x) {
44
+ this.inMove = true;
45
+ this.targetX = x;
46
+ };
47
+
48
+ translateByY(y) {
49
+ this.inMove = true;
50
+ this.targetY = y;
51
+ }
52
+
53
+ translateByZ(z) {
54
+ this.inMove = true;
55
+ this.targetZ = z;
56
+ }
57
+
58
+ translateByXY(x, y) {
59
+ this.inMove = true;
60
+ this.targetX = x;
61
+ this.targetY = y;
62
+ }
63
+
64
+ translateByXZ(x, z) {
65
+ this.inMove = true;
66
+ this.targetX = x;
67
+ this.targetZ = z;
68
+ }
69
+
70
+ translateByYZ(y, z) {
71
+ this.inMove = true;
72
+ this.targetY = y;
73
+ this.targetZ = z;
74
+ }
75
+
76
+ onTargetPositionReach() {}
77
+
78
+ update() {
79
+ var tx = this.targetX - this.x,
80
+ ty = this.targetY - this.y,
81
+ tz = this.targetZ - this.z,
82
+ dist = Math.sqrt(tx * tx + ty * ty + tz * tz);
83
+ this.velX = (tx / dist) * this.thrust;
84
+ this.velY = (ty / dist) * this.thrust;
85
+ this.velZ = (tz / dist) * this.thrust;
86
+ if(this.inMove == true) {
87
+ if(dist > this.thrust) {
88
+ this.x += this.velX;
89
+ this.y += this.velY;
90
+ this.z += this.velZ;
91
+
92
+ // // from me
93
+ // if(net && net.connection && typeof em === 'undefined' && App.scene[this.nameUniq].net.enable == true) net.connection.send({
94
+ // netPos: {x: this.x, y: this.y, z: this.z},
95
+ // netObjId: this.nameUniq,
96
+ // });
97
+
98
+ } else {
99
+ this.x = this.targetX;
100
+ this.y = this.targetY;
101
+ this.z = this.targetZ;
102
+ this.inMove = false;
103
+ this.onTargetPositionReach();
104
+
105
+ // // from me
106
+ // if(net && net.connection && typeof em === 'undefined' && App.scene[this.nameUniq].net.enable == true) net.connection.send({
107
+ // netPos: {x: this.x, y: this.y, z: this.z},
108
+ // netObjId: this.nameUniq,
109
+ // });
110
+ }
111
+ }
112
+ }
113
+
114
+ get worldLocation() {
115
+ return [this.x, this.y, this.z];
116
+ }
117
+
118
+ SetX(newx, em) {
119
+ this.x = newx;
120
+ this.targetX = newx;
121
+ this.inMove = false;
122
+
123
+ // if(net && net.connection && typeof em === 'undefined' &&
124
+ // App.scene[this.nameUniq].net && App.scene[this.nameUniq].net.enable == true) {
125
+ // net.connection.send({
126
+ // netPos: {x: this.x, y: this.y, z: this.z},
127
+ // netObjId: this.nameUniq,
128
+ // });
129
+ // }
130
+ }
131
+
132
+ SetY(newy, em) {
133
+ this.y = newy;
134
+ this.targetY = newy;
135
+ this.inMove = false;
136
+ // if(net && net.connection && typeof em === 'undefined' &&
137
+ // App.scene[this.nameUniq].net && App.scene[this.nameUniq].net.enable == true) net.connection.send({
138
+ // netPos: {x: this.x, y: this.y, z: this.z},
139
+ // netObjId: this.nameUniq,
140
+ // });
141
+ }
142
+
143
+ SetZ(newz, em) {
144
+ this.z = newz;
145
+ this.targetZ = newz;
146
+ this.inMove = false;
147
+ // if(net && net.connection && typeof em === 'undefined' &&
148
+ // App.scene[this.nameUniq].net && App.scene[this.nameUniq].net.enable == true) net.connection.send({
149
+ // netPos: {x: this.x, y: this.y, z: this.z},
150
+ // netObjId: this.nameUniq,
151
+ // });
152
+ }
153
+
154
+ setPosition(newx, newy, newz) {
155
+ this.x = newx;
156
+ this.y = newy;
157
+ this.z = newz;
158
+ this.targetX = newx;
159
+ this.targetY = newy;
160
+ this.targetZ = newz;
161
+ this.inMove = false;
162
+
163
+ // from me
164
+ // if(App.scene[this.nameUniq] && net && net.connection && typeof em === 'undefined' &&
165
+ // App.scene[this.nameUniq].net && App.scene[this.nameUniq].net.enable == true) net.connection.send({
166
+ // netPos: {x: this.x, y: this.y, z: this.z},
167
+ // netObjId: this.nameUniq,
168
+ // });
169
+ }
170
+ }
171
+