gate groundwork
authorhgn <hgodden00@gmail.com>
Fri, 17 Jun 2022 02:44:19 +0000 (03:44 +0100)
committerhgn <hgodden00@gmail.com>
Fri, 17 Jun 2022 02:44:19 +0000 (03:44 +0100)
blender_export.py
gate.h
main.c
model.h

index 38de9298eddda445e833e13aec2d93aeefe84b5e..3e7567d8b09734f4616c976a4f585a5c42dde575 100644 (file)
@@ -6,7 +6,8 @@ class model(Structure):
    _fields_ = [("identifier",c_uint32),
                ("vertex_count",c_uint32),
                ("indice_count",c_uint32),
-               ("layer_count",c_uint32)]
+               ("layer_count",c_uint32),
+               ("marker_count",c_uint32)]
 
 class sdf_primative(Structure):
    _pack_ = 1
@@ -25,6 +26,13 @@ class submodel(Structure):
                ("sdf_type",c_int32),
                ("name",c_char*32)]
 
+class marker(Structure):
+   _pack_ = 1
+   _fields_ = [("co",c_float*3),
+               ( "q",c_float*4),
+               ( "s",c_float*3),
+               ("name",c_char*32)]
+
 class model_vert(Structure):
    _pack_ = 1
    _fields_ = [("co",c_float*3),
@@ -32,10 +40,93 @@ class model_vert(Structure):
                ("colour",c_float*4),
                ("uv",c_float*2)]
 
-def fixed_string(dest,string):
-   return
-   for i in range(len(string)):
-      dest[i] = string[i]
+def v4_dot( a, b ):
+       return a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*a[3]
+
+def v4_length( a ):
+   return math.sqrt( v4_dot(a,a) )
+
+def m3x3_mul( a, b, d ):
+   a00 = a[0][0]
+   a01 = a[0][1]
+   a02 = a[0][2]
+   a10 = a[1][0]
+   a11 = a[1][1]
+   a12 = a[1][2]
+   a20 = a[2][0]
+   a21 = a[2][1]
+   a22 = a[2][2]
+   b00 = b[0][0]
+   b01 = b[0][1]
+   b02 = b[0][2]
+   b10 = b[1][0]
+   b11 = b[1][1]
+   b12 = b[1][2]
+   b20 = b[2][0]
+   b21 = b[2][1]
+   b22 = b[2][2]
+   d[0][0] = a00*b00 + a10*b01 + a20*b02
+   d[0][1] = a01*b00 + a11*b01 + a21*b02
+   d[0][2] = a02*b00 + a12*b01 + a22*b02
+   d[1][0] = a00*b10 + a10*b11 + a20*b12
+   d[1][1] = a01*b10 + a11*b11 + a21*b12
+   d[1][2] = a02*b10 + a12*b11 + a22*b12
+   d[2][0] = a00*b20 + a10*b21 + a20*b22
+   d[2][1] = a01*b20 + a11*b21 + a21*b22
+   d[2][2] = a02*b20 + a12*b21 + a22*b22
+
+def q_m3x3( q, d ):
+   l = v4_length(q)
+   s = 2.0 if l > 0.0 else 0.0
+   xx = s*q[0]*q[0]
+   xy = s*q[0]*q[1]
+   wx = s*q[3]*q[0]
+   yy = s*q[1]*q[1]
+   yz = s*q[1]*q[2]
+   wy = s*q[3]*q[1]
+   zz = s*q[2]*q[2]
+   xz = s*q[0]*q[2]
+   wz = s*q[3]*q[2]
+   d[0][0] = 1.0 - yy - zz
+   d[1][1] = 1.0 - xx - zz
+   d[2][2] = 1.0 - xx - yy
+   d[0][1] = xy + wz
+   d[1][2] = yz + wx
+   d[2][0] = xz + wy
+   d[1][0] = xy - wz
+   d[2][1] = yz - wx
+   d[0][2] = xz - wy
+
+def m3x3_q( m, q ):
+   diag = m[0][0] + m[1][1] + m[2][2]
+   if diag >= 0.0:
+      r    = math.sqrt( 1.0 + diag )
+      rinv = 0.5 / r
+      q[0] = rinv * (m[1][2] - m[2][1])
+      q[1] = rinv * (m[2][0] - m[0][2])
+      q[2] = rinv * (m[0][1] - m[1][0])
+      q[3] = r    * 0.5
+   elif m[0][0] >= m[1][1] and m[0][0] >= m[2][2]:
+      r    = math.sqrt( 1.0 - m[1][1] - m[2][2] + m[0][0] )
+      rinv = 0.5 / r
+      q[0] = r    * 0.5
+      q[1] = rinv * (m[0][1] + m[1][0])
+      q[2] = rinv * (m[0][2] + m[2][0])
+      q[3] = rinv * (m[1][2] - m[2][1])
+   elif m[1][1] >= m[2][2]:
+      r    = math.sqrt( 1.0 - m[0][0] - m[2][2] + m[1][1] )
+      rinv = 0.5 / r
+      q[0] = rinv * (m[0][1] + m[1][0])
+      q[1] = r    * 0.5
+      q[2] = rinv * (m[1][2] + m[2][1])
+      q[3] = rinv * (m[2][0] - m[0][2])
+   else:
+      r    = math.sqrt( 1.0 - m[0][0] - m[1][1] + m[2][2] )
+      rinv = 0.5 / r
+      q[0] = rinv * (m[0][2] + m[2][0])
+      q[1] = rinv * (m[1][2] + m[2][1])
+      q[2] = r    * 0.5
+      q[3] = rinv * (m[0][1] - m[1][0])
 
 def write_model(name):
    fp = open(F"/home/harry/Documents/carve/models/{name}.mdl", "wb")
