5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
1

Проекты на Three.js и Babylon.js

11.01.2018, 00:34. Показов 9558. Ответов 38

Author24 — интернет-сервис помощи студентам
Предлагаю делиться здесь проектами/примерами на Three.js и Babylon.js

Для затравки выложу примеры из начальных официальных туториалов.

Getting Started (Three.js)

Песочница: https://plnkr.co/edit/vaiCvJNy... ?p=preview

Исходники

PHP/HTML
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
<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <title>Three.js - Getting Started</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/89/three.min.js"></script>
 
    <style>
        body {
            margin: 0;
        }
 
        canvas {
            width: 100%;
            height: 100%
        }
    </style>
</head>
 
<body>
    <script>
        var scene = new THREE.Scene();
        var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
 
        var renderer = new THREE.WebGLRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);
 
        var geometry = new THREE.BoxGeometry(1, 1, 1);
        var material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
        var cube = new THREE.Mesh(geometry, material);
        scene.add(cube);
 
        camera.position.z = 5;
 
        var animate = function ()
        {
            requestAnimationFrame(animate);
 
            cube.rotation.x += 0.1;
            cube.rotation.y += 0.1;
 
            renderer.render(scene, camera);
        };
 
        animate();
    </script>
</body>
 
</html>


Getting Started (Babylon.js)

Песочница: https://plnkr.co/edit/HUdxpwY3... ?p=preview

Исходники

PHP/HTML
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
<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <title>Babylon.js - Getting Started</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babylonjs/2.5.0/babylon.js"></script>
 
    <style>
        html,
        body {
            overflow: hidden;
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
        }
 
        #renderCanvas {
            width: 100%;
            height: 100%;
            touch-action: none;
        }
    </style>
</head>
 
<body>
    <canvas id="renderCanvas"></canvas>
 
    <script>
        window.addEventListener('DOMContentLoaded', function ()
        {
            // get the canvas DOM element
            var canvas = document.getElementById('renderCanvas');
 
            // load the 3D engine
            var engine = new BABYLON.Engine(canvas, true);
 
            // createScene function that creates and return the scene
            var createScene = function ()
            {
                // create a basic BJS Scene object
                var scene = new BABYLON.Scene(engine);
 
                // create a FreeCamera, and set its position to (x:0, y:5, z:-10)
                var camera = new BABYLON.FreeCamera('camera1', new BABYLON.Vector3(0, 5, -10), scene);
 
                // target the camera to scene origin
                camera.setTarget(BABYLON.Vector3.Zero());
 
                // attach the camera to the canvas
                camera.attachControl(canvas, false);
 
                // create a basic light, aiming 0,1,0 - meaning, to the sky
                var light = new BABYLON.HemisphericLight('light1', new BABYLON.Vector3(0, 1, 0), scene);
 
                // create a built-in "sphere" shape; its constructor takes 5 params: name, width, depth, subdivisions, scene
                var sphere = BABYLON.Mesh.CreateSphere('sphere1', 16, 2, scene);
 
                // move the sphere upward 1/2 of its height
                sphere.position.y = 1;
 
                // create a built-in "ground" shape; its constructor takes the same 5 params as the sphere's one
                var ground = BABYLON.Mesh.CreateGround('ground1', 6, 6, 2, scene);
 
                // return the created scene
                return scene;
            }
 
            // call the createScene function
            var scene = createScene();
 
            // run the render loop
            engine.runRenderLoop(function ()
            {
                scene.render();
            });
 
            // the canvas/window resize event handler
            window.addEventListener('resize', function ()            
            {
                engine.resize();
            });
        });
    </script>
</body>
 
</html>
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
11.01.2018, 00:34
Ответы с готовыми решениями:

Babylon JS Не отображается текстура skybox
Я только начал изучать Babylon JS, и столкнулся с проблемой. Изучая данный...

При обращении к словарю Babylon система зависает
При обращении к словарю Babylon система зависает так, что невозможно даже запустить Диспетчер...

Поиск в Google перескакивает в utils.babylon (Firefox)
При любом поиске в гугле сначала выходит собственно результат поиска, а через секунду перескакивает...

Проекты, не видят другие проекты в одном решении
Столкнулся с такой проблемой, что проекты не видят друг друга в одном решении, пишу комплексное...

Проекты c#
Мужики подскажите какой нибудь сайт, на котором присутствует большое кол-во исходников, всяческих...

38
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
06.06.2023, 15:52  [ТС] 21
Author24 — интернет-сервис помощи студентам
Подключение Babylon.js с помощь importmap

PHP/HTML
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
<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
 
    <title>Document</title>
</head>
 
<body>
    <a href="https://forum.babylonjs.com/t/problems-loading-babylon-via-es-modules/2031">Topic</a>
    <br>
    <br>
    <div id="output"><div>
 
    <canvas id="renderCanvas"></canvas>
 
    <!-- Import maps polyfill -->
    <!-- Remove this when import maps will be widely supported -->
    <script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script>
 
    <script type="importmap">
        {
            "imports": {
                "@babylonjs/core": "https://unpkg.com/@babylonjs/core@6.3.1",
                "@babylonjs/core/": "https://unpkg.com/@babylonjs/core@6.3.1/"
            }
        }
    </script>
 
    <script type="module">
        import { Engine } from "@babylonjs/core/Engines/engine.js";
        import { Scene } from "@babylonjs/core/scene.js";
 
        const canvas = document.getElementById("renderCanvas");
        const engine = new Engine(canvas, true);
        console.log(engine);
        const scene = new Scene(engine);
        console.log(Scene);
    </script>
 
    <!-- <script type="module" src="js/bundle.js"></script> -->
</body>
 
</html>
0
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
09.06.2023, 21:12  [ТС] 22
Подключение Phaser и @box2d/core с помощью importmap

Заметка в документации о поддержке ESM: New Feature - ESM Support

index.html

PHP/HTML
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
<!doctype html>
 
<html>
<head>
    <title>Example</title>
    <link rel="stylesheet" href="css/style.css">
</head>
 
<body>
    <canvas id="renderCanvas"></canvas>
 
    <!-- Since importmap is not yet supported by all browsers, it is
        necessary to add the polyfill es-module-shims.min.js -->
    <script async src="https://unpkg.com/es-module-shims@0.1.7/dist/es-module-shims.min.js"></script>
 
    <script type="importmap">
        {
            "imports": {
                "@box2d/core": "https://cdn.jsdelivr.net/npm/@box2d/core@0.10.0/+esm",
                "phaser": "https://cdn.jsdelivr.net/npm/phaser@3.60.0/dist/phaser.esm.js"
            }
        }
    </script>
 
    <script type="module" src="./js/main.js"></script>
</body>
</html>
js/main.js

Javascript
1
2
3
4
5
6
7
8
9
import { b2World } from "@box2d/core";
import { AUTO, Scene, Game } from "phaser";
 
// Box2D
const world = b2World.Create({ x: 0, y: 3 });
console.log(world.GetGravity());
 
// Phaser
console.log(Game);
0
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
21.07.2023, 17:08  [ТС] 23
Сделал отладочное рисование коллайдеров типа "Коробка" и "Круг" с помощью движка игровой физики Box2D-WASM и игрового движка Melon.js на JavaScript

Живая демка в браузере

Код на GitHub

Песочницы:



Миниатюры
Название: debug-drawer-box2dwasm-melonjs-js.gif
Просмотров: 302

Размер: 188.7 Кб
0
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
01.08.2023, 16:52  [ТС] 24
Jumping with ground check using ray casting, Box2D-WASM, Melon.js, and JavaScript

Playgrounds/Sandboxes:

Topic and discussions:



Miniatures
Проекты на Three.js и Babylon.js
Вложения
Тип файла: zip can-jump-with-ray-casting-box2dwasm-melonjs-js.zip (246.6 Кб, 0 просмотров)
0
219 / 22 / 2
Регистрация: 12.06.2021
Сообщений: 205
Записей в блоге: 2
22.09.2023, 22:07 25
Изучаю Babylon. Поэтому вот пример сцены: лес, сундук, костер и небо.
Проекты на Three.js и Babylon.js

Всего используется две модели: sky и campfire.
Сам код:
PHP/HTML
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
<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
 
    <title>Scene - BabylonJS</title>
 
    <style>
        html,
        body {
            overflow: hidden;
            width: 100%;
            height: 100%;
            margin: 0;
            padding: 0;
        }
 
        #renderCanvas {
            width: 100%;
            height: 100%;
            touch-action: none;
        }
    </style>
