aboutsummaryrefslogtreecommitdiff
path: root/v_windows/v/examples/sokol/01_cubes/cube.v
diff options
context:
space:
mode:
Diffstat (limited to 'v_windows/v/examples/sokol/01_cubes/cube.v')
-rw-r--r--v_windows/v/examples/sokol/01_cubes/cube.v432
1 files changed, 432 insertions, 0 deletions
diff --git a/v_windows/v/examples/sokol/01_cubes/cube.v b/v_windows/v/examples/sokol/01_cubes/cube.v
new file mode 100644
index 0000000..c933dbf
--- /dev/null
+++ b/v_windows/v/examples/sokol/01_cubes/cube.v
@@ -0,0 +1,432 @@
+/**********************************************************************
+*
+* Sokol 3d cube demo
+*
+* Copyright (c) 2021 Dario Deledda. All rights reserved.
+* Use of this source code is governed by an MIT license
+* that can be found in the LICENSE file.
+*
+* TODO:
+* - add instancing
+* - add an exampel with shaders
+**********************************************************************/
+import gg
+import gx
+import math
+import sokol.sapp
+import sokol.gfx
+import sokol.sgl
+
+const (
+ win_width = 800
+ win_height = 800
+ bg_color = gx.white
+)
+
+struct App {
+mut:
+ gg &gg.Context
+ pip_3d C.sgl_pipeline
+ texture C.sg_image
+ init_flag bool
+ frame_count int
+ mouse_x int = -1
+ mouse_y int = -1
+}
+
+/******************************************************************************
+*
+* Texture functions
+*
+******************************************************************************/
+fn create_texture(w int, h int, buf &u8) C.sg_image {
+ sz := w * h * 4
+ mut img_desc := C.sg_image_desc{
+ width: w
+ height: h
+ num_mipmaps: 0
+ min_filter: .linear
+ mag_filter: .linear
+ // usage: .dynamic
+ wrap_u: .clamp_to_edge
+ wrap_v: .clamp_to_edge
+ label: &byte(0)
+ d3d11_texture: 0
+ }
+ // commen if .dynamic is enabled
+ img_desc.data.subimage[0][0] = C.sg_range{
+ ptr: buf
+ size: size_t(sz)
+ }
+
+ sg_img := C.sg_make_image(&img_desc)
+ return sg_img
+}
+
+fn destroy_texture(sg_img C.sg_image) {
+ C.sg_destroy_image(sg_img)
+}
+
+// Use only if usage: .dynamic is enabled
+fn update_text_texture(sg_img C.sg_image, w int, h int, buf &byte) {
+ sz := w * h * 4
+ mut tmp_sbc := C.sg_image_data{}
+ tmp_sbc.subimage[0][0] = C.sg_range{
+ ptr: buf
+ size: size_t(sz)
+ }
+ C.sg_update_image(sg_img, &tmp_sbc)
+}
+
+/******************************************************************************
+*
+* Draw functions
+*
+******************************************************************************/
+fn draw_triangle() {
+ sgl.defaults()
+ sgl.begin_triangles()
+ sgl.v2f_c3b(0.0, 0.5, 255, 0, 0)
+ sgl.v2f_c3b(-0.5, -0.5, 0, 0, 255)
+ sgl.v2f_c3b(0.5, -0.5, 0, 255, 0)
+ sgl.end()
+}
+
+// vertex specification for a cube with colored sides and texture coords
+fn cube() {
+ sgl.begin_quads()
+ // edge color
+ sgl.c3f(1.0, 0.0, 0.0)
+ // edge coord
+ // x,y,z, texture cord: u,v
+ sgl.v3f_t2f(-1.0, 1.0, -1.0, -1.0, 1.0)
+ sgl.v3f_t2f(1.0, 1.0, -1.0, 1.0, 1.0)
+ sgl.v3f_t2f(1.0, -1.0, -1.0, 1.0, -1.0)
+ sgl.v3f_t2f(-1.0, -1.0, -1.0, -1.0, -1.0)
+ sgl.c3f(0.0, 1.0, 0.0)
+ sgl.v3f_t2f(-1.0, -1.0, 1.0, -1.0, 1.0)
+ sgl.v3f_t2f(1.0, -1.0, 1.0, 1.0, 1.0)
+ sgl.v3f_t2f(1.0, 1.0, 1.0, 1.0, -1.0)
+ sgl.v3f_t2f(-1.0, 1.0, 1.0, -1.0, -1.0)
+ sgl.c3f(0.0, 0.0, 1.0)
+ sgl.v3f_t2f(-1.0, -1.0, 1.0, -1.0, 1.0)
+ sgl.v3f_t2f(-1.0, 1.0, 1.0, 1.0, 1.0)
+ sgl.v3f_t2f(-1.0, 1.0, -1.0, 1.0, -1.0)
+ sgl.v3f_t2f(-1.0, -1.0, -1.0, -1.0, -1.0)
+ sgl.c3f(1.0, 0.5, 0.0)
+ sgl.v3f_t2f(1.0, -1.0, 1.0, -1.0, 1.0)
+ sgl.v3f_t2f(1.0, -1.0, -1.0, 1.0, 1.0)
+ sgl.v3f_t2f(1.0, 1.0, -1.0, 1.0, -1.0)
+ sgl.v3f_t2f(1.0, 1.0, 1.0, -1.0, -1.0)
+ sgl.c3f(0.0, 0.5, 1.0)
+ sgl.v3f_t2f(1.0, -1.0, -1.0, -1.0, 1.0)
+ sgl.v3f_t2f(1.0, -1.0, 1.0, 1.0, 1.0)
+ sgl.v3f_t2f(-1.0, -1.0, 1.0, 1.0, -1.0)
+ sgl.v3f_t2f(-1.0, -1.0, -1.0, -1.0, -1.0)
+ sgl.c3f(1.0, 0.0, 0.5)
+ sgl.v3f_t2f(-1.0, 1.0, -1.0, -1.0, 1.0)
+ sgl.v3f_t2f(-1.0, 1.0, 1.0, 1.0, 1.0)
+ sgl.v3f_t2f(1.0, 1.0, 1.0, 1.0, -1.0)
+ sgl.v3f_t2f(1.0, 1.0, -1.0, -1.0, -1.0)
+ sgl.end()
+}
+
+fn draw_cubes(app App) {
+ rot := [f32(1.0) * (app.frame_count % 360), 0.5 * f32(app.frame_count % 360)]
+ // rot := [f32(app.mouse_x), f32(app.mouse_y)]
+
+ sgl.defaults()
+ sgl.load_pipeline(app.pip_3d)
+
+ sgl.matrix_mode_projection()
+ sgl.perspective(sgl.rad(45.0), 1.0, 0.1, 100.0)
+
+ sgl.matrix_mode_modelview()
+ sgl.translate(0.0, 0.0, -12.0)
+ sgl.rotate(sgl.rad(rot[0]), 1.0, 0.0, 0.0)
+ sgl.rotate(sgl.rad(rot[1]), 0.0, 1.0, 0.0)
+ cube()
+ sgl.push_matrix()
+ sgl.translate(0.0, 0.0, 3.0)
+ sgl.scale(0.5, 0.5, 0.5)
+ sgl.rotate(-2.0 * sgl.rad(rot[0]), 1.0, 0.0, 0.0)
+ sgl.rotate(-2.0 * sgl.rad(rot[1]), 0.0, 1.0, 0.0)
+ cube()
+ sgl.push_matrix()
+ sgl.translate(0.0, 0.0, 3.0)
+ sgl.scale(0.5, 0.5, 0.5)
+ sgl.rotate(-3.0 * sgl.rad(2 * rot[0]), 1.0, 0.0, 0.0)
+ sgl.rotate(3.0 * sgl.rad(2 * rot[1]), 0.0, 0.0, 1.0)
+ cube()
+ sgl.pop_matrix()
+ sgl.pop_matrix()
+}
+
+fn cube_t(r f32, g f32, b f32) {
+ sgl.begin_quads()
+ // edge color
+ sgl.c3f(r, g, b)
+ // edge coord
+ // x,y,z, texture cord: u,v
+ sgl.v3f_t2f(-1.0, 1.0, -1.0, 0.0, 0.25)
+ sgl.v3f_t2f(1.0, 1.0, -1.0, 0.25, 0.25)
+ sgl.v3f_t2f(1.0, -1.0, -1.0, 0.25, 0.0)
+ sgl.v3f_t2f(-1.0, -1.0, -1.0, 0.0, 0.0)
+ sgl.c3f(r, g, b)
+ sgl.v3f_t2f(-1.0, -1.0, 1.0, 0.0, 0.25)
+ sgl.v3f_t2f(1.0, -1.0, 1.0, 0.25, 0.25)
+ sgl.v3f_t2f(1.0, 1.0, 1.0, 0.25, 0.0)
+ sgl.v3f_t2f(-1.0, 1.0, 1.0, 0.0, 0.0)
+ sgl.c3f(r, g, b)
+ sgl.v3f_t2f(-1.0, -1.0, 1.0, 0.0, 0.25)
+ sgl.v3f_t2f(-1.0, 1.0, 1.0, 0.25, 0.25)
+ sgl.v3f_t2f(-1.0, 1.0, -1.0, 0.25, 0.0)
+ sgl.v3f_t2f(-1.0, -1.0, -1.0, 0.0, 0.0)
+ sgl.c3f(r, g, b)
+ sgl.v3f_t2f(1.0, -1.0, 1.0, 0.0, 0.25)
+ sgl.v3f_t2f(1.0, -1.0, -1.0, 0.25, 0.25)
+ sgl.v3f_t2f(1.0, 1.0, -1.0, 0.25, 0.0)
+ sgl.v3f_t2f(1.0, 1.0, 1.0, 0.0, 0.0)
+ sgl.c3f(r, g, b)
+ sgl.v3f_t2f(1.0, -1.0, -1.0, 0.0, 0.25)
+ sgl.v3f_t2f(1.0, -1.0, 1.0, 0.25, 0.25)
+ sgl.v3f_t2f(-1.0, -1.0, 1.0, 0.25, 0.0)
+ sgl.v3f_t2f(-1.0, -1.0, -1.0, 0.0, 0.0)
+ sgl.c3f(r, g, b)
+ sgl.v3f_t2f(-1.0, 1.0, -1.0, 0.0, 0.25)
+ sgl.v3f_t2f(-1.0, 1.0, 1.0, 0.25, 0.25)
+ sgl.v3f_t2f(1.0, 1.0, 1.0, 0.25, 0.0)
+ sgl.v3f_t2f(1.0, 1.0, -1.0, 0.0, 0.0)
+ sgl.end()
+}
+
+fn draw_texture_cubes(app App) {
+ rot := [f32(app.mouse_x), f32(app.mouse_y)]
+ sgl.defaults()
+ sgl.load_pipeline(app.pip_3d)
+
+ sgl.enable_texture()
+ sgl.texture(app.texture)
+
+ sgl.matrix_mode_projection()
+ sgl.perspective(sgl.rad(45.0), 1.0, 0.1, 100.0)
+
+ sgl.matrix_mode_modelview()
+ sgl.translate(0.0, 0.0, -12.0)
+ sgl.rotate(sgl.rad(rot[0]), 1.0, 0.0, 0.0)
+ sgl.rotate(sgl.rad(rot[1]), 0.0, 1.0, 0.0)
+ cube_t(1, 1, 1)
+ sgl.push_matrix()
+ sgl.translate(0.0, 0.0, 3.0)
+ sgl.scale(0.5, 0.5, 0.5)
+ sgl.rotate(-2.0 * sgl.rad(rot[0]), 1.0, 0.0, 0.0)
+ sgl.rotate(-2.0 * sgl.rad(rot[1]), 0.0, 1.0, 0.0)
+ cube_t(1, 1, 1)
+ sgl.push_matrix()
+ sgl.translate(0.0, 0.0, 3.0)
+ sgl.scale(0.5, 0.5, 0.5)
+ sgl.rotate(-3.0 * sgl.rad(2 * rot[0]), 1.0, 0.0, 0.0)
+ sgl.rotate(3.0 * sgl.rad(2 * rot[1]), 0.0, 0.0, 1.0)
+ cube_t(1, 1, 1)
+ sgl.pop_matrix()
+ sgl.pop_matrix()
+
+ sgl.disable_texture()
+}
+
+fn cube_field(app App) {
+ rot := [f32(app.mouse_x), f32(app.mouse_y)]
+ xyz_sz := f32(2.0)
+ field_size := 20
+
+ sgl.defaults()
+ sgl.load_pipeline(app.pip_3d)
+
+ sgl.enable_texture()
+ sgl.texture(app.texture)
+
+ sgl.matrix_mode_projection()
+ sgl.perspective(sgl.rad(45.0), 1.0, 0.1, 200.0)
+
+ sgl.matrix_mode_modelview()
+
+ sgl.translate(field_size, 0.0, -120.0)
+ sgl.rotate(sgl.rad(rot[0]), 0.0, 1.0, 0.0)
+ sgl.rotate(sgl.rad(rot[1]), 1.0, 0.0, 0.0)
+
+ // draw field_size*field_size cubes
+ for y in 0 .. field_size {
+ for x in 0 .. field_size {
+ sgl.push_matrix()
+ z := f32(math.cos(f32(x * 2) / field_size) * math.sin(f32(y * 2) / field_size) * xyz_sz) * (xyz_sz * 5)
+ sgl.translate(x * xyz_sz, z, y * xyz_sz)
+ cube_t(f32(f32(x) / field_size), f32(f32(y) / field_size), 1)
+ sgl.pop_matrix()
+ }
+ }
+ sgl.disable_texture()
+}
+
+fn frame(mut app App) {
+ ws := gg.window_size_real_pixels()
+ ratio := f32(ws.width) / ws.height
+ dw := ws.width
+ dh := ws.height
+ ww := int(dh / 3) // not a bug
+ hh := int(dh / 3)
+ x0 := int(f32(dw) * 0.05)
+ // x1 := dw/2
+ y0 := 0
+ y1 := int(f32(dh) * 0.5)
+
+ app.gg.begin()
+ // sgl.defaults()
+
+ // 2d triangle
+ sgl.viewport(x0, y0, ww, hh, true)
+ draw_triangle()
+
+ // colored cubes with viewport
+ sgl.viewport(x0, y1, ww, hh, true)
+ draw_cubes(app)
+
+ // textured cubed with viewport
+ sgl.viewport(0, int(dh / 5), dw, int(dh * ratio), true)
+ draw_texture_cubes(app)
+
+ // textured field of cubes with viewport
+ sgl.viewport(0, int(dh / 5), dw, int(dh * ratio), true)
+ cube_field(app)
+
+ app.frame_count++
+
+ app.gg.end()
+}
+
+/******************************************************************************
+*
+* Init / Cleanup
+*
+******************************************************************************/
+fn my_init(mut app App) {
+ app.init_flag = true
+
+ // set max vertices,
+ // for a large number of the same type of object it is better use the instances!!
+ desc := sapp.create_desc()
+ gfx.setup(&desc)
+ sgl_desc := C.sgl_desc_t{
+ max_vertices: 50 * 65536
+ }
+ sgl.setup(&sgl_desc)
+
+ // 3d pipeline
+ mut pipdesc := C.sg_pipeline_desc{}
+ unsafe { C.memset(&pipdesc, 0, sizeof(pipdesc)) }
+
+ color_state := C.sg_color_state{
+ blend: C.sg_blend_state{
+ enabled: true
+ src_factor_rgb: gfx.BlendFactor(C.SG_BLENDFACTOR_SRC_ALPHA)
+ dst_factor_rgb: gfx.BlendFactor(C.SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA)
+ }
+ }
+ pipdesc.colors[0] = color_state
+
+ pipdesc.depth = C.sg_depth_state{
+ write_enabled: true
+ compare: gfx.CompareFunc(C.SG_COMPAREFUNC_LESS_EQUAL)
+ }
+ pipdesc.cull_mode = .back
+ app.pip_3d = sgl.make_pipeline(&pipdesc)
+
+ // create chessboard texture 256*256 RGBA
+ w := 256
+ h := 256
+ sz := w * h * 4
+ tmp_txt := unsafe { malloc(sz) }
+ mut i := 0
+ for i < sz {
+ unsafe {
+ y := (i >> 0x8) >> 5 // 8 cell
+ x := (i & 0xFF) >> 5 // 8 cell
+ // upper left corner
+ if x == 0 && y == 0 {
+ tmp_txt[i] = byte(0xFF)
+ tmp_txt[i + 1] = byte(0)
+ tmp_txt[i + 2] = byte(0)
+ tmp_txt[i + 3] = byte(0xFF)
+ }
+ // low right corner
+ else if x == 7 && y == 7 {
+ tmp_txt[i] = byte(0)
+ tmp_txt[i + 1] = byte(0xFF)
+ tmp_txt[i + 2] = byte(0)
+ tmp_txt[i + 3] = byte(0xFF)
+ } else {
+ col := if ((x + y) & 1) == 1 { 0xFF } else { 0 }
+ tmp_txt[i] = byte(col) // red
+ tmp_txt[i + 1] = byte(col) // green
+ tmp_txt[i + 2] = byte(col) // blue
+ tmp_txt[i + 3] = byte(0xFF) // alpha
+ }
+ i += 4
+ }
+ }
+ unsafe {
+ app.texture = create_texture(w, h, tmp_txt)
+ free(tmp_txt)
+ }
+}
+
+fn cleanup(mut app App) {
+ gfx.shutdown()
+}
+
+/******************************************************************************
+*
+* event
+*
+******************************************************************************/
+fn my_event_manager(mut ev gg.Event, mut app App) {
+ if ev.typ == .mouse_move {
+ app.mouse_x = int(ev.mouse_x)
+ app.mouse_y = int(ev.mouse_y)
+ }
+ if ev.typ == .touches_began || ev.typ == .touches_moved {
+ if ev.num_touches > 0 {
+ touch_point := ev.touches[0]
+ app.mouse_x = int(touch_point.pos_x)
+ app.mouse_y = int(touch_point.pos_y)
+ }
+ }
+}
+
+/******************************************************************************
+*
+* Main
+*
+******************************************************************************/
+// is needed for easier diagnostics on windows
+[console]
+fn main() {
+ // App init
+ mut app := &App{
+ gg: 0
+ }
+
+ app.gg = gg.new_context(
+ width: win_width
+ height: win_height
+ create_window: true
+ window_title: '3D Cube Demo'
+ user_data: app
+ bg_color: bg_color
+ frame_fn: frame
+ init_fn: my_init
+ cleanup_fn: cleanup
+ event_fn: my_event_manager
+ )
+
+ app.gg.run()
+}