From 51a9d6b9321b951b79dff0d52a82116c678ad8aa Mon Sep 17 00:00:00 2001 From: hgn Date: Fri, 17 Jun 2022 03:44:19 +0100 Subject: [PATCH] gate groundwork --- blender_export.py | 127 ++++++++++++++++++- gate.h | 304 ++++++++++++++++++++++++++++++++++++++++++++++ main.c | 102 +++++++++++++--- model.h | 33 ++++- 4 files changed, 543 insertions(+), 23 deletions(-) diff --git a/blender_export.py b/blender_export.py index 38de929..3e7567d 100644 --- a/blender_export.py +++ b/blender_export.py @@ -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 541cec8..c0bdbaa 100644 --- 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; iother->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 bdd8197..9b7bef6 100644 --- 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 467ad98..9788dc1 100644 --- 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; imarker_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 ); -- 2.25.1