</head>
 
<body>
    <canvas id="renderCanvas"></canvas>
    <script src="https://cdn.babylonjs.com/babylon.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@pryme8/scrolls.js/src/scrolls.min.js"></script>
    <script src="https://cdn.babylonjs.com/babylon.js"></script>
    <script src="https://cdn.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
    <script src='https://code.jquery.com/pep/0.4.1/pep.js'></script>
    <script id="rendered-js">
        "use strict";
        class Game {
            constructor(canvasElement) {
                // Создание холста и движка.
                this._canvas = document.getElementById(canvasElement);
                this._engine = new BABYLON.Engine(this._canvas, true);
            }
 
            createScene() {
                // Создание базового объект сцены BJS.
                this._scene = new BABYLON.Scene(this._engine);
                // Создание FreeCamera и установка положения (x:0, y:1, z:-5).
                this._camera = new BABYLON.FreeCamera('camera', new BABYLON.Vector3(0, 1, -5), this._scene);
 
                // Прикрепить камеру к холсту.
                this._camera.attachControl(this._canvas, false);
 
                this._camera.speed = 0.25;
 
                // Создание базового источника света, нацеливание на 0,1,0 — то есть в небо.
                this._light = new BABYLON.HemisphericLight('light1', new BABYLON.Vector3(0, 1, 0), this._scene);
 
                this._light.intensity = 0.5;
 
                const envTex = BABYLON.CubeTexture.CreateFromPrefilteredData(
                    "./environment/sky.env",
                    this._scene
                );
 
                this._scene.environmentTexture = envTex;
                this._scene.createDefaultSkybox(envTex, true);
            }
 
            async CreateCampfire() {
                const models = BABYLON.SceneLoader.ImportMeshAsync("", "./models/", "campfire.glb", this._scene);
                console.log("Babylon");
                console.log("models", models);
            }
 
            async CreateBarrel() {
                BABYLON.SceneLoader.ImportMesh("", "./models/", "barrel.glb", this._scene, (meshes) => { console.log("meshes", meshes); });
 
                //const models = BABYLON.SceneLoader.ImportMeshAsync("", "./models/", "barrel.glb", this._scene); 
                //console.log("models",models);
            }
 
            doRender() {
                //Запуск цикла рендеринга.
                this._engine.runRenderLoop(() => {
                    this._scene.render();
                });
                //Обработчик событий. Изменения размера холста/окна.
                window.addEventListener('resize', () => {
                    this._engine.resize();
                });
            }
        }
 
        window.addEventListener('DOMContentLoaded', () => {
            // Создание игры, используя renderCanvas.
            let game = new Game('renderCanvas');
            // Создание сцены
            game.createScene();
            //game.CreateBarrel();
            game.CreateCampfire();
            //Запуск цикла рендеринга
            game.doRender();
        });
    </script>
</body>
 
</html>
Модели вместе с исходниками можно скачать по ссылке.
https://disk.yandex.ru/d/bRav8F3obhzDCA

Чтобы поворачивать объект нужно зажимать кнопку мыши. Перемещение стрелки.
Вложения
Тип файла: zip Babylon3DEx1.zip (2.76 Мб, 5 просмотров)
1
219 / 22 / 2
Регистрация: 12.06.2021
Сообщений: 205
Записей в блоге: 2
24.09.2023, 16:08 26
Наша солнечная система в натуральную величину, выполненная на ThreeJS.
Добавлены звезды и у каждой планеты есть своя орбита.
Проекты на Three.js и Babylon.js

Размещены все планеты, солнечной системе. Чтобы приблизить к каждой планете, нужно нажимать стрелки на клавиатуре или кнопку мыши.
Проекты на Three.js и Babylon.js

Код:
PHP/HTML
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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
<html>
<head>
<meta charset="utf8">
<title>Solar System</title>
<style>
body{
  background: black;
}
 
</style>
<script src="./three.js"></script>
<script src="RollControls.js"></script>
</head>
<body>
<script>
var scene, camera, render, container, controls;
var light;
 
 
var Orbit = function(radius){
  this.radius = radius;
  this.draw = function(scene){
    var og = new THREE.Geometry();
    var om = new THREE.ParticleBasicMaterial({color:0xbfbfbf,size:1,opacity:0.3,sizeAttenuation:false});
    for(var i = 0; i<500;i++){
      var v = new THREE.Vector3();
      v.x = Math.sin(180/Math.PI*i)*this.radius;
      v.z = Math.cos(180/Math.PI*i)*this.radius;
      og.vertices.push(v);
    }
    var obj = new THREE.ParticleSystem(og,om);
    scene.add(obj);
  
  };
};
 
var Planet = function(radius, texture){
  this.radius = radius;
  this.texture = texture;
  this.init = function(){
    var g = new THREE.SphereGeometry(this.radius,40,40);
    var onloadT = THREE.ImageUtils.loadTexture(this.texture);
    onloadT.anisotropy = 8;
    var m = new THREE.MeshPhongMaterial({map:onloadT});
    var M = new THREE.Mesh(g,m);
    M.castShadow = true;
    return M;
  }
}
 
 
var W,H;
 W = parseInt(document.body.clientWidth);
 H = parseInt(document.body.clientHeight);
 
container = document.createElement('div');
document.body.appendChild(container);
 
camera = new THREE.PerspectiveCamera(45,W/H,1,1000000);
camera.position.z = 200000;
 
 
scene = new THREE.Scene();
controls = new THREE.RollControls(camera);
controls.movementSpeed = 20000;
controls.lookSpeed = 1.6;
 
 
light = new THREE.PointLight(0xffffff,1.4,30000);
light.position.set(0,0,0);
 
light.castShadow = true;
light.shaowMapWidth = 2048;
light.shadowMapHeight = 2048;
scene.add(light);
 
var starsGeometry = new THREE.Geometry();
var starsMaterial = new THREE.ParticleBasicMaterial({color:0xbbbbbb,opacity:0.8,size:1,sizeAttenuation:false});
var stars; //реальный объект Particle
 
for(var i=0; i<15000; i++){
  var vertex = new THREE.Vector3();
  vertex.x = Math.random()*2-1;
  vertex.y = Math.random()*2-1;
  vertex.z = Math.random()*2-1;
  vertex.multiplyScalar(6000);
  starsGeometry.vertices.push(vertex);
}
 
stars = new THREE.ParticleSystem(starsGeometry,starsMaterial);
stars.scale.set(50,50,50);
scene.add(stars);
 
var starsGeometry2 = new THREE.Geometry();
var starsMaterial2 = new THREE.ParticleBasicMaterial({color:0xbbbbbb,opacity:1,size:1,sizeAttenuation:false});
var stars2; //реальный объект Particle
 
for(var i=0; i<3000; i++){
  var vertex = new THREE.Vector3();
  vertex.x = Math.random()*2-1;
  vertex.y = Math.random()*2-1;
  vertex.z = Math.random()*2-1;
  vertex.multiplyScalar(6000);
  starsGeometry2.vertices.push(vertex);
}
 
stars2 = new THREE.ParticleSystem(starsGeometry2,starsMaterial2);
stars2.scale.set(70,150,30);
scene.add(stars2);
 
var ambient = new THREE.AmbientLight(0x222222);
scene.add(ambient);
 
//Sun
var sun, sun_geom, sun_mat;
sun_geom = new THREE.SphereGeometry(2300,30,30);
 
var texture = THREE.ImageUtils.loadTexture('./textures/2k_sun.jpg');
texture.anisotropy = 8;
 
sun_mat = new THREE.MeshPhongMaterial({map:texture,emissive:0xffffff});
sun = new THREE.Mesh(sun_geom,sun_mat);
scene.add(sun);
 
//Mercury
var mercury = new Planet(60,'./textures/2k_mercury.jpg').init();
scene.add(mercury);
 
 
//Venus
var venus = new Planet(90,'./textures/2k_venus_surface.jpg').init();
scene.add(venus);
 
//Mars
var mars = new Planet(80,'./textures/2k_mars.jpg').init();
scene.add(mars);
 
 
//Jupeter
var jupiter = new Planet(350,'./textures/2k_jupiter.jpg').init();
scene.add(jupiter);
 
 
 
