forked from KhronosGroup/glTF-Sample-Viewer
-
Notifications
You must be signed in to change notification settings - Fork 1
/
scene.js
115 lines (95 loc) · 4.24 KB
/
scene.js
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
class Scene {
constructor(gl, glState, model, gltf) {
this.globalState = glState;
this.nodes = gltf.nodes;
this.meshes = [];
this.assets = {};
this.pendingTextures = 0;
this.pendingBuffers = 0;
this.samplerIndex = 3; // skip the first three because of the cubemaps
for (var meshIdx in gltf.meshes) {
this.meshes.push(new Mesh(gl, this, this.globalState, model, gltf, meshIdx));
}
}
getNextSamplerIndex() {
var result = this.samplerIndex++;
if (result > 31) {
throw new Error('Too many texture samplers in use.');
}
return result;
}
drawScene(gl) {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
if (this.pendingTextures > 0 || this.pendingBuffers > 0) {
return;
}
document.getElementById('loadSpinner').style.display = 'none';
var drawNodeRecursive = function(scene, node, parentTransform) {
// Transform
var localTransform;
if (node.matrix) {
localTransform = mat4.clone(node.matrix);
} else {
localTransform = mat4.create();
var scale = node.scale ? node.scale : [1.0, 1.0, 1.0];
var rotation = node.rotation ? node.rotation : [0.0, 0.0, 0.0, 1.0];
var translate = node.translation ? node.translation : [0.0, 0.0, 0.0];
mat4.fromRotationTranslationScale(localTransform, rotation, translate, scale);
}
mat4.multiply(localTransform, localTransform, parentTransform);
if (defined(node.mesh) && node.mesh < scene.meshes.length) {
scene.meshes[node.mesh].drawMesh(gl, localTransform, scene.viewMatrix, scene.projectionMatrix, scene.globalState);
}
if (defined(node.children) && node.children.length > 0) {
for (var i = 0; i < node.children.length; i++) {
drawNodeRecursive(scene, scene.nodes[node.children[i]], localTransform);
}
}
};
// set up the camera position and view matrix
var cameraPos = [-translate * Math.sin(roll) * Math.cos(-pitch),
-translate * Math.sin(-pitch),
translate * Math.cos(roll) * Math.cos(-pitch)];
this.globalState.uniforms['u_Camera'].vals = cameraPos;
// Update view matrix
// roll, pitch and translate are all globals.
var xRotation = mat4.create();
mat4.rotateY(xRotation, xRotation, roll);
var yRotation = mat4.create();
mat4.rotateX(yRotation, yRotation, pitch);
this.viewMatrix = mat4.create();
mat4.multiply(this.viewMatrix, yRotation, xRotation);
this.viewMatrix[14] = -translate;
var firstNode = this.nodes[0];
drawNodeRecursive(this, firstNode, mat4.create());
// draw to the front buffer
this.frontBuffer.drawImage(this.backBuffer, 0, 0);
}
loadImage(imageInfo, gl) {
var scene = this;
var image = new Image();
this.pendingTextures++;
image.src = imageInfo.uri;
image.onload = function() {
var texture = gl.createTexture();
var glIndex = gl.TEXTURE0 + imageInfo.samplerIndex; // gl.TEXTUREn enums are in numeric order.
gl.activeTexture(glIndex);
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, imageInfo.clamp ? gl.CLAMP_TO_EDGE : gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, imageInfo.clamp ? gl.CLAMP_TO_EDGE : gl.REPEAT);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA,/*imageInfo.colorSpace, imageInfo.colorSpace,*/ gl.UNSIGNED_BYTE, image);
scene.pendingTextures--;
scene.drawScene(gl);
};
return image;
}
loadImages(imageInfos, gl) {
this.pendingTextures = 0;
for (var i in imageInfos) {
this.loadImage(imageInfos[i], gl);
}
}
}