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

Управление героем стрелками в 3D, вид от 3-го лица, на WebGL

13.01.2022, 23:12. Показов 3272. Ответов 30
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Цитата Сообщение от Olga28 Посмотреть сообщение
Я не знаю работали вы с технологией FLASH AS 3.0. и библиотекой Away3D. У меня есть один пример из одной старой книги. Книга была на английском языке, там рассказывается как сделать управление героем стрелками, вид от 3-его лица. Вот исходники.
CameraDemo.zip
А вот сам скриншот.


Технология flash, примерно 5 лет как устарела. Как сделать такой же пример вид от 3-его лица на WebGL? В Флеше я знаю как сделать а вот WebGL только изучаю.

Чтобы запустить сам пример в только что созданном проекте Flash, просто следует добавить класс в свойства как показано на картинке



и запускать нужно в браузере или другом проигрывателе (не Flash Player, там пример плохо работает).
С Flash я сейчас сталкиваюсь немного, потому что изучаю физический движок Box2D по урокам на Flash, переписывая примеры уроков на WebGL. Переписал первую часть осталась вторая с игрой:

Todd's Box2D Tutorials

https://kerp.net/box2d/

Lesson 1.1 - Introduction to Chapter 1 - http://youtu.be/2NvNoBUNIX0
Lesson 1.2 - Disclaimers, thanks, and comments - http://youtu.be/jhKWFgvR8No
Lesson 1.3 - What you're gonna need... - http://youtu.be/rB_WrFt4-5s
Lesson 1.4 - Understanding Box2D - http://youtu.be/95lW-zWkZPE
Lesson 1.5 - The kinda long and boring lesson on setting everything up - http://youtu.be/MDtGGyI8OTc
Lesson 1.6 - Creating the world and getting to know some classes - http://youtu.be/WzIacPkLtIc
Lesson 1.7 - Defining the size of the universe - http://youtu.be/vYksP9ctHMI
Lesson 1.8 - A quick digression about units - http://youtu.be/CnCS2NeBZ0E
Lesson 1.9 - Finishing up our b2World object - http://youtu.be/lVtVKeGiBco
Lesson 1.10 - If you're following along and getting errors... - http://youtu.be/7yqEjjFfrIE
Lesson 1.11 - How do you make a body? - http://youtu.be/h6TozLhho80
Lesson 1.12 - Creating our first shape definition - http://youtu.be/sbbsvKMMr_w
Lesson 1.13 - Finishing up our floor - http://youtu.be/OSwRv4Nzdz0
Lesson 1.14 - Creating the walls - http://youtu.be/iCLP-Ok1ab4
Lesson 1.15 - Creating our falling crate - http://youtu.be/31sVPYW3icE
Lesson 1.16 - Making our world update over time - http://youtu.be/_MbfGRD8Ibk
Lesson 1.17 - Let's Get Visual, Visual - http://youtu.be/KNm8fdkrFuE
Lesson 1.18 - Adding lots of crates! Whee! - http://youtu.be/1d72y6oX9nc
Lesson 1.19 - Experimenting with our values - http://youtu.be/2PCeecp3vv4
Lesson 1.20 - The difference between a shape and a body - http://youtu.be/s_t0MaFDUsM
Lesson 1.21 - Defs, OrientedBoxes, and Coordinates - http://youtu.be/g0FR0WCVFFA
Lesson 1.22 - Conclusion - http://youtu.be/Di5rrYHhN6g

Chapter 2: Making Puggle

Lesson 2.1 - Making a real application -- an Introduction to Chapter 2 - http://youtu.be/85FoF_w-HOM
Lesson 2.2 - Everything we did in Chapter 1 in about six minutes - http://youtu.be/SPAEPPGClQg
Lesson 2.3 - Getting a Sprite to move like a Body - http://youtu.be/fyDGU0haNcg
Lesson 2.4 - Introducing the Actor Class! - http://youtu.be/deA4MMsuOHk
Lesson 2.5 - Creating our first Actor class - http://youtu.be/7e7iF2_Dr0o
Lesson 2.6 - Creating the BallActor class - http://youtu.be/ouEkR8Wlg_E
Lesson 2.7 - Creating the PegActor, Part 1 - http://youtu.be/5wQIrISylxs
Lesson 2.8 - Creating the PegActor, Part 2 - http://youtu.be/268gpaMz0XE
Lesson 2.9 - Adding all those pegs to the world - http://youtu.be/bjeiNwIv5DY
Lesson 2.10 - The ArbitraryStaticActor... as exciting as it sounds! - http://youtu.be/HJ8HeREdjmM
Lesson 2.11 - Finishing the ArbiStaticActor, and adding some walls - http://youtu.be/FZ9SdB4M9og
Lesson 2.12 - Adding some ramps! Yay! - http://youtu.be/G0sqizu4XqQ
Lesson 2.13 - Discussion Questions, like "Why isn't Todd a better coder?" - http://youtu.be/5pxRiw7wuA4
Lesson 2.14 - More Discussion Questions that you probably weren't wondering about - http://youtu.be/Q9JHCTqsY0E
Lesson 2.15 - Getting to know the b2ContactListener - http://youtu.be/FklxMpYi8ww
Lesson 2.16 - Figuring out who bumped into who - http://youtu.be/OBVxTSJjRGs
Lesson 2.17 - Making a peg light up! And some warnings... - http://youtu.be/eP4T8BE7qq0
Lesson 2.18 - How to remove an Actor (insert Hollywood-themed joke here) - http://youtu.be/MGX8GOmzJ8A
Lesson 2.19 - Finishing that Actor's destroy() function - http://youtu.be/CgK3IgYnua4
Lesson 2.20 - Removing our ball and creating a custom event - http://youtu.be/tOgNzVRe_po
Lesson 2.21 - Removing those PegActors we took so long to make (sigh) - http://youtu.be/YT34taQO3QI
Lesson 2.22 - Our game's got a lotta balls. - http://youtu.be/KnEODTxkg54
Lesson 2.23 - Creating the BonusChuteActor class - http://youtu.be/0hQ8CJT2kxc
Lesson 2.24 - Adding a sensor to our BonusChute - http://youtu.be/MZLizo67dA0
Lesson 2.25 - Getting a platform to move -- the wrong way - http://youtu.be/Kiy28DvQxnA
Lesson 2.26 - Getting a platform to move -- the right way - http://youtu.be/C1sgWy07Ek4
Lesson 2.27 - Fixing bugs in our platform and using bullets - http://youtu.be/WBvAnaxJ9KI
Lesson 2.28 - Introducing the camera! - http://youtu.be/PLcsxKRPVbw
Lesson 2.29 - Making our camera dumbly zoom in - http://youtu.be/ess3kNVvvF8
Lesson 2.30 - Tracking our ball and Goal Peg - http://youtu.be/2oAcFim65is
Lesson 2.31 - Zooming in, the smart way - http://youtu.be/JMTb0PJp1_w
Lesson 2.32 - How to control time! (Katana not required) - http://youtu.be/K6Oh-8Yux_8
Lesson 2.33 - Cleaning up, part 1: Removing the flicker - http://youtu.be/DsGJ41ERIKE
Lesson 2.34 - Cleaning up, part 2: Allowing multiple goal pegs - http://youtu.be/H_I0gpqvb6E
Lesson 2.35 - Creating the aiming line, part 1 - http://youtu.be/v0HHg3nrWCE
Lesson 2.36 - Creating the aiming line, part 2 - http://youtu.be/pv-VLmurMo0
Lesson 2.37 - Tweaking the settings - http://youtu.be/dntwtnGDDdY
Lesson 2.38 - Making a rotating shooter turret thing - http://youtu.be/BIIYnGseBTM
Lesson 2.39 - Oops! Fixing one bug with the shooter - http://youtu.be/1i7H2B7hPOM
Lesson 2.40 - Making a smooth camera zoom through TweenLite - http://youtu.be/R98ER9iREW8
Lesson 2.41 - Smoothing the zoom out and slow down moments - http://youtu.be/led40OjZtjI
Lesson 2.42 - Making the pegs fade out - http://youtu.be/iVuJhoTO2dw
Lesson 2.43 - How to NOT make Peggle - http://youtu.be/24Rm18C5E_I
Lesson 2.44 - Turning our static pegs to moving pegs - http://youtu.be/ZU5P7kPdURM
Lesson 2.45 - REALLY turning our static pegs into moving ones - http://youtu.be/7lHoKW2j1o4
Lesson 2.46 - Getting our chute to follow our mouse - http://youtu.be/Pc6PJha93cI
Lesson 2.47 - Making our pegs react more realistically, part 1 - http://youtu.be/7AQv88f14-M
Lesson 2.48 - Even more realistic pegs, ApplyForce and ApplyImpulse - http://youtu.be/IgUr4xrcTEI
Lesson 2.49 - Normals and crazy mathy stuff - http://youtu.be/JruODUnV2o4
Lesson 2.50 - Final to-do list and conclusion - http://youtu.be/pUZ-PVCquOI


Перемещение героя на Flash я не смотрел и не запускал, но я примерно понимаю, как он движется. Я сделал пример, где шар двигается вперёд и назад с помощью клавиш "w" и "s", а поворачивается с помощью клавиш "a" и "d". Клавишей "b" можно включать и отключать рисование коллайдеров. Рисовать коллайдеры помогает физический движок Ammo.js. Изучайте код, экспериментируйте, задавайте вопросы.

Управление героем стрелками в 3D, вид от 3-го лица, на WebGL
Управление героем стрелками в 3D, вид от 3-го лица, на WebGL


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
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
<!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>Third Person Movement. DAE, Ammo.js, WebGL, JavaScript</title>
 
    <script src="https://dl.dropboxusercontent.com/s/e5iytx67noqoew7/ammo.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/gl-matrix@3.4.3/gl-matrix-min.js"></script>
 
    <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>
 
    <img id="playerImage" src="assets/player.png" hidden>
    <img id="floorImage" src="assets/floor.png" hidden>
 
    <script type="x-shader/x-vertex" id="defaultVertexShader">
        attribute vec4 aPosition;
        attribute vec4 aNormal;
        attribute vec2 aTexCoord;
        uniform mat4 uMvpMatrix;
        uniform mat4 uModelMatrix;
        uniform mat4 uNormalMatrix;
        varying vec3 vPosition;
        varying vec3 vNormal;
        varying vec2 vTexCoord;
        void main()
        {
            gl_Position = uMvpMatrix * aPosition;
            vPosition = vec3(uModelMatrix * aPosition);
            vNormal = normalize(vec3(uNormalMatrix * aNormal));
            vTexCoord = aTexCoord;
        }
    </script>
 
    <script type="x-shader/x-fragment" id="defaultFragmentShader">
        precision mediump float;
        const vec3 lightColor = vec3(1.0, 1.0, 1.0);
        const float ambient = 0.3;
        uniform vec3 uLightPosition;
        uniform sampler2D uSampler;
        varying vec3 vPosition;
        varying vec3 vNormal;
        varying vec2 vTexCoord;
        void main()
        {
            vec4 color = texture2D(uSampler, vTexCoord);
            vec3 normal = normalize(vNormal);
            vec3 lightDirection = normalize(uLightPosition - vPosition);
            float nDotL = max(dot(lightDirection, normal), ambient);
            vec3 diffuse = lightColor * color.rgb * nDotL;
            gl_FragColor = vec4(diffuse, color.a);
        }
    </script>
 
    <script type="x-shader/x-vertex" id="edgeVertexShader">
        attribute vec3 aPosition;
        uniform mat4 uMvpMatrix;
        void main()
        {
            gl_Position = uMvpMatrix * vec4(aPosition, 1.0);
        }
    </script>
 
    <script type="x-shader/x-fragment" id="edgeFragmentShader">
        precision mediump float;
        void main()
        {
            gl_FragColor = vec4(0.1, 1.0, 0.3, 1.0);
        }
    </script>
 
    <script src="js/webgl-context.js"></script>
    <script src="js/shader-program.js"></script>
    <script src="js/vertex-buffers.js"></script>
    <script src="js/object-for-graphics.js"></script>
    <script src="js/object-for-physics.js"></script>
    <script src="js/object-for-edge.js"></script>
    <script src="js/debug-drawer.js"></script>
    <script src="js/keyboard.js"></script>
    <script src="js/main.js"></script>
