I can't draw my figure while moving camera in Web Gl - javascript

I'm doing a project that I have to move a camera with an object in the scene. I can move the camera correctly in the scene. However there's not the object.
I don't understand which is the error because I transform the object and then I multiply that matrix with the camera matrix and I think it's the steps I have to follow.
Hope you can help me.
const {mat4} = glMatrix;
var examplePlane = { // 4 vértices, 2 triángulos
"vertices" : [-0.5, 0.0, 0.5,
0.5, 0.0, 0.5,
0.5, 0.0,-0.5,
-0.5, 0.0,-0.5],
"indices" : [0, 1, 2, 0, 2, 3]
};
var exampleCube = { // 8 vértices, 12 triángulos
"vertices" : [-0.5,-0.5, 0.5,
0.5,-0.5, 0.5,
0.5, 0.5, 0.5,
-0.5, 0.5, 0.5,
-0.5,-0.5, -0.5,
0.5,-0.5, -0.5,
0.5, 0.5, -0.5,
-0.5, 0.5, -0.5],
"indices" : [ 0, 1, 2, 0, 2, 3,
1, 5, 6, 1, 6, 2,
3, 2, 6, 3, 6, 7,
5, 4, 7, 5, 7, 6,
4, 0, 3, 4, 3, 7,
4, 5, 1, 4, 1, 0]
};
var exampleCover = { // 13 vértices, 12 triángulos
"vertices" : [ 1, 0, 0, 0.866, 0.5, 0, 0.5, 0.866, 0,
0, 1, 0, -0.5, 0.866, 0, -0.86, 0.5, 0,
-1, 0, 0, -0.866, -0.5, 0, -0.5, -0.866, 0,
0, -1, 0, 0.5, -0.866, 0, 0.866, -0.5, 0,
0, 0, 0],
"indices" : [ 0, 1, 12, 1, 2, 12, 2, 3, 12, 3, 4, 12, 4, 5, 12, 5, 6, 12,
6, 7, 12, 7, 8, 12, 8, 9, 12, 9, 10, 12, 10, 11, 12, 11, 0, 12]
};
var exampleCone = { // 13 vértices, 12 triángulos
"vertices" : [ 1, 0, 0, 0.866, 0.5, 0, 0.5, 0.866, 0,
0, 1, 0, -0.5, 0.866, 0, -0.86, 0.5, 0,
-1, 0, 0, -0.866, -0.5, 0, -0.5, -0.866, 0,
0, -1, 0, 0.5, -0.866, 0, 0.866, -0.5, 0,
0, 0, 1],
"indices" : [ 0, 1, 12, 1, 2, 12, 2, 3, 12, 3, 4, 12, 4, 5, 12, 5, 6, 12,
6, 7, 12, 7, 8, 12, 8, 9, 12, 9, 10, 12, 10, 11, 12, 11, 0, 12]
};
var exampleCylinder = { // 24 vértices, 24 triángulos
"vertices" : [ 1, 0, 0, 0.866, 0.5, 0, 0.5, 0.866, 0,
0, 1, 0, -0.5, 0.866, 0, -0.86, 0.5, 0,
-1, 0, 0, -0.866, -0.5, 0, -0.5, -0.866, 0,
0, -1, 0, 0.5, -0.866, 0, 0.866, -0.5, 0,
1, 0, 1, 0.866, 0.5, 1, 0.5, 0.866, 1,
0, 1, 1, -0.5, 0.866, 1, -0.86, 0.5, 1,
-1, 0, 1, -0.866, -0.5, 1, -0.5, -0.866, 1,
0, -1, 1, 0.5, -0.866, 1, 0.866, -0.5, 1],
"indices" : [ 0, 1, 12, 1, 2, 13, 2, 3, 14, 3, 4, 15, 4, 5, 16, 5, 6, 17,
6, 7, 18, 7, 8, 19, 8, 9, 20, 9, 10, 21, 10, 11, 22, 11, 0, 23,
1, 13, 12, 2, 14, 13, 3, 15, 14, 4, 16, 15, 5, 17, 16, 6, 18, 17,
7, 19, 18, 8, 20, 19, 9, 21, 20, 10, 22, 21, 11, 23, 22, 0, 12, 23]
};
var exampleSphere = { // 42 vértices, 80 triángulos
"vertices" : [ 0.000000, 0.850651, 0.525731,
-0.309017, 0.500000, 0.809017,
0.309017, 0.500000, 0.809017,
-0.525731, 0.000000, 0.850651,
0.000000, 0.000000, 1.000000,
0.525731, 0.000000, 0.850651,
-0.850651, 0.525731, 0.000000,
-0.809017, 0.309017, 0.500000,
-0.500000, 0.809017, 0.309017,
0.000000, 0.850651,-0.525731,
-0.500000, 0.809017,-0.309017,
0.000000, 1.000000, 0.000000,
0.500000, 0.809017,-0.309017,
0.500000, 0.809017, 0.309017,
0.850651, 0.525731, 0.000000,
0.809017, 0.309017, 0.500000,
0.850651,-0.525731, 0.000000,
1.000000, 0.000000, 0.000000,
0.809017,-0.309017, 0.500000,
0.525731, 0.000000,-0.850651,
0.809017, 0.309017,-0.500000,
0.809017,-0.309017,-0.500000,
0.309017, 0.500000,-0.809017,
-0.525731, 0.000000,-0.850651,
-0.309017, 0.500000,-0.809017,
0.000000, 0.000000,-1.000000,
0.000000,-0.850651,-0.525731,
-0.309017,-0.500000,-0.809017,
0.309017,-0.500000,-0.809017,
0.500000,-0.809017,-0.309017,
0.000000,-0.850651, 0.525731,
0.000000,-1.000000, 0.000000,
0.500000,-0.809017, 0.309017,
-0.850651,-0.525731, 0.000000,
-0.500000,-0.809017,-0.309017,
-0.500000,-0.809017, 0.309017,
-0.809017,-0.309017, 0.500000,
-0.309017,-0.500000, 0.809017,
0.309017,-0.500000, 0.809017,
-1.000000, 0.000000, 0.000000,
-0.809017,-0.309017,-0.500000,
-0.809017, 0.309017,-0.500000],
"indices" : [ 1, 2, 0, 4, 1, 3, 2, 4, 5, 4, 2, 1, 7, 8, 6, 1, 7, 3, 8, 1, 0, 1, 8, 7,10,11, 9, 8,10, 6,
11, 8, 0, 8,11,10,11,12, 9,13,11, 0,12,13,14,13,12,11,13,15,14, 2,13, 0,15, 2, 5, 2,15,13,
17,18,16,15,17,14,18,15, 5,15,18,17,20,21,19,17,20,14,21,17,16,17,21,20,22,20,19,12,22, 9,
20,12,14,12,20,22,24,25,23,22,24, 9,25,22,19,22,25,24,27,28,26,25,27,23,28,25,19,25,28,27,
29,21,16,28,29,26,21,28,19,28,21,29,31,32,30,29,31,26,32,29,16,29,32,31,34,35,33,31,34,26,
35,31,30,31,35,34,36,37, 3,35,36,33,37,35,30,35,37,36, 4,38, 5,37, 4, 3,38,37,30,37,38, 4,
38,18, 5,32,38,30,18,32,16,32,18,38, 7,36, 3,39, 7, 6,36,39,33,39,36, 7,39,40,33,41,39, 6,
40,41,23,41,40,39,41,24,23,10,41, 6,24,10, 9,10,24,41,27,40,23,34,27,26,40,34,33,34,40,27]
};
function makeTorus (innerRadius, outerRadius, nSides, nRings) {
var torus = {
"vertices" : [],
"indices" : []
};
if (nSides < 3 ) nSides = 3;
if (nRings < 3 ) nRings = 3;
var dpsi = 2.0 * Math.PI / nRings ;
var dphi = -2.0 * Math.PI / nSides ;
var psi = 0.0;
for (var j = 0; j < nRings; j++) {
var cpsi = Math.cos ( psi ) ;
var spsi = Math.sin ( psi ) ;
var phi = 0.0;
for (var i = 0; i < nSides; i++) {
var offset = 3 * ( j * (nSides+1) + i ) ;
var cphi = Math.cos ( phi ) ;
var sphi = Math.sin ( phi ) ;
torus.vertices[offset + 0] = cpsi * ( outerRadius + cphi * innerRadius ) ;
torus.vertices[offset + 1] = spsi * ( outerRadius + cphi * innerRadius ) ;
torus.vertices[offset + 2] = sphi * innerRadius ;
phi += dphi;
}
var offset = torus.vertices.length;
for (var i = 0; i < 3; i++)
torus.vertices[offset + i] = torus.vertices[offset-nSides*3+i];
psi += dpsi;
}
var offset = torus.vertices.length;
for (var i = 0; i < 3*(nSides+1); i++)
torus.vertices[offset+i] = torus.vertices[i];
for (var j = 0; j < nRings; j++){
var desp = j * (nSides + 1);
for (var i = 0; i < nSides; i++){
torus.indices.push(desp + i, desp + i + 1, desp + i + (nSides+1));
torus.indices.push(desp + i + 1, desp + i + (nSides+1) + 1, desp + i + (nSides+1));
}
}
return torus;
}
var gl, program;
var myTorus;
var myZeta = 0.0, myPhi = Math.PI/2.0, radius = 1.4, fovy = 1.4;
function getWebGLContext() {
var canvas = document.getElementById("myCanvas");
try {
return canvas.getContext("webgl2",{antialias:true});
}
catch(e) {
}
return null;
}
function initShaders() {
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, document.getElementById("myVertexShader").text);
gl.compileShader(vertexShader);
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(vertexShader));
return null;
}
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, document.getElementById("myFragmentShader").text);
gl.compileShader(fragmentShader);
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(fragmentShader));
return null;
}
program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
idMyColor = gl.getUniformLocation (program, "myColor" );
program.vertexPositionAttribute = gl.getAttribLocation(program, "VertexPosition");
gl.enableVertexAttribArray(program.vertexPositionAttribute);
program.modelViewMatrixIndex = gl.getUniformLocation(program,"modelViewMatrix");
program.projectionMatrixIndex = gl.getUniformLocation(program,"projectionMatrix");
}
function initRendering() {
gl.clearColor(0.95,0.95,0.95,1.0);
gl.lineWidth(1.5);
gl.enable(gl.DEPTH_TEST);
}
function initBuffers(model) {
model.idBufferVertices = gl.createBuffer ();
gl.bindBuffer (gl.ARRAY_BUFFER, model.idBufferVertices);
gl.bufferData (gl.ARRAY_BUFFER, new Float32Array(model.vertices), gl.STATIC_DRAW);
model.idBufferIndices = gl.createBuffer ();
gl.bindBuffer (gl.ELEMENT_ARRAY_BUFFER, model.idBufferIndices);
gl.bufferData (gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(model.indices), gl.STATIC_DRAW);
}
function draw(model) {
console.log(model);
gl.bindBuffer(gl.ARRAY_BUFFER, model.idBufferVertices);
gl.vertexAttribPointer(program.vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, model.idBufferIndices);
for (var i = 0; i < model.indices.length; i += 3)
// Si paint es true vol dir que volem pintar per tant farem el triangle_fan
gl.drawElements (gl.TRIANGLE_FAN, 3, gl.UNSIGNED_SHORT, i*2);
}
// set projection (apliquem una projecció al dibuix)
function setProjection() {
// obtiene la matriz de transformación de la proyección perspectiva
var projectionMatrix = mat4.create();
// perspective
mat4.perspective(projectionMatrix, Math.PI/4.0, 1., 0.1, 100.0);
// envía la matriz de transformación de la proyección al shader de vértices
gl.uniformMatrix4fv(program.projectionMatrixIndex,false,projectionMatrix);
}
function initPrimitives() {
initBuffers(examplePlane);
initBuffers(exampleCube);
initBuffers(exampleCover);
initBuffers(exampleCone);
initBuffers(exampleCylinder);
initBuffers(exampleSphere);
myTorus = makeTorus(0.4, 1.0, 8, 12);
initBuffers(myTorus);
}
function getCameraMatrix() {
// coordenadas esféricas a rectangulares: https://en.wikipedia.org/wiki/Spherical_coordinate_system
var x = radius * Math.sin(myPhi) * Math.sin(myZeta);
var y = radius * Math.cos(myPhi);
var z = radius * Math.sin(myPhi) * Math.cos(myZeta);
return mat4.lookAt(mat4.create(), [x, y, z], [0, 0, 0], [0, 1, 0]);
}
////////////////////
// move the Eye
////////////////////
var eye = [0, 0, 1.4];
var center = [0, 0, 0];
function moveEye () {
return mat4.lookAt(mat4.create(), eye, center, [0, 1, 0]);
}
///////////////////
///////////////////
function start_draw(model, rx, ry, rz, r1x, r1y, r1z, sx, sy, sz, tx, ty, tz, c1, c2, c3, c4){
// 1. calcula la matriz de transformación
var modelMatrix = mat4.create();
var rotationmatr = mat4.create();
var rotation2 = mat4.create();
var transmatr = mat4.create();
var scalematr = mat4.create();
mat4.fromRotation (rotationmatr, Math.PI/2, [rx, ry, rz]);
mat4.fromRotation (rotation2, Math.PI/2, [r1x, r1y, r1z]);
mat4.fromScaling (scalematr, [sx, sy, sz]);
mat4.multiply (modelMatrix, rotationmatr, rotation2);
mat4.fromTranslation(transmatr,[tx, ty, tz]);
mat4.multiply(modelMatrix, transmatr, modelMatrix);
mat4.multiply(modelMatrix, modelMatrix, scalematr);
var modelMatrixM = mat4.create();
var modelViewMatrixM = mat4.create();
mat4.fromScaling(modelMatrixM, [0.5, 0.5, 0.5]);
mat4.multiply(modelViewMatrixM, moveEye(), modelMatrixM);
mat4.multiply(modelViewMatrixM, getCameraMatrix(), modelViewMatrixM);
var finalProj = mat4.create();
mat4.multiply(finalProj, modelViewMatrixM, modelMatrix);
// 2. establece la matriz modelMatrix en el shader de vértices
console.log(finalProj);
gl.uniformMatrix4fv(program.modelMatrixIndex, false, finalProj);
gl.uniform4f (idMyColor, c1, c2, c3, c4);
setProjection();
draw(model);
}
function drawall(){
start_draw(exampleCylinder, .5, 0, 0, 0, 0, 0, .1, .1, .6, -.6, .1, -3, .5, 0, .5, .7);
}
function drawScene() {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
drawall();
}
function initHandlers() {
var mouseDown = false;
var lastMouseX;
var lastMouseY;
var canvas = document.getElementById("myCanvas");
var htmlPhi = document.getElementById("Phi");
var htmlZeta = document.getElementById("Zeta");
var htmlRadius = document.getElementById("Radius");
var htmlFovy = document.getElementById("Fovy");
htmlPhi.innerHTML = (myPhi * 180 / Math.PI).toFixed(1);
htmlZeta.innerHTML = (myZeta * 180 / Math.PI).toFixed(1);
htmlRadius.innerHTML = radius.toFixed(1);
htmlFovy.innerHTML = (fovy * 180 / Math.PI).toFixed(1);
canvas.addEventListener("wheel",
function (event) {
var delta = 0.0;
if (event.deltaMode == 0)
delta = event.deltaY * 0.001;
else if (event.deltaMode == 1)
delta = event.deltaY * 0.03;
else
delta = event.deltaY;
if (event.shiftKey == 1) { // fovy
fovy *= Math.exp(-delta)
fovy = Math.max (0.1, Math.min(3.0, fovy));
htmlFovy.innerHTML = (fovy * 180 / Math.PI).toFixed(1);
} else {
radius *= Math.exp(-delta);
radius = Math.max(Math.min(radius, 30), 0.05);
htmlRadius.innerHTML = radius.toFixed(1);
}
event.preventDefault();
requestAnimationFrame(drawScene);
}, false);
}
function handleKeyDown(event) {
console.log(event.keyCode);
switch (event.keyCode) {
//MOVEMENT
case 87: // ’w’ key
eye[2] -= 0.01;
center[2] -=0.01;
break;
// right
case 83: // ’s’ key
eye[2] += 0.01;
center[2] +=0.01;
break;
case 65: // ’a’ key
eye[0] -= 0.01;
center[0] -=0.01;
break;
// right
case 68: // ’d’ key
eye[0] += 0.01;
center[0] +=0.01;
break;
//CAMERA MOVEMENT
case 38: // ’up arrow’ key
myPhi+=0.01;
break;
// right
case 40: // ’down arrow’ key
myPhi-=0.01;
break;
case 37: // ’up arrow’ key
myZeta+=0.01;
break;
// right
case 39: // ’down arrow’ key
myZeta-=0.01;
break;
break;
}
requestAnimationFrame(drawScene);
}
function initWebGL() {
gl = getWebGLContext();
if (!gl) {
alert("WebGL 2.0 no está disponible");
return;
}
document.onkeydown = handleKeyDown;
initShaders();
initPrimitives();
initRendering();
initHandlers();
requestAnimationFrame(drawScene);
}
initWebGL();
canvas {border: 1px solid black;}
<script id="myVertexShader"
type="x-shader/x-vertex">#version 300 es
uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;
in vec3 VertexPosition;
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(VertexPosition, 1.0);
}
</script>
<script id="myFragmentShader"
type="x-shader/x-fragment">#version 300 es
// Shader de fragmentos
precision mediump float;
uniform vec4 myColor;
out vec4 fragmentColor;
void main() {
fragmentColor = myColor;
}
</script>
<br>
<strong>Phi: </strong><span id="Phi"></span>°
<br>
<strong>Zeta: </strong><span id="Zeta"></span>°
<br>
<strong>Fovy: </strong><span id="Fovy"></span>°
<br>
<strong>Radius: </strong><span id="Radius"></span>
<br>
<canvas id="myCanvas" width="600" height="600">
El Navegador no soporta HTML5
</canvas>
<script src="https://cdn.jsdelivr.net/npm/gl-matrix#3.3.0/gl-matrix-min.js"></script>