//Saturn 
var saturn = new Planet(230,'./textures/2k_saturn.jpg').init();
scene.add(saturn);
 
 
 
var ring_saturn_geom = new THREE.Geometry();
var ring_saturn_mat = new THREE.ParticleBasicMaterial({color:0x3A3A3A,opacity:0.3,size:1,sizeAttenuation:false});
 
for(var i=0; i<20000;i++)
{
  var vertex = new THREE.Vector3();
  vertex.x = Math.sin(180/Math.PI*i)*(550-i/80);
  vertex.y = Math.random()*20;
  vertex.z = Math.cos(180/Math.PI*i)*(550-i/80);
  ring_saturn_geom.vertices.push(vertex);
}
 
var ring = new THREE.ParticleSystem(ring_saturn_geom,ring_saturn_mat);
ring.castShadow = true;
scene.add(ring);
 
//Uranus
var uranus = new Planet(170,'./textures/2k_uranus.jpg').init();
scene.add(uranus);
 
 
//Neptune
var neptune = new Planet(170,'./textures/2k_neptune.jpg').init();
scene.add(neptune);
 
 
//Earth
var earth = new Planet(50,'./textures/2k_earth_daymap.jpg').init();
scene.add(earth);
 
 
var earth_orbit_geom = new THREE.Geometry();
var earth_orbit_mat = new THREE.ParticleBasicMaterial({color:0xbfbfbf,size:1,opacity:0.3,sizeAttenuation:false});
 
for(var i=0; i<400;i++)
{
  var vertex = new THREE.Vector3();
  vertex.x = Math.sin(180/Math.PI*i)*30000;
  vertex.z = Math.cos(180/Math.PI*i)*30000;
  earth_orbit_geom.vertices.push(vertex);
}
 
var earth_orbit = new THREE.ParticleSystem(earth_orbit_geom,earth_orbit_mat);
earth_orbit.castShadow = true;
scene.add(earth_orbit);
 
var mercury_orbit = new Orbit(8000);
mercury_orbit.draw(scene);
 
var venus_orbit = new Orbit(17000);
venus_orbit.draw(scene);
 
var mars_orbit = new Orbit(50000);
mars_orbit.draw(scene);
 
var jupiter_orbit = new Orbit(-74000);
jupiter_orbit.draw(scene);
 
var saturn_orbit = new Orbit(98000);
saturn_orbit.draw(scene);
 
var uranus_orbit = new Orbit(120000);
uranus_orbit.draw(scene);
 
var neptune_orbit = new Orbit(180000);
neptune_orbit.draw(scene);
 
render = new THREE.WebGLRenderer();
render.setSize(W,H);
container.appendChild(render.domElement);
var t = 0;
var y = 0;
 
document.addEventListener('mousemove',function(event){
  y = parseInt(event.offsetY);
});
 
animate();
 
function animate(){
  requestAnimationFrame(animate);
  controls.update(0.01);
  sun.rotation.y+=0.001;
  
  earth.position.x = Math.sin(t*0.1)*30000;
  earth.position.z = Math.cos(t*0.1)*30000;
  
 
  mercury.position.x = Math.sin(t*0.5)*8000;
  mercury.position.z = Math.cos(t*0.5)*8000;
  
  venus.position.x = Math.sin(t*0.2)*17000;
  venus.position.z = Math.cos(t*0.2)*17000;
  
  mars.position.x = Math.sin(t*0.08)*50000;
  mars.position.z = Math.cos(t*0.08)*50000;
  
  jupiter.position.x = Math.sin(t*0.08)*(-74000);
  jupiter.position.z = Math.cos(t*0.08)*(-74000);
  
  saturn.position.x = Math.sin(t*0.08)*98000;
  saturn.position.z = Math.cos(t*0.08)*98000;
  
  ring.position.x = saturn.position.x;
  ring.position.z = saturn.position.z;
  
  uranus.position.x = Math.sin(t*0.02)*120000;
  uranus.position.z = Math.cos(t*0.02)*120000;
  
  neptune.position.x = Math.sin(t*0.01)*180000;
  neptune.position.z = Math.cos(t*0.01)*180000;
  
  earth.rotation.y += 0.01;
  mercury.rotation.y += 0.01;
  venus.rotation.y += 0.01;
  mars.rotation.y += 0.01;
  jupiter.rotation.y += 0.01;
  saturn.rotation.y+=0.01;
  ring.rotation.y-=0.001;
  uranus.rotation.y+=0.01;
  neptune.rotation.y+=0.01;
 
  t+=Math.PI/180*2*0.1;
  
  render.render(scene,camera);
}
</script>
</body>
</html>
Архив для скачивания, в котором присутствуют текстуры в высоком разрешении и дополнительный код RollControls.js, отвечающий за управление камеры.

https://disk.yandex.ru/d/C6kHrBQFlIScJQ
Вложения
Тип файла: zip SolarSystem.zip (7.20 Мб, 6 просмотров)
1
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
24.09.2023, 16:50  [ТС] 27
Рисование коллайдеров на Babylon.js для физических движков: Box2D-WASM, OimoPhysics, Ammo.js и rapier3d-compat

Ссылка на тему на официальном форуме Babylon.js: Table of contents for examples with debug drawers of colliders for physics engines using Babylon.js and JavaScript

1. Box2D-WASM:

Проекты на Three.js и Babylon.js


2. OimoPhysics:

Проекты на Three.js и Babylon.js


3. Ammo.js:

Проекты на Three.js и Babylon.js


4. rapier3d-compat:

Название: d1cdbdc8b3d333bcccc60009cdf33acb60b88ec3.gif
Просмотров: 230

Размер: 479.8 Кб
Вложения
Тип файла: zip debug-drawer-box2dwasm-babylonjs-js-main.zip (279.2 Кб, 0 просмотров)
Тип файла: zip debug-drawer-oimophysics-babylonjs-js-main.zip (495.8 Кб, 0 просмотров)
Тип файла: zip debug-drawer-ammo-babylonjs-js-main.zip (525.7 Кб, 0 просмотров)
Тип файла: zip debug-render-by-frankieali-rapier3dcompat-rollup-babylonjs-js-main.zip (418.9 Кб, 0 просмотров)
1
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
24.09.2023, 17:02  [ТС] 28
Рисование коллайдеров на Three.js для физического движка Box2D-WASM

Ссылка на тему на официальном форуме Box2D-WASM: Basic Examples of Using Box2D-WASM with Three.js in JavaScript

Название: 262547008-9b455762-8f78-470a-8227-f7799d1ee45c.gif
Просмотров: 231

Размер: 71.4 Кб
Вложения
Тип файла: zip debug-drawer-box2dwasm-threejs-js-main.zip (71.9 Кб, 0 просмотров)
0
219 / 22 / 2
Регистрация: 12.06.2021
Сообщений: 205
Записей в блоге: 2
24.09.2023, 22:35 29
Интересный эксперимент, оказывается можно использовать свои 2d проекты для 3d, точнее математику.
Проекты на Three.js и Babylon.js

Пример, перемещение планет по орбите. Вот код 2d.
HTML5
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
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Пример перемещение объекта по кругу</title>
 