</body>
 
</html>
js/debug-drawer.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
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
class DebugDrawer
{
    constructor(edge)
    {
        this.edge = edge;
        this.projViewMatrix = null;
 
        this.heap = null;
        this.debugDrawer = new Ammo.DebugDrawer();
        this.debugDrawer.drawLine = ((from, to, color) => { this.drawLine(from, to, color) }).bind(this);
        this.debugDrawer.setDebugMode = () => { };
 
        this.debugMode = 1; // 0 - 0ff, 1 - on
        this.debugDrawer.getDebugMode = () => { return this.debugMode; };
        this.debugDrawer.setDebugMode(1);
 
        this.debugDrawer.drawContactPoint = (pointOnB, normalOnB, distance, lifeTime, color) => { };
        this.debugDrawer.reportErrorWarning = (warningString) => { };
        this.debugDrawer.draw3dText = (location, textString) => { };
 
        world.setDebugDrawer(this.debugDrawer);
 
        this.fromX = 0;
        this.fromY = 0;
        this.fromZ = 0;
        this.toX = 0;
        this.toY = 0;
        this.toZ = 0;
        this.centerX = 0;
        this.centerY = 0;
        this.centerZ = 0;
 
        this.length = 0;
        this.vec = glMatrix.vec3.create();
        this.x = 0;
        this.y = 0;
        this.z = 0;
        this.unitX = glMatrix.vec3.fromValues(1, 0, 0);
    }
 
    drawLine(from, to, color)
    {
        this.heap = Ammo.HEAPF32;
 
        this.fromX = this.heap[(parseInt(from) + 0) / 4];
        this.fromY = this.heap[(parseInt(from) + 4) / 4];
        this.fromZ = this.heap[(parseInt(from) + 8) / 4];
 
        this.toX = this.heap[(parseInt(to) + 0) / 4];
        this.toY = this.heap[(parseInt(to) + 4) / 4];
        this.toZ = this.heap[(parseInt(to) + 8) / 4];
 
        if (this.fromX > this.toX)
        {
            this.centerX = this.toX + Math.abs(this.fromX - this.toX) / 2;
        }
        else
        {
            this.centerX = this.fromX + Math.abs(this.toX - this.fromX) / 2;
        }
 
        if (this.fromY > this.toY)
        {
            this.centerY = this.toY + Math.abs(this.fromY - this.toY) / 2;
        }
        else
        {
            this.centerY = this.fromY + Math.abs(this.toY - this.fromY) / 2;
        }
 
        if (this.fromZ > this.toZ)
        {
            this.centerZ = this.toZ + Math.abs(this.fromZ - this.toZ) / 2;
        }
        else
        {
            this.centerZ = this.fromZ + Math.abs(this.toZ - this.fromZ) / 2;
        }
 
        this.vec[0] = this.toX - this.fromX;
        this.vec[1] = this.toY - this.fromY;
        this.vec[2] = this.toZ - this.fromZ;
        this.length = glMatrix.vec3.length(this.vec);
 
        glMatrix.vec3.normalize(this.vec, this.vec);
        glMatrix.quat.rotationTo(this.edge.rotation, this.unitX, this.vec);
 
        this.edge.scale = [this.length, 0.05, 0.05];
        this.edge.position = [this.centerX, this.centerY, this.centerZ];
        this.edge.draw(this.projViewMatrix);
    }
}
keyboard.js

Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Keyboard
{
    constructor()
    {
        this.keys = {};
        document.addEventListener("keydown", (event) => { this.onKeyChange(event, true) }, true);
        document.addEventListener("keyup", (event) => { this.onKeyChange(event, false) }, false);
    }
 
    pressed(key)
    {
        return this.keys[key];
    }
 
    onKeyChange(event, pressed)
    {
        this.keys[event.key] = pressed;
    }
}
js/main.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
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
let defaultProgram, edgeProgram;
let player, floor, edge, cube;
let debugDrawer, keyboard;
let debugMode = true;
const angularSpeed = 200;
const linearSpeed = 200;
const dt = 0.015;
 
const forward = glMatrix.vec3.fromValues(0, 0, 1);
const zUnit = glMatrix.vec3.fromValues(0, 0, 1);
const playerRotation = glMatrix.quat.create();
glMatrix.quat.rotationTo(playerRotation, zUnit, forward);
const direction = glMatrix.vec3.fromValues(forward[0], forward[1], forward[2]);
let dirAngle = 0;
 
const projMatrix = glMatrix.mat4.create();
const viewMatrix = glMatrix.mat4.create();
const projViewMatrix = glMatrix.mat4.create();
 
initVertexBuffers(["assets/player.dae", "assets/floor.dae", "assets/cube.dae"],
    (vertPosVBOs, normalVBOs, texCoordVBOs, amounts) =>
    {
        defaultProgram = createProgram("defaultVertexShader", "defaultFragmentShader");
        edgeProgram = createProgram("edgeVertexShader", "edgeFragmentShader");
        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
 
        Ammo().then(() =>
        {
            const collisionConfiguration = new Ammo.btDefaultCollisionConfiguration();
            const dispatcher = new Ammo.btCollisionDispatcher(collisionConfiguration);
            const overlappingPairCache = new Ammo.btDbvtBroadphase();
            const solver = new Ammo.btSequentialImpulseConstraintSolver();
 
            world = new Ammo.btDiscreteDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfiguration);
            world.setGravity(new Ammo.btVector3(0, -9.81, 0));
 
            const playerImage = document.getElementById("playerImage");
            const playerTexture = gl.createTexture();
            gl.bindTexture(gl.TEXTURE_2D, playerTexture);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, playerImage);
            const playserSize = 0.5;
            const playerShape = new Ammo.btSphereShape(playserSize);
            player = new ObjectForPhysics(defaultProgram, [0, 3, 2], playerRotation, amounts[0],
                vertPosVBOs[0], normalVBOs[0], texCoordVBOs[0], playerTexture, playerShape, 50);
            player.scale = [playserSize, playserSize, playserSize];
            player.body.setAngularFactor(0, 1, 0);
            player.body.setDamping(0.9, 0.99);
 
            const floorImage = document.getElementById("floorImage");
            const floorTexture = gl.createTexture();
            gl.bindTexture(gl.TEXTURE_2D, floorTexture);
            gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, floorImage);
            const floorSize = [10, 1, 10];
            const floorShape = new Ammo.btBoxShape(
                new Ammo.btVector3(floorSize[0] / 2, floorSize[1] / 2, floorSize[2] / 2));
            floor = new ObjectForPhysics(defaultProgram, [0, -2, 0], [0, 0, 0, 1], amounts[1],
                vertPosVBOs[1], normalVBOs[1], texCoordVBOs[1], floorTexture, floorShape, 0);
            floor.scale = [10, 5, 10];
 
            edge = new ObjectForEdge(edgeProgram, amounts[2], vertPosVBOs[2]);
            debugDrawer = new DebugDrawer(edge);
            debugDrawer.debugMode = 1;
 
            keyboard = new Keyboard();
 
            init();
        });
    });
 
function init()
{
    glMatrix.mat4.perspective(projMatrix, 55 * Math.PI / 180, 1, 0.1, 500);
    glMatrix.mat4.lookAt(viewMatrix, [0, 3, 10], [0, 0, 0], [0, 1, 0]);
 
    gl.useProgram(defaultProgram);
    const lightPosition = glMatrix.vec3.fromValues(2, 3, 5);
    const uLightPositionLocation = gl.getUniformLocation(defaultProgram, "uLightPosition");
    gl.uniform3fv(uLightPositionLocation, lightPosition);
 
    window.onresize = () =>
    {
        const w = canvas.clientWidth;
        const h = canvas.clientHeight;
        gl.canvas.width = w;
        gl.canvas.height = h;
        gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
        glMatrix.mat4.perspective(projMatrix, 55 * Math.PI / 180, w / h, 0.1, 500);
        createPhysicsSimulation();
        draw();
    };
    window.onresize(null);
 
    document.onkeydown = (event) =>
    {
        if (event.repeat) return;
 
        if (event.key === "b")
        {
            debugMode = !debugMode;
            if (debugMode)
            {
                debugDrawer.debugMode = 1;
            }
            else
            {
                debugDrawer.debugMode = 0;
            }
        }
    }
}
 
function createPhysicsSimulation()
{
    setInterval(() =>
    {
        updatePhysics();
    }, 15);
}
 
function updatePhysics()
{
    if (keyboard.pressed("w"))
    {
        let vy = player.body.getLinearVelocity().y();
        const impulse = new Ammo.btVector3(direction[0] * linearSpeed * dt, vy, direction[2] * linearSpeed * dt);
        player.body.setLinearVelocity(impulse);
    }
    if (keyboard.pressed("s"))
    {
        const vy = player.body.getLinearVelocity().y();
        const impulse = new Ammo.btVector3(-direction[0] * linearSpeed * dt, vy, -direction[2] * linearSpeed * dt);
        player.body.setLinearVelocity(impulse);
    }
    if (keyboard.pressed("a"))
    {
        const impulse = new Ammo.btVector3(0, angularSpeed * dt, 0);
        player.body.setAngularVelocity(impulse);
    }
    if (keyboard.pressed("d"))
    {
        const impulse = new Ammo.btVector3(0, -angularSpeed * dt, 0);
        player.body.setAngularVelocity(impulse);
    }
 
    glMatrix.vec3.transformQuat(direction, forward, player.rotation);
    world.stepSimulation(dt, 8);
    player.update();
}
 
function draw()
{
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    glMatrix.mat4.mul(projViewMatrix, projMatrix, viewMatrix);
 
    player.draw(projViewMatrix);
    floor.draw(projViewMatrix);
 
    debugDrawer.projViewMatrix = projViewMatrix;
 
    if (debugMode)
    {
        world.debugDrawWorld();
    }
 
    requestAnimationFrame(draw);
}
js/object-for-edge.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
29
30
31
32
33
34
35
36
37
38
class ObjectForEdge
{
    constructor(program, amountOfVertices, vertPosBuffer)
    {
        this.position = [0, 0, 0];
        this.rotation = glMatrix.quat.create();
        this.scale = [1, 1, 1];
 
        this.amountOfVertices = amountOfVertices;
        this.vertPosBuffer = vertPosBuffer;
 
        this.mvpMatrix = glMatrix.mat4.create();
        this.modelMatrix = glMatrix.mat4.create();
 
        gl.useProgram(program);
        this.uMvpMatrixLocation = gl.getUniformLocation(program, "uMvpMatrix");
        this.program = program;
    }
 
    bind()
    {
        gl.bindBuffer(gl.ARRAY_BUFFER, this.vertPosBuffer);
        gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(0);
    }
 
    draw(projViewMatrix)
    {
        gl.useProgram(this.program);
 
        glMatrix.mat4.fromRotationTranslationScale(this.modelMatrix, this.rotation, this.position, this.scale);
        glMatrix.mat4.mul(this.mvpMatrix, projViewMatrix, this.modelMatrix);
        gl.uniformMatrix4fv(this.uMvpMatrixLocation, false, this.mvpMatrix);
 
        this.bind();
        gl.drawArrays(gl.TRIANGLES, 0, this.amountOfVertices);
    }
}
Вложения
Тип файла: zip third-person-movement-dae-ammojs-webgl-js.zip (428.7 Кб, 14 просмотров)
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
13.01.2022, 23:12
Ответы с готовыми решениями:

Перенести управление стрелками на управление WASD
Мне нужно чтобы в игре вместо стрелок управление осуществлялось WASD и при этом сами WASD не...

Вид от 1 лица в Unity 5
Всем привет. Народ столкнулся с такой бедой. Раньше работал в Unity3D Pro 3.5 сейчас перешел на...

Вид от 3 лица в 3D game studio a7
Наверное опрос не в тему. Но как в 3D game studio сделать вид от 3 лица. Я знаю только как от 1 но...