So the first thing I did once I got your code to run is add in webgl-lint with
<script src="https://greggman.github.io/webgl-lint/webgl-lint.js" crossorigin></script>
That immediately brought up this error in the JavaScript console
webgl-lint.js:2163 Uncaught Error: https://greggman.github.io/webgl-lint/webgl-lint.js:2942: error in uniformMatrix4fv(undefined, false, [0.05000000074505806, 0, 0, 0, 0, -4.5621650389774436e-26, 0.05000000074505806, 0, 0, -0.30000001192092896, -7.29946406236391e-25, 0, -0.30000001192092896, 0.05000000074505806, -4.300000190734863, 1]): argument 0 is undefined
at reportError (VM9 webgl-lint.js:2163)
at reportFunctionError (VM9 webgl-lint.js:2924)
at checkArgs (VM9 webgl-lint.js:2942)
at WebGL2RenderingContext.ctx. [as uniformMatrix4fv] (VM9 webgl-lint.js:3016)
at start_draw (js:417)
at drawall (js:428)
at drawScene (js:435)\
clicking the first stack trace line related to your code brought me here
// 2. establece la matriz modelMatrix en el shader de vértices
console.log(finalProj);
---> gl.uniformMatrix4fv(program.modelViewMatrix, false, finalProj);
It's not program.modelMatrixIndex it's program.modelViewMatrixIndex
and that got something on the screen
const {mat4} = glMatrix;
var examplePlane = { // 4 vértices, 2 triángulos
"vertices" : [-0.5, 0.0, 0.5,
0.5, 0.0, 0.5,
0.5, 0.0,-0.5,
-0.5, 0.0,-0.5],
"indices" : [0, 1, 2, 0, 2, 3]
};
var exampleCube = { // 8 vértices, 12 triángulos
"vertices" : [-0.5,-0.5, 0.5,
0.5,-0.5, 0.5,
0.5, 0.5, 0.5,
-0.5, 0.5, 0.5,
-0.5,-0.5, -0.5,
0.5,-0.5, -0.5,
0.5, 0.5, -0.5,
-0.5, 0.5, -0.5],
"indices" : [ 0, 1, 2, 0, 2, 3,
1, 5, 6, 1, 6, 2,
3, 2, 6, 3, 6, 7,
5, 4, 7, 5, 7, 6,
4, 0, 3, 4, 3, 7,
4, 5, 1, 4, 1, 0]
};
var exampleCover = { // 13 vértices, 12 triángulos
"vertices" : [ 1, 0, 0, 0.866, 0.5, 0, 0.5, 0.866, 0,
0, 1, 0, -0.5, 0.866, 0, -0.86, 0.5, 0,
-1, 0, 0, -0.866, -0.5, 0, -0.5, -0.866, 0,
0, -1, 0, 0.5, -0.866, 0, 0.866, -0.5, 0,
0, 0, 0],
"indices" : [ 0, 1, 12, 1, 2, 12, 2, 3, 12, 3, 4, 12, 4, 5, 12, 5, 6, 12,
6, 7, 12, 7, 8, 12, 8, 9, 12, 9, 10, 12, 10, 11, 12, 11, 0, 12]
};
var exampleCone = { // 13 vértices, 12 triángulos
"vertices" : [ 1, 0, 0, 0.866, 0.5, 0, 0.5, 0.866, 0,
0, 1, 0, -0.5, 0.866, 0, -0.86, 0.5, 0,
-1, 0, 0, -0.866, -0.5, 0, -0.5, -0.866, 0,
0, -1, 0, 0.5, -0.866, 0, 0.866, -0.5, 0,
0, 0, 1],
"indices" : [ 0, 1, 12, 1, 2, 12, 2, 3, 12, 3, 4, 12, 4, 5, 12, 5, 6, 12,
6, 7, 12, 7, 8, 12, 8, 9, 12, 9, 10, 12, 10, 11, 12, 11, 0, 12]
};
var exampleCylinder = { // 24 vértices, 24 triángulos
"vertices" : [ 1, 0, 0, 0.866, 0.5, 0, 0.5, 0.866, 0,
0, 1, 0, -0.5, 0.866, 0, -0.86, 0.5, 0,
-1, 0, 0, -0.866, -0.5, 0, -0.5, -0.866, 0,
0, -1, 0, 0.5, -0.866, 0, 0.866, -0.5, 0,
1, 0, 1, 0.866, 0.5, 1, 0.5, 0.866, 1,
0, 1, 1, -0.5, 0.866, 1, -0.86, 0.5, 1,
-1, 0, 1, -0.866, -0.5, 1, -0.5, -0.866, 1,
0, -1, 1, 0.5, -0.866, 1, 0.866, -0.5, 1],
"indices" : [ 0, 1, 12, 1, 2, 13, 2, 3, 14, 3, 4, 15, 4, 5, 16, 5, 6, 17,
6, 7, 18, 7, 8, 19, 8, 9, 20, 9, 10, 21, 10, 11, 22, 11, 0, 23,
1, 13, 12, 2, 14, 13, 3, 15, 14, 4, 16, 15, 5, 17, 16, 6, 18, 17,
7, 19, 18, 8, 20, 19, 9, 21, 20, 10, 22, 21, 11, 23, 22, 0, 12, 23]
};
var exampleSphere = { // 42 vértices, 80 triángulos
"vertices" : [ 0.000000, 0.850651, 0.525731,
-0.309017, 0.500000, 0.809017,
0.309017, 0.500000, 0.809017,
-0.525731, 0.000000, 0.850651,
0.000000, 0.000000, 1.000000,
0.525731, 0.000000, 0.850651,
-0.850651, 0.525731, 0.000000,
-0.809017, 0.309017, 0.500000,
-0.500000, 0.809017, 0.309017,
0.000000, 0.850651,-0.525731,
-0.500000, 0.809017,-0.309017,
0.000000, 1.000000, 0.000000,
0.500000, 0.809017,-0.309017,
0.500000, 0.809017, 0.309017,
0.850651, 0.525731, 0.000000,
0.809017, 0.309017, 0.500000,
0.850651,-0.525731, 0.000000,
1.000000, 0.000000, 0.000000,
0.809017,-0.309017, 0.500000,
0.525731, 0.000000,-0.850651,
0.809017, 0.309017,-0.500000,
0.809017,-0.309017,-0.500000,
0.309017, 0.500000,-0.809017,
-0.525731, 0.000000,-0.850651,
-0.309017, 0.500000,-0.809017,
0.000000, 0.000000,-1.000000,
0.000000,-0.850651,-0.525731,
-0.309017,-0.500000,-0.809017,
0.309017,-0.500000,-0.809017,
0.500000,-0.809017,-0.309017,
0.000000,-0.850651, 0.525731,
0.000000,-1.000000, 0.000000,
0.500000,-0.809017, 0.309017,
-0.850651,-0.525731, 0.000000,
-0.500000,-0.809017,-0.309017,
-0.500000,-0.809017, 0.309017,
-0.809017,-0.309017, 0.500000,
-0.309017,-0.500000, 0.809017,
0.309017,-0.500000, 0.809017,
-1.000000, 0.000000, 0.000000,
-0.809017,-0.309017,-0.500000,
-0.809017, 0.309017,-0.500000],
"indices" : [ 1, 2, 0, 4, 1, 3, 2, 4, 5, 4, 2, 1, 7, 8, 6, 1, 7, 3, 8, 1, 0, 1, 8, 7,10,11, 9, 8,10, 6,
11, 8, 0, 8,11,10,11,12, 9,13,11, 0,12,13,14,13,12,11,13,15,14, 2,13, 0,15, 2, 5, 2,15,13,
17,18,16,15,17,14,18,15, 5,15,18,17,20,21,19,17,20,14,21,17,16,17,21,20,22,20,19,12,22, 9,
20,12,14,12,20,22,24,25,23,22,24, 9,25,22,19,22,25,24,27,28,26,25,27,23,28,25,19,25,28,27,
29,21,16,28,29,26,21,28,19,28,21,29,31,32,30,29,31,26,32,29,16,29,32,31,34,35,33,31,34,26,
35,31,30,31,35,34,36,37, 3,35,36,33,37,35,30,35,37,36, 4,38, 5,37, 4, 3,38,37,30,37,38, 4,
38,18, 5,32,38,30,18,32,16,32,18,38, 7,36, 3,39, 7, 6,36,39,33,39,36, 7,39,40,33,41,39, 6,
40,41,23,41,40,39,41,24,23,10,41, 6,24,10, 9,10,24,41,27,40,23,34,27,26,40,34,33,34,40,27]
};
function makeTorus (innerRadius, outerRadius, nSides, nRings) {
var torus = {
"vertices" : [],
"indices" : []
};
if (nSides < 3 ) nSides = 3;
if (nRings < 3 ) nRings = 3;
var dpsi = 2.0 * Math.PI / nRings ;
var dphi = -2.0 * Math.PI / nSides ;
var psi = 0.0;
for (var j = 0; j < nRings; j++) {
var cpsi = Math.cos ( psi ) ;
var spsi = Math.sin ( psi ) ;
var phi = 0.0;
for (var i = 0; i < nSides; i++) {
var offset = 3 * ( j * (nSides+1) + i ) ;
var cphi = Math.cos ( phi ) ;
var sphi = Math.sin ( phi ) ;
torus.vertices[offset + 0] = cpsi * ( outerRadius + cphi * innerRadius ) ;
torus.vertices[offset + 1] = spsi * ( outerRadius + cphi * innerRadius ) ;
torus.vertices[offset + 2] = sphi * innerRadius ;
phi += dphi;
}
var offset = torus.vertices.length;
for (var i = 0; i < 3; i++)
torus.vertices[offset + i] = torus.vertices[offset-nSides*3+i];
psi += dpsi;
}
var offset = torus.vertices.length;
for (var i = 0; i < 3*(nSides+1); i++)
torus.vertices[offset+i] = torus.vertices[i];
for (var j = 0; j < nRings; j++){
var desp = j * (nSides + 1);
for (var i = 0; i < nSides; i++){
torus.indices.push(desp + i, desp + i + 1, desp + i + (nSides+1));
torus.indices.push(desp + i + 1, desp + i + (nSides+1) + 1, desp + i + (nSides+1));
}
}
return torus;
}
var gl, program;
var myTorus;
var myZeta = 0.0, myPhi = Math.PI/2.0, radius = 1.4, fovy = 1.4;
function getWebGLContext() {
var canvas = document.getElementById("myCanvas");
try {
return canvas.getContext("webgl2",{antialias:true});
}
catch(e) {
}
return null;
}
function initShaders() {
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, document.getElementById("myVertexShader").text);
gl.compileShader(vertexShader);
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(vertexShader));
return null;
}
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, document.getElementById("myFragmentShader").text);
gl.compileShader(fragmentShader);
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(fragmentShader));
return null;
}
program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
idMyColor = gl.getUniformLocation (program, "myColor" );
program.vertexPositionAttribute = gl.getAttribLocation(program, "VertexPosition");
gl.enableVertexAttribArray(program.vertexPositionAttribute);
program.modelViewMatrixIndex = gl.getUniformLocation(program,"modelViewMatrix");
program.projectionMatrixIndex = gl.getUniformLocation(program,"projectionMatrix");
}
function initRendering() {
gl.clearColor(0.95,0.95,0.95,1.0);
gl.lineWidth(1.5);
gl.enable(gl.DEPTH_TEST);
}
function initBuffers(model) {
model.idBufferVertices = gl.createBuffer ();
gl.bindBuffer (gl.ARRAY_BUFFER, model.idBufferVertices);
gl.bufferData (gl.ARRAY_BUFFER, new Float32Array(model.vertices), gl.STATIC_DRAW);
model.idBufferIndices = gl.createBuffer ();
gl.bindBuffer (gl.ELEMENT_ARRAY_BUFFER, model.idBufferIndices);
gl.bufferData (gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(model.indices), gl.STATIC_DRAW);
}
function draw(model) {
console.log(model);
gl.bindBuffer(gl.ARRAY_BUFFER, model.idBufferVertices);
gl.vertexAttribPointer(program.vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, model.idBufferIndices);
for (var i = 0; i < model.indices.length; i += 3)
// Si paint es true vol dir que volem pintar per tant farem el triangle_fan
gl.drawElements (gl.TRIANGLE_FAN, 3, gl.UNSIGNED_SHORT, i*2);
}
// set projection (apliquem una projecció al dibuix)
function setProjection() {
// obtiene la matriz de transformación de la proyección perspectiva
var projectionMatrix = mat4.create();
// perspective
mat4.perspective(projectionMatrix, Math.PI/4.0, 1., 0.1, 100.0);
// envía la matriz de transformación de la proyección al shader de vértices
gl.uniformMatrix4fv(program.projectionMatrixIndex,false,projectionMatrix);
}
function initPrimitives() {
initBuffers(examplePlane);
initBuffers(exampleCube);
initBuffers(exampleCover);
initBuffers(exampleCone);
initBuffers(exampleCylinder);
initBuffers(exampleSphere);
myTorus = makeTorus(0.4, 1.0, 8, 12);
initBuffers(myTorus);
}
function getCameraMatrix() {
// coordenadas esféricas a rectangulares: https://en.wikipedia.org/wiki/Spherical_coordinate_system
var x = radius * Math.sin(myPhi) * Math.sin(myZeta);
var y = radius * Math.cos(myPhi);
var z = radius * Math.sin(myPhi) * Math.cos(myZeta);
return mat4.lookAt(mat4.create(), [x, y, z], [0, 0, 0], [0, 1, 0]);
}
////////////////////
// move the Eye
////////////////////
var eye = [0, 0, 1.4];
var center = [0, 0, 0];
function moveEye () {
return mat4.lookAt(mat4.create(), eye, center, [0, 1, 0]);
}
///////////////////
///////////////////
function start_draw(model, rx, ry, rz, r1x, r1y, r1z, sx, sy, sz, tx, ty, tz, c1, c2, c3, c4){
// 1. calcula la matriz de transformación
var modelMatrix = mat4.create();
var rotationmatr = mat4.create();
var rotation2 = mat4.create();
var transmatr = mat4.create();
var scalematr = mat4.create();
mat4.fromRotation (rotationmatr, Math.PI/2, [rx, ry, rz]);
mat4.fromRotation (rotation2, Math.PI/2, [r1x, r1y, r1z]);
mat4.fromScaling (scalematr, [sx, sy, sz]);
mat4.multiply (modelMatrix, rotationmatr, rotation2);
mat4.fromTranslation(transmatr,[tx, ty, tz]);
mat4.multiply(modelMatrix, transmatr, modelMatrix);
mat4.multiply(modelMatrix, modelMatrix, scalematr);
var modelMatrixM = mat4.create();
var modelViewMatrixM = mat4.create();
mat4.fromScaling(modelMatrixM, [0.5, 0.5, 0.5]);
mat4.multiply(modelViewMatrixM, moveEye(), modelMatrixM);
mat4.multiply(modelViewMatrixM, getCameraMatrix(), modelViewMatrixM);
var finalProj = mat4.create();
mat4.multiply(finalProj, modelViewMatrixM, modelMatrix);
// 2. establece la matriz modelMatrix en el shader de vértices
console.log(finalProj);
gl.uniformMatrix4fv(program.modelViewMatrixIndex, false, finalProj);
gl.uniform4f (idMyColor, c1, c2, c3, c4);
setProjection();
draw(model);
}
function drawall(){
start_draw(exampleCylinder, .5, 0, 0, 0, 0, 0, .1, .1, .6, -.6, .1, -3, .5, 0, .5, .7);
}
function drawScene() {
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
drawall();
}
function initHandlers() {
var mouseDown = false;
var lastMouseX;
var lastMouseY;
var canvas = document.getElementById("myCanvas");
var htmlPhi = document.getElementById("Phi");
var htmlZeta = document.getElementById("Zeta");
var htmlRadius = document.getElementById("Radius");
var htmlFovy = document.getElementById("Fovy");
htmlPhi.innerHTML = (myPhi * 180 / Math.PI).toFixed(1);
htmlZeta.innerHTML = (myZeta * 180 / Math.PI).toFixed(1);
htmlRadius.innerHTML = radius.toFixed(1);
htmlFovy.innerHTML = (fovy * 180 / Math.PI).toFixed(1);
canvas.addEventListener("wheel",
function (event) {
var delta = 0.0;
if (event.deltaMode == 0)
delta = event.deltaY * 0.001;
else if (event.deltaMode == 1)
delta = event.deltaY * 0.03;
else
delta = event.deltaY;
if (event.shiftKey == 1) { // fovy
fovy *= Math.exp(-delta)
fovy = Math.max (0.1, Math.min(3.0, fovy));
htmlFovy.innerHTML = (fovy * 180 / Math.PI).toFixed(1);
} else {
radius *= Math.exp(-delta);
radius = Math.max(Math.min(radius, 30), 0.05);
htmlRadius.innerHTML = radius.toFixed(1);
}
event.preventDefault();
requestAnimationFrame(drawScene);
}, false);
}
function handleKeyDown(event) {
console.log(event.keyCode);
switch (event.keyCode) {
//MOVEMENT
case 87: // ’w’ key
eye[2] -= 0.01;
center[2] -=0.01;
break;
// right
case 83: // ’s’ key
eye[2] += 0.01;
center[2] +=0.01;
break;
case 65: // ’a’ key
eye[0] -= 0.01;
center[0] -=0.01;
break;
// right
case 68: // ’d’ key
eye[0] += 0.01;
center[0] +=0.01;
break;
//CAMERA MOVEMENT
case 38: // ’up arrow’ key
myPhi+=0.01;
break;
// right
case 40: // ’down arrow’ key
myPhi-=0.01;
break;
case 37: // ’up arrow’ key
myZeta+=0.01;
break;
// right
case 39: // ’down arrow’ key
myZeta-=0.01;
break;
break;
}
requestAnimationFrame(drawScene);
}
function initWebGL() {
gl = getWebGLContext();
if (!gl) {
alert("WebGL 2.0 no está disponible");
return;
}
document.onkeydown = handleKeyDown;
initShaders();
initPrimitives();
initRendering();
initHandlers();
requestAnimationFrame(drawScene);
}
initWebGL();
canvas {border: 1px solid black;}
<script id="myVertexShader"
type="x-shader/x-vertex">#version 300 es
uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;
in vec3 VertexPosition;
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(VertexPosition, 1.0);
}
</script>
<script id="myFragmentShader"
type="x-shader/x-fragment">#version 300 es
// Shader de fragmentos
precision mediump float;
uniform vec4 myColor;
out vec4 fragmentColor;
void main() {
fragmentColor = myColor;
}
</script>
<br>
<strong>Phi: </strong><span id="Phi"></span>°
<br>
<strong>Zeta: </strong><span id="Zeta"></span>°
<br>
<strong>Fovy: </strong><span id="Fovy"></span>°
<br>
<strong>Radius: </strong><span id="Radius"></span>
<br>
<canvas id="myCanvas" width="600" height="600">
El Navegador no soporta HTML5
</canvas>
<script src="https://cdn.jsdelivr.net/npm/gl-matrix#3.3.0/gl-matrix-min.js"></script>
PS: Please learn how to use snippets and CDNs for libraries
Also, just FYI, getContext never throws so this code
function getWebGLContext() {
var canvas = document.getElementById("myCanvas");
try {
return canvas.getContext("webgl2",{antialias:true});
}
catch(e) {
}
return null;
}
makes no sense. It should just be
function getWebGLContext() {
var canvas = document.getElementById("myCanvas");
return canvas.getContext("webgl2",{antialias:true});
}
and further, antialias: true is the default so
function getWebGLContext() {
var canvas = document.getElementById("myCanvas");
return canvas.getContext("webgl2");
}