<script>
window.onload = function()
{
  var degrees = 0;
  var orbit = new Array();
  var sun1, planet1, planet2, planet3;
  const canvas = document.getElementById("drawingCanvas");
  const ctx = canvas.getContext("2d");
  canvas.style.background = "#A0A0A0"
 
  
 
SpaceObj = function(x,y,r,color)
{
  this.x = x;
  this.y = y;
  this.r = r;
  this.color = color;
  this.orbit = orbit;
  this.degrees = degrees;
  this.draw = function(ctx)
  {
    ctx.beginPath();
    ctx.fillStyle = this.color;
    ctx.ellipse(this.x, this.y, this.r, this.r, Math.PI / 2, 0, 2 * Math.PI);
    ctx.stroke();
    ctx.fill();
    
  }
}
function draw()
{
  sun1 = new SpaceObj(400,300,40,"orange");
  sun1.draw(ctx);
 
  planet1 = new SpaceObj(400,50,20,"Silver");
  planet1.orbit = {
    radius: 100,
    speed: 2,
    angle: 0 
  };
  
  planet1.draw(ctx);
  
  planet2 = new SpaceObj(400,50,20,"LightGrey");
  planet2.orbit = {
    radius: 200,
    speed: 1,
    angle: 0 
  };
  planet2.draw(ctx);
  planet3 = new SpaceObj(400,50,20,"LightYellow");
  planet3.orbit = {
    radius: 250,
    speed: 0.5,
    angle: 0 
  };
  planet3.draw(ctx);
  
 
 
}
 
draw();
 
function moveObject(){
 
  ctx.clearRect(0,0,800,600);
  //Отрисовка объектов в цикле(повторений)
  planet1.draw(ctx);    
  planet2.draw(ctx);
  planet3.draw(ctx);        
  sun1.draw(ctx);   
 
    planet1.orbit.angle = planet1.degrees * (Math.PI/180);
    planet1.degrees = planet1.degrees+planet1.orbit.speed;
    
    planet2.orbit.angle = planet2.degrees * (Math.PI/180);
    planet2.degrees = planet2.degrees+planet2.orbit.speed;
    
    planet3.orbit.angle = planet3.degrees * (Math.PI/180);
    planet3.degrees = planet3.degrees+planet3.orbit.speed;
    
    //Создание точных координат как в Babylon
    planet1.x = sun1.x+planet1.orbit.radius * Math.sin(planet1.orbit.angle);
    planet1.y = sun1.y+planet1.orbit.radius * Math.cos(planet1.orbit.angle);
    
    planet2.x = sun1.x+planet2.orbit.radius * Math.sin(planet2.orbit.angle);
    planet2.y = sun1.y+planet2.orbit.radius * Math.cos(planet2.orbit.angle);
    
    planet3.x = sun1.x+planet3.orbit.radius * Math.sin(planet3.orbit.angle);
    planet3.y = sun1.y+planet3.orbit.radius * Math.cos(planet3.orbit.angle);
    
    window.requestAnimationFrame(moveObject);
}
 
moveObject();
 
}
</script>
</head>
<body>
<canvas id="drawingCanvas" width="800" height="600"></canvas>
</body>
</html>
Примечание: код я написала, чтобы был похож на конструкцию Babylon.
Теперь 3d код:
HTML5
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
<!DOCTYPE html>
<html lang="en" >
 
<head>
  <meta charset="UTF-8">
 
<title>BabylonJS Planets</title>
 
 
<style>
html,body{
  overflow:hidden;
  width:100%;
  height:100%;
  margin:0;
  padding:0;
}
 
#renderCanvas{
  width:100%;
  height:100%;
}
</style>
 
 
  
  
</head>
 
<body>
  <canvas id="renderCanvas">
</canvas>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/babylonjs/2.4.1/babylon.js'></script>
      <script>
var canvas = document.getElementById('renderCanvas');
var engine = new BABYLON.Engine(canvas, true);
 
var init = function () {
 
  var scene = new BABYLON.Scene(engine);
 
  var camera = new BABYLON.ArcRotateCamera('camera', 0, 0, 15, BABYLON.Vector3.Zero(), scene);
 
  camera.upperRadiusLimit = 20000;
 
  camera.attachControl(canvas);
 
  scene.clearColor = new BABYLON.Color3(0, 0, 0);
 
  var sun = BABYLON.Mesh.CreateSphere('sun', 16, 4, scene);
 
  var sunMaterial = new BABYLON.StandardMaterial('sunMaterial', scene);
  
  sunMaterial.emissiveTexture = new BABYLON.Texture('./textures/2k_sun.jpg', scene);
  sunMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0);
  sunMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
 
  sun.material = sunMaterial;
 
 
  //sunlight
  var sunlight = new BABYLON.PointLight('sunlight', BABYLON.Vector3.Zero(), scene);
  sunlight.intesity = 2;
 
 
  //2k_earth
  var planetMaterial1 = new BABYLON.StandardMaterial('planetMat', scene);
 
 
  planetMaterial1.diffuseTexture = new BABYLON.Texture('./textures/2k_earth_daymap.jpg', scene);
  planetMaterial1.specularColor = new BABYLON.Color3(0, 0, 0);
  
  //2k_saturn
  var planetMaterial2 = new BABYLON.StandardMaterial('planetMat', scene);
  
  
  planetMaterial2.diffuseTexture = new BABYLON.Texture('./textures/2k_saturn.jpg', scene);
  planetMaterial2.specularColor = new BABYLON.Color3(0, 0, 0);
 
  //2k_mars.jpg
  var planetMaterial3 = new BABYLON.StandardMaterial('planetMat', scene);
  
  planetMaterial3.diffuseTexture = new BABYLON.Texture('./textures/2k_mars.jpg', scene);
  planetMaterial3.specularColor = new BABYLON.Color3(0, 0, 0);
 
 
 
  var planet1 = BABYLON.Mesh.CreateSphere('planet1', 16, 1, scene);
  var planet2 = BABYLON.Mesh.CreateSphere('planet2', 16, 2, scene);
  var planet3 = BABYLON.Mesh.CreateSphere('planet3', 16, 3, scene);
 
  planet1.position.x = 4;
  planet2.position.x = 8;
  planet3.position.x = 16;
 
  planet1.material = planetMaterial1;
  planet2.material = planetMaterial2;
  planet3.material = planetMaterial3;
  
  
 
  planet1.orbit = {
    radius: planet1.position.x,
    speed: 0.01,
    angle: 0 };
 
 
  planet2.orbit = {
    radius: planet2.position.x,
    speed: 0.001,
    angle: 0 };
 
 
  planet3.orbit = {
    radius: planet3.position.x,
    speed: 0.02,
    angle: 0 };
 
 
 
  //Skybox
  var skybox = BABYLON.Mesh.CreateBox('skybox', 10000, scene);
  var skyboxMaterial = new BABYLON.StandardMaterial('skyboxMat', scene);
 
  skyboxMaterial.backFaceCulling = false;
  skyboxMaterial.infiniteDistance = true;
 
  skyboxMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0);
  skyboxMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
 
 
 
  skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture('https://www.babylonjs-playground.com/textures/skyboxBlack', scene);
  skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
 
  skybox.material = skyboxMaterial;
 
  scene.beforeRender = function () {
    planet1.position.x = planet1.orbit.radius * Math.sin(planet1.orbit.angle);
    planet1.position.z = planet1.orbit.radius * Math.cos(planet1.orbit.angle);
    planet1.orbit.angle += planet1.orbit.speed;
 
    planet2.position.x = planet2.orbit.radius * Math.sin(planet2.orbit.angle);
    planet2.position.z = planet2.orbit.radius * Math.cos(planet2.orbit.angle);
    planet2.orbit.angle += planet2.orbit.speed;
 
    planet3.position.x = planet3.orbit.radius * Math.sin(planet3.orbit.angle);
    planet3.position.z = planet3.orbit.radius * Math.cos(planet3.orbit.angle);
    planet3.orbit.angle += planet3.orbit.speed;
  };
 
  return scene;
 
};
 
var scene = init();
 
engine.runRenderLoop(function () {
  scene.render();
});
 
window.addEventListener('resize', function () {
  engine.resize();
});
 
</script>
 
  
</body>
 
</html>
В отличии от ThreeJS где задний фон вселенной мы использовали текстуру в высоком разрешении, здесь я использую коробку CubeTexture.

Есть известные мне старые игры, где игровой мир завернут в коробку, это GTA 3, Vice City и Serious Sam. Давно приметила, что в редакторе Серьезного Сэма, предлагается выбрать фон для уровня “коробку”

Вот где я взяла текстуры https://endoc.cnbabylon.com/resources/playground_textures, там есть раздел cubeTexture.

Исходники на Babylon(с текстурами) и 2D(с функцией ellipse, вместо текстур).