Камера персонажа, вид от первого лица
Все здравствуйте. Кто может подсказать по какому принципу создаётся и работает камера игрока в 3D...

Управление стрелками
Здравствуйте. Помогите пожалуйста. Есть класс, работает как надо, если он является основным....

30
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
13.01.2022, 23:12  [ТС] 2
js/object-for-graphics.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
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
class ObjectForGraphics
{
    constructor(program, position, amountOfVertices, vertPosBuffer, normalBuffer, texCoordBuffer, texture)
    {
        this.position = position;
        this.rotation = glMatrix.quat.create();
        this.scale = [1, 1, 1];
 
        this.amountOfVertices = amountOfVertices;
        this.vertPosBuffer = vertPosBuffer;
        this.normalBuffer = normalBuffer;
        this.texCoordBuffer = texCoordBuffer;
        this.texture = texture;
 
        this.mvpMatrix = glMatrix.mat4.create();
        this.modelMatrix = glMatrix.mat4.create();
        this.normalMatrix = glMatrix.mat4.create();
 
        gl.useProgram(program);
        this.uMvpMatrixLocation = gl.getUniformLocation(program, "uMvpMatrix");
        this.uModelMatrixLocation = gl.getUniformLocation(program, "uModelMatrix");
        this.uNormalMatrixLocation = gl.getUniformLocation(program, "uNormalMatrix");
        this.program = program;
    }
 
    bind()
    {
        gl.bindBuffer(gl.ARRAY_BUFFER, this.vertPosBuffer);
        gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(0);
 
        gl.bindBuffer(gl.ARRAY_BUFFER, this.normalBuffer);
        gl.vertexAttribPointer(1, 3, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(1);
 
        gl.bindBuffer(gl.ARRAY_BUFFER, this.texCoordBuffer);
        gl.vertexAttribPointer(2, 2, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(2);
 
        gl.bindTexture(gl.TEXTURE_2D, this.texture);
    }
 
    draw(projViewMatrix)
    {
        gl.useProgram(this.program);
 
        glMatrix.mat4.fromRotationTranslationScale(this.modelMatrix, this.rotation, this.position, this.scale);
        glMatrix.mat4.mul(this.mvpMatrix, projViewMatrix, this.modelMatrix);
        gl.uniformMatrix4fv(this.uMvpMatrixLocation, false, this.mvpMatrix);
        gl.uniformMatrix4fv(this.uModelMatrixLocation, false, this.modelMatrix);
 
        glMatrix.mat4.invert(this.normalMatrix, this.modelMatrix);
        glMatrix.mat4.transpose(this.normalMatrix, this.normalMatrix);
        gl.uniformMatrix4fv(this.uNormalMatrixLocation, false, this.normalMatrix);
 
        this.bind();
        gl.drawArrays(gl.TRIANGLES, 0, this.amountOfVertices);
    }
}
js/object-for-physics.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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class ObjectForPhysics extends ObjectForGraphics
{
    constructor(program, position, rotation, amountOfVertices, vertPosBuffer, normalBuffer, texCoordBuffer, texture, shape, mass)
    {
        super(program, position, amountOfVertices, vertPosBuffer, normalBuffer, texCoordBuffer, texture);
 
        this.tempMotionState = null;
        this.tempTransform = new Ammo.btTransform();
        this.tempRotation = null;
        const initialPosition = new Ammo.btVector3(position[0], position[1], position[2]);
        const initialRotation = new Ammo.btQuaternion(rotation[0], rotation[1], rotation[2], rotation[3]);
        const transform = new Ammo.btTransform();
        transform.setIdentity();
        transform.setOrigin(initialPosition);
        transform.setRotation(initialRotation);
        const motionState = new Ammo.btDefaultMotionState(transform);
 
        const localInertia = new Ammo.btVector3(0, 0, 0);
        if (mass !== 0)
        {
            shape.calculateLocalInertia(mass, localInertia);
        }
 
        const rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, shape, localInertia);
        this.body = new Ammo.btRigidBody(rbInfo);
        this.body.setActivationState(4); // Disable deactivation
 
        // this.body.setFriction(1);
        // this.body.setRollingFriction(1);
 
        world.addRigidBody(this.body);
    }
 
    update()
    {
        this.tempMotionState = this.body.getMotionState();
        if (this.tempMotionState)
        {
            this.tempMotionState.getWorldTransform(this.tempTransform);
            this.position[0] = this.tempTransform.getOrigin().x();
            this.position[1] = this.tempTransform.getOrigin().y();
            this.position[2] = this.tempTransform.getOrigin().z();
            this.tempRotation = this.tempTransform.getRotation();
            this.rotation[0] = this.tempRotation.x();
            this.rotation[1] = this.tempRotation.y();
            this.rotation[2] = this.tempRotation.z();
            this.rotation[3] = this.tempRotation.w();
        }
    }
}
js/shader-program.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
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
function createProgram(vertexShaderName, fragmentShaderName)
{
    // Get shader elements
    var vShaderElement = document.getElementById(vertexShaderName);
    var fShaderElement = document.getElementById(fragmentShaderName);
    
    if (vShaderElement == null)
    {
        console.log(`Failed to get an element with name "${vertexShaderName}"`);
        return null;
    }
 
    if (fShaderElement == null)
    {
        console.log(`Failed to get an element with name "${fragmentShaderName}"`);
        return null;
    }
 
    const vertShaderSource = vShaderElement.firstChild.textContent;
    const vShader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(vShader, vertShaderSource);
    gl.compileShader(vShader);
    let ok = gl.getShaderParameter(vShader, gl.COMPILE_STATUS);
    if (!ok)
    {
        console.log("vert: " + gl.getShaderInfoLog(vShader));
        return null;
    };
 
    const fragShaderSource = fShaderElement.firstChild.textContent;
    const fShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(fShader, fragShaderSource);
    gl.compileShader(fShader);
    ok = gl.getShaderParameter(vShader, gl.COMPILE_STATUS);
    if (!ok)
    {
        console.log("frag: " + gl.getShaderInfoLog(fShader));
        return null;
    };
 
    const program = gl.createProgram();
    gl.attachShader(program, vShader);
    gl.attachShader(program, fShader);
    gl.bindAttribLocation(program, 0, "aPosition");
    gl.bindAttribLocation(program, 1, "aNormal");
    gl.bindAttribLocation(program, 2, "aTexCoord");
    gl.linkProgram(program);
    ok = gl.getProgramParameter(program, gl.LINK_STATUS);
    if (!ok)
    {
        console.log("link: " + gl.getProgramInfoLog(program));
        return null;
    };
    gl.useProgram(program);
 
    return program;
}
js/vertex-buffers.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
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
async function initVertexBuffers(modelPaths, callback)
{
    const vertPosBuffers = [];
    const normalBuffers = [];
    const texCoordBuffers = [];
    const amounts = [];
 
    for (let i = 0; i < modelPaths.length; ++i)
    {
        const contentResponse = await fetch(modelPaths[i]);
        const content = await contentResponse.text();
 
        const parser = new DOMParser();
        const xmlDoc = parser.parseFromString(content, "text/xml");
 
        const expForIndexes = "//*[local-name() = 'p']/text()";
        let nodes = xmlDoc.evaluate(expForIndexes, xmlDoc, null, XPathResult.ANY_TYPE, null);
        let result = nodes.iterateNext();
        const order = result.textContent.trim().split(" ").map((value) => { return parseInt(value); });
        // console.log(order);
 
        const partOfPositionsId = "mesh-positions-array";
        const expForPositions = `//*[local-name() = 'float_array'][substring(@id, string-length(@id) -` +
            `string-length('${partOfPositionsId}') + 1) = '${partOfPositionsId}']`;
        nodes = xmlDoc.evaluate(expForPositions, xmlDoc, null, XPathResult.ANY_TYPE, null);
        result = nodes.iterateNext();
        const positions = result.textContent.trim().split(" ").map((value) => { return parseFloat(value); });
        // console.log(positions);
 
        const partOfNormalsId = "mesh-normals-array";
        const expForNormals = `//*[local-name() = 'float_array'][substring(@id, string-length(@id) -` +
            `string-length('${partOfNormalsId}') + 1) = '${partOfNormalsId}']`;
        nodes = xmlDoc.evaluate(expForNormals, xmlDoc, null, XPathResult.ANY_TYPE, null);
        result = nodes.iterateNext();
        const normals = result.textContent.trim().split(" ").map((value) => { return parseFloat(value); });
        // console.log(normals);
 
        const partOfTexCoordsId = "mesh-map-0-array";
        const expForTexCoords = `//*[local-name() = 'float_array'][substring(@id, string-length(@id) -` +
            `string-length('${partOfTexCoordsId}') + 1) = '${partOfTexCoordsId}']`;
        nodes = xmlDoc.evaluate(expForTexCoords, xmlDoc, null, XPathResult.ANY_TYPE, null);
        result = nodes.iterateNext();
        const texCoords = result.textContent.trim().split(" ").map((value) => { return parseFloat(value); });
        // console.log(texCoords);
 
        const correctionMatrix = glMatrix.mat4.create();
        glMatrix.mat4.fromXRotation(correctionMatrix, -Math.PI / 2);
 
        const vertPosResult = [];
        const normalsResult = [];
        const texCoordsResult = [];
 
        const amountOfTriangles = order.length / 9;
        for (let i = 0; i < amountOfTriangles; ++i)
        {
            for (let j = 0; j < 9; ++j)
            {
                if ((i * 9 + j) % 3 === 0)
                {
                    const vx = positions[order[i * 9 + j] * 3 + 0];
                    const vy = positions[order[i * 9 + j] * 3 + 1];
                    const vz = positions[order[i * 9 + j] * 3 + 2];
                    const oldPos = glMatrix.vec3.fromValues(vx, vy, vz);
                    const newPos = glMatrix.vec3.create();
                    glMatrix.vec3.transformMat4(newPos, oldPos, correctionMatrix);
                    vertPosResult.push(newPos[0]);
                    vertPosResult.push(newPos[1]);
                    vertPosResult.push(newPos[2]);
                }
                else if((i * 9 + j) % 3 === 1)
                {
                    const nx = normals[order[i * 9 + j] * 3 + 0];
                    const ny = normals[order[i * 9 + j] * 3 + 1];
                    const nz = normals[order[i * 9 + j] * 3 + 2];
                    const oldNormal = glMatrix.vec3.fromValues(nx, ny, nz);
                    const newNormal = glMatrix.vec3.create();
                    glMatrix.vec3.transformMat4(newNormal, oldNormal, correctionMatrix);
                    normalsResult.push(newNormal[0]);
                    normalsResult.push(newNormal[1]);
                    normalsResult.push(newNormal[2]);
                }
                else if((i * 9 + j) % 3 === 2)
                {
                    texCoordsResult.push(texCoords[order[i * 9 + j] * 2 + 0]);
                    texCoordsResult.push(texCoords[order[i * 9 + j] * 2 + 1]);
                }
            }
        }
        // console.log(vertPosResult);
        // console.log(texCoordsResult);
 
        const vertPosBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, vertPosBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertPosResult), gl.STATIC_DRAW);
 
        const normalBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(normalsResult), gl.STATIC_DRAW);
 
        const texCoordBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(texCoordsResult), gl.STATIC_DRAW);
 
        vertPosBuffers.push(vertPosBuffer);
        normalBuffers.push(normalBuffer);
        texCoordBuffers.push(texCoordBuffer);
        amounts.push(vertPosResult.length / 3);
    }
 
    callback(vertPosBuffers, normalBuffers, texCoordBuffers, amounts);
}
js/webgl-context.js

Javascript
1
2
3
4
const canvas = document.getElementById("renderCanvas");
const gl = canvas.getContext("webgl");
gl.enable(gl.DEPTH_TEST);
gl.clearColor(0.5, 0.6, 0.8, 1.0);
0
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
13.01.2022, 23:21  [ТС] 3
Изображения
 