Related

Draw text at center of polygons

I get an array of polygons from a database. Each shape may be a triangle, a rectangle, a square, or any polygon.
I want to draw text at the center of each polygon. Font size must be dynamic according to the size of each polygon. Text color should match the line color.
Example from database:
Here is my code:
var polygons = [
{
text: "ROI", color: "#00ff00",
jointLength: 5, lineWidth: 3,
X: [890, 893, 409, 21, 27], Y: [658, 205, 199, 556, 659],
}, {
text: "Lane 3", color: "#ff0000",
jointLength: 4, lineWidth: 3,
X: [915, 911, 643, 879], Y: [5, 682, 683, 2],
}, {
text: "Lane 4", color: "#ff0000",
jointLength: 4, lineWidth: 3,
X: [888, 656, 170, 701], Y: [2, 680, 682, 1],
}, {
text: "Lane 5", color: "#ff0000",
jointLength: 5, lineWidth: 3,
X: [712, 182, 4, 4, 590], Y: [1, 681, 682, 532, 1],
}, {
text: "Speed", color: "#0000ff",
jointLength: 4, lineWidth: 3,
X: [290, 911, 873, 5], Y: [367, 357, 668, 664],
}
];
polygons.forEach((polygon) => {
const ctx = document.getElementById("canvas").getContext("2d");
ctx.strokeStyle = polygon.color;
ctx.lineWidth = polygon.lineWidth;
ctx.beginPath();
ctx.moveTo(polygon.X[0], polygon.Y[0]);
for (let i = 1; i < polygon.jointLength; i++) {
ctx.lineTo(polygon.X[i], polygon.Y[i]);
}
ctx.closePath();
ctx.stroke();
});
<canvas id="canvas" width=999 height=999></canvas>
Explanation of main logic:
The center of polygon I calculated by the formula of the arithmetic mean
The size of font I calculated by getting the width of text with font-size = 300 (but you can change the first check size as you want) and then check if text with is more than the smallest distance between 2 nearest dots (I think that this is good limit if text will be at the center of polygon). If yes then I start to find correct font-size with binary search algorithm
Because of this logic the text in second polygon is smaller than it can be because we have 2 dots at the top which are very close to each other
There is a code (open in full page for better visibility):
const polygons = [
{
text: "ROI",
color: "red",
jointLength: 5,
lineWidth: 3,
X: [890, 893, 409, 21, 27],
Y: [658, 205, 199, 556, 659],
},
{
text: "Lane 3",
color: "blue",
jointLength: 4,
lineWidth: 3,
X: [915, 911, 643, 879],
Y: [5, 682, 683, 2],
},
{
text: "Lane 4",
color: "green",
jointLength: 4,
lineWidth: 3,
X: [888, 656, 170, 701],
Y: [2, 680, 682, 1],
},
{
text: "Lane 5",
color: "orange",
jointLength: 5,
lineWidth: 3,
X: [712, 182, 4, 4, 590],
Y: [1, 681, 682, 532, 1],
},
{
text: "Speed",
color: "purple",
jointLength: 4,
lineWidth: 3,
X: [290, 911, 873, 5],
Y: [367, 357, 668, 664],
},
];
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext("2d");
canvas.width = 1000;
canvas.height = 1000;
class Polygon {
#ctx;
#dots = [];
#text;
#color;
#lineWidth;
#dotsCount;
constructor(ctx, data) {
this.#ctx = ctx;
this.#text = data.text;
this.#color = data.color;
this.#lineWidth = data.lineWidth;
this.#dotsCount = data.jointLength;
for (let i = 0; i < this.#dotsCount; ++ i) {
this.#dots.push({x: data.X[i], y: data.Y[i]})
}
}
#getCenterCoords() {
const x = this.#dots.reduce((sum, dot) => sum += dot.x, 0) / this.#dotsCount;
const y = this.#dots.reduce((sum, dot) => sum += dot.y, 0) / this.#dotsCount;
return {x, y};
}
#distance = (dot1, dot2) => Math.sqrt((dot1.x - dot2.x) ** 2 + (dot1.y - dot2.y) ** 2);
#getMinimalDistanceBetweenDots() {
let minDist = Infinity;
for (let i = 0; i < this.#dotsCount; ++i) {
const dot1 = this.#dots[i];
for (let j = i + 1; j < this.#dotsCount; ++j) {
const dot2 = this.#dots[j];
const dist = this.#distance(dot1, dot2);
if (dist < minDist) minDist = dist;
}
}
return minDist;
}
#getTextSize() {
const minAvailableWidth = this.#getMinimalDistanceBetweenDots();
let rightBound = 300;
let leftBound = 0;
let fontSize = rightBound;
while (rightBound - leftBound > 1) {
fontSize = Math.round((leftBound + rightBound) / 2);
this.#ctx.font = `${fontSize}px verdana`;
const textSize = this.#ctx.measureText(this.#text).width;
if (textSize > minAvailableWidth) {
rightBound = fontSize;
continue;
}
if (textSize < minAvailableWidth) {
leftBound = fontSize;
continue;
}
if (textSize === minAvailableWidth) {
break;
}
}
return fontSize;
}
draw() {
const path = new Path2D();
const firstDot = this.#dots[0];
const center = this.#getCenterCoords();
this.#dots.forEach(dot => path.lineTo(dot.x, dot.y));
path.lineTo(firstDot.x, firstDot.y);
this.#ctx.strokeStyle = this.#color;
this.#ctx.lineWidth = this.#lineWidth;
this.#ctx.lineCap = 'round';
this.#ctx.lineJoin = 'round';
this.#ctx.stroke(path);
this.#ctx.font = `${this.#getTextSize()}px verdana`;
this.#ctx.fillStyle = this.#color;
this.#ctx.textAlign = 'center';
this.#ctx.fillText(this.#text, center.x, center.y);
}
}
polygons.forEach((polygon) => new Polygon(ctx, polygon).draw());
<canvas id="canvas"></canvas>