https://disk.yandex.ru/d/0Xx0ijZS6QHu2w
Вложения
Тип файла: zip PlanetOrbits2D_3D.zip (2.11 Мб, 0 просмотров)
1
219 / 22 / 2
Регистрация: 12.06.2021
Сообщений: 205
Записей в блоге: 2
24.09.2023, 22:44 30
Пока делала функцию c sin и cos для 2d перемещения по орбите, также сделала еще перемещение по орбите без синусов и косинусов используя sqrt. Пример (достаточно скопировать в html документ и запустить в браузере). В этом примере учитывается такой показатель как масса объектов.
HTML5
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
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Пример перемещение объекта по кругу</title>
<script>
window.onload = function()
{
var G = 1;
var t0,dt;
var arr1 = {x:0,y:0};
var r1 = {x:0,y:0};
var force = {x:0,y:0};
var M,m,acc;
var r = 250;
var sun1, planet;
const canvas = document.getElementById("drawingCanvas");
const ctx = canvas.getContext("2d");
 
SpaceObj = function(x,y,r,color,m)
{
  this.x = x;
  this.y = y;
  this.r = r;
  this.color = color;
  this.m = m;
  this.draw = function(ctx)
  {
    ctx.beginPath();
    ctx.fillStyle = this.color;
    ctx.ellipse(this.x, this.y, this.r, this.r, Math.PI / 2, 0, 2 * Math.PI);
    ctx.stroke();
    ctx.fill();
    
  }
}
function draw()
{
  sun1 = new SpaceObj(400,300,70,"orange",1000000);
  sun1.draw(ctx);
 
  planet = new SpaceObj(400,50,20,"red",1);
  planet.draw(ctx);
  
  var M = sun1.m;
  var m = planet.m;
 
  var v = Math.sqrt(G*M*m/r);
 
 
 
  arr1 = 
  {
    x:v,y:0
  };
 
}
 
t0 = new Date().getTime(); 
 
draw();
 
 
function next() {
    var t1 = new Date().getTime(); 
 
 
   window.requestAnimationFrame(next);
   
   var t1 = new Date().getTime(); 
  
    dt = 0.001*(t1-t0); 
    t0 = t1;
    if (dt>0.2) {dt=0;};    
   
   move1();
   
}
function move1()
{
 moveObject();
 calcForce();
 updateAccel();
 updateVelo();
}
 
function moveObject(){
 
  ctx.clearRect(0,0,800,600);
  planet.draw(ctx); 
  sun1.draw(ctx);   
 
    planet.x = planet.x + dt*arr1.x;
  planet.y = planet.y + dt*arr1.y;
}
 
 
 
 
function calcForce()
{
  r1 = 
    {
        x:planet.x - sun1.x,
        y:planet.y - sun1.y
  };
  
  var lengthSquared = 
    (planet.x - sun1.x)*(planet.x - sun1.x) + 
    (planet.y - sun1.y)*(planet.y - sun1.y);  
    var len = Math.sqrt(lengthSquared); 
    force = 
    {
        x:-G*sun1.m*planet.m/(lengthSquared*len)*r1.x, 
        y:-G*sun1.m*planet.m/(lengthSquared*len)*r1.y
    }
}
 
function updateAccel(){
 
 
    var lengthSquared = (planet.x - sun1.x)*(planet.x - sun1.x) + 
    (planet.y - sun1.y)*(planet.y - sun1.y);  
    var len = Math.sqrt(lengthSquared); 
 
    acc = 
    {
      x:1/planet.m*(-G*sun1.m*planet.m/(lengthSquared*len))*r1.x,
      y:1/planet.m*(-G*sun1.m*planet.m/(lengthSquared*len))*r1.y
    }
    
    console.log(acc);
 
}
 
function updateVelo(){
  arr1 = 
  {
      x:arr1.x + dt*acc.x,
      y:arr1.y + dt*acc.y
  };
}
 
next();
}
</script>
</head>
<body>
<canvas id="drawingCanvas" width="800" height="600"></canvas>
</body>
</html>
1
219 / 22 / 2
Регистрация: 12.06.2021
Сообщений: 205
Записей в блоге: 2
26.09.2023, 08:15 31
Освещение с красным оттенком как в клубе.
Проекты на Three.js и Babylon.js

Дневной свет.
Проекты на Three.js и Babylon.js

Полумрачное освещение, как от слабой лампы.
Проекты на Three.js и Babylon.js

Накладывание теней(не доделано).
Проекты на Three.js и Babylon.js

Исходники находятся в архиве, также в архив добавлены необходимые библиотеки.
3DLighting.zip

Для перенаправления освещения используется инструмент перемещения по оси Gizmos, такой же можно видеть в графических 3d редакторах типа Blender.
Название: img5.jpg
Просмотров: 201

Размер: 9.5 Кб

Чтобы запустить исходники вам потребуется модель. Ее я упаковала в отдельный архив. Это комната занимает места 100мб. Разумеется, создавать браузерные игры с такими большими моделями не рекомендуется. Но наш пример создан с целью ознакомления и показа как работает освещение.

Кому интересно скачайте архив по ссылке https://disk.yandex.ru/d/EsCgBhDJMtj5qQ, там папка 3d room, в ней находится папка models. В исходниках также есть пустая папка models, (файл 3d-модели LightingScene.glb) поместите в пустую папку models и запускайте исходники.
Вложения
Тип файла: rar room3D.part1.rar (20.00 Мб, 0 просмотров)
Тип файла: rar room3D.part2.rar (20.00 Мб, 0 просмотров)
Тип файла: rar room3D.part3.rar (20.00 Мб, 0 просмотров)
Тип файла: rar room3D.part4.rar (20.00 Мб, 0 просмотров)
Тип файла: rar room3D.part5.rar (19.52 Мб, 0 просмотров)
1
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
17.01.2024, 00:44  [ТС] 32
Пример воспроизведения звука с помощью Web Audio API на Qt WebAssembly, C++ и JavaScript. Здесь 2D звук, но Web Audio API может воспроизводить 3D звуки. В примере две кнопки: "Run" и "Play". Сначала нужно нажать "Run", а потом "Play". С помощью WebAssembly приложение написанное на C++ запускается в один клик прямо в браузере, без необходимости скачивать EXE: https://replit.com/@8Observer8... pi-qt6-cpp



main.cpp

C++ (Qt)
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
#include <QtWidgets/QApplication>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QWidget>
#include <emscripten.h>
 
EM_JS(void, call_init, (),
      {
          my_init();
      })
 
EM_JS(void, call_run, (),
      {
          my_run();
      })
 
EM_JS(void, call_play, (),
      {
          playSound();
      })
 
class Widget : public QWidget
{
    Q_OBJECT
 
public:
    Widget()
    {
        call_init();
        runButton = new QPushButton("Run");
        playButton = new QPushButton("Play");
        playButton->setEnabled(false);
        QVBoxLayout *vbox = new QVBoxLayout();
        vbox->addWidget(runButton);
        vbox->addWidget(playButton);
        vbox->addStretch();
        setLayout(vbox);
        connect(runButton, &QPushButton::pressed, this, &Widget::runButtonClick);
        connect(playButton, &QPushButton::pressed, this, &Widget::playButtonClick);
    }
 
private slots:
 
    void runButtonClick() {
        call_run();
        runButton->setEnabled(false);
        playButton->setEnabled(true);
    }
 
    void playButtonClick() {
        call_play();
    }
 
private:
    QPushButton *runButton;
    QPushButton *playButton;
};
 
#include "main.moc"
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}
my_script.js

Javascript
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
let audioContext, decideArrayBuffer, decideAudioBuffer;
 
async function my_init() {
    console.log("init");
    const decideResponse = await fetch("assets/sounds/decidemp3-14575.mp3");
    decideArrayBuffer = await decideResponse.arrayBuffer();
}
 
async function my_run() {
    console.log("my run");
    audioContext = new window.AudioContext();
    decideAudioBuffer = await audioContext.decodeAudioData(decideArrayBuffer);
}
 
function play(audioBuffer, isLoop = false) {
    const source = audioContext.createBufferSource();
    source.buffer = audioBuffer;
    source.loop = isLoop;
    const gain = audioContext.createGain();
    source.connect(gain).connect(audioContext.destination);
    gain.gain.value = 0.3;
    source.start();
    return source;
}
 
function playSound() {
    play(decideAudioBuffer);
}
Миниатюры
Проекты на Three.js и Babylon.js
0
219 / 22 / 2
Регистрация: 12.06.2021
Сообщений: 205
Записей в блоге: 2
28.01.2024, 15:48 33
Перемещение машинки с прицепами. Может ездить по горам есть гравитация. Пример выполнен на Babylon + Energy.js.
Проекты на Three.js и Babylon.js

Пример не мой, вот ссылка на видео.

Исходники находятся в описании и есть демонстративная версия в онлайне. Именно ее я и выгрузила вместе с ассетами, чтобы протестировать. Вот ссылка на исходники.
https://disk.yandex.ru/d/cW5vcDJRnVHtig
Вложения
Тип файла: zip CameraRotateThirdPerson.zip (1.40 Мб, 6 просмотров)
0
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
06.03.2024, 17:11  [ТС] 34
Пример на PhysX и Three.js. Взят отсюда. Здесь PhysX и Three.js загружаются в скрипт типа "module". Я скопировал оригинальный пример из песочницы SBEdit в песочницу Plunker. Мне из всех песочниц больше всего нравится Plunker потому что в ней мой разбивать свой код на файлы и загружать модели, текстуры, звуки и другие ассеты.

