cube working

This commit is contained in:
Tyler Murphy 2023-01-19 13:39:40 -05:00
parent 19a144a609
commit 76446f179d
15 changed files with 304 additions and 265 deletions

View file

@ -1,57 +0,0 @@
export const gen_cube = () => {
var cube_data = [
-1.0, 1.0, -1.0, 0.5, 0.5, 0.5,
-1.0, 1.0, 1.0, 0.5, 0.5, 0.5,
1.0, 1.0, 1.0, 0.5, 0.5, 0.5,
1.0, 1.0, -1.0, 0.5, 0.5, 0.5,
-1.0, 1.0, 1.0, 0.75, 0.25, 0.5,
-1.0, -1.0, 1.0, 0.75, 0.25, 0.5,
-1.0, -1.0, -1.0, 0.75, 0.25, 0.5,
-1.0, 1.0, -1.0, 0.75, 0.25, 0.5,
1.0, 1.0, 1.0, 0.25, 0.25, 0.75,
1.0, -1.0, 1.0, 0.25, 0.25, 0.75,
1.0, -1.0, -1.0, 0.25, 0.25, 0.75,
1.0, 1.0, -1.0, 0.25, 0.25, 0.75,
1.0, 1.0, 1.0, 1.0, 0.0, 0.15,
1.0, -1.0, 1.0, 1.0, 0.0, 0.15,
-1.0, -1.0, 1.0, 1.0, 0.0, 0.15,
-1.0, 1.0, 1.0, 1.0, 0.0, 0.15,
1.0, 1.0, -1.0, 0.0, 1.0, 0.15,
1.0, -1.0, -1.0, 0.0, 1.0, 0.15,
-1.0, -1.0, -1.0, 0.0, 1.0, 0.15,
-1.0, 1.0, -1.0, 0.0, 1.0, 0.15,
-1.0, -1.0, -1.0, 0.5, 0.5, 1.0,
-1.0, -1.0, 1.0, 0.5, 0.5, 1.0,
1.0, -1.0, 1.0, 0.5, 0.5, 1.0,
1.0, -1.0, -1.0, 0.5, 0.5, 1.0,
];
var cube_indicies = [
0, 1, 2,
0, 2, 3,
5, 4, 6,
6, 4, 7,
8, 9, 10,
8, 10, 11,
13, 12, 14,
15, 14, 12,
16, 17, 18,
16, 18, 19,
21, 20, 22,
22, 20, 23
];
var cube_verticies = []
var cube_colors = []
for (let x = 0; x < cube_indicies.length; x++) {
var i = cube_indicies[x]
cube_verticies.push(cube_data[i * 6 + 0])
cube_verticies.push(cube_data[i * 6 + 1])
cube_verticies.push(cube_data[i * 6 + 2])
cube_colors.push(cube_data[i * 6 + 3])
cube_colors.push(cube_data[i * 6 + 4])
cube_colors.push(cube_data[i * 6 + 5])
}
return [cube_verticies, cube_colors, cube_indicies.length]
}

View file

@ -0,0 +1,50 @@
import { Input } from '../io/Input.js'
import { M } from '../math/Math.js'
import { Vec3 } from '../math/Vec3.js'
export class SimpleController {
constructor(camera) {
this.camera = camera
this.lookSpeed = 100
this.moveSpeed = 10
}
update(dt) {
var press = Input.isKeyDown
var rotate = new Vec3();
if (press('ArrowRight')) rotate.y += 1;
if (press('ArrowLeft')) rotate.y -= 1;
if (press('ArrowUp')) rotate.x -= 1;
if (press('ArrowDown')) rotate.x += 1;
if(rotate.dot(rotate) > Number.EPSILON) {
var normal = rotate.normalize()
this.camera.rotation.x += this.lookSpeed * dt * normal.x;
this.camera.rotation.y += this.lookSpeed * dt * normal.y;
this.camera.rotation.z += this.lookSpeed * dt * normal.z;
}
this.camera.rotation.x = M.clamp(this.camera.rotation.x, -90, 90)
this.camera.rotation.y = this.camera.rotation.y % 360
const yaw = this.camera.rotation.y * (Math.PI/180);
var forward = new Vec3(Math.sin(yaw), 0, Math.cos(yaw))
var left = new Vec3(-forward.z, 0, forward.x)
var up = new Vec3(0, 1, 0)
var move = new Vec3();
if (press('w')) move.add(forward)
if (press('s')) move.sub(forward)
if (press('a')) move.add(left)
if (press('d')) move.sub(left)
if (press('q')) move.sub(up)
if (press('e')) move.add(up)
if(move.dot(move) > Number.EPSILON) {
var normal = move.normalize()
this.camera.position.x += this.moveSpeed * dt * normal.x;
this.camera.position.y += this.moveSpeed * dt * normal.y;
this.camera.position.z += this.moveSpeed * dt * normal.z;
}
}
}

View file

@ -9,10 +9,38 @@ export class Camera {
}
view() {
return new Mat4()
.identity()
.rot(this.rotation.clone().multS(Math.PI/180))
.pos(this.position.clone().multS(-1))
const view = new Mat4()
const d = view.data
const c3 = Math.cos(this.rotation.z * (Math.PI / 180))
const s3 = Math.sin(this.rotation.z * (Math.PI / 180))
const c2 = Math.cos(this.rotation.x * (Math.PI / 180))
const s2 = Math.sin(this.rotation.x * (Math.PI / 180))
const c1 = Math.cos(this.rotation.y * (Math.PI / 180))
const s1 = Math.sin(this.rotation.y * (Math.PI / 180))
const u = new Vec3((c1 * c3 + s1 * s2 * s3), (c2 * s3), (c1 * s2 * s3 - c3 * s1));
const v = new Vec3((c3 * s1 * s2 - c1 * s3), (c2 * c3), (c1 * c3 * s2 + s1 * s3));
const w = new Vec3((c2 * s1), (-s2), (c1 * c2));
d[0] = u.x;
d[1] = v.x;
d[2] = w.x;
d[3] = 1
d[4] = u.y;
d[5] = v.y;
d[6] = w.y;
d[7] = 1
d[8] = u.z;
d[9] = v.z;
d[10] = w.z;
d[11] = 1
d[12] = -u.dot(this.position)
d[13] = -v.dot(this.position)
d[14] = -w.dot(this.position)
d[15] = 1
return view
}
}

View file

@ -18,11 +18,38 @@ export class Entity {
this.rotation.x %= 360;
this.rotation.y %= 360;
this.rotation.z %= 360;
return new Mat4()
.identity()
.pos(this.position)
.rot(this.rotation.clone().multS(Math.PI/180))
.scale(this.scale)
const tran = new Mat4().identity()
const d = tran.data
const c3 = Math.cos(this.rotation.z * (Math.PI / 180))
const s3 = Math.sin(this.rotation.z * (Math.PI / 180))
const c2 = Math.cos(this.rotation.x * (Math.PI / 180))
const s2 = Math.sin(this.rotation.x * (Math.PI / 180))
const c1 = Math.cos(this.rotation.y * (Math.PI / 180))
const s1 = Math.sin(this.rotation.y * (Math.PI / 180))
d[0] = this.scale.x * (c1 * c3 + s1 * s2 * s3);
d[1] = this.scale.x * (c2 * s3)
d[2] = this.scale.x * (c1 * s2 * s3 - c3 * s1)
d[3] = 0
d[4] = this.scale.y * (c3 * s1 * s2 - c1 * s3)
d[5] = this.scale.y * (c2 * c3)
d[6] = this.scale.y * (c1 * c3 * s2 + s1 * s3)
d[7] = 0
d[8] = this.scale.z * (c2 * s1)
d[9] = this.scale.z * (-s2)
d[10] = this.scale.z * (c1 * c2)
d[11] = 0
d[12] = this.position.x
d[13] = this.position.y
d[14] = this.position.z
d[15] = 1
return tran
}
}

View file

@ -61,20 +61,18 @@ export class Renderer {
}
proj() {
const proj = new Mat4()
const d = proj.data
const tanHalfFovy = Math.tan((this.FOV * (Math.PI/180))/ 2.0);
const aspect = canvas.width / canvas.height
const f = 1.0 / Math.tan((this.FOV * (Math.PI/180)) / 2)
const fa = f / aspect
const nf = 1.0 / (this.NEAR - this.FAR)
const c1 = (this.NEAR + this.FAR) * nf
const c2 = this.NEAR * this.FAR * nf * 2
d[0] = 1.0 / (aspect / tanHalfFovy)
d[5] = 1.0 / tanHalfFovy
d[10] = this.FAR / (this.FAR - this.NEAR)
d[11] = 1.0
d[14] = -(this.FAR * this.NEAR) / (this.FAR)
return new Mat4().set(
fa, 0, 0, 0,
0, f, 0, 0,
0, 0, c1, c2,
0, 0, -1, 0
)
return proj
}
}

View file

@ -88,7 +88,8 @@ export class Shader {
}
loadMat4(name, m) {
gl.uniformMatrix4fv(this.#uniforms[name], gl.FALSE, new Float32Array(m.get()))
// console.log(name, m.get())
gl.uniformMatrix4fv(this.#uniforms[name], gl.FALSE, m.get())
}
loadBool(name, bool) {

View file

@ -1,3 +1,4 @@
export { SimpleController } from './controller/SimpleController.js'
export { Camera } from './core/Camera.js'
export { Entity } from './core/Entity.js'
export { Material } from './core/Material.js'
@ -5,16 +6,21 @@ export { Mesh } from './core/Mesh.js'
export { Renderer } from './core/Renderer.js'
export { Scene } from './core/Scene.js'
export { Shader } from './core/Shader.js'
export { readFileAsync } from './io/file.js'
export { File } from './io/File.js'
export { Input } from './io/Input.js'
export { Mat4 } from './math/Mat4.js'
export { Vec2 } from './math/Vec2.js'
export { M as Math } from './math/Math.js'
export { Vec3 } from './math/Vec3.js'
export { Cube } from './model/Cube.js'
export { Loop }
export { DT }
import { Input } from './io/Input.js'
var DT = 0;
var last = Date.now()
const Loop = (fn) => {
Input.setup()
const callback = () => {
var now = Date.now()
DT = ( now - last) / 1000

View file

@ -1,6 +1,6 @@
export { readFileAsync }
export const File = {}
const readFileAsync = async (path) => {
File.readFileAsync = async (path) => {
try {
let data = await fetch(path)
let text = await data.text()

16
public/gl/io/Input.js Normal file
View file

@ -0,0 +1,16 @@
export const Input = {}
const keys = {}
Input.setup = () => {
document.onkeydown = function(e) {
keys[e.key] = true
};
document.onkeyup = function(e) {
keys[e.key] = false
}
}
Input.isKeyDown = (key) => {
return keys[key]
}

View file

@ -1,11 +1,27 @@
const PI = Math.PI
const PI2 = PI * 2
const PIH = PI * 0.5
const cosFromSin = (sin, angle) => {
const pih = PI / 2;
const pi2 = PI * 2
const cos = Math.sqrt(1.0 - sin * sin);
const a = angle + PIH;
const b = a - parseInt(a / PI2) * PI2;
if (b < 0.0)
b = PIH + b;
if (b >= PI)
return -cos;
return cos;
}
export class Mat4 {
constructor() {
this.data = [
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0
]
}
@ -65,25 +81,45 @@ export class Mat4 {
}
rot(v) {
const da = this.data;
const c3 = Math.cos(v.z)
const s3 = Math.sin(v.z)
const c2 = Math.cos(v.x)
const s2 = Math.sin(v.x)
const c1 = Math.cos(v.y)
const s1 = Math.sin(v.y)
this.rotX(v.x)
this.rotY(v.y)
this.rotZ(v.z)
da[0] = c1 * c3 + s1 * s2 * s3
da[4] = c2 * s3
da[8] = c1 * s2 * s3 - c3 * s1
return this
}
da[1] = c3 * s1 * s2 - c1 * s3
da[5] = c2 * c3
da[9] = c1 * c3 * s2 + s1 * s3
rotX(a) {
const s = Math.sin(a), c = cosFromSin(s, a);
const d = this.data;
da[2] = c2 * s1
da[6] = -s2
da[10] = c1 * c2
d[5] = c
d[6] = s
d[9] = -s
d[10] = c
return this
}
rotY(a) {
const s = Math.sin(a), c = cosFromSin(s, a);
const d = this.data;
d[0] = c
d[3] = -s
d[8] = c
d[10] = c
return this
}
rotZ(a) {
const s = Math.sin(a), c = cosFromSin(s, a);
const d = this.data;
d[0] = c
d[1] = s
d[4] = -s
d[5] = c
return this
}
@ -100,12 +136,6 @@ export class Mat4 {
}
get() {
const d = this.data
return new Float32Array([
d[0], d[4], d[8], d[12],
d[1], d[5], d[9], d[13],
d[2], d[6], d[10], d[14],
d[3], d[7], d[11], d[15]
])
return new Float32Array(this.data)
}
}

3
public/gl/math/Math.js Normal file
View file

@ -0,0 +1,3 @@
export const M = {}
M.clamp = (num, min, max) => Math.min(Math.max(num, min), max)

View file

@ -1,78 +0,0 @@
export class Vec2 {
constructor(x = 0, y = 0) {
this.x = x
this.y = y
}
set(x,y) {
this.x = x
this.y = y
return this
}
clone() {
return new Vec2(this.x, this.y)
}
add(v) {
this.x += v.x
this.y += v.y
return this
}
sub(v) {
this.x -= v.x
this.y -= v.y
return this
}
copy(v) {
this.x = v.x
this.y = v.y
return this
}
multV(v) {
this.x *= v.x
this.y *= v.y
return this
}
multS(s) {
this.x *= s
this.y *= s
return this
}
divV(v) {
this.x *= (1 / v.x)
this.y *= (1 / v.y)
return this
}
divS(s) {
this.x *= (1 / s)
this.y *= (1 / s)
return this
}
invert() {
this.x = this.x == 0 ? 0 : (1 / this.x)
this.y = this.y == 0 ? 0 : (1 / this.y)
return this
}
normalize() {
return this.divS(this.length() || 1)
}
dot(v) {
return this.x * v.x + this.y * v.y;
}
length() {
return Math.sqrt(this.x * this.x + this.y * this.y);
}
}

View file

@ -20,14 +20,14 @@ export class Vec3 {
add(v) {
this.x += v.x
this.y += v.y
this.x += v.x
this.z += v.z
return this
}
sub(v) {
this.x -= v.x
this.y -= v.y
this.x -= v.z
this.z -= v.z
return this
}
@ -81,6 +81,21 @@ export class Vec3 {
return this.x * v.x + this.y * v.y + this.z * v.z;
}
cross(v) {
return this.crossV(this, v)
}
crossV(a, b) {
const ax = a.x, ay = a.y, az = a.z;
const bx = b.x, by = b.y, bz = b.z;
this.x = ay * bz - az * by;
this.y = az * bx - ax * bz;
this.z = ax * by - ay * bx;
return this;
}
length() {
return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
}

68
public/gl/model/Cube.js Normal file
View file

@ -0,0 +1,68 @@
import { Mesh } from '../core/Mesh.js'
export class Cube {
constructor() {
this.data = [
-1.0, 1.0, -1.0, 0.5, 0.5, 0.5,
-1.0, 1.0, 1.0, 0.5, 0.5, 0.5,
1.0, 1.0, 1.0, 0.5, 0.5, 0.5,
1.0, 1.0, -1.0, 0.5, 0.5, 0.5,
-1.0, 1.0, 1.0, 0.75, 0.25, 0.5,
-1.0, -1.0, 1.0, 0.75, 0.25, 0.5,
-1.0, -1.0, -1.0, 0.75, 0.25, 0.5,
-1.0, 1.0, -1.0, 0.75, 0.25, 0.5,
1.0, 1.0, 1.0, 0.25, 0.25, 0.75,
1.0, -1.0, 1.0, 0.25, 0.25, 0.75,
1.0, -1.0, -1.0, 0.25, 0.25, 0.75,
1.0, 1.0, -1.0, 0.25, 0.25, 0.75,
1.0, 1.0, 1.0, 1.0, 0.0, 0.15,
1.0, -1.0, 1.0, 1.0, 0.0, 0.15,
-1.0, -1.0, 1.0, 1.0, 0.0, 0.15,
-1.0, 1.0, 1.0, 1.0, 0.0, 0.15,
1.0, 1.0, -1.0, 0.0, 1.0, 0.15,
1.0, -1.0, -1.0, 0.0, 1.0, 0.15,
-1.0, -1.0, -1.0, 0.0, 1.0, 0.15,
-1.0, 1.0, -1.0, 0.0, 1.0, 0.15,
-1.0, -1.0, -1.0, 0.5, 0.5, 1.0,
-1.0, -1.0, 1.0, 0.5, 0.5, 1.0,
1.0, -1.0, 1.0, 0.5, 0.5, 1.0,
1.0, -1.0, -1.0, 0.5, 0.5, 1.0,
];
this.indicies = [
0, 1, 2,
0, 2, 3,
5, 4, 6,
6, 4, 7,
8, 9, 10,
8, 10, 11,
13, 12, 14,
15, 14, 12,
16, 17, 18,
16, 18, 19,
21, 20, 22,
22, 20, 23
];
this.verticies = []
this.colors = []
for (let x = 0; x < this.indicies.length; x++) {
var i = this.indicies[x]
this.verticies.push(this.data[i * 6 + 2])
this.verticies.push(this.data[i * 6 + 1])
this.verticies.push(this.data[i * 6 + 0])
this.colors.push(this.data[i * 6 + 3])
this.colors.push(this.data[i * 6 + 4])
this.colors.push(this.data[i * 6 + 5])
}
this.mesh = new Mesh(this.indicies.length)
.store(this.verticies, 3)
.store(this.colors, 3)
.finish()
}
}

View file

@ -1,101 +1,33 @@
import * as GL from '/gl/gl.js'
import { gen_cube } from './cube.js'
async function main() {
const main = async () => {
var Renderer = new GL.Renderer()
var Scene = new GL.Scene()
var Camera = new GL.Camera()
var SimpleController = new GL.SimpleController(Camera)
var Shader = new GL.Shader(
await GL.readFileAsync("shader/simple.vert"),
await GL.readFileAsync("shader/simple.frag")
await GL.File.readFileAsync("shader/simple.vert"),
await GL.File.readFileAsync("shader/simple.frag")
)
var Material = new GL.Material(Shader)
var cube_data = gen_cube()
var Mesh = new GL.Mesh(cube_data[2])
.store(cube_data[0], 3)
.store(cube_data[1], 3)
.finish()
var Mesh = new GL.Cube().mesh
var Cube = new GL.Entity(Mesh)
Cube.position.z = -5;
Cube.position.z = 3;
Scene.add(Material, Cube)
const a = new GL.Vec3(1,1,1)
Renderer.FOV = 70
GL.Loop(() => {
Renderer.draw(Scene, Camera)
Cube.rotation.add(a)
updateInputs(Camera)
SimpleController.update(GL.DT)
});
}
const clamp = (num, min, max) => Math.min(Math.max(num, min), max);
const LEFT = 37;
const RIGHT = 39;
const UP = 38;
const DOWN = 40;
const W = 87;
const A = 65;
const S = 83;
const D = 68;
const Q = 81;
const E = 69;
const lookSpeed = 50;
const moveSpeed = 10;
function updateInputs(Camera) {
var rotate = new GL.Vec3();
if (keys[RIGHT]) rotate.y += 1;
if (keys[LEFT]) rotate.y -= 1;
if (keys[UP]) rotate.x -= 1;
if (keys[DOWN]) rotate.x += 1;
if(rotate.dot(rotate) > Number.EPSILON) {
var normal = rotate.normalize()
console.log(lookSpeed * GL.DT * normal.x, lookSpeed * GL.DT * normal.y)
Camera.rotation.x += lookSpeed * GL.DT * normal.x;
Camera.rotation.y += lookSpeed * GL.DT * normal.y;
Camera.rotation.z += lookSpeed * GL.DT * normal.z;
}
Camera.rotation.x = clamp(Camera.rotation.x, -90, 90)
Camera.rotation.y = Camera.rotation.y % 360
const yaw = Camera.rotation.y * (Math.PI/180);
var forward = new GL.Vec3(Math.sin(yaw), 0, Math.cos(yaw));
var right = new GL.Vec3(forward.z, 0, -forward.x);
var up = new GL.Vec3(0, 1, 0);
var move = new GL.Vec3();
if (keys[W]) move.sub(forward)
if (keys[S]) move.add(forward)
if (keys[A]) move.sub(right)
if (keys[D]) move.add(right)
if (keys[Q]) move.sub(up)
if (keys[E]) move.add(up)
if(move.dot(move) > Number.EPSILON) {
var normal = move.normalize()
Camera.position.x += moveSpeed * GL.DT * normal.x;
Camera.position.y += moveSpeed * GL.DT * normal.y;
Camera.position.z += moveSpeed * GL.DT * normal.z;
}
}
var keys = {}
function setupInputs() {
document.onkeydown = function(e) {
keys[e.keyCode] = true;
};
document.onkeyup = function(e) {
keys[e.keyCode] = false;
}
}
setupInputs()
main()