Three.js how to make a FULLY beveled cube?

I'm trying to get a beveled cube, but I can't seem to figure out how. I've found THREE.ExtrudeGeometry here, but if you notice, in the sample editor it only has beveled sides on the top and bottom faces, so I'm getting something like this:
Instead of something like this, which is what I'm going for:
Code:
var bevelShape = new THREE.Shape();
bevelShape.moveTo(0, unitSize - 0.2);
bevelShape.lineTo(0, unitSize - 0.2);
bevelShape.lineTo(unitSize - 0.2, unitSize - 0.2);
bevelShape.lineTo(unitSize - 0.2, 0);
bevelShape.lineTo(0, 0);
var extrudeSettings = {
steps: 20,
depth: unitSize - 0.2,
bevelEnabled: true,
bevelThickness: 0.1,
bevelSize: 0.1,
bevelOffset: 0,
bevelSegments: 1
};
var blockGeometry = new THREE.ExtrudeGeometry(bevelShape, extrudeSettings);
var blockMaterial = new THREE.MeshStandardMaterial({color: color, roughness: 1, metalness: -1});
var block = new THREE.Mesh(blockGeometry, blockMaterial);
scene.add(block);
What should I do to achieve this?
Thanks!
You can build your own geometry.
Or feel free to search the forum, as you can find many useful and intersting things there.
For example: https://discourse.threejs.org/t/faceted-box-geometry/5474
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, 1, 1, 1000);
camera.position.set(15, 10, 20).setLength(130);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setClearColor(0x404040);
//renderer.setPixelRatio(0.5);
var canvas = renderer.domElement;
document.body.appendChild(canvas);
var controls = new THREE.OrbitControls(camera, canvas);
var light = new THREE.DirectionalLight(0xffffff, 0.5);
light.position.set(1, 2, 1);
scene.add(light);
scene.add(new THREE.AmbientLight(0xffffff, 0.5));
for (let i = 0; i < 11; i++) {
let r = 10;
let posX = (-5 + i) * 12.5;
let wireGeom = facetedBox(r, r, r, i * 0.5, true);
let wire = new THREE.LineSegments(
wireGeom,
new THREE.LineBasicMaterial({ color: Math.random() * 0x808080 + 0x808080 })
);
wire.position.x = posX;
scene.add(wire);
let geom = facetedBox(r, r, r, i * 0.5, false);
let mesh = new THREE.Mesh(
geom,
new THREE.MeshStandardMaterial({
color: Math.random() * 0x808080 + 0x808080,
flatShading: true
})
);
mesh.position.x = posX;
scene.add(mesh);
}
var clock = new THREE.Clock();
renderer.setAnimationLoop(() => {
if (resize(renderer)) {
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
renderer.render(scene, camera);
});
function resize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
html, body {
height: 100%;
margin: 0;
overflow: hidden;
}
canvas {
width: 100%;
height: 100%;
display; block;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script>
function facetedBox(w, h, d, f, isWireframed){
let hw = w * 0.5, hh = h * 0.5, hd = d * 0.5;
let vertices = [
// px
hw, hh - f, -hd + f, // 0
hw, -hh + f, -hd + f, // 1
hw, -hh + f, hd - f, // 2
hw, hh - f, hd - f, // 3
// pz
hw - f, hh - f, hd, // 4
hw - f, -hh + f, hd, // 5
-hw + f, -hh + f, hd, // 6
-hw + f, hh - f, hd, // 7
// nx
-hw, hh - f, hd - f, // 8
-hw, -hh + f, hd - f, // 9
-hw, -hh + f, -hd + f, // 10
-hw, hh - f, -hd + f, // 11
// nz
-hw + f, hh - f, -hd, // 12
-hw + f, -hh + f, -hd, // 13
hw - f, -hh + f, -hd, // 14
hw - f, hh - f, -hd, // 15
// py
hw - f, hh, -hd + f, // 16
hw - f, hh, hd - f, // 17
-hw + f, hh, hd - f, // 18
-hw + f, hh, -hd + f, // 19
// ny
hw - f, -hh, -hd + f, // 20
hw - f, -hh, hd - f, // 21
-hw + f, -hh, hd - f, // 22
-hw + f, -hh, -hd + f // 23
];
let indices = [
0, 2, 1, 3, 2, 0,
4, 6, 5, 7, 6, 4,
8, 10, 9, 11, 10, 8,
12, 14, 13, 15, 14, 12,
16, 18, 17, 19, 18, 16,
20, 21, 22, 23, 20, 22,
// link the sides
3, 5, 2, 4, 5, 3,
7, 9, 6, 8, 9, 7,
11, 13, 10, 12, 13, 11,
15, 1, 14, 0, 1, 15,
// link the lids
// top
16, 3, 0, 17, 3, 16,
17, 7, 4, 18, 7, 17,
18, 11, 8, 19, 11, 18,
19, 15, 12, 16, 15, 19,
// bottom
1, 21, 20, 2, 21, 1,
5, 22, 21, 6, 22, 5,
9, 23, 22, 10, 23, 9,
13, 20, 23, 14, 20, 13,
// corners
// top
3, 17, 4,
7, 18, 8,
11, 19, 12,
15, 16, 0,
// bottom
2, 5, 21,
6, 9, 22,
10, 13, 23,
14, 1, 20
];
let indicesWire = [
0, 1, 1, 2, 2, 3, 3, 0,
4, 5, 5, 6, 6, 7, 7, 4,
8, 9, 9, 10, 10, 11, 11, 8,
12, 13, 13, 14, 14, 15, 15, 12,
16, 17, 17, 18, 18, 19, 19, 16,
20, 21, 21, 22, 22, 23, 23, 20,
// link the sides
2, 5, 3, 4, //px - pz
6, 9, 7, 8, // pz - nx
10, 13, 11, 12, // nx - nz
15, 0, 14, 1, // nz - px
// link the lids
// top
16, 0, 17, 3, // px
17, 4, 18, 7, // pz
18, 8, 19, 11, // nx
19, 12, 16, 15, // nz
// bottom
20, 1, 21, 2,
21, 5, 22, 6,
22, 9, 23, 10,
23, 13, 20, 14
];
let geom = new THREE.BufferGeometry();
geom.setAttribute("position", new THREE.BufferAttribute(new Float32Array(vertices), 3));
geom.setIndex(isWireframed ? indicesWire : indices);
if (!isWireframed) geom.computeVertexNormals();
return geom;
}
</script>

Decoding alphanumeric code into key values object using bytes

I have a "crosshair code" from CS:GO game: CSGO-O4Jsi-V36wY-rTMGK-9w7qF-jQ8WB
I can decode some values by using this function:
import BigNumber from 'bignumber.js';
// Intentionally no 0 and 1 number in DICTIONARY
const DICTIONARY = 'ABCDEFGHJKLMNOPQRSTUVWXYZabcdefhijkmnopqrstuvwxyz23456789';
const DICTIONARY_LENGTH = DICTIONARY.length;
const SHARECODE_PATTERN = /CSGO(-?[\w]{5}){5}$/;
function bigNumberToByteArray(big) {
const str = big.toString(16).padStart(36, '0');
const bytes = [];
for (let i = 0; i < str.length; i += 2) {
bytes.push(parseInt(str.slice(i, i + 2), 16));
}
return bytes;
}
function bytesToInt32(bytes) {
let number = 0;
for (let i = 0; i < bytes.length; i++) {
number += bytes[i];
if (i < bytes.length - 1) {
number = number << 8;
}
}
return number;
}
const decode = shareCode => {
if (!shareCode.match(SHARECODE_PATTERN)) {
throw new Error('Invalid share code');
}
shareCode = shareCode.replace(/CSGO|-/g, '');
const chars = Array.from(shareCode).reverse();
let big = new BigNumber(0);
for (let i = 0; i < chars.length; i++) {
big = big.multipliedBy(DICTIONARY_LENGTH).plus(DICTIONARY.indexOf(chars[i]));
}
const bytes = bigNumberToByteArray(big);
return {
cl_crosshaircolor_r: bytesToInt32(bytes.slice(4, 5).reverse()),
cl_crosshaircolor_g: bytesToInt32(bytes.slice(5, 6).reverse()),
cl_crosshaircolor_b: bytesToInt32(bytes.slice(6, 7).reverse())
};
};
console.log(decode('CSGO-O4Jsi-V36wY-rTMGK-9w7qF-jQ8WB'))
// { cl_crosshaircolor_r: 50, cl_crosshaircolor_g: 250, cl_crosshaircolor_b: 84
I can't figure out how to get the rest of the values, because it does not show correct numbers.
I should get these values from it:
{
cl_crosshair_drawoutline: 0,
cl_crosshair_dynamic_maxdist_splitratio: 0.3,
cl_crosshair_dynamic_splitalpha_innermod: 0.6,
cl_crosshair_dynamic_splitalpha_outermod: 0.8,
cl_crosshair_dynamic_splitdist: 127,
cl_crosshair_outlinethickness: 1.5,
cl_crosshair_t: 1,
cl_crosshairalpha: 200,
cl_crosshaircolor: 5,
cl_crosshaircolor_b: 84,
cl_crosshaircolor_g: 250,
cl_crosshaircolor_r: 50,
cl_crosshairdot: 1,
cl_crosshairgap: 1,
cl_crosshairgap_useweaponvalue: 0,
cl_crosshairsize: 33,
cl_crosshairstyle: 2,
cl_crosshairthickness: 4.1,
cl_crosshairusealpha: 0,
cl_fixedcrosshairgap: -10
}
Additional examples:
CSGO-tEAHu-36Ro8-Oyms7-NVvnV-F6XDJ
{
cl_crosshair_drawoutline: 0,
cl_crosshair_dynamic_maxdist_splitratio: 0.1,
cl_crosshair_dynamic_splitalpha_innermod: 0.8,
cl_crosshair_dynamic_splitalpha_outermod: 0.6,
cl_crosshair_dynamic_splitdist: 13,
cl_crosshair_outlinethickness: 2,
cl_crosshair_t: 0,
cl_crosshairalpha: 250,
cl_crosshaircolor: 5,
cl_crosshaircolor_b: 90,
cl_crosshaircolor_g: 255,
cl_crosshaircolor_r: 55,
cl_crosshairdot: 1,
cl_crosshairgap: -2,
cl_crosshairgap_useweaponvalue: 0,
cl_crosshairsize: 10,
cl_crosshairstyle: 2,
cl_crosshairthickness: 4.5,
cl_crosshairusealpha: 1,
cl_fixedcrosshairgap: 12
}
CSGO-rGhtd-eWuUm-EWVO7-72rvk-zqAUM
{
cl_crosshair_drawoutline: 1,
cl_crosshair_dynamic_maxdist_splitratio: 0.9,
cl_crosshair_dynamic_splitalpha_innermod: 0.5,
cl_crosshair_dynamic_splitalpha_outermod: 0.6,
cl_crosshair_dynamic_splitdist: 12,
cl_crosshair_outlinethickness: 0.5,
cl_crosshair_t: 0,
cl_crosshairalpha: 189,
cl_crosshaircolor: 2,
cl_crosshaircolor_b: 123,
cl_crosshaircolor_g: 229,
cl_crosshaircolor_r: 67,
cl_crosshairdot: 1,
cl_crosshairgap: 3,
cl_crosshairgap_useweaponvalue: 0,
cl_crosshairsize: 7,
cl_crosshairstyle: 4,
cl_crosshairthickness: 1.2,
cl_crosshairusealpha: 0,
cl_fixedcrosshairgap: -5
}
CSGO-wQ3FD-JiRVa-kKcFt-6XfbF-uMD7K
{
cl_crosshair_drawoutline: 1,
cl_crosshair_dynamic_maxdist_splitratio: 0.9,
cl_crosshair_dynamic_splitalpha_innermod: 0.5,
cl_crosshair_dynamic_splitalpha_outermod: 0.6,
cl_crosshair_dynamic_splitdist: 12,
cl_crosshair_outlinethickness: 1.5,
cl_crosshair_t: 1,
cl_crosshairalpha: 158,
cl_crosshaircolor: 5,
cl_crosshaircolor_b: 198,
cl_crosshaircolor_g: 182,
cl_crosshaircolor_r: 91,
cl_crosshairdot: 1,
cl_crosshairgap: 1.4,
cl_crosshairgap_useweaponvalue: 1,
cl_crosshairsize: 6.4,
cl_crosshairstyle: 4,
cl_crosshairthickness: 1.8,
cl_crosshairusealpha: 1,
cl_fixedcrosshairgap: -5
}
Range of properties:
{
// acts like boolean
cl_crosshair_drawoutline: {
min: 0,
max: 1
},
cl_crosshair_dynamic_maxdist_splitratio: {
min: 0,
step: 0.1, // e.g: 0, 0.1, 0.2, 0.3 etc.
max: 1
},
cl_crosshair_dynamic_splitalpha_innermod: {
min: 0,
step: 0.1, // e.g: 0, 0.1, 0.2, 0.3 etc.
max: 1
},
cl_crosshair_dynamic_splitalpha_outermod: {
min: 0.3,
step: 0.1, // 0.3, 0.4, 0.5 etc.
max: 1
},
cl_crosshair_dynamic_splitdist: {
min: 0,
step: 1, // e.g: 0, 1, 2, 3, ..., 127
max: 127
},
cl_crosshair_outlinethickness: {
min: 0,
step: 0.5, // e.g: 0, 0.5, 1, ..., 3
max: 3
},
// acts like boolean
cl_crosshair_t: {
min: 0,
max: 1
},
cl_crosshairalpha: {
min: 0,
step: 1, // e.g: 1, 2, 3, ..., 255
max: 255
},
cl_crosshaircolor: {
min: 0,
step: 1, // e.g: 1, 2, 3, ..., 7
max: 7
},
cl_crosshaircolor_b: {
min: 0,
step: 1, // e.g: 1, 2, 3, ..., 255
max: 255
},
cl_crosshaircolor_g: {
min: 0,
step: 1, // e.g: 1, 2, 3, ..., 255
max: 255
},
cl_crosshaircolor_r: {
min: 0,
step: 1, // e.g: 1, 2, 3, ..., 255
max: 255
},
// acts like boolean
cl_crosshairdot: {
min: 0,
max: 1
},
cl_crosshairgap: {
min: -12.8,
step: 0.1, // e.g: 10, 10.1 etc.
max: 12.7
},
// acts like boolean
cl_crosshairgap_useweaponvalue: {
min: 0,
max: 1
},
cl_crosshairsize: {
min: 0,
step: 0.1, // e.g: 0, 0.1, 0.2, 14.4 etc.
max: 819.100037 // can't say why such an unusual output
},
cl_crosshairstyle: {
min: 0,
step: 1, // e.g: 1, 2, 3, ..., 7
max: 7
}
cl_crosshairthickness: {
min: 0,
step: 0.1, // e.g: 0, 0.1, 0.2, ..., 6.3
max: 6.3
}
// acts like boolean
cl_crosshairusealpha: {
min: 0,
max: 1
},
cl_fixedcrosshairgap: {
min: -12.8,
step: 0.1, // e.g: 10, 10.1 etc.
max: 12.7
}
}
Values changed one at a time:
Default: CSGO-6G2cS-WzcxT-fH3dp-Rf7oq-X9oJN
{
cl_crosshair_drawoutline: 1,
cl_crosshair_dynamic_maxdist_splitratio: 0.3,
cl_crosshair_dynamic_splitalpha_innermod: 1,
cl_crosshair_dynamic_splitalpha_outermod: 0.5,
cl_crosshair_dynamic_splitdist: 7,
cl_crosshair_outlinethickness: 1,
cl_crosshair_t: 0,
cl_crosshairalpha: 200,
cl_crosshaircolor: 1,
cl_crosshaircolor_b: 50,
cl_crosshaircolor_g: 250,
cl_crosshaircolor_r: 50,
cl_crosshairdot: 1,
cl_crosshairgap: 1,
cl_crosshairgap_useweaponvalue: 0,
cl_crosshairsize: 5,
cl_crosshairstyle: 2,
cl_crosshairthickness: 0.5,
cl_crosshairusealpha: 1,
cl_fixedcrosshairgap: 3
}
The only value changed is described beside, rest stays the same as default
above.
cl_crosshair_drawoutline
1 = CSGO-6G2cS-WzcxT-fH3dp-Rf7oq-X9oJN
0 = CSGO-of9RX-KD5Fp-4kb7Q-EoVSz-cb7nM
cl_crosshair_dynamic_maxdist_splitratio
0 = CSGO-Vtkiw-zkx82-6AYMS-9OXdk-6yXHK
0.5 = CSGO-Trqu8-WUQCn-5MfrP-KDUGF-CFeKP
1 = CSGO-QMSEL-6KJoK-vvajh-WpPKZ-Bh2ED
cl_crosshair_dynamic_splitalpha_innermod
0 = CSGO-Tabp9-L98iF-Btmcu-64Das-MdaEC
0.5 = CSGO-HRKjJ-R5sqr-Q6t9r-GsADN-SthGH
1 = CSGO-6G2cS-WzcxT-fH3dp-Rf7oq-X9oJN
cl_crosshair_dynamic_splitalpha_outermod
0.3 = CSGO-RBqva-DumOx-WPvGy-cDxic-5zcBN
0.7 = CSGO-jNCMK-q6UXz-pA93e-FAGu4-2GzQN
1 = CSGO-DWSPa-oEJum-4Tn8R-SrTXs-jxkbN
cl_crosshair_dynamic_splitdist
0 = CSGO-Dxzuf-AUuea-G7enM-c3Zza-sBhrM
50 = CSGO-LcTca-Laf43-7pmXZ-jnJGu-oS9zP
127 = CSGO-xa4d4-MN8pW-aETR7-jhzeQ-6DjjD
cl_crosshair_outlinethickness
0 = CSGO-aQUWL-7ysnT-Ve8rS-PHXDY-5zcBN
1.5 = CSGO-LhmCW-jzV4T-m6T4z-SOtbU-nhPNN
3 = CSGO-5x4rh-N29JU-3VqEY-WUF3Q-VPBYN
cl_crosshair_t
0 = CSGO-6G2cS-WzcxT-fH3dp-Rf7oq-X9oJN
1 = CSGO-iyOcd-YLrjN-8xQqU-xZa3G-zjRFE
cl_crosshairalpha
0 = CSGO-sQOF4-9RKDe-sLeFU-wqGMn-uonpQ
200 = CSGO-6G2cS-WzcxT-fH3dp-Rf7oq-X9oJN
255 = CSGO-BqGwL-hirNt-AX6Dy-YbCoB-fFDmQ
cl_crosshaircolor
0 = CSGO-4KA8L-stYs2-aqTxt-3R3GF-KZEFN
4 = CSGO-C8ZDo-TJrEr-uafja-dOLSe-GqZUN
7 = CSGO-JxAn9-Qa5UE-AvLpN-r6X6T-yWMfN
cl_crosshaircolor_b
0 = CSGO-8fuTL-n9Uqy-iF6pY-6tOYX-brNAK
200 = CSGO-xWpEr-keTtj-QmeUw-XpE3a-FCPcF
255 = CSGO-W58Ja-mo8Q6-e7Phv-3mK2v-NJn6J
cl_crosshaircolor_g
0 = CSGO-BvDs8-JUwK4-54sLY-c745T-yWMfN
200 = CSGO-h7whC-Uiy99-WKxr3-HLJYX-brNAK
255 = CSGO-Wnbcy-QvJ47-65Eqz-MQUXs-jxkbN
cl_crosshaircolor_r
0 = CSGO-uznHJ-WZpew-rQpJS-p2F8W-brNAK
200 = CSGO-aaBpx-XNVPr-zES6H-MTdMc-FCPcF
255 = CSGO-nOKuX-kEo8c-hBOZh-WaOpx-NJn6J
cl_crosshairdot
0 = CSGO-c8tdf-txA5L-UFDY3-zuu69-i6OJM
1 = CSGO-6G2cS-WzcxT-fH3dp-Rf7oq-X9oJN
cl_crosshairgap
-12.8 = CSGO-N5fyF-u3u8M-4jU9j-O9vLu-aSYbD
0 = CSGO-qis8G-DpZxE-Z9QeN-upthN-OSveM
12.7 = CSGO-XuT3W-BvVvv-cvEFo-cM8iA-CtxXD
cl_crosshairgap_useweaponvalue
0 = CSGO-6G2cS-WzcxT-fH3dp-Rf7oq-X9oJN
1 = CSGO-zYEbz-m4Zmk-5MfrP-KDUGF-CFeKP
cl_crosshairsize
0 = CSGO-hzFpv-XtPmX-wHSxa-LvOYX-brNAK
100 = CSGO-Cn2cE-Mau97-N4rOC-typ7o-ayzpH
819 = CSGO-GC68x-Jh9L4-73R6P-zjXN8-WGSyL
819.100037 = CSGO-MjLui-qkX6J-CUzmL-Pybui-mp33L
cl_crosshairstyle
0 = CSGO-TjyO2-rj2yR-OWps8-pjocQ-asS4M
4 = CSGO-ho3st-BGGwV-y3ERW-4bPzG-VPBYN
7 = CSGO-875F5-AdfP5-QfXa5-S3qGu-vnhvN
cl_crosshairthickness
0 = CSGO-r6TO2-WsYFC-K6GCD-RVj6o-MKsyM
3.1 = CSGO-ToYxk-5EQKD-ciNhr-tn3ya-kq8vO
6.3 = CSGO-LAYaa-DEf8T-2n2tR-mKQRz-OwxwQ
cl_crosshairusealpha
0 = CSGO-GfZhN-2sjMv-t8iFe-hcMv4-Gw8GJ
1 = CSGO-6G2cS-WzcxT-fH3dp-Rf7oq-X9oJN
cl_fixedcrosshairgap
-12.80 = CSGO-OPDHV-Ab3cf-pmoFG-8ecMS-eNqRP
0 = CSGO-NJ6Z7-bRb8Y-qSBRv-cZ8Ys-7xSOG
12.70 = CSGO-SSCsS-u4nYT-rKGYL-iRYoq-QoFOP
Here you go. Add this parseBytes function, modify decode as shown, and keep the rest of your code as it.
function parseBytes(bytes) {
return {
cl_crosshairgap: Int8Array.of(bytes[2])[0] / 10.0,
cl_crosshair_outlinethickness: (bytes[3] & 7) / 2.0,
cl_crosshaircolor_r: bytes[4],
cl_crosshaircolor_g: bytes[5],
cl_crosshaircolor_b: bytes[6],
cl_crosshairalpha: bytes[7],
cl_crosshair_dynamic_splitdist: bytes[8],
cl_fixedcrosshairgap: Int8Array.of(bytes[9])[0] / 10.0,
cl_crosshaircolor: bytes[10] & 7,
cl_crosshair_drawoutline: bytes[10] & 8 ? 1 : 0,
cl_crosshair_dynamic_splitalpha_innermod: ((bytes[10] & 0xF0) >> 4) / 10.0,
cl_crosshair_dynamic_splitalpha_outermod: (bytes[11] & 0xF) / 10.0,
cl_crosshair_dynamic_maxdist_splitratio: ((bytes[11] & 0xF0) >> 4) / 10.0,
cl_crosshairthickness: (bytes[12] & 0x3F) / 10.0,
cl_crosshairstyle: (bytes[13] & 0xE) >> 1,
cl_crosshairdot: bytes[13] & 0x10 ? 1 : 0,
cl_crosshairgap_useweaponvalue: bytes[13] & 0x20 ? 1 : 0,
cl_crosshairusealpha: bytes[13] & 0x40 ? 1 : 0,
cl_crosshair_t: bytes[13] & 0x80 ? 1 : 0,
cl_crosshairsize: (((bytes[15] & 0x1f) << 8) + bytes[14]) / 10.0
};
}
const decode = shareCode => {
if (!shareCode.match(SHARECODE_PATTERN)) {
throw new Error('Invalid share code');
}
shareCode = shareCode.replace(/CSGO|-/g, '');
const chars = Array.from(shareCode).reverse();
let big = new BigNumber(0);
for (let i = 0; i < chars.length; i++) {
big = big.multipliedBy(DICTIONARY_LENGTH).plus(DICTIONARY.indexOf(chars[i]));
}
return parseBytes(bigNumberToByteArray(big));
}

Webgl vertexAttribPointer: index out of range

I'm trying to pass uv buffer as well as the normal buffer in webgl. But for some reason I get this warning vertexAttribPointer: index out of range when passing values. I don't get what I m doing wrong since the uv array seems to be good, same goes for the normals.
It seems like the errors only occured with normal and uv not with position.
enableVertexAttribArray: index out of range
vertexAttribPointer: index out of range
let canvas = document.querySelector("canvas");
let gl = canvas.getContext("webgl");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
const vsSource = `
attribute vec4 position;
attribute vec2 uv;
attribute vec3 normal;
uniform mat4 modelViewMatrix;
varying vec4 vColor;
void main(void) {
gl_Position = position;
}
`;
const fsSource = `
precision mediump float;
varying vec4 vColor;
void main(void) {
gl_FragColor = vec4(1.0,0.0,1.0,1.0);
}
`;
// Shader setup
let vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vsSource);
gl.compileShader(vertexShader);
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
var log = gl.getShaderInfoLog(vertexShader);
throw "Shader compilation failed\n\n" + log + "\n\n";
}
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fsSource);
gl.compileShader(fragmentShader);
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
var log = gl.getShaderInfoLog(fragmentShader);
throw "Shader compilation failed\n\n" + log + "\n\n";
}
let program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.validateProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
var log = gl.getProgramInfoLog(program);
throw "Program link failed\n\n" + log;
}
gl.useProgram(program);
let modelViewMatrix = gl.getUniformLocation(program, "modelViewMatrix");
let model = mat4.create();
gl.uniformMatrix4fv(modelViewMatrix, false, model);
var vertices = new Float32Array([
0.5,
0.5,
0.5,
0.5,
0.5,
-0.5,
0.5,
-0.5,
0.5,
0.5,
-0.5,
-0.5,
-0.5,
0.5,
-0.5,
-0.5,
0.5,
0.5,
-0.5,
-0.5,
-0.5,
-0.5,
-0.5,
0.5,
-0.5,
0.5,
-0.5,
0.5,
0.5,
-0.5,
-0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
-0.5,
-0.5,
0.5,
0.5,
-0.5,
0.5,
-0.5,
-0.5,
-0.5,
0.5,
-0.5,
-0.5,
-0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
-0.5,
-0.5,
0.5,
0.5,
-0.5,
0.5,
0.5,
0.5,
-0.5,
-0.5,
0.5,
-0.5,
0.5,
-0.5,
-0.5,
-0.5,
-0.5,
-0.5
]);
var vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
let position = gl.getAttribLocation(program, "position");
gl.vertexAttribPointer(position, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(position);
var uvBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, uvBuffer);
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array([
0,
1,
1,
1,
0,
0,
1,
0,
0,
1,
1,
1,
0,
0,
1,
0,
0,
1,
1,
1,
0,
0,
1,
0,
0,
1,
1,
1,
0,
0,
1,
0,
0,
1,
1,
1,
0,
0,
1,
0,
0,
1,
1,
1,
0,
0,
1,
0
]),
gl.STATIC_DRAW
);
let uv = gl.getAttribLocation(program, "uv");
gl.vertexAttribPointer(uv, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(uv);
var normalBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, normalBuffer);
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array([
1,
0,
0,
1,
0,
0,
1,
0,
0,
1,
0,
0,
-1,
0,
0,
-1,
0,
0,
-1,
0,
0,
-1,
0,
0,
0,
1,
0,
0,
1,
0,
0,
1,
0,
0,
1,
0,
0,
-1,
0,
0,
-1,
0,
0,
-1,
0,
0,
-1,
0,
0,
0,
1,
0,
0,
1,
0,
0,
1,
0,
0,
1,
0,
0,
-1,
0,
0,
-1,
0,
0,
-1,
0,
0,
-1
]),
gl.STATIC_DRAW
);
let normal = gl.getAttribLocation(program, "normal");
gl.vertexAttribPointer(normal, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(normal);
var indices = new Uint16Array([
0,
2,
1,
2,
3,
1,
4,
6,
5,
6,
7,
5,
8,
10,
9,
10,
11,
9,
12,
14,
13,
14,
15,
13,
16,
18,
17,
18,
19,
17,
20,
22,
21,
22,
23,
21
]);
var indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min.js"></script>
<canvas></canvas>
Your shaders are not using uv or normal so your driver is optimizing out those attributes. In that case gl.getAttribLocation returns -1 for location (-1 = attribute by this name does not exist). -1 is out of range. Valid values are 0 to gl.getParameter(gl.MAX_VERTEX_ATTRIBS) - 1
In other words you need check the location of your attributes and if they don't exist, don't set them up.
This is one reason why it's good to write some helper functions for WebGL to kind of handle these issues for you so as you modify your shaders your code doesn't break.

three.js buffer is already interleaved

I have geometries created on my server which have vertices and normals interleaved in one array. I tried colors also since it is easier to debug. The ONLY example I can find is webgl_buffergeometry_instancing_interleaved_dynamic.html.
Here is what I tried based on the example. That example is a bit different since it also uses InstancedBufferGeometry but this is based on my understanding of that example:
function exp_crate() {
var geometry = new THREE.BufferGeometry();
// per mesh data x,y,z,r,g,b for 6-element stride
var vertexBuffer = new THREE.InterleavedBuffer(new Float32Array([
// Front
-1000, 1000, 1000, 0, 0, 1,
1000, 1000, 1000, 0, 1, 0,
-1000, -1000, 1000, 1, 0, 1,
1000, -1000, 1000, 0, 1, 1,
// Back
1000, 1000, -1000, 0, 0, 1,
-1000, 1000, -1000, 0, 0, 1,
1000, -1000, -1000, 0, 0, 1,
-1000, -1000, -1000, 0, 0, 1,
// Left
-1000, 1000, -1000, 0, 0, 1,
-1000, 1000, 1000, 0, 0, 1,
-1000, -1000, -1000, 0, 0, 1,
-1000, -1000, 1000, 0, 0, 1,
// Right
1000, 1000, 1000, 0, 0, 1,
1000, 1000, -1000, 0, 0, 1,
1000, -1000, 1000, 0, 0, 1,
1000, -1000, -1000, 0, 0, 1,
// Top
-1000, 1000, 1000, 0, 0, 1,
1000, 1000, 1000, 0, 0, 1,
-1000, 1000, -1000, 0, 0, 1,
1000, 1000, -1000, 0, 0, 1,
// Bottom
1000, -1000, 1000, 0, 0, 1,
-1000, -1000, 1000, 0, 0, 1,
1000, -1000, -1000, 0, 0, 1,
-1000, -1000, -1000, 0, 0, 1,
]), 6);
// Use vertexBuffer, starting at offset 0, 3 items in position attribute
var positions = new THREE.InterleavedBufferAttribute(vertexBuffer, 3, 0);
geometry.addAttribute('inVertex', positions);
// Use vertexBuffer, starting at offset 4, 3 items in color attribute
var colors = new THREE.InterleavedBufferAttribute(vertexBuffer, 3, 4);
geometry.addAttribute('inColor', colors);
var indices = new Uint16Array([
0, 1, 2,
2, 1, 3,
4, 5, 6,
6, 5, 7,
8, 9, 10,
10, 9, 11,
12, 13, 14,
14, 13, 15,
16, 17, 18,
18, 17, 19,
20, 21, 22,
22, 21, 23
]);
geometry.setIndex(new THREE.BufferAttribute(indices, 1));
docvShader = document.getElementById('cratevertexShader').textContent;
docfShader = document.getElementById('cratefragmentShader').textContent;
var material = new THREE.ShaderMaterial({
uniforms: [],
vertexShader: docvShader,
fragmentShader: docfShader
});
material.side= THREE.DoubleSide;
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
}
Here are the shaders:
<script id="cratevertexShader" type="x-shader/x-vertex">
attribute highp vec3 inVertex;
attribute highp vec3 inColor;
varying mediump vec4 Color;
void main()
{
float df;
float opac;
gl_Position = projectionMatrix * modelViewMatrix * vec4(inVertex, 1.0);
Color = vec4(inColor, 1.0);
}
</script>
<script id="cratefragmentShader" type="x-shader/x-fragment">
varying mediump vec4 Color;
void main()
{
gl_FragColor = Color;
gl_FragColor.w = Color.w;
}
</script>
If I comment out this line:
geometry.addAttribute('inColor', colors);
I see a black cube. If I leave that line in I get the following GL error:
GL ERROR :GL_INVALID_OPERATION : glDrawElements: attempt to access out of range vertices in attribute 1
And nothing is displayed at all. Can anyone offer a suggestion?
Your offset for the 2nd attribute is not correct.
// Use vertexBuffer, starting at offset 0, 3 items in position attribute
var positions = new THREE.InterleavedBufferAttribute( vertexBuffer, 3, 0 );
geometry.addAttribute( 'inVertex', positions );
// Use vertexBuffer, starting at offset 3, 3 items in color attribute
var colors = new THREE.InterleavedBufferAttribute( vertexBuffer, 3, 3 );
geometry.addAttribute( 'inColor', colors );
three.js r.85

Categories

Resources