Песочницы:



PHP/HTML
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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
<!doctype html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <title>Physx Example</title>
        <meta name="description" content="Trying out Nvidia Physx using physx-js and Threejs" />
        <style>
            body {
                overflow: hidden;
                margin: 0px;
            }
        </style>
        <script type="importmap">
            {
                "imports": {
                    "three": "/build/three.module.js",
                    "three/addons/": "/jsm/"
                }
            }
        </script>
        <script src="https://cdn.jsdelivr.net/npm/physx-js/dist/physx.release.js"></script>
    </head>
    <body>
        <script type="module">
            import * as THREE from 'three'
            import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
 
            // Inspired from code found at 
            // https://github.com/ashconnell/physx-js
            // https://manthrax.github.io/acp/
 
            const makeEntities = () => {
                let ids = 0
                const entities = []
 
                entities.push({
                    id: ++ids,
                    transform: {
                        position: [0, 0, 0],
                        rotation: [0, 0, 0, 1]
                    },
                    model: {
                        type: 'box',
                        size: [10, 0.1, 10]
                    },
                    body: {
                        type: 'box',
                        size: [10, 0.1, 10],
                        dynamic: false
                    }
                })
 
                for (let i = 0; i < 12; i++) {
                    for (let j = 0; j < 12; j++) {
                        entities.push({
                            id: ++ids,
                            transform: {
                                position: [-2.5 + i + 0.1 * i, Math.floor(Math.random() * 10) + 1, -2.5 + j + 0.1 * j],
                                rotation: [0, 0, 0.3, 0.7]
                            },
                            model: {
                                type: 'box',
                                size: [1, 1, 1]
                            },
                            body: {
                                type: 'box',
                                size: [1, 1, 1],
                                dynamic: true
                            }
                        })
                    }
                }
 
                return entities
            }
 
            const PhysX = PHYSX({
                locateFile(path) {
                    if (path.endsWith('.wasm')) {
                        return 'https://cdn.jsdelivr.net/npm/physx-js/dist/physx.release.wasm'
                    }
                    return path
                },
                onRuntimeInitialized() {
                    console.clear()
                    console.log('PhysX loaded')
 
                    // setup physx scene
                    const entities = makeEntities()
                    const bodies = {}
 
                    const version = PhysX.PX_PHYSICS_VERSION
                    const defaultErrorCallback = new PhysX.PxDefaultErrorCallback()
                    const allocator = new PhysX.PxDefaultAllocator()
                    const foundation = PhysX.PxCreateFoundation(version, allocator, defaultErrorCallback)
                    const triggerCallback = {
                        onContactBegin: () => {},
                        onContactEnd: () => {},
                        onContactPersist: () => {},
                        onTriggerBegin: () => {},
                        onTriggerEnd: () => {}
                    }
                    const physxSimulationCallbackInstance = PhysX.PxSimulationEventCallback.implement(triggerCallback)
 
                    const physics = PhysX.PxCreatePhysics(version, foundation, new PhysX.PxTolerancesScale(), false, null)
                    PhysX.PxInitExtensions(physics, null)
                    const sceneDesc = PhysX.getDefaultSceneDesc(physics.getTolerancesScale(), 0, physxSimulationCallbackInstance)
                    const physxScene = physics.createScene(sceneDesc)
 
                    entities.forEach((entity) => {
                        let geometry
                        if (entity.body.type === 'box') {
                            geometry = new PhysX.PxBoxGeometry(
                                // PhysX uses half-extents
                                entity.body.size[0] / 2,
                                entity.body.size[1] / 2,
                                entity.body.size[2] / 2
                            )
                        }
                        if (entity.body.type === 'sphere') {
                            geometry = new Physx.PxSphereGeometry(...entity.body.size)
                        }
                        const material = physics.createMaterial(0.2, 0.2, 0.2)
                        const flags = new PhysX.PxShapeFlags(PhysX.PxShapeFlag.eSCENE_QUERY_SHAPE.value | PhysX.PxShapeFlag.eSIMULATION_SHAPE.value)
                        const shape = physics.createShape(geometry, material, false, flags)
 
                        const filterData = new PhysX.PxFilterData(1, 1, 0, 0)
                        shape.setQueryFilterData(filterData)
                        shape.setSimulationFilterData(filterData)
 
                        const transform = {
                            translation: {
                                x: entity.transform.position[0],
                                y: entity.transform.position[1],
                                z: entity.transform.position[2]
                            },
                            rotation: {
                                x: entity.transform.rotation[0],
                                y: entity.transform.rotation[1],
                                z: entity.transform.rotation[2],
                                w: entity.transform.rotation[3]
                            }
                        }
                        let body
                        if (entity.body.dynamic) {
                            body = physics.createRigidDynamic(transform)
                        } else {
                            body = physics.createRigidStatic(transform)
                        }
                        body.attachShape(shape)
                        bodies[entity.id] = body
                        physxScene.addActor(body, null)
                    })
 
                    const updatePhysx = (entities) => {
                        physxScene.simulate(1 / 60, true)
                        physxScene.fetchResults(true)
                        entities.forEach((entity) => {
                            const body = bodies[entity.id]
 
                            const transform = body.getGlobalPose()
                            if (transform.translation.y < -10) {
                                const v = body.getLinearVelocity()
                                v.x = 0
                                v.y = 0
                                v.z = 0
                                body.setLinearVelocity(v, true)
 
                                transform.translation.x = Math.random() * 5 - 2.5
                                transform.translation.y = Math.random() * 6 + 4
                                transform.translation.z = Math.random() * 5 - 2.5
                                body.setGlobalPose(transform, true)
                            }
 
                            entity.transform.position[0] = transform.translation.x
                            entity.transform.position[1] = transform.translation.y
                            entity.transform.position[2] = transform.translation.z
                            entity.transform.rotation[0] = transform.rotation.x
                            entity.transform.rotation[1] = transform.rotation.y
                            entity.transform.rotation[2] = transform.rotation.z
                            entity.transform.rotation[3] = transform.rotation.w
                        })
                    }
 
                    // setup threejs
                    const meshes = {}
 
                    const scene = new THREE.Scene()
 
                    const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
                    camera.position.set(5, 7, 9)
 
                    const renderer = new THREE.WebGLRenderer()
                    renderer.setSize(window.innerWidth, window.innerHeight)
                    document.body.appendChild(renderer.domElement)
 
                    const controls = new OrbitControls(camera, renderer.domElement)
                    controls.enableDamping = true
 
                    entities.forEach((entity) => {
                        let geometry
                        if (entity.model.type === 'box') {
                            geometry = new THREE.BoxGeometry(entity.model.size[0], entity.model.size[1], entity.model.size[2])
                        }
                        const material = new THREE.MeshNormalMaterial()
                        const mesh = new THREE.Mesh(geometry, material)
                        mesh.position.fromArray(entity.transform.position)
                        mesh.quaternion.fromArray(entity.transform.rotation)
                        mesh.castShadow = true
                        mesh.receiveShadow = true
                        meshes[entity.id] = mesh
                        scene.add(mesh)
                    })
 
                    function onWindowResize() {
                        camera.aspect = window.innerWidth / window.innerHeight
                        camera.updateProjectionMatrix()
                        renderer.setSize(window.innerWidth, window.innerHeight)
                    }
                    window.addEventListener('resize', onWindowResize, false)
 
                    // start rendering updates
                    function animate() {
                        requestAnimationFrame(animate)
 
                        controls.update()
 
                        entities.forEach((entity) => {
                            meshes[entity.id].position.fromArray(entity.transform.position)
                            meshes[entity.id].quaternion.fromArray(entity.transform.rotation)
                        })
 
                        updatePhysx(entities)
 
                        renderer.render(scene, camera)
                    }
 
                    animate()
                }
            })
        </script>
    </body>
</html>
0
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
06.03.2024, 17:13  [ТС] 35
Пример рисования коллайдеров физического движка PhysX на <canvas> в контексте "2d" с использованием библиотеки линейной алгебры glMatrix. PhysX используется в скрипте типа "module". Пример не мой. Его опубликовали в теме здесь. PhysX - кандидат на создание контроллера от третьего лица.