0
219 / 22 / 2
Регистрация: 12.06.2021
Сообщений: 205
Записей в блоге: 2
21.01.2022, 07:23 4
8Observer8, здравствуйте, у меня есть пример выполненный с помощью babylon.
https://codepen.io/Smith37/pen/abLgyEJ
Так же вот управление 3d персонажем, от 3-его лица (я пока плохо разбираюсь в babylon и не знаю как загружать текстуры, поэтому модель персонажа в сетку).
https://codepen.io/Smith37/pen/NWaZvYZ. Чтобы перемещать нужно нажать "Space (пробел)". Двигается правда медленно.

Еще несколько примеров работы с камерой добавлено вот сюда Проекты на Three.js и Babylon.js

Я заметила, что вы используете библиотеку Ammo для симуляции физики. В интернете нашла несколько интересных примеров.
Пример 1: http://kripken.github.io/ammo.... index.html

Демки (с лева в углу есть кнопка demo можно выбирать какую демку загрузить): http://lo-th.github.io/Ammo.lab/#basic
1
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
21.01.2022, 17:08  [ТС] 5
Olga28, вам надо обязательно изучать эту статью для управления 3D персонажем: Moving Objects In JavaScript 3D Physics using Ammo.js and Three.js

Я вчера и сегодня сильно продвинулся с Jill. Написал скрипт на Python для Blender 2.67b, который импортирует позиции и углы анимации из программы RE1MV. Я загружаю пока только один фрейм. Осталось загрузить все фреймы. Тогда я смогу объединить анимации модели и физику перемещения на Ammo.js в WebGL.



Миниатюры
Управление героем стрелками в 3D, вид от 3-го лица, на WebGL
2
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
21.01.2022, 17:40  [ТС] 6
Цитата Сообщение от Olga28 Посмотреть сообщение
Я заметила, что вы используете библиотеку Ammo для симуляции физики. В интернете нашла несколько интересных примеров.
Пример 1: http://kripken.github.io/ammo.... index.html
Этот пример я ещё не разбирал, но я его видел, он из официальных примеров GitHub репозитория Ammo.js, там ещё есть примеры: https://github.com/kripken/amm... n/examples

Для 3D я два физических движка изучаю: Ammo.js и Cannon.js (а также Cannon-es). Они очень похожи между собой. Изначальный Cannon.js заброшен, но от него был сделан fork, который активно развивается и называется Cannon-es

Если вы используете Browserify, то разницы в подключении Cannon.js и Cannon-es - нет, но если вы используете Cannon-es в index.html, то у скрипта нужно написать тип: type="module" и использовать import, вот так:

PHP/HTML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="en">
 
<head>
    <title>Example</title>
</head>
 
<body>
    <script type="module">
        import * as CANNON from "https://cdn.jsdelivr.net/npm/cannon-es@0.18.0/dist/cannon-es.js";
 
        const gravity = new CANNON.Vec3(0, -9.82, 0);
        console.log(gravity);
    </script>
</body>
 
</html>
Вывод программы:

Vec3 {x: 0, y: -9.82, z: 0}
0
219 / 22 / 2
Регистрация: 12.06.2021
Сообщений: 205
Записей в блоге: 2
22.01.2022, 09:51 7
8Observer8, я сейчас кроме книги по WebGL изучаю исходники Away3d 3.6 Essentials, это аналог современных web 3d движков только на flash.
Управление героем стрелками в 3D, вид от 3-го лица, на WebGL

Технология конечно устарела, но некоторые примеры в книге я пытаюсь реализовать под Treejs или babylon. Например слежение за сферой и поворот камеры на шахматном поле взят из этой книги. Вот исходники, там есть несколько примеров как загрузить 3d объект космического кораблей и монстров https://disk.yandex.ru/d/daIXDgkJ3b18hQ.

Самые интересные примеры работы с камерой я сделала на flash. Вот мои исходники https://disk.yandex.ru/d/9f4cFDA3u7u1eA. В папке demo есть 3 html файла их нужно запустить в браузере чтобы проиграть флеш. Сейчас современные браузеры блокируют flash, поэтому не знаю запуститься или нет. Я использую старые браузеры.

При работе появляется сообщение, что некоторые функции из книги Away3d 3.6 Essentials, требуют обновить Flex SDK. Поэтому я переписала ту часть отвечающую за загрузку картинок, пришлось и освещение настроить теперь они работают на чистом Flash.

Эти исходники мне нужны, чтобы потом их переписать на другой графический web движок. На одном форуме есть ваш пост ссылки на книгу Babylon и исходники.

Вот этот пост: List of the best Babylon.js video and text tutorials and books. Там ссылки битые. У вас есть копии книги и исходников?

Books:
Learning Babylonjs
Babylon.JS Essentials (source code)
1
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
22.01.2022, 14:20  [ТС] 8
Цитата Сообщение от Olga28 Посмотреть сообщение
я сейчас кроме книги по WebGL изучаю исходники Away3d 3.6 Essentials, это аналог современных web 3d движков только на flash.
Я буду посматривать исходники к этой книге и может книгу. Я всегда выискиваю что-то универсальное, что можно применить на чистом WebGL. Особенно то что касается математики и физики универсально на любом движке и графическом API. Вы, самое главное, изучайте книгу WebGL Мацуды и Ли. Вам понимание WebGL и особенно знание языка GLSL просто необходимо будет даже если вы будете использовать только движки: Babylon.js, Three.js и Phaser, потому что все они написаны на WebGL и GLSL и написание шейдеров - это необходимая часть программирования графики из движков на чуть более продвинутом уровне профессионализма, чем базовый. Смотрите мои примеры, где я использую glMatrix вместо их авторской библиотеки для работы с матрицами и векторами: Небольшие примеры на WebGL. Знаете, как интереснее всего делать? Вы старайтесь учиться писать код на WebGL каждый раз с нуля из головы. Делайте очень маленькие упражнения с написанием с нуля. Сначала подглядывайте в готовые примеры, а потом вы заметите, что с каждым разом вам нужно подглядывать всё меньше и меньше. У вас конструкции будут отпечатываться в голове и вы не заметите, как вы на автомате будете кодить и не будете спотыкаться на простых вещах. Надо доводить алгоритмы разработки до автоматизма.

Цитата Сообщение от Olga28 Посмотреть сообщение
Там ссылки битые. У вас есть копии книги и исходников?
Там только одна ссылка битая - это ссылка на исходники книги "Babylon.JS Essentials". Исходники к этой книге я приложил к данному сообщению, но саму книгу не могу, потому что это запрещено правилами форума:

Правило 5.3. Запрещено размещать любые материалы, нарушающие авторские права (без разрешения правообладателя), а также ссылки на них.
Для книги "Learning Babylonjs" у меня нет даже исходников. Я её собирался купить в электронном виде, так и не купил. А книгу "Babylon.JS Essentials" вы можете прочитать за триал период за неделю по ссылке. Если нет времени прочитать за неделю, то можете скопировать текст и оформить для себя в виде локального простого HTML сайта (я так и сделал). Для себя можно - распространять нельзя. Исходники к этой книге лежали в открытом доступе.
Вложения
Тип файла: zip 9781785884795_Code.zip (19.47 Мб, 2 просмотров)
1
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
22.01.2022, 17:49  [ТС] 9
Надо заметить, что исходники к книге "Babylon.JS Essentials" на языке TypeScript, но его не нужно пугаться. Кстати, он очень сильно похож на ActionScript, поэтому вам будет привычно. TypeScript - это как JavaScript, в который добавили ActionScript.
0
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
25.01.2022, 20:02  [ТС] 10
Olga28, для браузера лучше делать персонажей от третьего лица без скиннинга, а разбивать 3D-модель на части для скелетной анимации. Я для автоматизации работы для экономии времени пишу скрипты на Python в Blender 2.67b. Советую вам изучать это направление. Здесь я собрал полезные материалы: Генерация логотипа Mitsubishi на Blender Python API



Со скиннингом я делал на чистом WebGL, но мой браузер начинает шуметь:



Миниатюры

Управление героем стрелками в 3D, вид от 3-го лица, на WebGL

Управление героем стрелками в 3D, вид от 3-го лица, на WebGL

0
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
25.01.2022, 20:07  [ТС] 11
Цитата Сообщение от 8Observer8 Посмотреть сообщение
но мой браузер начинает шуметь
*ноутбук
0
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
26.01.2022, 12:41  [ТС] 12
Я вчера загрузил оригинальную анимацию покоя Jill в WebGL из файла формата COLLADA (.dae). Jill ведёт меня от цели к цели. Следующие цели, на которые показала Jill - это загрузка анимации ходьбы, переключение между анимацией покоя и анимацией ходьбы и ходьба с помощью контроллера от третьего лица из первого поста данной темы на физическом движке Ammo.js. Я хочу потом переписать контроллер с Ammo.js на Cannon-es, чтобы увидеть различия и сходства. Может для каких-то проектов лучше подойдёт Ammo.js, а для других Cannon-es, по каким-то причинам. Я пробовал Cannon.js в этом примере (от этого движка был сделан fork - Cannon-es, а Cannon.js более 6 лет заброшен). Cannon.js проще в использовании, чем Ammo.js, а значит и Cannon-es тоже. Неплохо уметь использовать оба популярных физических движка Ammo.js и Cannon-es. Ammo.js - это порт физического движка Bullet Physics с С++ на JavaScript. Если будете изучать программирование 2D игр, то берите движок Planck.js (это порт физического движка Box2D) и Matter.js

Оригинальная анимация покоя Jill на WebGL (немного ускоренная):


Загрузка анимаций на Blender Python API из файл .ani, который был извлечён из игры "Resident Evil" с помощью программы RE1MV:



Работа с программой RE1MV:



Миниатюры

Управление героем стрелками в 3D, вид от 3-го лица, на WebGL

Управление героем стрелками в 3D, вид от 3-го лица, на WebGL

1
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
17.04.2022, 16:54  [ТС] 13
Цитата Сообщение от 8Observer8 Посмотреть сообщение
Оригинальная анимация покоя Jill на WebGL
Загрузил все игровые анимации этого персонажа из файла формата DAE COLLADA в WebGL на TypeScript:

0
219 / 22 / 2
Регистрация: 12.06.2021
Сообщений: 205
Записей в блоге: 2
18.04.2022, 14:58 14
8Observer8, пример глянуть можно demo?
0
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
18.04.2022, 22:26  [ТС] 15
Цитата Сообщение от Olga28 Посмотреть сообщение
пример глянуть можно demo?
Я опасаюсь выкладывать исходники этого примера в открытый доступ на Github (он у меня в приватном репозитории), потому что права на модель и анимации к ней принадлежат Capcom. Позже заменю модель и анимации на бесплатные или свои и выложу вместе с управлением персонажа с помощью физического движка Ammo.js, как в примере темы. Сейчас я переписываю этот пример на Python и OpenGL на PyQt5 для лучшего понимания и самообучения. На Python есть возможность использовать физический движок из Panda3D - там как раз Bullet Physics, а модуль panda3d.bullet можно использовать отдельно от Panda3D. Потом перепишу на Qt C++ OpenGL ES, чтобы собирать для Windows и Android.