@@ -48,11 +139,33 @@ def write_model(name):
    header.layer_count = 0
 
    layers = []
+   markers = []
    vertex_buffer = []
    indice_buffer = []
 
    for obj in collection.objects:
-      if obj.type == 'MESH':
+      if obj.type == 'EMPTY':
+         mk = marker()
+         mk.co[0] =  obj.location[0]
+         mk.co[1] =  obj.location[2]
+         mk.co[2] = -obj.location[1]
+         
+         # Convert rotation quat to our space type
+         quat = obj.matrix_world.to_quaternion()
+         mk.q[0] =  quat[1]
+         mk.q[1] =  quat[3]
+         mk.q[2] = -quat[2]
+         mk.q[3] =  quat[0]
+         
+         mk.s[0] = obj.scale[0]
+         mk.s[1] = obj.scale[2]
+         mk.s[2] = obj.scale[1]
+         mk.name = obj.name.encode('utf-8')
+
+         markers += [mk]
+         header.marker_count += 1
+
+      elif obj.type == 'MESH':
          dgraph = bpy.context.evaluated_depsgraph_get()
          data = obj.evaluated_get(dgraph).data
          data.calc_loop_triangles()
@@ -134,6 +247,8 @@ def write_model(name):
    fp.write( bytearray( header ) )
    for l in layers:
       fp.write( bytearray(l) )
+   for m in markers:
+      fp.write( bytearray(m) )
    for v in vertex_buffer:
       fp.write( bytearray(v) )
    for i in indice_buffer:
diff --git a/gate.h b/gate.h
index 541cec8c627d2e9cb62f6e9e9dad2c5c87717806..c0bdbaab9ce8b0b8f1705582a43f6bcb25e079f2 100644 (file)
--- a/gate.h
+++ b/gate.h
@@ -1,4 +1,308 @@
 #ifndef GATE_H
 #define GATE_H
 
