Published
Edited
Nov 19, 2021
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.clearColor(0, 0.25, 0.25, 1);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

setModelMatrix();
if (keys.w === true && noCollision(translation[0].x, translation[0].z + 1)) {
translation[0].z += 1
} else if (keys.s === true && noCollision(translation[0].x, translation[0].z - 1)) {
translation[0].z -= 1
} else if (keys.d === true && noCollision(translation[0].x - 1, translation[0].z)) {
translation[0].x -= 1
} else if (keys.a === true && noCollision(translation[0].x + 1, translation[0].z)) {
translation[0].x += 1
}

modelObjects[0].modelMatrix = getModelMatrix(translation[0].x, translation[0].y, translation[0].z, 0)
renderScene(shaders,
getViewMatrix(radius, deg2rad(cameraAngles.x), deg2rad(cameraAngles.y)),
getProjectionMatrix(fov_y, near, far));

return gl.canvas;
}
Insert cell
Insert cell
gl = {
const myCanvas = DOM.canvas(width, 400);

const gl = myCanvas.getContext("webgl2");
//gl.enable(gl.CULL_FACE);
gl.enable(gl.DEPTH_TEST);
gl.clearColor(0.3, 0.4, 0.5, 1);
return gl;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
noCollision = (translateX, translateZ) => {
for (let i = 1; i < translation.length; i++) {
const obstacleMinX = translation[i].x + modelObjects[i].modelExtents.min[0];
const obstacleMaxX = translation[i].x + modelObjects[i].modelExtents.max[0];
const obstacleMinZ = translation[i].z + modelObjects[i].modelExtents.min[2];
const obstacleMaxZ = translation[i].z + modelObjects[i].modelExtents.max[2];
if ((translateX >= obstacleMinX && translateX <= obstacleMaxX) &&
(translateZ >= obstacleMinZ && translateZ <= obstacleMaxZ))
return false;
}

return true;
}
Insert cell
renderScene = (sceneProgramInfo, viewMatrix, projectionMatrix) => {
const eyePosition = m4.inverse(viewMatrix).slice(12,15);

gl.useProgram(sceneProgramInfo.program);

for (let i = 0; i < modelObjects.length; i++) {
const uniforms = {
modelMatrix: modelObjects[i].modelMatrix,
viewMatrix,
projectionMatrix
}

twgl.setUniforms(sceneProgramInfo, uniforms);
modelObjects[i].bufferInfoArray.forEach((bufferInfo) => {
twgl.setBuffersAndAttributes(gl, sceneProgramInfo, bufferInfo);
twgl.drawBufferInfo(gl, bufferInfo);
});
}
}
Insert cell
Insert cell
shaders = {
const vs = `#version 300 es
precision mediump float;
in vec3 position;
in vec3 normal;
in vec2 uv;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
out vec3 fragNormal;
out vec3 fragPosition;
out vec2 fragUV;
void main () {
vec4 finalPosition = modelMatrix*vec4(position,1);
fragPosition = finalPosition.xyz;
gl_Position = projectionMatrix*viewMatrix*modelMatrix*vec4(position,1);
mat4 normalMatrix = transpose(inverse(modelMatrix));
fragNormal = normalize((normalMatrix*vec4(normal,0)).xyz);
fragUV = uv;
}`;

const fs = `#version 300 es
precision mediump float;

in vec3 fragNormal;

out vec4 outColor;

void main () {
vec3 N = normalize(fragNormal);
vec3 color = (N+1.0)/2.0;
outColor = vec4(abs(N), 1);
}`;

errorBlock.style.height = "20px";
errorBlock.innerHTML = "Program Shader compilation successful";
return twgl.createProgramInfo(gl, [vs, fs], (message) => {
errorBlock.style.height = "400px";
errorBlock.innerHTML = "Scene Program Shader compilation error\n" + message;
});
}
Insert cell
computePrimitiveExtent = function (o) {
const extents = () => {
const xExtent = d3.extent(o.position.filter((_, i) => i % 3 === 0));
const yExtent = d3.extent(o.position.filter((_, i) => i % 3 === 1));
const zExtent = d3.extent(o.position.filter((_, i) => i % 3 === 2));
return {
min: [xExtent[0], yExtent[0], zExtent[0]],
max: [xExtent[1], yExtent[1], zExtent[1]]
}
}

const transformedExtents = extents.map((extent, i) => {
return o[i].modelMatrix
? {
min: m4.transformPoint(o.indices, extent.min),
max: m4.transformPoint(o.indices, extent.max)
}
: extent;
});
const xMin = d3.min(transformedExtents, (d) => d.min[0]);
const xMax = d3.max(transformedExtents, (d) => d.max[0]);
const yMin = d3.min(transformedExtents, (d) => d.min[1]);
const yMax = d3.max(transformedExtents, (d) => d.max[1]);
const zMin = d3.min(transformedExtents, (d) => d.min[2]);
const zMax = d3.max(transformedExtents, (d) => d.max[2]);
const min = [xMin, yMin, zMin],
max = [xMax, yMax, zMax];
const center = v3.divScalar(v3.add(min, max), 2); // center of AABB
const dia = v3.length(v3.subtract(max, min)); // Diagonal length of the AABB
return {
min,
max,
center,
dia
};
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more