Olga28, я делаю анимацию по книге Мацуды и Ли WebGL. Программирование трехмерной графики, точнее по главе 9 "Иерархические объекты". В этой главе объясняются три примера (примеры запускаются в JSFiddle через VPN):
  • ch09/JointModel: https://jsfiddle.net/8Observer8/vqse5egz/
    Исходник

    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
    
        <p>&larr;&rarr;: arm1 rotation(y-axis), &uarr;&darr;: joint1 rotation(z-axis)</p>
        <canvas id="webgl" width="400" height="400">
            Please use a browser that supports "canvas"
        </canvas>
     
        <script type="x-shader/x-vertex" id="VertexShader">
            attribute vec4 a_Position;
            attribute vec4 a_Normal;
            uniform mat4 u_MvpMatrix;
            uniform mat4 u_NormalMatrix;
            varying vec4 v_Color;
     
            void main()
            {
                gl_Position = u_MvpMatrix * a_Position;
     
                // Shading calculation to make the arm look three-dimensional
                vec3 lightDirection = normalize(vec3(0.0, 0.5, 0.7)); // Light direction
                vec4 color = vec4(1.0, 0.4, 0.0, 1.0);
                vec3 normal = normalize((u_NormalMatrix * a_Normal).xyz);
                float nDotL = max(dot(normal, lightDirection), 0.0);
                v_Color = vec4(color.rgb * nDotL + vec3(0.1), color.a);
            }
        </script>
     
        <script type="x-shader/x-fragment" id="FragmentShader">
            precision mediump float;
     
            varying vec4 v_Color;
     
            void main()
            {
                gl_FragColor = v_Color;
            }
        </script>
     
        <script src="https://dl.dropboxusercontent.com/s/ylw7v7a44xtrwv0/webgl-utils.js"></script>
        <script src="https://dl.dropboxusercontent.com/s/iz1n21c8xafd76n/webgl-debug.js"></script>
        <script src="https://dl.dropboxusercontent.com/s/subm1yzylxuao8v/cuon-utils.js"></script>
        <script src="https://dl.dropboxusercontent.com/s/jw3p82lq1cjwekg/cuon-matrix.js"></script>
    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
    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
    
    // JointModel.js (c) 2012 matsuda
    // This is an example from the book "WebGL Programming Guide"
    // by Kouichi Matsuda and Rodger Lea
     
    var ANGLE_STEP = 3.0;    // The increments of rotation angle (degrees)
    var g_arm1Angle = -90.0; // The rotation angle of arm1 (degrees)
    var g_joint1Angle = 0.0; // The rotation angle of joint1 (degrees)
     
    // Coordinate transformation matrix
    var g_modelMatrix = new Matrix4(), g_mvpMatrix = new Matrix4();
     
    // Coordinate transformation matrix for normals
    var g_normalMatrix = new Matrix4();
     
    main();
    //window.onload = main;
     
    function main()
    {
        // Retrieve <canvas> element
        var canvas = document.getElementById('webgl');
     
        // Get the rendering context for WebGL
        var gl = getWebGLContext(canvas);
        if (!gl)
        {
            console.log('Failed to get the rendering context for WebGL');
            return;
        }
     
        // Get shader elements
        var vShaderElement = document.getElementById("VertexShader");
        var fShaderElement = document.getElementById("FragmentShader");
        if (vShaderElement == null)
        {
            console.log("Failed to get the vertex shader element");
            return;
        }
        if (fShaderElement == null)
        {
            console.log("Failed to get the fragment shader element");
            return;
        }
     
        // Get shader sources
        var vShaderSource = vShaderElement.firstChild.textContent;
        var fShaderSource = fShaderElement.firstChild.textContent;
     
        // Initialize shaders
        if (!initShaders(gl, vShaderSource, fShaderSource))
        {
            console.log('Failed to intialize shaders');
            return;
        }
     
        // Set the vertex information
        var n = initVertexBuffers(gl);
        if (n < 0)
        {
            console.log('Failed to set the vertex information');
            return;
        }
     
        // Set the clear color and enable the depth test
        gl.clearColor(0.0, 0.0, 0.0, 1.0);
        gl.enable(gl.DEPTH_TEST);
     
        // Get the storage locations of uniform variables
        var u_MvpMatrix = gl.getUniformLocation(gl.program, 'u_MvpMatrix');
        var u_NormalMatrix = gl.getUniformLocation(gl.program, 'u_NormalMatrix');
        if (!u_MvpMatrix || !u_NormalMatrix)
        {
            console.log('Failed to get the storage location');
            return;
        }
     
        // Calculate the view projection matrix
        var viewProjMatrix = new Matrix4();
        viewProjMatrix.setPerspective(50.0, canvas.width / canvas.height, 1.0, 100.0);
        viewProjMatrix.lookAt(20.0, 10.0, 30.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
     
        // Register the event handler to be called when keys are pressed
        document.onkeydown = function (ev) { keydown(ev, gl, n, viewProjMatrix, u_MvpMatrix, u_NormalMatrix); };
     
        draw(gl, n, viewProjMatrix, u_MvpMatrix, u_NormalMatrix);  // Draw the robot arm
    }
     
    function keydown(ev, gl, n, viewProjMatrix, u_MvpMatrix, u_NormalMatrix)
    {
        switch (ev.keyCode)
        {
            case 38: // Up arrow key -> the positive rotation of joint1 around the z-axis
                if (g_joint1Angle < 135.0) g_joint1Angle += ANGLE_STEP;
                break;
            case 40: // Down arrow key -> the negative rotation of joint1 around the z-axis
                if (g_joint1Angle > -135.0) g_joint1Angle -= ANGLE_STEP;
                break;
            case 39: // Right arrow key -> the positive rotation of arm1 around the y-axis
                g_arm1Angle = (g_arm1Angle + ANGLE_STEP) % 360;
                break;
            case 37: // Left arrow key -> the negative rotation of arm1 around the y-axis
                g_arm1Angle = (g_arm1Angle - ANGLE_STEP) % 360;
                break;
            default: return; // Skip drawing at no effective action
        }
        // Draw the robot arm
        draw(gl, n, viewProjMatrix, u_MvpMatrix, u_NormalMatrix);
    }
     
    function initVertexBuffers(gl)
    {
        // Vertex coordinates(a cuboid 3.0 in width, 10.0 in height, and 3.0 in length with its origin at the center of its bottom)
        var vertices = new Float32Array([
          1.5, 10.0, 1.5, -1.5, 10.0, 1.5, -1.5, 0.0, 1.5, 1.5, 0.0, 1.5, // v0-v1-v2-v3 front
          1.5, 10.0, 1.5, 1.5, 0.0, 1.5, 1.5, 0.0, -1.5, 1.5, 10.0, -1.5, // v0-v3-v4-v5 right
          1.5, 10.0, 1.5, 1.5, 10.0, -1.5, -1.5, 10.0, -1.5, -1.5, 10.0, 1.5, // v0-v5-v6-v1 up
         -1.5, 10.0, 1.5, -1.5, 10.0, -1.5, -1.5, 0.0, -1.5, -1.5, 0.0, 1.5, // v1-v6-v7-v2 left
         -1.5, 0.0, -1.5, 1.5, 0.0, -1.5, 1.5, 0.0, 1.5, -1.5, 0.0, 1.5, // v7-v4-v3-v2 down
          1.5, 0.0, -1.5, -1.5, 0.0, -1.5, -1.5, 10.0, -1.5, 1.5, 10.0, -1.5  // v4-v7-v6-v5 back
        ]);
     
        // Normal
        var normals = new Float32Array([
          0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, // v0-v1-v2-v3 front
          1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, // v0-v3-v4-v5 right
          0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, // v0-v5-v6-v1 up
         -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, // v1-v6-v7-v2 left
          0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, // v7-v4-v3-v2 down
          0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0  // v4-v7-v6-v5 back
        ]);
     
        // Indices of the vertices
        var indices = new Uint8Array([
           0, 1, 2, 0, 2, 3,    // front
           4, 5, 6, 4, 6, 7,    // right
           8, 9, 10, 8, 10, 11,    // up
          12, 13, 14, 12, 14, 15,    // left
          16, 17, 18, 16, 18, 19,    // down
          20, 21, 22, 20, 22, 23     // back
        ]);
     
        // Write the vertex property to buffers (coordinates and normals)
        if (!initArrayBuffer(gl, 'a_Position', vertices, gl.FLOAT, 3)) return -1;
        if (!initArrayBuffer(gl, 'a_Normal', normals, gl.FLOAT, 3)) return -1;
     
        // Unbind the buffer object
        gl.bindBuffer(gl.ARRAY_BUFFER, null);
     
        // Write the indices to the buffer object
        var indexBuffer = gl.createBuffer();
        if (!indexBuffer)
        {
            console.log('Failed to create the buffer object');
            return -1;
        }
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
     
        return indices.length;
    }
     
    function initArrayBuffer(gl, attribute, data, type, num)
    {
        // Create a buffer object
        var buffer = gl.createBuffer();
        if (!buffer)
        {
            console.log('Failed to create the buffer object');
            return false;
        }
        // Write date into the buffer object
        gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
        gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
     
        // Assign the buffer object to the attribute variable
        var a_attribute = gl.getAttribLocation(gl.program, attribute);
        if (a_attribute < 0)
        {
            console.log('Failed to get the storage location of ' + attribute);
            return false;
        }
        gl.vertexAttribPointer(a_attribute, num, type, false, 0, 0);
        // Enable the assignment of the buffer object to the attribute variable
        gl.enableVertexAttribArray(a_attribute);
     
        return true;
    }
     
    function draw(gl, n, viewProjMatrix, u_MvpMatrix, u_NormalMatrix)
    {
        // Clear color and depth buffer
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
     
        // Arm1
        var arm1Length = 10.0; // Length of arm1
        g_modelMatrix.setTranslate(0.0, -12.0, 0.0);
        g_modelMatrix.rotate(g_arm1Angle, 0.0, 1.0, 0.0);    // Rotate around the y-axis
        drawBox(gl, n, viewProjMatrix, u_MvpMatrix, u_NormalMatrix); // Draw
     
        // Arm2
        g_modelMatrix.translate(0.0, arm1Length, 0.0);    // Move to joint1
        g_modelMatrix.rotate(g_joint1Angle, 0.0, 0.0, 1.0);  // Rotate around the z-axis
        g_modelMatrix.scale(1.3, 1.0, 1.3); // Make it a little thicker
        drawBox(gl, n, viewProjMatrix, u_MvpMatrix, u_NormalMatrix); // Draw
    }
     
    // Draw the cube
    function drawBox(gl, n, viewProjMatrix, u_MvpMatrix, u_NormalMatrix)
    {
        // Calculate the model view project matrix and pass it to u_MvpMatrix
        g_mvpMatrix.set(viewProjMatrix);
        g_mvpMatrix.multiply(g_modelMatrix);
        gl.uniformMatrix4fv(u_MvpMatrix, false, g_mvpMatrix.elements);
     
        // Calculate the normal transformation matrix and pass it to u_NormalMatrix
        g_normalMatrix.setInverseOf(g_modelMatrix);
        g_normalMatrix.transpose();
        gl.uniformMatrix4fv(u_NormalMatrix, false, g_normalMatrix.elements);
     
        // Draw
        gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0);
    }
    CSS
    1
    2
    3
    
    body {
      overflow: hidden;
    }
  • ch09/MultiJointModel: https://jsfiddle.net/8Observer8/sL53wkn3/
    Исходник

    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
    
        <p>&larr;&rarr;: arm1 rotation,&uarr;&darr;: joint1 rotation, xz: joint2(wrist) rotation, cv: finger rotation</p>
        <canvas id="webgl" width="400" height="400">
            Please use a browser that supports "canvas"
        </canvas>
     
        <script type="x-shader/x-vertex" id="VertexShader">
            attribute vec4 a_Position;
            attribute vec4 a_Normal;
            uniform mat4 u_MvpMatrix;
            uniform mat4 u_NormalMatrix;
            varying vec4 v_Color;
     
            void main()
            {
                gl_Position = u_MvpMatrix * a_Position;
     
                // Shading calculation to make the arm look three-dimensional
                vec3 lightDirection = normalize(vec3(0.0, 0.5, 0.7)); // Light direction
                vec4 color = vec4(1.0, 0.4, 0.0, 1.0);  // Robot color
                vec3 normal = normalize((u_NormalMatrix * a_Normal).xyz);
                float nDotL = max(dot(normal, lightDirection), 0.0);
                v_Color = vec4(color.rgb * nDotL + vec3(0.1), color.a);
            }
        </script>
     
        <script type="x-shader/x-fragment" id="FragmentShader">
            precision mediump float;
     
            varying vec4 v_Color;
     
            void main()
            {
                gl_FragColor = v_Color;
            }
        </script>
     
        <script src="https://dl.dropboxusercontent.com/s/ylw7v7a44xtrwv0/webgl-utils.js"></script>
        <script src="https://dl.dropboxusercontent.com/s/iz1n21c8xafd76n/webgl-debug.js"></script>
        <script src="https://dl.dropboxusercontent.com/s/subm1yzylxuao8v/cuon-utils.js"></script>
        <script src="https://dl.dropboxusercontent.com/s/jw3p82lq1cjwekg/cuon-matrix.js"></script>
    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
    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
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    
    // MultiJointModel.js (c) 2012 matsuda and itami
    // This is an example from the book "WebGL Programming Guide"
    // by Kouichi Matsuda and Rodger Lea
     
    var ANGLE_STEP = 3.0;     // The increments of rotation angle (degrees)
    var g_arm1Angle = 90.0;   // The rotation angle of arm1 (degrees)
    var g_joint1Angle = 45.0; // The rotation angle of joint1 (degrees)
    var g_joint2Angle = 0.0;  // The rotation angle of joint2 (degrees)
    var g_joint3Angle = 0.0;  // The rotation angle of joint3 (degrees)
     
    // Coordinate transformation matrix
    var g_modelMatrix = new Matrix4(), g_mvpMatrix = new Matrix4();
     
    // Coordinate transformation matrix for normals
    var g_normalMatrix = new Matrix4();
     
    // Array for storing a matrix
    var g_matrixStack = [];
     
    main();
    //window.onload = main;
     
    function main()
    {
        // Retrieve <canvas> element
        var canvas = document.getElementById('webgl');
     
        // Get the rendering context for WebGL
        var gl = getWebGLContext(canvas);
        if (!gl)
        {
            console.log('Failed to get the rendering context for WebGL');
            return;
        }
     
        // Get shader elements
        var vShaderElement = document.getElementById("VertexShader");
        var fShaderElement = document.getElementById("FragmentShader");
        if (vShaderElement == null)
        {
            console.log("Failed to get the vertex shader element");
            return;
        }
        if (fShaderElement == null)
        {
            console.log("Failed to get the fragment shader element");
            return;
        }
     
        // Get shader sources
        var vShaderSource = vShaderElement.firstChild.textContent;
        var fShaderSource = fShaderElement.firstChild.textContent;
     
        // Initialize shaders
        if (!initShaders(gl, vShaderSource, fShaderSource))
        {
            console.log('Failed to intialize shaders');
            return;
        }
     
        // Set the vertex information
        var n = initVertexBuffers(gl);
        if (n < 0)
        {
            console.log('Failed to set the vertex information');
            return;
        }
     
        // Set the clear color and enable the depth test
        gl.clearColor(0.0, 0.0, 0.0, 1.0);
        gl.enable(gl.DEPTH_TEST);
     
        // Get the storage locations of uniform variables
        var u_MvpMatrix = gl.getUniformLocation(gl.program, 'u_MvpMatrix');
        var u_NormalMatrix = gl.getUniformLocation(gl.program, 'u_NormalMatrix');
        if (!u_MvpMatrix || !u_NormalMatrix)
        {
            console.log('Failed to get the storage location');
            return;
        }
     
        // Calculate the view projection matrix
        var viewProjMatrix = new Matrix4();
        viewProjMatrix.setPerspective(50.0, canvas.width / canvas.height, 1.0, 100.0);
        viewProjMatrix.lookAt(20.0, 10.0, 30.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
     
        // Register the event handler to be called on key press
        document.onkeydown = function (ev) { keydown(ev, gl, n, viewProjMatrix, u_MvpMatrix, u_NormalMatrix); };
     
        draw(gl, n, viewProjMatrix, u_MvpMatrix, u_NormalMatrix); // Draw the robot arm
    }
     
    function keydown(ev, gl, n, viewProjMatrix, u_MvpMatrix, u_NormalMatrix)
    {
        switch (ev.keyCode)
        {
            case 40: // Up arrow key -> the positive rotation of joint1 around the z-axis
                if (g_joint1Angle < 135.0) g_joint1Angle += ANGLE_STEP;
                break;
            case 38: // Down arrow key -> the negative rotation of joint1 around the z-axis
                if (g_joint1Angle > -135.0) g_joint1Angle -= ANGLE_STEP;
                break;
            case 39: // Right arrow key -> the positive rotation of arm1 around the y-axis
                g_arm1Angle = (g_arm1Angle + ANGLE_STEP) % 360;
                break;
            case 37: // Left arrow key -> the negative rotation of arm1 around the y-axis
                g_arm1Angle = (g_arm1Angle - ANGLE_STEP) % 360;
                break;
            case 90: // 'z'key -> the positive rotation of joint2
                g_joint2Angle = (g_joint2Angle + ANGLE_STEP) % 360;
                break;
            case 88: // 'x'key -> the negative rotation of joint2
                g_joint2Angle = (g_joint2Angle - ANGLE_STEP) % 360;
                break;
            case 86: // 'v'key -> the positive rotation of joint3
                if (g_joint3Angle < 60.0) g_joint3Angle = (g_joint3Angle + ANGLE_STEP) % 360;
                break;
            case 67: // 'c'key -> the nagative rotation of joint3
                if (g_joint3Angle > -60.0) g_joint3Angle = (g_joint3Angle - ANGLE_STEP) % 360;
                break;
            default: return; // Skip drawing at no effective action
        }
     
        // Draw the robot arm
        draw(gl, n, viewProjMatrix, u_MvpMatrix, u_NormalMatrix);
    }
     
    function initVertexBuffers(gl)
    {
        // Coordinates(Cube which length of one side is 1 with the origin on the center of the bottom)
        var vertices = new Float32Array([
          0.5, 1.0, 0.5, -0.5, 1.0, 0.5, -0.5, 0.0, 0.5, 0.5, 0.0, 0.5, // v0-v1-v2-v3 front
          0.5, 1.0, 0.5, 0.5, 0.0, 0.5, 0.5, 0.0, -0.5, 0.5, 1.0, -0.5, // v0-v3-v4-v5 right
          0.5, 1.0, 0.5, 0.5, 1.0, -0.5, -0.5, 1.0, -0.5, -0.5, 1.0, 0.5, // v0-v5-v6-v1 up
         -0.5, 1.0, 0.5, -0.5, 1.0, -0.5, -0.5, 0.0, -0.5, -0.5, 0.0, 0.5, // v1-v6-v7-v2 left
         -0.5, 0.0, -0.5, 0.5, 0.0, -0.5, 0.5, 0.0, 0.5, -0.5, 0.0, 0.5, // v7-v4-v3-v2 down
          0.5, 0.0, -0.5, -0.5, 0.0, -0.5, -0.5, 1.0, -0.5, 0.5, 1.0, -0.5  // v4-v7-v6-v5 back
        ]);
     
        // Normal
        var normals = new Float32Array([
          0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, // v0-v1-v2-v3 front
          1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, // v0-v3-v4-v5 right
          0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, // v0-v5-v6-v1 up
         -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, // v1-v6-v7-v2 left
          0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, // v7-v4-v3-v2 down
          0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0  // v4-v7-v6-v5 back
        ]);
     
        // Indices of the vertices
        var indices = new Uint8Array([
           0, 1, 2, 0, 2, 3,    // front
           4, 5, 6, 4, 6, 7,    // right
           8, 9, 10, 8, 10, 11,    // up
          12, 13, 14, 12, 14, 15,    // left
          16, 17, 18, 16, 18, 19,    // down
          20, 21, 22, 20, 22, 23     // back
        ]);
     
        // Write the vertex property to buffers (coordinates and normals)
        if (!initArrayBuffer(gl, 'a_Position', vertices, gl.FLOAT, 3)) return -1;
        if (!initArrayBuffer(gl, 'a_Normal', normals, gl.FLOAT, 3)) return -1;
     
        // Unbind the buffer object
        gl.bindBuffer(gl.ARRAY_BUFFER, null);
     
        // Write the indices to the buffer object
        var indexBuffer = gl.createBuffer();
        if (!indexBuffer)
        {
            console.log('Failed to create the buffer object');
            return -1;
        }
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
     
        return indices.length;
    }
     
    function initArrayBuffer(gl, attribute, data, type, num)
    {
        // Create a buffer object
        var buffer = gl.createBuffer();
        if (!buffer)
        {
            console.log('Failed to create the buffer object');
            return false;
        }
     
        // Write date into the buffer object
        gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
        gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
     
        // Assign the buffer object to the attribute variable
        var a_attribute = gl.getAttribLocation(gl.program, attribute);
        if (a_attribute < 0)
        {
            console.log('Failed to get the storage location of ' + attribute);
            return false;
        }
        gl.vertexAttribPointer(a_attribute, num, type, false, 0, 0);
     
        // Enable the assignment of the buffer object to the attribute variable
        gl.enableVertexAttribArray(a_attribute);
     
        return true;
    }
     
    function draw(gl, n, viewProjMatrix, u_MvpMatrix, u_NormalMatrix)
    {
        // Clear color and depth buffer
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
     
        // Draw a base
        var baseHeight = 2.0;
        g_modelMatrix.setTranslate(0.0, -12.0, 0.0);
        drawBox(gl, n, 10.0, baseHeight, 10.0, viewProjMatrix, u_MvpMatrix, u_NormalMatrix);
     
        // Arm1
        var arm1Length = 10.0;
        g_modelMatrix.translate(0.0, baseHeight, 0.0);     // Move onto the base
        g_modelMatrix.rotate(g_arm1Angle, 0.0, 1.0, 0.0);  // Rotate around the y-axis
        drawBox(gl, n, 3.0, arm1Length, 3.0, viewProjMatrix, u_MvpMatrix, u_NormalMatrix); // Draw
     
        // Arm2
        var arm2Length = 10.0;
        g_modelMatrix.translate(0.0, arm1Length, 0.0);       // Move to joint1
        g_modelMatrix.rotate(g_joint1Angle, 0.0, 0.0, 1.0);  // Rotate around the z-axis
        drawBox(gl, n, 4.0, arm2Length, 4.0, viewProjMatrix, u_MvpMatrix, u_NormalMatrix); // Draw
     
        // A palm
        var palmLength = 2.0;
        g_modelMatrix.translate(0.0, arm2Length, 0.0);       // Move to palm
        g_modelMatrix.rotate(g_joint2Angle, 0.0, 1.0, 0.0);  // Rotate around the y-axis
        drawBox(gl, n, 2.0, palmLength, 6.0, viewProjMatrix, u_MvpMatrix, u_NormalMatrix);  // Draw
     
        // Move to the center of the tip of the palm
        g_modelMatrix.translate(0.0, palmLength, 0.0);
     
        // Draw finger1
        pushMatrix(g_modelMatrix);
        g_modelMatrix.translate(0.0, 0.0, 2.0);
        g_modelMatrix.rotate(g_joint3Angle, 1.0, 0.0, 0.0);  // Rotate around the x-axis
        drawBox(gl, n, 1.0, 2.0, 1.0, viewProjMatrix, u_MvpMatrix, u_NormalMatrix);
        g_modelMatrix = popMatrix();
     
        // Draw finger2
        g_modelMatrix.translate(0.0, 0.0, -2.0);
        g_modelMatrix.rotate(-g_joint3Angle, 1.0, 0.0, 0.0);  // Rotate around the x-axis
        drawBox(gl, n, 1.0, 2.0, 1.0, viewProjMatrix, u_MvpMatrix, u_NormalMatrix);
    }
     
    // Store the specified matrix to the array
    function pushMatrix(m)
    {
        var m2 = new Matrix4(m);
        g_matrixStack.push(m2);
    }
     
    // Retrieve the matrix from the array
    function popMatrix()
    {
        return g_matrixStack.pop();
    }
     
    // Draw rectangular solid
    function drawBox(gl, n, width, height, depth, viewProjMatrix, u_MvpMatrix, u_NormalMatrix)
    {
        // Save the model matrix
        pushMatrix(g_modelMatrix);
     
        // Scale a cube and draw
        g_modelMatrix.scale(width, height, depth);
     
        // Calculate the model view project matrix and pass it to u_MvpMatrix
        g_mvpMatrix.set(viewProjMatrix);
        g_mvpMatrix.multiply(g_modelMatrix);
        gl.uniformMatrix4fv(u_MvpMatrix, false, g_mvpMatrix.elements);
     
        // Calculate the normal transformation matrix and pass it to u_NormalMatrix
        g_normalMatrix.setInverseOf(g_modelMatrix);
        g_normalMatrix.transpose();
        gl.uniformMatrix4fv(u_NormalMatrix, false, g_normalMatrix.elements);
     
        // Draw
        gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0);
     
        // Retrieve the model matrix
        g_modelMatrix = popMatrix();
    }
    CSS
    1
    2
    3
    
    body {
      overflow: hidden;
    }