Песочница: https://sbedit.net/41255c40b51... a28db2f052



PHP/HTML
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
<!DOCTYPE html>
<head>
    <title>PhysX Test</title>
    <style>
        html, body, canvas {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
        }
 
        canvas {
            display: block;
        }
    </style>
</head>
<body>
    <canvas></canvas>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/3.4.2/gl-matrix-min.js" integrity="sha512-eV9ExyTa3b+YHr99IBTYpwk4wbgDMDlfW8uTxhywO8dWb810fGUSKDgHhEv1fAqmJT4jyYnt1iWWMW4FRxeQOQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script type="module">
        import PhysX from "https://esm.sh/physx-js-webidl"
 
        PhysX().then(function(PhysX) {
            var version = PhysX.PHYSICS_VERSION;
            console.log('PhysX loaded! Version: ' + ((version >> 24) & 0xff) + '.' + ((version >> 16) & 0xff) + '.' + ((version >> 8) & 0xff));
 
            var allocator = new PhysX.PxDefaultAllocator();
            var errorCb = new PhysX.PxDefaultErrorCallback();
            var foundation = PhysX.CreateFoundation(version, allocator, errorCb);
            console.log('Created PxFoundation');
 
            var tolerances = new PhysX.PxTolerancesScale();
            var physics = PhysX.CreatePhysics(version, foundation, tolerances);
            console.log('Created PxPhysics');
 
            // create scene
            var tmpVec = new PhysX.PxVec3(0, -9.81, 0);
            var sceneDesc = new PhysX.PxSceneDesc(tolerances);
            sceneDesc.set_gravity(tmpVec);
            sceneDesc.set_cpuDispatcher(PhysX.DefaultCpuDispatcherCreate(0));
            sceneDesc.set_filterShader(PhysX.DefaultFilterShader());
            var scene = physics.createScene(sceneDesc);
            console.log('Created scene');
 
            // create a default material
            var material = physics.createMaterial(0.5, 0.5, 0.5);
            // create default simulation shape flags
            var shapeFlags = new PhysX.PxShapeFlags(PhysX.PxShapeFlagEnum.eSCENE_QUERY_SHAPE | PhysX.PxShapeFlagEnum.eSIMULATION_SHAPE |  PhysX.PxShapeFlagEnum.eVISUALIZATION);
 
            // create a few temporary objects used during setup
            var tmpPose = new PhysX.PxTransform(PhysX.PxIDENTITYEnum.PxIdentity);
            var tmpFilterData = new PhysX.PxFilterData(1, 1, 0, 0);
 
            // create a large static box with size 20x1x20 as ground
            var groundGeometry = new PhysX.PxBoxGeometry(10, 0.5, 10);   // PxBoxGeometry uses half-sizes
            var groundShape = physics.createShape(groundGeometry, material, true, shapeFlags);
            var ground = physics.createRigidStatic(tmpPose);
            groundShape.setSimulationFilterData(tmpFilterData);
            ground.attachShape(groundShape);
            scene.addActor(ground);
 
            // create a few dynamic boxes with size 1x1x1, which will fall on the ground
            var boxGeometry = new PhysX.PxBoxGeometry(0.5, 0.5, 0.5);   // PxBoxGeometry uses half-sizes
            var lastBox = null;
            for (var y = 0; y < 10; y++) {
                tmpVec.set_x(0); tmpVec.set_y(y*2 + 5); tmpVec.set_z(0);
                tmpPose.set_p(tmpVec);
                var boxShape = physics.createShape(boxGeometry, material, true, shapeFlags);
                var box = physics.createRigidDynamic(tmpPose);
                boxShape.setSimulationFilterData(tmpFilterData);
                box.attachShape(boxShape);
                scene.addActor(box);
                lastBox = box;
            }
 
            // clean up temp objects
            PhysX.destroy(groundGeometry);
            PhysX.destroy(boxGeometry);
            PhysX.destroy(tmpFilterData);
            PhysX.destroy(tmpPose);
            PhysX.destroy(tmpVec);
            PhysX.destroy(shapeFlags);
            PhysX.destroy(sceneDesc);
            PhysX.destroy(tolerances);
            console.log('Created scene objects');
 
            // setup debug drawing stuff
            const { mat4, vec4, vec3 } = glMatrix;
            const viewMatrix = mat4.create();
            const projectionMatrix = mat4.create();
            const viewProjectionMatrix = mat4.create();
            const tmpVec4 = vec4.create();
 
            const canvas = document.querySelector('canvas');
            const context = canvas.getContext('2d');
            setupDebugDrawer(PhysX, scene);
 
            // simulate forever!
            simulationLoop();
 
            function setupDebugDrawer() {
                canvas.width = canvas.clientWidth;
                canvas.height = canvas.clientHeight;
 
                // compute projection matrix
                mat4.lookAt(viewMatrix, [12, 15, 20], [0, 0, 0], [0, 1, 0])
                mat4.perspective(projectionMatrix, 45 * (Math.PI / 180), canvas.width / canvas.height, 0.01, 75);
                mat4.multiply(viewProjectionMatrix, projectionMatrix, viewMatrix);
 
                // setup debug drawer
                const context = canvas.getContext('2d');
                scene.setVisualizationParameter(PhysX.eSCALE, 1);
                scene.setVisualizationParameter(PhysX.eWORLD_AXES, 1);
                scene.setVisualizationParameter(PhysX.eACTOR_AXES, 1);
                scene.setVisualizationParameter(PhysX.eCOLLISION_SHAPES, 1);
            }
 
            function simulationLoop() {
                let lastFrame = 0;
                requestAnimationFrame(function loop(hrTime) {
                    var timeStep = Math.min(0.03, (hrTime - lastFrame) / 1000);
                    scene.simulate(timeStep);
                    scene.fetchResults(true);
 
                    // use debug drawer interface to draw boxes on a canvas.
                    // in a real world application you would query the box poses and update your graphics boxes accordingly
                    debugDraw(scene);
                    
                    var lastBoxPos = lastBox.getGlobalPose().get_p();
                    console.log('Last box position: ' + lastBoxPos.get_x() + ", " + lastBoxPos.get_y() + ", " + lastBoxPos.get_z());
 
                    lastFrame = hrTime;
                    requestAnimationFrame(loop);
                });
            }
 
            function project(x, y, z) {
                const result = vec4.transformMat4(tmpVec4, [x, y, z, 1], viewProjectionMatrix);
                const clipX = (result[0] / result[3]);
                const clipY = (result[1] / result[3]);
                return [(canvas.width / 2) * (1 + clipX), (canvas.height / 2) * (1 - clipY)];
            }
 
            function drawLine(from, to, color) {
                const [r, g, b] = color;
 
                context.beginPath();
                context.strokeStyle = `rgb(${255 * r}, ${255 * g}, ${255 * b})`;
                context.moveTo(...from);
                context.lineTo(...to);
                context.stroke();
            }
 
            function debugDraw() {
                canvas.width = canvas.width;    // clears the canvas
 
                const rb = scene.getRenderBuffer();
                for(let i = 0; i < rb.getNbLines(); i++) {
                    const line = PhysX.NativeArrayHelpers.prototype.getDebugLineAt(rb.getLines(), i);
                    const from = project(line.pos0.get_x(), line.pos0.get_y(), line.pos0.get_z());
                    const to   = project(line.pos1.get_x(), line.pos1.get_y(), line.pos1.get_z());
                    drawLine(from, to, colors[line.get_color0()]);
                }
            }
 
            const colors = {
                [PhysX.PxDebugColorEnum.eARGB_BLACK]:     [  0,   0,   0],
                [PhysX.PxDebugColorEnum.eARGB_RED]:       [  1,   0,   0],
                [PhysX.PxDebugColorEnum.eARGB_GREEN]:     [  0,   1,   0],
                [PhysX.PxDebugColorEnum.eARGB_BLUE]:      [  0,   0,   1],
                [PhysX.PxDebugColorEnum.eARGB_YELLOW]:    [  1,   1,   0],
                [PhysX.PxDebugColorEnum.eARGB_MAGENTA]:   [  1,   0,   1],
                [PhysX.PxDebugColorEnum.eARGB_CYAN]:      [  0,   1,   1],
                [PhysX.PxDebugColorEnum.eARGB_WHITE]:     [  1,   1,   1],
                [PhysX.PxDebugColorEnum.eARGB_GREY]:      [0.5, 0.5, 0.5],
                [PhysX.PxDebugColorEnum.eARGB_DARKRED]:   [0.5,   0,   0],
                [PhysX.PxDebugColorEnum.eARGB_DARKGREEN]: [  0, 0.5,   0],
                [PhysX.PxDebugColorEnum.eARGB_DARKBLUE]:  [  0,   0, 0.5],
            };
        });
    </script>