+#include "vg/vg.h"
+
+static const float k_gatesize = 4.0f;
+
+SHADER_DEFINE( shader_gate,
+   "layout (location=0) in vec3 a_co;"
+   "uniform mat4 uPv;"
+   "uniform mat4x3 uMdl;"
+   ""
+       "void main()"
+       "{"
+               "gl_Position = uPv * vec4(uMdl * vec4( a_co, 1.0 ),1.0);"
+       "}",
+
+   /* Fragment */
+       "out vec4 FragColor;"
+       ""
+   "uniform sampler2D uTexMain;"
+   "uniform vec2 uInvRes;"
+   ""
+       "void main()"
+       "{"
+      "vec2 uv = gl_FragCoord.xy*uInvRes;"
+      "FragColor = texture( uTexMain, uv );"
+       "}"
+       ,
+       UNIFORMS({ "uPv", "uMdl", "uTexMain", "uInvRes" })
+)
+
+typedef struct teleport_gate teleport_gate;
+
+static struct
+{
+   GLuint fb, rgb, rb, vao, vbo;
+}
+grender;
+
+struct teleport_gate
+{ 
+   v3f co;
+   v4f q;
+
+   m4x3f to_world, to_local;
+   teleport_gate *other;
+};
+
+static void gate_transform_update( teleport_gate *gate )
+{
+   q_m3x3( gate->q, gate->to_world );
+   v3_copy( gate->co, gate->to_world[3] );
+   
+   m4x3_invert_affine( gate->to_world, gate->to_local );
+}
+
+static void gate_register(void)
+{
+   SHADER_INIT( shader_gate );
+}
+
+static void gate_init(void)
+{
+   glGenFramebuffers( 1, &grender.fb );
+   glBindFramebuffer( GL_FRAMEBUFFER, grender.fb );
+
+   glGenTextures( 1, &grender.rgb );
+   glBindTexture( GL_TEXTURE_2D, grender.rgb );
+   glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vg_window_x, vg_window_y, 
+         0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+
+   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+   glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 
+         GL_TEXTURE_2D, grender.rgb, 0);
+
+   /* TODO: Check for DEPTH32f availiblity and use if possible */
+
+   glGenRenderbuffers( 1, &grender.rb );
+   glBindRenderbuffer( GL_RENDERBUFFER, grender.rb );
+   glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 
+         vg_window_x, vg_window_y );
+
+   glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
+         GL_RENDERBUFFER, grender.rb );
+
+   {
+      float ksz = k_gatesize;
+      float quad[] = { -ksz,-ksz,0.0f,  ksz, ksz,0.0f, -ksz, ksz,0.0f,
+                       -ksz,-ksz,0.0f,  ksz,-ksz,0.0f,  ksz, ksz,0.0f,
+                       -ksz,-ksz,0.0f, -ksz, ksz,0.0f,  ksz, ksz,0.0f, 
+                       -ksz,-ksz,0.0f,  ksz, ksz,0.0f,  ksz,-ksz,0.0f };
+
+      glGenVertexArrays( 1, &grender.vao );
+      glGenBuffers( 1, &grender.vbo );
+      glBindVertexArray( grender.vao );
+      glBindBuffer( GL_ARRAY_BUFFER, grender.vbo );
+      glBufferData( GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW );
+      glBindVertexArray( grender.vao );
+      glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 
+            sizeof(float)*3, (void*)0 );
+      glEnableVertexAttribArray( 0 );
+      VG_CHECK_GL();
+   }
+}
+
+static void render_world(m4x4f pv);
+
+/* 
+ * http://www.terathon.com/lengyel/Lengyel-Oblique.pdf 
+ */
+static void plane_clip_projection( m4x4f mat, v4f plane )
+{
+   v4f c = 
+   {
+      (vg_signf(plane[0]) + mat[2][0]) / mat[0][0],
+      (vg_signf(plane[1]) + mat[2][1]) / mat[1][1],
+      -1.0f,
+      (1.0f + mat[2][2]) / mat[3][2]
+   };
+
+   v4_muls( plane, 2.0f / v4_dot(plane,c), c );
+
+   mat[0][2] = c[0];
+   mat[1][2] = c[1];
+   mat[2][2] = c[2] + 1.0f;
+   mat[3][2] = c[3];
+}
+
+static void render_gate( teleport_gate *gate, m4x3f camera, float fov )
+{
+   m4x3f transport;
+
+   m4x3_mul( gate->other->to_world, gate->to_local, transport );
+   
+   v3f a,b,c,d;
+   
+   float ksz = k_gatesize;
+   m4x3_mulv( gate->to_world, (v3f){-ksz,-ksz,0.0f}, a );
+   m4x3_mulv( gate->to_world, (v3f){ ksz,-ksz,0.0f}, b );
+   m4x3_mulv( gate->to_world, (v3f){ ksz, ksz,0.0f}, c );
+   m4x3_mulv( gate->to_world, (v3f){-ksz, ksz,0.0f}, d );
+
+   vg_line( a,b, 0xffffa000 );
+   vg_line( b,c, 0xffffa000 );
+   vg_line( c,d, 0xffffa000 );
+   vg_line( d,a, 0xffffa000 );
+
+   vg_line( gate->co, gate->other->co, 0xffffffff );
+
+   m4x3f cam_new;
+   m4x3_mul( transport, camera, cam_new );
+   
+   vg_line_pt3( cam_new[3], 0.3f, 0xff00ff00 );
+
+   glBindFramebuffer( GL_FRAMEBUFFER, grender.fb );
+   glClearColor( 0.0f, 0.0f, 1.0f, 1.0f );
+   glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
+
+
+   m4x3f inverse;
+   m4x3_invert_affine( cam_new, inverse );
+
+   m4x4f view;
+   m4x3_expand( inverse, view );
+
+   v4f surface;
+   m3x3_mulv( gate->other->to_world, (v3f){0.0f,0.0f,-1.0f}, surface );
+   surface[3] = v3_dot( surface, gate->other->co );
+
+   m4x4f projection;
+   m4x4_projection( projection,
+         fov,
+         (float)vg_window_x / (float)vg_window_y, 
+         0.01f, 900.0f );
+
+#if 0 /* For debugging frustum */
+   {
+      m4x4f devm;
+      m4x4_mul( projection, view, devm );
+      m4x4_inv( devm, devm );
+      
+      v4f corners[] =
+      {
+         {-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}
+      };
+
+      for( int i=0; i<vg_list_size(corners); i++ )
+      {
+         m4x4_mulv( devm, corners[i], corners[i] );
+         v3_muls( corners[i], 1.0f/corners[i][3], corners[i] );
+      }
+
+      vg_line( corners[0], corners[1], 0xffffffff );
+      vg_line( corners[1], corners[2], 0xffffffff );
+      vg_line( corners[2], corners[3], 0xffffffff );
+      vg_line( corners[3], corners[0], 0xffffffff );
+      vg_line( corners[4], corners[5], 0xffffffff );
+      vg_line( corners[5], corners[6], 0xffffffff );
+      vg_line( corners[6], corners[7], 0xffffffff );
+      vg_line( corners[7], corners[4], 0xffffffff );
+      vg_line( corners[0], corners[4], 0xffffffff );
+      vg_line( corners[1], corners[5], 0xffffffff );
+      vg_line( corners[2], corners[6], 0xffffffff );
+      vg_line( corners[3], corners[7], 0xffffffff );
+      
+      v3f clipped[4];
+      for( int i=0; i<4; i++ )
+      {
+         v3f v0, c, delta, p0;
+         v3_sub( corners[4+i],corners[0+i], v0 );
+         v3_normalize(v0);
+
+         v3_muls( surface, surface[3], c );
+         v3_sub( c, corners[0+i], delta );
+
+         float t = v3_dot(delta, surface) / v3_dot(surface, v0);
+         v3_muladds( corners[0+i], v0, t, clipped[i] );
+      }
+
+      vg_line( clipped[0], clipped[1], 0xff0000ff );
+      vg_line( clipped[1], clipped[2], 0xff0000ff );
+      vg_line( clipped[2], clipped[3], 0xff0000ff );
+      vg_line( clipped[3], clipped[0], 0xff0000ff );
+
+      m4x3_mulv( gate->other->to_world, (v3f){-2.0f,-2.0f,0.0f}, a );
+      m4x3_mulv( gate->other->to_world, (v3f){ 2.0f,-2.0f,0.0f}, b );
+      m4x3_mulv( gate->other->to_world, (v3f){ 2.0f, 2.0f,0.0f}, c );
+      m4x3_mulv( gate->other->to_world, (v3f){-2.0f, 2.0f,0.0f}, d );
+
+      vg_line( clipped[0], a, 0xff0000ff );
+      vg_line( clipped[1], b, 0xff0000ff );
+      vg_line( clipped[2], c, 0xff0000ff );
+      vg_line( clipped[3], d, 0xff0000ff );
+   }
+#endif
+   
+   m4x3_mulp( inverse, surface, surface );
+   surface[3] = -fabsf(surface[3]);
+   plane_clip_projection( projection, surface );
+
+   m4x4_mul( projection, view, projection );
+   
+   render_world( projection );
+   glBindFramebuffer( GL_FRAMEBUFFER, 0 );
+
+   SHADER_USE( shader_gate );
+
+       glUniformMatrix4fv( SHADER_UNIFORM( shader_gate, "uPv" ), 
+         1, GL_FALSE, (float *)vg_pv );
+       glUniformMatrix4x3fv( SHADER_UNIFORM( shader_gate, "uMdl" ), 
+         1, GL_FALSE, (float *)gate->to_world );
+
+   glActiveTexture( GL_TEXTURE0 );
+   glBindTexture( GL_TEXTURE_2D, grender.rgb );
+   glUniform1i( SHADER_UNIFORM( shader_gate, "uTexMain"), 0 );
+   glUniform2f( SHADER_UNIFORM( shader_gate, "uInvRes"),
+         1.0f / (float)vg_window_x,
+         1.0f / (float)vg_window_y );
+
+   glBindVertexArray( grender.vao );
+   glDrawArrays( GL_TRIANGLES, 0, 12 );
+}
+
+static int gate_intersect( teleport_gate *gate, v3f pos, v3f last )
+{
+   v4f surface;
+   m3x3_mulv( gate->to_world, (v3f){0.0f,0.0f,-1.0f}, surface );
+   surface[3] = v3_dot( surface, gate->co );
+
+   v3f v0, c, delta, p0;
+   v3_sub( pos, last, v0 );
+   float l = v3_length( v0 );
+   v3_divs( v0, l, v0 );
+
+   v3_muls( surface, surface[3], c );
+   v3_sub( c, last, delta );
+
+   float d = v3_dot(surface, v0);
+
+   if( fabsf(d) > 0.00001f )
+   {
+      float t = v3_dot(delta, surface) / d;
+      if( t >= 0.0f && t <= l )
+      {
+         v3f local, rel;
+         v3_muladds( last, v0, t, local );
+         v3_sub( gate->co, local, rel );
+
+         v3f vup, vside;
+         m3x3_mulv( gate->to_world, (v3f){0.0f,1.0f,0.0f}, vup );
+         m3x3_mulv( gate->to_world, (v3f){1.0f,0.0f,0.0f}, vside );
+
+         v2f xy = { v3_dot( rel, vside ), v3_dot( rel, vup ) };
+
+         if( fabsf(xy[0]) <= k_gatesize && fabsf(xy[1]) <= k_gatesize )
+         {
+            return 1;
+         }
+      }
+   }
+
+   return 0;
+}
+
 #endif
diff --git a/main.c b/main.c
index bdd819739554e2c35c8ed8b97b30f3e96c832750..9b7bef66b0ad491410818f5be00ce919e135f2b1 100644 (file)
--- a/main.c
+++ b/main.c
@@ -69,6 +69,7 @@ static int replay_buffer_frame = 0;
 #include "terrain.h"
 #include "ragdoll.h"
 #include "rigidbody.h"
+#include "gate.h"
 
 int main( int argc, char *argv[] )
 { 
@@ -80,7 +81,7 @@ m4x3f world_matrix;
 static struct gplayer
 {
    /* Physics */
-   v3f co, v, a;
+   v3f co, v, a, v_last;
    v4f rot;
    float vswitch, slip, slip_last,
          reverse;
@@ -139,6 +140,15 @@ rigidbody mrs_box = {
    .bbx = {{ -0.5f, -0.25f, -0.25f }, { 0.5f, 0.25f, 0.25f }}
 };
 
+teleport_gate gate_a = {
+   .co = { 0.0f, -3.0f, -15.0f },
+   .q = { 0.0f, 0.0f, 0.0f, 1.0f }
+}, 
+gate_b = {
+   .co = { -8.0f, -3.0f, -17.0f },
+   .q = { 0.0f, 0.0f, 0.0f, 1.0f }
+};
+
 static void player_transform_update(void)
 {
    q_normalize( player.rot );
@@ -188,6 +198,7 @@ static int playermodel( int argc, char const *argv[] )
 void vg_register(void)
 {
    scene_register();
+   gate_register();
    character_shader_register();
    SHADER_INIT( shader_blit );
 }
@@ -297,7 +308,24 @@ void vg_start(void)
          (v3f){0.0f,0.0f,0.0f}, 0.0f, 1.0f );
    scene_copy_slice( &world.geo, &world.sm_terrain );
 
-   v3_copy( submodel_get( mworld, "tutorial" )->pivot, world.tutorial );
+   v3_copy( model_marker_get( mworld, "mp_dev_tutorial" )->co, world.tutorial );
+
+
+   /* GATE DEV */
+   {
+      model_marker *ga = model_marker_get(mworld,"gate_a"),
+                   *gb = model_marker_get(mworld,"gate_a_recv");
+
+      v3_copy( ga->co, gate_a.co );
+      v3_copy( gb->co, gate_b.co );
+      v4_copy( ga->q, gate_a.q );
+      v4_copy( gb->q, gate_b.q );
+      gate_a.other = &gate_b;
+      gate_b.other = &gate_a;
+
+      gate_transform_update( &gate_a );
+      gate_transform_update( &gate_b );
+   }
 
    free( mworld );
    scene_upload( &world.geo );
@@ -321,13 +349,14 @@ void vg_start(void)
          GL_TEXTURE_2D, 
          render.rgb_background, 0);
 
+   gate_init();
+
    {
       float quad[] = { 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,
                        0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f };
 
       glGenVertexArrays( 1, &render.fsquad.vao );
       glGenBuffers( 1, &render.fsquad.vbo );
-      glGenBuffers( 1, &render.fsquad.ebo );
       glBindVertexArray( render.fsquad.vao );
       glBindBuffer( GL_ARRAY_BUFFER, render.fsquad.vbo );
       glBufferData( GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW );
@@ -424,6 +453,7 @@ static void player_start_air(void)
       v3f pco, pco1, pv;
       v3_copy( player.co, pco );
       v3_copy( player.v, pv );
+      v3_muladds( pco, pv, ktimestep, pco );
 
       /* 
        * Try different 'rotations' of the velocity to find the best possible
@@ -800,7 +830,15 @@ static void player_update(void)
    player.joy_l[0] = vg_signf(horizontal) * powf( horizontal, 2.0f );
    player.joy_l[1] = vg_signf(vertical) * powf( vertical, 2.0f );
 
+   if( player.in_air )
+      player_physics_air();
+
+   if( !player.in_air )
+      player_physics_ground();
+   
    /* Integrate velocity */
+   v3f prevco;
+   v3_copy( player.co, prevco );
    if( sv_phys )
    {
       apply_gravity( player.v, ktimestep );
@@ -825,14 +863,23 @@ static void player_update(void)
 
    player.iY = 0.0f; /* temp */
 
-   if( player.in_air )
-      player_physics_air();
+   /* GATE COLLISION */
+   if( gate_intersect( &gate_a, player.co, prevco ) )
+   {
+      teleport_gate *gate = &gate_a;
 
-   if( !player.in_air )
-      player_physics_ground();
-   
-   /* Camera and character */
+      m4x3f transport;
+      m4x3_mul( gate->other->to_world, gate->to_local, transport );
+      m4x3_mulv( transport, player.co, player.co );
+      m3x3_mulv( transport, player.v, player.v );
+      m3x3_mulv( transport, player.v_last, player.v_last );
 
+      v4f transport_rotation;
+      m3x3_q( transport, transport_rotation );
+      q_mul( transport_rotation, player.rot, player.rot );
+   }
+
+   /* Camera and character */
    player_transform_update();
    q_normalize(player.rot);
    player_animate();
@@ -886,11 +933,10 @@ void vg_update(void)
 static void player_animate(void)
 {
    /* Camera position */
-   static v3f last_vel = { 0.0f, 0.0f, 0.0f };
    static v3f momentum, bob;
 
-   v3_sub( player.v, last_vel, player.a );
-   v3_copy( player.v, last_vel );
+   v3_sub( player.v, player.v_last, player.a );
+   v3_copy( player.v, player.v_last );
 
    v3_add( momentum, player.a, momentum );
    v3_lerp( momentum, (v3f){0.0f,0.0f,0.0f}, 0.1f, momentum );
@@ -1103,6 +1149,27 @@ static void vg_framebuffer_resize( int w, int h )
          GL_RGB, GL_UNSIGNED_BYTE, NULL );
 }
 
+static void render_world( m4x4f projection )
+{
+   SHADER_USE(shader_standard_lit);
+
+   m4x3f identity_matrix;
+   m4x3_identity( identity_matrix );
+
+       glUniformMatrix4fv( SHADER_UNIFORM( shader_standard_lit, "uPv" ), 
+         1, GL_FALSE, (float *)projection );
+       glUniformMatrix4x3fv( SHADER_UNIFORM( shader_standard_lit, "uMdl" ), 
+         1, GL_FALSE, (float *)identity_matrix );
+
+   vg_tex2d_bind( &tex_grid, 0 );
+   glUniform1i( SHADER_UNIFORM( shader_standard_lit, "uTexMain" ), 0 );
+   glUniform4f( SHADER_UNIFORM(shader_standard_lit,"uColour"), 
+         0.4f,0.4f,0.4f,1.0f );
+
+   scene_bind( &world.geo );
+   scene_draw( &world.geo );
+}
+
 void vg_render(void) 
 {
    glBindFramebuffer( GL_FRAMEBUFFER, 0 );
@@ -1183,10 +1250,11 @@ void vg_render(void)
    
    m4x4f world_4x4;
    m4x3_expand( world_matrix, world_4x4 );
-   m4x4_projection( vg_pv, 
-         freecam? 60.0f: 120.0f,
-         (float)vg_window_x / (float)vg_window_y, 
+
+   float fov = freecam? 60.0f: 120.0f;
+   m4x4_projection( vg_pv,  fov, (float)vg_window_x / (float)vg_window_y, 
          0.01f, 1000.0f );
+
    m4x4_mul( vg_pv, world_4x4, vg_pv );
 
    vg_line( (v3f){ 0.0f, 0.0f, 0.0f }, (v3f){ 1.0f, 0.0f, 0.0f }, 0xffff0000 );
@@ -1236,6 +1304,10 @@ void vg_render(void)
    }
 #endif
 
+   m4x3f cam_transform;
+   m4x3_invert_affine( world_matrix, cam_transform );
+   render_gate( &gate_a, cam_transform, fov );
+
 
    
    /* Copy the RGB of what we have into the background buffer */
diff --git a/model.h b/model.h
index 467ad989bffab99637ea0e1e00db7a4ed7aa7bce..9788dc1446c080aaf15f71a00beee5fb1b163c8d 100644 (file)
--- a/model.h
+++ b/model.h
@@ -7,6 +7,7 @@ typedef struct model model;
 typedef struct glmesh glmesh;
 typedef struct submodel submodel;
 typedef struct model_vert model_vert;
+typedef struct model_marker model_marker;
 typedef struct sdf_primative sdf_primative;
 typedef enum esdf_type esdf_type;
 
@@ -17,7 +18,8 @@ struct model
 
    u32 vertex_count,
        indice_count,
-       layer_count;
+       layer_count,
+       marker_count;
 };
 
 struct sdf_primative
@@ -53,6 +55,14 @@ struct submodel
    char name[32];
 };
 
+struct model_marker
+{
+   v3f co;
+   v4f q;
+   v3f s;
+   char name[32];
+};
+
 struct model_vert
 {
    v3f co,
@@ -130,15 +140,21 @@ static void mesh_draw( glmesh *mesh )
 
 /*
  * Helper functions for file offsets
+ * TODO: Revise this
  */
 static submodel *model_get_submodel( model *mdl, int id )
 {
    return ((submodel*)(mdl+1)) + id;
 }
 
+static model_marker *model_get_marker( model *mdl, int id )
+{
+   return ((model_marker*)model_get_submodel(mdl,mdl->layer_count)) + id;
+}
+
 static model_vert *model_vertex_base( model *mdl )
 {
-   return (model_vert *)model_get_submodel( mdl, mdl->layer_count );
+   return (model_vert *)model_get_marker( mdl, mdl->marker_count );
 }
 
 static u32 *model_indice_base( model *mdl )
@@ -169,6 +185,19 @@ static submodel *submodel_get( model *mdl, const char *name )
    return NULL;
 }
 
+static model_marker *model_marker_get( model *mdl, const char *name )
+{
+   for( int i=0; i<mdl->marker_count; i++ )
+   {
+      model_marker *mk = model_get_marker( mdl,i );
+
+      if( !strcmp( mk->name, name ) )
+         return mk;
+   }
+   
+   return NULL;
+}
+
 static void submodel_draw( submodel *sm )
 {
    mesh_drawn( sm->indice_start, sm->indice_count );