0
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
18.04.2022, 22:27  [ТС] 16
  • ch09/MultiJointModel_segment: https://jsfiddle.net/8Observer8/ygvk7odv/
    Исходник

    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
    
        <p>&larr;&rarr;: arm1 rotation,&uarr;&darr;: joint1 rotation, xz: joint2(wrist) rotation, cv: finger rotation</p>
        <canvas id="webgl" width="400" height="400">
            Please use a browser that supports "canvas"
        </canvas>
     
        <script type="x-shader/x-vertex" id="VertexShader">
            attribute vec4 a_Position;
            attribute vec4 a_Normal;
            uniform mat4 u_MvpMatrix;
            uniform mat4 u_NormalMatrix;
            varying vec4 v_Color;
     
            void main()
            {
                gl_Position = u_MvpMatrix * a_Position;
     
                // The followings are some shading calculation to make the
                // arm look three-dimensional
                vec3 lightDirection = normalize(vec3(0.0, 0.5, 0.7));
                vec4 color = vec4(1.0, 0.4, 0.0, 1.0);  // Robot color
                vec3 normal = normalize((u_NormalMatrix * a_Normal).xyz);
                float nDotL = max(dot(normal, lightDirection), 0.0);
                v_Color = vec4(color.rgb * nDotL + vec3(0.1), color.a);
            }
        </script>
     
        <script type="x-shader/x-fragment" id="FragmentShader">
            precision mediump float;
     
            varying vec4 v_Color;
     
            void main()
            {
                gl_FragColor = v_Color;
            }
        </script>
     
        <script src="https://dl.dropboxusercontent.com/s/ylw7v7a44xtrwv0/webgl-utils.js"></script>
        <script src="https://dl.dropboxusercontent.com/s/iz1n21c8xafd76n/webgl-debug.js"></script>
        <script src="https://dl.dropboxusercontent.com/s/subm1yzylxuao8v/cuon-utils.js"></script>
        <script src="https://dl.dropboxusercontent.com/s/jw3p82lq1cjwekg/cuon-matrix.js"></script>
    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
    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
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    
    // MultiJointModel_segment.js (c) 2012 matsuda
    // This is an example from the book "WebGL Programming Guide"
    // by Kouichi Matsuda and Rodger Lea
     
    var ANGLE_STEP = 3.0;     // The increments of rotation angle (degrees)
    var g_arm1Angle = 90.0;   // The rotation angle of arm1 (degrees)
    var g_joint1Angle = 45.0; // The rotation angle of joint1 (degrees)
    var g_joint2Angle = 0.0;  // The rotation angle of joint2 (degrees)
    var g_joint3Angle = 0.0;  // The rotation angle of joint3 (degrees)
     
    var g_baseBuffer = null;     // Buffer object for a base
    var g_arm1Buffer = null;     // Buffer object for arm1
    var g_arm2Buffer = null;     // Buffer object for arm2
    var g_palmBuffer = null;     // Buffer object for a palm
    var g_fingerBuffer = null;   // Buffer object for fingers
     
    // Coordinate transformation matrix
    var g_modelMatrix = new Matrix4(), g_mvpMatrix = new Matrix4();
     
    // Array for storing a matrix
    var g_matrixStack = [];
     
    // Coordinate transformation matrix for normals
    var g_normalMatrix = new Matrix4();
     
    main();
    //window.onload = main;
     
    function main()
    {
        // Retrieve <canvas> element
        var canvas = document.getElementById('webgl');
     
        // Get the rendering context for WebGL
        var gl = getWebGLContext(canvas);
        if (!gl)
        {
            console.log('Failed to get the rendering context for WebGL');
            return;
        }
     
        // Get shader elements
        var vShaderElement = document.getElementById("VertexShader");
        var fShaderElement = document.getElementById("FragmentShader");
        if (vShaderElement == null)
        {
            console.log("Failed to get the vertex shader element");
            return;
        }
        if (fShaderElement == null)
        {
            console.log("Failed to get the fragment shader element");
            return;
        }
     
        // Get shader sources
        var vShaderSource = vShaderElement.firstChild.textContent;
        var fShaderSource = fShaderElement.firstChild.textContent;
     
        // Initialize shaders
        if (!initShaders(gl, vShaderSource, fShaderSource))
        {
            console.log('Failed to intialize shaders');
            return;
        }
     
        // Set the vertex information
        var n = initVertexBuffers(gl);
        if (n < 0)
        {
            console.log('Failed to set the vertex information');
            return;
        }
     
        // Set the clear color and enable the depth test
        gl.clearColor(0.0, 0.0, 0.0, 1.0);
        gl.enable(gl.DEPTH_TEST);
     
        // Get the storage locations of attribute and uniform variables
        var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
        var u_MvpMatrix = gl.getUniformLocation(gl.program, 'u_MvpMatrix');
        var u_NormalMatrix = gl.getUniformLocation(gl.program, 'u_NormalMatrix');
        if (a_Position < 0 || !u_MvpMatrix || !u_NormalMatrix)
        {
            console.log('Failed to get the storage location of attribute or uniform variable');
            return;
        }
     
        // Calculate the view projection matrix
        var viewProjMatrix = new Matrix4();
        viewProjMatrix.setPerspective(50.0, canvas.width / canvas.height, 1.0, 100.0);
        viewProjMatrix.lookAt(20.0, 10.0, 30.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
     
        // Register the event handler to be called on key press
        document.onkeydown = function (ev) { keydown(ev, gl, n, viewProjMatrix, a_Position, u_MvpMatrix, u_NormalMatrix); };
     
        draw(gl, n, viewProjMatrix, a_Position, u_MvpMatrix, u_NormalMatrix);
    }
     
    function keydown(ev, gl, o, viewProjMatrix, a_Position, u_MvpMatrix, u_NormalMatrix)
    {
        switch (ev.keyCode)
        {
            case 40: // Up arrow key -> the positive rotation of joint1 around the z-axis
                if (g_joint1Angle < 135.0) g_joint1Angle += ANGLE_STEP;
                break;
            case 38: // Down arrow key -> the negative rotation of joint1 around the z-axis
                if (g_joint1Angle > -135.0) g_joint1Angle -= ANGLE_STEP;
                break;
            case 39: // Right arrow key -> the positive rotation of arm1 around the y-axis
                g_arm1Angle = (g_arm1Angle + ANGLE_STEP) % 360;
                break;
            case 37: // Left arrow key -> the negative rotation of arm1 around the y-axis
                g_arm1Angle = (g_arm1Angle - ANGLE_STEP) % 360;
                break;
            case 90: // 'z'key -> the positive rotation of joint2
                g_joint2Angle = (g_joint2Angle + ANGLE_STEP) % 360;
                break;
            case 88: // 'x'key -> the negative rotation of joint2
                g_joint2Angle = (g_joint2Angle - ANGLE_STEP) % 360;
                break;
            case 86: // 'v'key -> the positive rotation of joint3
                if (g_joint3Angle < 60.0) g_joint3Angle = (g_joint3Angle + ANGLE_STEP) % 360;
                break;
            case 67: // 'c'key -> the nagative rotation of joint3
                if (g_joint3Angle > -60.0) g_joint3Angle = (g_joint3Angle - ANGLE_STEP) % 360;
                break;
            default: return; // Skip drawing at no effective action
        }
     
        // Draw
        draw(gl, o, viewProjMatrix, a_Position, u_MvpMatrix, u_NormalMatrix);
    }
     
    function initVertexBuffers(gl)
    {
        // Vertex coordinate (prepare coordinates of cuboids for all segments)
        var vertices_base = new Float32Array([ // Base(10x2x10)
           5.0, 2.0, 5.0, -5.0, 2.0, 5.0, -5.0, 0.0, 5.0, 5.0, 0.0, 5.0, // v0-v1-v2-v3 front
           5.0, 2.0, 5.0, 5.0, 0.0, 5.0, 5.0, 0.0, -5.0, 5.0, 2.0, -5.0, // v0-v3-v4-v5 right
           5.0, 2.0, 5.0, 5.0, 2.0, -5.0, -5.0, 2.0, -5.0, -5.0, 2.0, 5.0, // v0-v5-v6-v1 up
          -5.0, 2.0, 5.0, -5.0, 2.0, -5.0, -5.0, 0.0, -5.0, -5.0, 0.0, 5.0, // v1-v6-v7-v2 left
          -5.0, 0.0, -5.0, 5.0, 0.0, -5.0, 5.0, 0.0, 5.0, -5.0, 0.0, 5.0, // v7-v4-v3-v2 down
           5.0, 0.0, -5.0, -5.0, 0.0, -5.0, -5.0, 2.0, -5.0, 5.0, 2.0, -5.0  // v4-v7-v6-v5 back
        ]);
     
        var vertices_arm1 = new Float32Array([  // Arm1(3x10x3)
           1.5, 10.0, 1.5, -1.5, 10.0, 1.5, -1.5, 0.0, 1.5, 1.5, 0.0, 1.5, // v0-v1-v2-v3 front
           1.5, 10.0, 1.5, 1.5, 0.0, 1.5, 1.5, 0.0, -1.5, 1.5, 10.0, -1.5, // v0-v3-v4-v5 right
           1.5, 10.0, 1.5, 1.5, 10.0, -1.5, -1.5, 10.0, -1.5, -1.5, 10.0, 1.5, // v0-v5-v6-v1 up
          -1.5, 10.0, 1.5, -1.5, 10.0, -1.5, -1.5, 0.0, -1.5, -1.5, 0.0, 1.5, // v1-v6-v7-v2 left
          -1.5, 0.0, -1.5, 1.5, 0.0, -1.5, 1.5, 0.0, 1.5, -1.5, 0.0, 1.5, // v7-v4-v3-v2 down
           1.5, 0.0, -1.5, -1.5, 0.0, -1.5, -1.5, 10.0, -1.5, 1.5, 10.0, -1.5  // v4-v7-v6-v5 back
        ]);
     
        var vertices_arm2 = new Float32Array([  // Arm2(4x10x4)
           2.0, 10.0, 2.0, -2.0, 10.0, 2.0, -2.0, 0.0, 2.0, 2.0, 0.0, 2.0, // v0-v1-v2-v3 front
           2.0, 10.0, 2.0, 2.0, 0.0, 2.0, 2.0, 0.0, -2.0, 2.0, 10.0, -2.0, // v0-v3-v4-v5 right
           2.0, 10.0, 2.0, 2.0, 10.0, -2.0, -2.0, 10.0, -2.0, -2.0, 10.0, 2.0, // v0-v5-v6-v1 up
          -2.0, 10.0, 2.0, -2.0, 10.0, -2.0, -2.0, 0.0, -2.0, -2.0, 0.0, 2.0, // v1-v6-v7-v2 left
          -2.0, 0.0, -2.0, 2.0, 0.0, -2.0, 2.0, 0.0, 2.0, -2.0, 0.0, 2.0, // v7-v4-v3-v2 down
           2.0, 0.0, -2.0, -2.0, 0.0, -2.0, -2.0, 10.0, -2.0, 2.0, 10.0, -2.0  // v4-v7-v6-v5 back
        ]);
     
        var vertices_palm = new Float32Array([  // Palm(2x2x6)
           1.0, 2.0, 3.0, -1.0, 2.0, 3.0, -1.0, 0.0, 3.0, 1.0, 0.0, 3.0, // v0-v1-v2-v3 front
           1.0, 2.0, 3.0, 1.0, 0.0, 3.0, 1.0, 0.0, -3.0, 1.0, 2.0, -3.0, // v0-v3-v4-v5 right
           1.0, 2.0, 3.0, 1.0, 2.0, -3.0, -1.0, 2.0, -3.0, -1.0, 2.0, 3.0, // v0-v5-v6-v1 up
          -1.0, 2.0, 3.0, -1.0, 2.0, -3.0, -1.0, 0.0, -3.0, -1.0, 0.0, 3.0, // v1-v6-v7-v2 left
          -1.0, 0.0, -3.0, 1.0, 0.0, -3.0, 1.0, 0.0, 3.0, -1.0, 0.0, 3.0, // v7-v4-v3-v2 down
           1.0, 0.0, -3.0, -1.0, 0.0, -3.0, -1.0, 2.0, -3.0, 1.0, 2.0, -3.0  // v4-v7-v6-v5 back
        ]);
     
        var vertices_finger = new Float32Array([  // Fingers(1x2x1)
           0.5, 2.0, 0.5, -0.5, 2.0, 0.5, -0.5, 0.0, 0.5, 0.5, 0.0, 0.5, // v0-v1-v2-v3 front
           0.5, 2.0, 0.5, 0.5, 0.0, 0.5, 0.5, 0.0, -0.5, 0.5, 2.0, -0.5, // v0-v3-v4-v5 right
           0.5, 2.0, 0.5, 0.5, 2.0, -0.5, -0.5, 2.0, -0.5, -0.5, 2.0, 0.5, // v0-v5-v6-v1 up
          -0.5, 2.0, 0.5, -0.5, 2.0, -0.5, -0.5, 0.0, -0.5, -0.5, 0.0, 0.5, // v1-v6-v7-v2 left
          -0.5, 0.0, -0.5, 0.5, 0.0, -0.5, 0.5, 0.0, 0.5, -0.5, 0.0, 0.5, // v7-v4-v3-v2 down
           0.5, 0.0, -0.5, -0.5, 0.0, -0.5, -0.5, 2.0, -0.5, 0.5, 2.0, -0.5  // v4-v7-v6-v5 back
        ]);
     
        // Normal
        var normals = new Float32Array([
           0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, // v0-v1-v2-v3 front
           1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, // v0-v3-v4-v5 right
           0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, // v0-v5-v6-v1 up
          -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, // v1-v6-v7-v2 left
           0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, // v7-v4-v3-v2 down
           0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0  // v4-v7-v6-v5 back
        ]);
     
        // Indices of the vertices
        var indices = new Uint8Array([
           0, 1, 2, 0, 2, 3,    // front
           4, 5, 6, 4, 6, 7,    // right
           8, 9, 10, 8, 10, 11,    // up
          12, 13, 14, 12, 14, 15,    // left
          16, 17, 18, 16, 18, 19,    // down
          20, 21, 22, 20, 22, 23     // back
        ]);
     
        // Write coords to buffers, but don't assign to attribute variables
        g_baseBuffer = initArrayBufferForLaterUse(gl, vertices_base, 3, gl.FLOAT);
        g_arm1Buffer = initArrayBufferForLaterUse(gl, vertices_arm1, 3, gl.FLOAT);
        g_arm2Buffer = initArrayBufferForLaterUse(gl, vertices_arm2, 3, gl.FLOAT);
        g_palmBuffer = initArrayBufferForLaterUse(gl, vertices_palm, 3, gl.FLOAT);
        g_fingerBuffer = initArrayBufferForLaterUse(gl, vertices_finger, 3, gl.FLOAT);
        if (!g_baseBuffer || !g_arm1Buffer || !g_arm2Buffer || !g_palmBuffer || !g_fingerBuffer) return -1;
     
        // Write normals to a buffer, assign it to a_Normal and enable it
        if (!initArrayBuffer(gl, 'a_Normal', normals, 3, gl.FLOAT)) return -1;
     
        // Write the indices to the buffer object
        var indexBuffer = gl.createBuffer();
        if (!indexBuffer)
        {
            console.log('Failed to create the buffer object');
            return -1;
        }
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
     
        return indices.length;
    }
     
    function initArrayBufferForLaterUse(gl, data, num, type)
    {
        var buffer = gl.createBuffer();   // Create a buffer object
        if (!buffer)
        {
            console.log('Failed to create the buffer object');
            return null;
        }
     
        // Write date into the buffer object
        gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
        gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
     
        // Store the necessary information to assign the object to the attribute variable later
        buffer.num = num;
        buffer.type = type;
     
        return buffer;
    }
     
    function initArrayBuffer(gl, attribute, data, num, type)
    {
        var buffer = gl.createBuffer();   // Create a buffer object
        if (!buffer)
        {
            console.log('Failed to create the buffer object');
            return false;
        }
     
        // Write date into the buffer object
        gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
        gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
     
        // Assign the buffer object to the attribute variable
        var a_attribute = gl.getAttribLocation(gl.program, attribute);
        if (a_attribute < 0)
        {
            console.log('Failed to get the storage location of ' + attribute);
            return false;
        }
        gl.vertexAttribPointer(a_attribute, num, type, false, 0, 0);
     
        // Enable the assignment of the buffer object to the attribute variable
        gl.enableVertexAttribArray(a_attribute);
     
        return true;
    }
     
    function draw(gl, n, viewProjMatrix, a_Position, u_MvpMatrix, u_NormalMatrix)
    {
        // Clear color and depth buffer
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
     
        // Draw a base
        var baseHeight = 2.0;
        g_modelMatrix.setTranslate(0.0, -12.0, 0.0);
        drawSegment(gl, n, g_baseBuffer, viewProjMatrix, a_Position, u_MvpMatrix, u_NormalMatrix);
     
        // Arm1
        var arm1Length = 10.0;
        g_modelMatrix.translate(0.0, baseHeight, 0.0);     // Move onto the base
        g_modelMatrix.rotate(g_arm1Angle, 0.0, 1.0, 0.0);  // Rotate around the y-axis
        drawSegment(gl, n, g_arm1Buffer, viewProjMatrix, a_Position, u_MvpMatrix, u_NormalMatrix); // Draw
     
        // Arm2
        var arm2Length = 10.0;
        g_modelMatrix.translate(0.0, arm1Length, 0.0);       // Move to joint1
        g_modelMatrix.rotate(g_joint1Angle, 0.0, 0.0, 1.0);  // Rotate around the z-axis
        drawSegment(gl, n, g_arm2Buffer, viewProjMatrix, a_Position, u_MvpMatrix, u_NormalMatrix); // Draw
     
        // A palm
        var palmLength = 2.0;
        g_modelMatrix.translate(0.0, arm2Length, 0.0);       // Move to palm
        g_modelMatrix.rotate(g_joint2Angle, 0.0, 1.0, 0.0);  // Rotate around the y-axis
        drawSegment(gl, n, g_palmBuffer, viewProjMatrix, a_Position, u_MvpMatrix, u_NormalMatrix);  // Draw
     
        // Move to the center of the tip of the palm
        g_modelMatrix.translate(0.0, palmLength, 0.0);
     
        // Draw finger1
        pushMatrix(g_modelMatrix);
        g_modelMatrix.translate(0.0, 0.0, 2.0);
        g_modelMatrix.rotate(g_joint3Angle, 1.0, 0.0, 0.0);  // Rotate around the x-axis
        drawSegment(gl, n, g_fingerBuffer, viewProjMatrix, a_Position, u_MvpMatrix, u_NormalMatrix);
        g_modelMatrix = popMatrix();
     
        // Finger2
        g_modelMatrix.translate(0.0, 0.0, -2.0);
        g_modelMatrix.rotate(-g_joint3Angle, 1.0, 0.0, 0.0);  // Rotate around the x-axis
        drawSegment(gl, n, g_fingerBuffer, viewProjMatrix, a_Position, u_MvpMatrix, u_NormalMatrix);
    }
     
    // Store the specified matrix to the array
    function pushMatrix(m)
    {
        var m2 = new Matrix4(m);
        g_matrixStack.push(m2);
    }
     
    // Retrieve the matrix from the array
    function popMatrix()
    {
        return g_matrixStack.pop();
    }
     
    // Draw segments
    function drawSegment(gl, n, buffer, viewProjMatrix, a_Position, u_MvpMatrix, u_NormalMatrix)
    {
        gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
     
        // Assign the buffer object to the attribute variable
        gl.vertexAttribPointer(a_Position, buffer.num, buffer.type, false, 0, 0);
     
        // Enable the assignment of the buffer object to the attribute variable
        gl.enableVertexAttribArray(a_Position);
     
        // Calculate the model view project matrix and pass it to u_MvpMatrix
        g_mvpMatrix.set(viewProjMatrix);
        g_mvpMatrix.multiply(g_modelMatrix);
        gl.uniformMatrix4fv(u_MvpMatrix, false, g_mvpMatrix.elements);
     
        // Calculate matrix for normal and pass it to u_NormalMatrix
        g_normalMatrix.setInverseOf(g_modelMatrix);
        g_normalMatrix.transpose();
        gl.uniformMatrix4fv(u_NormalMatrix, false, g_normalMatrix.elements);
     
        // Draw
        gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0);
    }
    CSS
    1
    2
    3
    
    body {
      overflow: hidden;
    }

Советую вам пока с этими примерами разобраться.
0
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
16.07.2022, 14:24  [ТС] 17
В пример из первого сообщения добавил анимацию модели и препятствие: демка



Миниатюра
Управление героем стрелками в 3D, вид от 3-го лица, на WebGL
1
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
05.08.2022, 14:10  [ТС] 18
Рисование коллайдеров типов Box и Sphere созданных с помощью физического движка Cannon-ES на WebGL и TypeScript

Класс CannonDebugger я взял из этого сообщения.

Инструкция по сборке:
  • Установить пакеты глобально: `npm i -g typescipt parcel browserify uglify-js http-server`
  • Установить пакеты локально: `npm i`
  • Запустить parcel для отладки командой: `npm run dev`
  • Запустить http-server без кэширования: `http-server -c-1`
  • Перейти в браузер и ввести адрес: `localhost:8080`
  • Команда для сборки в релиз с сжатием бандла: `npm run release`

Вложения
Тип файла: zip cannon-es-box-sphere-debugger-webgl-ts-main.zip (29.6 Кб, 0 просмотров)
0
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
05.08.2022, 14:50  [ТС] 19
На Sandbox скройте и откройте предварительный просмотр, чтобы увидеть результат нажатием сочетаний клавиш: Ctrl+Shift+D
0
5158 / 2770 / 465
Регистрация: 05.10.2013
Сообщений: 7,321
Записей в блоге: 147
12.10.2022, 17:49  [ТС] 20
Жаль, что для Ammo.js нет NPM-пакета и поддержки ES6-module, а для физического движка OimoPhysics NPM-пакет есть: https://www.npmjs.com/package/oimophysics Правда, в OimoPhysics нет SoftBody, но мне мягкие тела не нужны.
  • OimoPhysics меньше напрягает систему
  • Имеет более простую возможность рисования границ коллайдеров
  • По интерфейсу он очень похож на Ammo.js. Многие методы называются точно так же как и в Ammo.js. Поэтому примеры легко переносить на OimoPhysics
  • Имеет поддержку ES6-module. Написан на языке Haxe и собран для JavaScript и TypeScript

Можно ещё посмотреть в сторону очень молодого физического движка rapier3d-compat. Есть ещё версия для 2D: rapier2d-compat. Движок написан на языке Rust. Доступен на JavaScript и TypeScript.
1
12.10.2022, 17:49
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
12.10.2022, 17:49
Помогаю со студенческими работами здесь

Управление стрелками C++
Написал программу, работает. Но вопрос в том, что когда нажимаю на стрелки, мой символ только...

Как сделать вид от 3 лица для шара?
Помогите пожалуйста, не могу разобраться!

Управление стрелками в консоли
Как сделать управление стрелками что-бы когда нажимаешь стрелочку выполнялось опридельоное действие...

Управление стрелками в игре
В продолжение этой темы Почему я нажимаю A W S D ,у меня ни чего не происходит,если же я потыкаю...

Управление стрелками на Android
Добрый день форумчане. Мучаюсь... не могу ни как реализовать управление стрелками по осям X и Y под...

Управление стрелками клавиатуры
Нужно присвоить действия при нажатии стрелок на клавиатуре. Пояснения Unity не смог понять....


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

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

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