</body>
</html>
0
1823 / 731 / 99
Регистрация: 01.10.2012
Сообщений: 3,738
12.03.2024, 20:12 36
Ваня, воспевание чужих примеров ни к чему хорошему не ведет Движок предназначен для использования, а не для созерцания. Попробуйте сделать что-то свое
0
1823 / 731 / 99
Регистрация: 01.10.2012
Сообщений: 3,738
13.03.2024, 15:02 37
---
Немного разовью мысль. Да, "объективно" пример выше крут, сделать его "руками", без движка, не выйдет. НО этого нажрались все кому не лень уже лет 15-20 назад, сейчас это типа "давно пройденный этап". Конечно можно (упорно) доказывать что сейчас это "и на WebGL делается!". Верю, но что с того? Запускать "прямо из браузера" конечно впечатляет ("по одежке встречают" никто не отменял), но как посмотришь на все эти скриптовые сопли - тоска зелёная По мне так не стоит оно того.

А ведь интересных и нужных задач с движком масса! Ну вот хотя бы скромное "движение (объекта) по заданному пути". Силами конечно, не лезть грязными руками в скорость и, тем более, в позицию. Чуть хитрее: движение к заданной цели. Которая, возможно, сама движется. Типа "хищник догоняет". И наоборот, "жертва убегает". Движение множества объектов, т.е. стая, стадо, рой и.т.п (когда-то я интересовался этим здесь, потом нашел отличную методику). Движение с обходом препятствий - там есть либы, правда непростые. В любом случае (хоть в игре хоть где) нужна какая-то активность/действие, на "базовой физике" (упало-прокатилось) далеко не уедешь.
0
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
09.04.2024, 12:35  [ТС] 38
Подключение Three.js с помощью import maps, как ES6-модуля

Все библиотеки на клиентской части удобно подключать через import maps:

PHP/HTML
1
2
3
4
5
6
7
    <script type="importmap">
        {
            "imports": {
                "three": "https://unpkg.com/three@0.163.0/build/three.module.min.js"
            }
        }
    </script>
Необходимо вставить в код поключение библиотеки "es-module-shims.js", потому что подключение библиотек с помощью import maps поддерживается не на всех браузерах, а эта библиотека позволяет запускать код с import maps на браузерах, где эта технология не поодерживается.

PHP/HTML
1
2
3
    <!-- Since importmap is not yet supported by all browsers, it is
        necessary to add the polyfill es-module-shims.min.js -->
    <script async src="https://unpkg.com/es-module-shims@1.9.0/dist/es-module-shims.js"></script>
Подключаем главный скрипт index.js, как ES6-модуль, указав тип "модуль":

PHP/HTML
1
    <script type="module" src="./js/index.js"></script>
В целом файл index.html выглядит теперь так:

PHP/HTML
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
<!DOCTYPE html>
 
<html>
 
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Set up Three.js with importmap as ES6-module</title>
</head>
 
<body>
    <!-- Since importmap is not yet supported by all browsers, it is
        necessary to add the polyfill es-module-shims.min.js -->
    <script async src="https://unpkg.com/es-module-shims@1.9.0/dist/es-module-shims.js"></script>
 
    <script type="importmap">
        {
            "imports": {
                "three": "https://unpkg.com/three@0.163.0/build/three.module.min.js"
            }
        }
    </script>
 
    <script type="module" src="./js/index.js"></script>
 
</body>
 
</html>
Теперь можно в главном скрипте воспользоваться ключевым словом "import" для доступа к API Three.js:

Javascript
1
import * as THREE from "three";
Создадим 3D-вектор и выведем его в консоль:

Javascript
1
2
3
4
import * as THREE from "three";
 
const v = new THREE.Vector3(1, 2, 3);
console.log(`vector = (${v.x}, ${v.y}, ${v.z})`);
Пример выше в песочнице: https://plnkr.co/edit/7mMXQ5bOcKWBnxPC
1
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
16.04.2024, 12:25  [ТС] 39
Базовые элементы Three.js

Базовые элементы Three.js, которые должны быть во всех программах: сцена, камера, отрисовщик, функция изменения размера и функция отрисовки:

Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import * as THREE from "three";
 
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
    50, window.innerWidth / window.innerHeight, 0.1, 500);
 
const canvas = document.getElementById("renderCanvas");
const renderer = new THREE.WebGLRenderer({ canvas: canvas });
renderer.setClearColor(new THREE.Color("rgb(50, 50, 50)"), 1);
 
function resize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
}
window.onresize = resize;
 
function render() {
    renderer.render(scene, camera);
    requestAnimationFrame(render);
}
render();
В констукторе камеры нужно передать 4 параметра, для создания перспективной матрицы внутри себя: угол обзора камеры, отношение ширины окна браузера к его ширине (точнее, внутренней части окна), ближняя плоскость отсечения и дальная плоскость отсечения. Плоскости отсечения - это термины для матрицы проекции. Весь видимый объём находится в усечённой пирамиде. Если бы это была ортогональная проекция, как используется для 2D, то была бы не усечённая пирамида, а параллелепипед. Можете скопировать в Гугл "perspective matrix" и переключить вкладку браузера на "Images" и вы увидите, как выглядит усечённая пирамида перспективной матрицы, и какие плоскоти названы "near" и "far", то есть ближней и дальней плоскостью отсечения.

Пример выше в песочнице: https://plnkr.co/edit/PTChLVW6pSlXwSdQ?preview

В этом примере цвет фона устанавливается в тёмно серый в этой строке:

Javascript
1
renderer.setClearColor(new THREE.Color("rgb(50, 50, 50)"), 1);
Цвет один раз устанавливается, а потом в функции render() этим цветом заливается элемент <canvas> с помощью метода renderer.render(scene, camera), который принимает сцену и камеру:

Javascript
1
2
3
4
5
function render() {
    renderer.render(scene, camera);
    requestAnimationFrame(render);
}
render();
В коде выше вызывается requestAnimationFrame(render), чтобы выставить функцию render() как функцию, которая будет вызвата для отрисовки следующего кадра. Это значит, что render() вызывается каждый кадр, а это 60 кадров в секунду. То есть уже готова функция для анимаций.

В примере создан элемент <canvas> в HTML-файле:
HTML5
1
<canvas id="renderCanvas"></canvas>
А в коде на JavaScript берётся ссылка на этот элемент и на передаётся отрисовщику:

Javascript
1
2
const canvas = document.getElementById("renderCanvas");
const renderer = new THREE.WebGLRenderer({ canvas: canvas });
Теперь функция resize:

Javascript
1
2
3
4
5
6
function resize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
}
window.onresize = resize;
Здесь установлено, что функция resize должна вызываться по событию onresize этой срокой: "window.onresize = resize;". При изменени размера окна нужно изменить отношение ширины окна к высоте: "camera.aspect = window.innerWidth / window.innerHeight", а так же вызвать метод updateProjectionMatrix(), чтобы обновить матрицу перспективной проекции, как как соотножения сторон усечённой пирамиды изменились.
0
16.04.2024, 12:25
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
16.04.2024, 12:25
Помогаю со студенческими работами здесь

проекты
Пользовательский интерфейс приложения составляют: A) Программные коды, которые разработчик...

Проекты с ООП
Здравствуйте, мне захотелось выполнить какой-нибудь проект с использованием принципов ООП для...

Текущие проекты
Добрый день всем. Просто из праздного любопытства, напишите, пожалуйста, ниже проекты, над...

Объединить проекты
Есть 3 проекта и есть основная форма. Как сделать чтобы при нажатии на кнопку в форме открывался...

Не запускаются проекты
Дважды переустанавливал студию. Устанавливал разные студии. Но все тоже самое - уже не знаю, что...

Соединить проекты
Могу ли я соединить проекты, В первомприложение парсинг и.т.д, а во втором coredata с таблицами...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
39
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru