Initial project import
This commit is contained in:
commit
23f2d29e32
11957 files changed
+1754577
No files matched your search
@@ -0,0 +1,25 @@
|
||||
# JS DOM Cube
|
||||
|
||||
## Run with veb
|
||||
|
||||
```sh
|
||||
cd examples/js_dom_cube
|
||||
v run main.v
|
||||
```
|
||||
|
||||
This starts a `veb` server at `http://localhost:3001/` and compiles `cube.js.v` to
|
||||
`cube.js` before serving `index.html`.
|
||||
|
||||
You can also run it from the repository root:
|
||||
|
||||
```sh
|
||||
v run examples/js_dom_cube/main.v
|
||||
```
|
||||
|
||||
## Compile manually
|
||||
|
||||
```sh
|
||||
v -b js_browser examples/js_dom_cube/cube.js.v
|
||||
```
|
||||
|
||||
Then open `index.html` in your favorite browser.
|
||||
@@ -0,0 +1,451 @@
|
||||
import js.dom
|
||||
import math
|
||||
|
||||
const vert_code = 'attribute vec3 position;uniform mat4 Pmatrix;uniform mat4 Vmatrix;uniform mat4 Mmatrix;attribute vec3 color;varying vec3 vColor;void main(void) {gl_Position = Pmatrix * Vmatrix * Mmatrix * vec4(position,1.);vColor = color;}
|
||||
'
|
||||
|
||||
const frag_code = 'precision mediump float;varying vec3 vColor;void main(void) {gl_FragColor = vec4(vColor, 1.);}
|
||||
'
|
||||
|
||||
const vertices = [
|
||||
f32(-1),
|
||||
-1,
|
||||
-1,
|
||||
1,
|
||||
-1,
|
||||
-1,
|
||||
1,
|
||||
1,
|
||||
-1,
|
||||
-1,
|
||||
1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
1,
|
||||
1,
|
||||
-1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
-1,
|
||||
1,
|
||||
1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
1,
|
||||
-1,
|
||||
-1,
|
||||
1,
|
||||
1,
|
||||
-1,
|
||||
-1,
|
||||
1,
|
||||
1,
|
||||
-1,
|
||||
-1,
|
||||
1,
|
||||
1,
|
||||
-1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
-1,
|
||||
1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
1,
|
||||
1,
|
||||
-1,
|
||||
1,
|
||||
1,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
1,
|
||||
-1,
|
||||
-1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
-1,
|
||||
]
|
||||
const colors = [
|
||||
f32(5),
|
||||
3,
|
||||
7,
|
||||
5,
|
||||
3,
|
||||
7,
|
||||
5,
|
||||
3,
|
||||
7,
|
||||
5,
|
||||
3,
|
||||
7,
|
||||
1,
|
||||
1,
|
||||
3,
|
||||
1,
|
||||
1,
|
||||
3,
|
||||
1,
|
||||
1,
|
||||
3,
|
||||
1,
|
||||
1,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
]
|
||||
const indices = [
|
||||
u16(0),
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
4,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
8,
|
||||
10,
|
||||
11,
|
||||
12,
|
||||
13,
|
||||
14,
|
||||
12,
|
||||
14,
|
||||
15,
|
||||
16,
|
||||
17,
|
||||
18,
|
||||
16,
|
||||
18,
|
||||
19,
|
||||
20,
|
||||
21,
|
||||
22,
|
||||
20,
|
||||
22,
|
||||
23,
|
||||
]
|
||||
const amortization = 0.95
|
||||
|
||||
fn get_webgl() (JS.HTMLCanvasElement, JS.WebGLRenderingContext) {
|
||||
JS.console.log(dom.document)
|
||||
elem := dom.document.getElementById('myCanvas'.str) or { panic('cannot get canvas') }
|
||||
match elem {
|
||||
JS.HTMLCanvasElement {
|
||||
webgl := elem.getContext('experimental-webgl'.str, js_undefined()) or {
|
||||
panic('context not found')
|
||||
}
|
||||
match webgl {
|
||||
JS.WebGLRenderingContext {
|
||||
return elem, webgl
|
||||
}
|
||||
else {
|
||||
panic('cannot get webgl')
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
panic('not an canvas')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_projection(angle f64, a f64, z_min f64, z_max f64) []f64 {
|
||||
ang := math.tan((angle * 0.5) * math.pi / 180)
|
||||
return [
|
||||
0.5 / ang,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0.5 * a / ang,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
-(z_max + z_min) / (z_max - z_min),
|
||||
-1,
|
||||
0,
|
||||
0,
|
||||
(-2 * z_max * z_min) / (z_max - z_min),
|
||||
0,
|
||||
]
|
||||
}
|
||||
|
||||
fn JS.Math.cos(JS.Number) JS.Number
|
||||
fn JS.Math.sin(JS.Number) JS.Number
|
||||
fn rotate_x(mut m []f64, angle f64) {
|
||||
c := math.cos(angle)
|
||||
s := math.sin(angle)
|
||||
mv1 := m[1]
|
||||
mv5 := m[5]
|
||||
mv9 := m[9]
|
||||
m[1] = m[1] * c - m[2] * s
|
||||
m[5] = m[5] * c - m[6] * s
|
||||
m[9] = m[9] * c - m[10] * s
|
||||
|
||||
m[2] = m[2] * c + mv1 * s
|
||||
m[6] = m[6] * c + mv5 * s
|
||||
m[10] = m[10] * c + mv9 * s
|
||||
}
|
||||
|
||||
fn rotate_y(mut m []f64, angle f64) {
|
||||
c := math.cos(angle)
|
||||
s := math.sin(angle)
|
||||
|
||||
mv0 := m[0]
|
||||
mv4 := m[4]
|
||||
mv8 := m[8]
|
||||
m[0] = c * m[0] + s * m[2]
|
||||
m[4] = c * m[4] + s * m[6]
|
||||
m[8] = c * m[8] + s * m[10]
|
||||
|
||||
m[2] = c * m[2] - s * mv0
|
||||
m[6] = c * m[6] - s * mv4
|
||||
m[10] = c * m[10] - s * mv8
|
||||
}
|
||||
|
||||
struct State {
|
||||
mut:
|
||||
drag bool
|
||||
gl JS.WebGLRenderingContext
|
||||
canvas JS.HTMLCanvasElement
|
||||
old_x f64
|
||||
old_y f64
|
||||
dx f64
|
||||
dy f64
|
||||
theta f64
|
||||
phi f64
|
||||
time_old f64
|
||||
mo_matrix []f64
|
||||
view_matrix []f64
|
||||
proj_matrix []f64
|
||||
pmatrix JS.WebGLUniformLocation
|
||||
vmatrix JS.WebGLUniformLocation
|
||||
mmatrix JS.WebGLUniformLocation
|
||||
index_buffer JS.WebGLBuffer
|
||||
}
|
||||
|
||||
fn animate(mut state State, time f64) {
|
||||
if !state.drag {
|
||||
state.dx = state.dx * amortization
|
||||
state.dy = state.dy * amortization
|
||||
state.theta += state.dx
|
||||
state.phi += state.dy
|
||||
}
|
||||
|
||||
state.mo_matrix[0] = 1
|
||||
state.mo_matrix[1] = 0
|
||||
state.mo_matrix[2] = 0
|
||||
state.mo_matrix[3] = 0
|
||||
|
||||
state.mo_matrix[4] = 0
|
||||
state.mo_matrix[5] = 1
|
||||
state.mo_matrix[6] = 0
|
||||
state.mo_matrix[7] = 0
|
||||
|
||||
state.mo_matrix[8] = 0
|
||||
state.mo_matrix[9] = 0
|
||||
state.mo_matrix[10] = 1
|
||||
state.mo_matrix[11] = 0
|
||||
|
||||
state.mo_matrix[12] = 0
|
||||
state.mo_matrix[13] = 0
|
||||
state.mo_matrix[14] = 0
|
||||
state.mo_matrix[15] = 1
|
||||
// println('${state.theta} ${state.phi}')
|
||||
rotate_x(mut state.mo_matrix, state.phi)
|
||||
rotate_y(mut state.mo_matrix, state.theta)
|
||||
state.time_old = time
|
||||
state.gl.enable(dom.gl_depth_test())
|
||||
state.gl.clearColor(JS.Number(0.5), JS.Number(0.5), JS.Number(0.5), JS.Number(0.9))
|
||||
state.gl.clearDepth(JS.Number(1.0))
|
||||
state.gl.viewport(JS.Number(0.0), JS.Number(0.0), state.canvas.width, state.canvas.height)
|
||||
state.gl.clear(JS.Number(int(dom.gl_color_buffer_bit()) | int(dom.gl_depth_buffer_bit())))
|
||||
|
||||
state.gl.uniformMatrix4fv(state.pmatrix, JS.Boolean(false), state.proj_matrix.to_number_array())
|
||||
state.gl.uniformMatrix4fv(state.vmatrix, JS.Boolean(false), state.view_matrix.to_number_array())
|
||||
state.gl.uniformMatrix4fv(state.mmatrix, JS.Boolean(false), state.mo_matrix.to_number_array())
|
||||
|
||||
state.gl.bindBuffer(dom.gl_element_array_buffer(), state.index_buffer)
|
||||
state.gl.drawElements(dom.gl_triangles(), JS.Number(indices.len), dom.gl_unsigned_short(),
|
||||
JS.Number(0))
|
||||
|
||||
dom.window().requestAnimationFrame(fn [mut state] (time JS.Number) {
|
||||
animate(mut state, f64(time))
|
||||
})
|
||||
}
|
||||
|
||||
fn main() {
|
||||
canvas, gl := get_webgl()
|
||||
|
||||
vertex_buffer := gl.createBuffer()?
|
||||
gl.bindBuffer(dom.gl_array_buffer(), vertex_buffer)
|
||||
gl.bufferData(dom.gl_array_buffer(), float32_array(vertices), dom.gl_static_draw())
|
||||
|
||||
color_buffer := gl.createBuffer()?
|
||||
gl.bindBuffer(dom.gl_array_buffer(), color_buffer)
|
||||
gl.bufferData(dom.gl_array_buffer(), float32_array(colors), dom.gl_static_draw())
|
||||
|
||||
index_buffer := gl.createBuffer()?
|
||||
gl.bindBuffer(dom.gl_element_array_buffer(), index_buffer)
|
||||
gl.bufferData(dom.gl_element_array_buffer(), uint16_array(indices), dom.gl_static_draw())
|
||||
|
||||
vert_shader := gl.createShader(dom.gl_vertex_shader())?
|
||||
gl.shaderSource(vert_shader, vert_code.str)
|
||||
gl.compileShader(vert_shader)
|
||||
|
||||
if !bool(JS.Boolean(gl.getShaderParameter(vert_shader, dom.gl_compile_status()))) {
|
||||
panic('An error occurred when compiling vertex shader: ${string(gl.getShaderInfoLog(vert_shader))}')
|
||||
}
|
||||
|
||||
frag_shader := gl.createShader(dom.gl_fragment_shader())?
|
||||
gl.shaderSource(frag_shader, frag_code.str)
|
||||
gl.compileShader(frag_shader)
|
||||
if !bool(JS.Boolean(gl.getShaderParameter(frag_shader, dom.gl_compile_status()))) {
|
||||
panic('An error occurred when compiling fragment shader: ${string(gl.getShaderInfoLog(frag_shader))}')
|
||||
}
|
||||
|
||||
shader_program := gl.createProgram()?
|
||||
gl.attachShader(shader_program, vert_shader)
|
||||
gl.attachShader(shader_program, frag_shader)
|
||||
gl.linkProgram(shader_program)
|
||||
|
||||
if !bool(JS.Boolean(gl.getProgramParameter(shader_program, dom.gl_link_status()))) {
|
||||
panic('unable to initialize the shader program: ${string(gl.getProgramInfoLog(shader_program))}')
|
||||
}
|
||||
|
||||
pmatrix := gl.getUniformLocation(shader_program, 'Pmatrix'.str)?
|
||||
vmatrix := gl.getUniformLocation(shader_program, 'Vmatrix'.str)?
|
||||
mmatrix := gl.getUniformLocation(shader_program, 'Mmatrix'.str)?
|
||||
|
||||
gl.bindBuffer(dom.gl_array_buffer(), vertex_buffer)
|
||||
position := gl.getAttribLocation(shader_program, 'position'.str)
|
||||
gl.vertexAttribPointer(position, JS.Number(3), dom.gl_float(), JS.Boolean(false), JS.Number(0),
|
||||
JS.Number(0))
|
||||
gl.enableVertexAttribArray(position)
|
||||
|
||||
gl.bindBuffer(dom.gl_array_buffer(), color_buffer)
|
||||
color := gl.getAttribLocation(shader_program, 'color'.str)
|
||||
gl.vertexAttribPointer(color, JS.Number(3), dom.gl_float(), JS.Boolean(false), JS.Number(0),
|
||||
JS.Number(0))
|
||||
gl.enableVertexAttribArray(color)
|
||||
gl.useProgram(shader_program)
|
||||
|
||||
mut proj_matrix := get_projection(40.0, f64(canvas.width) / f64(canvas.height), 1.0, 100.0)
|
||||
mut mo_matrix := [f64(1), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
|
||||
mut view_matrix := [f64(1), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]
|
||||
|
||||
view_matrix[14] = view_matrix[14] - 6
|
||||
|
||||
mut state :=
|
||||
State{false, gl, canvas, 0, 0, 0, 0, 0, 0, 0, mo_matrix, view_matrix, proj_matrix, pmatrix, vmatrix, mmatrix, index_buffer}
|
||||
|
||||
canvas.addEventListener('mousedown'.str, fn [mut state] (e JS.Event) {
|
||||
state.drag = true
|
||||
match e {
|
||||
JS.MouseEvent {
|
||||
state.old_x = f64(e.pageX)
|
||||
state.old_y = f64(e.pageY)
|
||||
e.preventDefault()
|
||||
}
|
||||
else {}
|
||||
}
|
||||
}, JS.EventListenerOptions{})
|
||||
|
||||
canvas.addEventListener('mouseup'.str, fn [mut state] (e JS.Event) {
|
||||
state.drag = false
|
||||
}, JS.EventListenerOptions{})
|
||||
canvas.addEventListener('mouseout'.str, fn [mut state] (e JS.Event) {
|
||||
state.drag = false
|
||||
}, JS.EventListenerOptions{})
|
||||
canvas.addEventListener('mousemove'.str, fn [mut state] (e JS.Event) {
|
||||
if !state.drag {
|
||||
return
|
||||
}
|
||||
match e {
|
||||
JS.MouseEvent {
|
||||
state.dx = (f64(e.pageX) - state.old_x) * 2.0 * math.pi / f64(state.canvas.width)
|
||||
state.dy = (f64(e.pageY) - state.old_y) * 2.0 * math.pi / f64(state.canvas.height)
|
||||
state.theta += state.dx
|
||||
state.phi += state.dy
|
||||
state.old_x = f64(e.pageX)
|
||||
state.old_y = f64(e.pageY)
|
||||
e.preventDefault()
|
||||
}
|
||||
else {
|
||||
panic('not a mouse event??')
|
||||
}
|
||||
}
|
||||
}, JS.EventListenerOptions{})
|
||||
|
||||
animate(mut state, 0)
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<body>
|
||||
<canvas width="570" height="570" id="myCanvas"></canvas>
|
||||
<script src="cube.js">
|
||||
|
||||
</script>
|
||||
</body>
|
||||
@@ -0,0 +1,28 @@
|
||||
module main
|
||||
|
||||
import os
|
||||
import veb
|
||||
|
||||
const http_port = 3001
|
||||
const vexe = os.quoted_path(os.getenv_opt('VEXE') or { @VEXE })
|
||||
|
||||
pub struct Context {
|
||||
veb.Context
|
||||
}
|
||||
|
||||
pub struct App {
|
||||
veb.StaticHandler
|
||||
}
|
||||
|
||||
fn main() {
|
||||
os.chdir(os.dir(@FILE))!
|
||||
mut app := &App{}
|
||||
veb.run_at[App, Context](mut app, port: http_port)!
|
||||
}
|
||||
|
||||
// before_accept_loop builds cube.js before the server starts and registers the static assets.
|
||||
pub fn (mut app App) before_accept_loop() {
|
||||
os.execute_or_panic('${vexe} -b js_browser cube.js.v')
|
||||
app.serve_static('/cube.js', 'cube.js') or { panic(err) }
|
||||
app.serve_static('/index.html', 'index.html') or { panic(err) }
|
||||
}
|
||||
Reference in new issue
Block a user