From: hgn Date: Fri, 19 May 2023 21:06:07 +0000 (+0100) Subject: point maps (wip) X-Git-Url: https://harrygodden.com/git/?a=commitdiff_plain;h=0310bab3c018e23f5516c3e3c3653b844a8106ed;p=carveJwlIkooP6JGAAIwe30JlM.git point maps (wip) --- diff --git a/blender_export.py b/blender_export.py index cc51987..8c1eaac 100644 --- a/blender_export.py +++ b/blender_export.py @@ -355,10 +355,16 @@ class ent_skateshop_boards(Structure): ("id_info",c_uint32), ("id_rack",c_uint32)] #} +class ent_skateshop_worlds(Structure): +#{ + _fields_ = [("id_display",c_uint32), + ("id_info",c_uint32)] +#} class ent_skateshop_anon_union(Union): #{ _fields_ = [("boards",ent_skateshop_boards), - ("character",ent_skateshop_characters)] + ("character",ent_skateshop_characters), + ("worlds",ent_skateshop_worlds)] #} class ent_skateshop(Structure): #{ @@ -697,6 +703,7 @@ def sr_compile_material( mat ): if mat.SR_data.skate_surface: flags |= 0x1 if mat.SR_data.grow_grass: flags |= 0x4 if mat.SR_data.grind_surface: flags |= 0x8 + if mat.SR_data.preview_visibile: flags |= 0x40 #} if mat.SR_data.shader == 'invisible': flags |= 0x10 if mat.SR_data.shader == 'boundary': flags |= (0x10|0x20) @@ -1694,6 +1701,11 @@ def sr_compile( collection ): charshop.id_display = sr_entity_id( obj_data.mark_display ) charshop.id_info = sr_entity_id( obj_data.mark_info ) #} + elif skateshop.type == 2:#{ + worldshop = skateshop._anonymous_union.worlds + worldshop.id_display = sr_entity_id( obj_data.mark_display ) + worldshop.id_info = sr_entity_id( obj_data.mark_info ) + #} skateshop.id_camera = sr_entity_id( obj_data.cam ) compile_obj_transform( obj, skateshop.transform ) sr_ent_push(skateshop) @@ -2226,6 +2238,7 @@ class SR_MATERIAL_PANEL(bpy.types.Panel): row.prop( active_mat.SR_data, "skate_surface" ) row.prop( active_mat.SR_data, "grind_surface" ) row.prop( active_mat.SR_data, "grow_grass" ) + row.prop( active_mat.SR_data, "preview_visibile" ) #} #} @@ -2818,7 +2831,8 @@ class SR_OBJECT_ENT_SKATESHOP(bpy.types.PropertyGroup): #{ tipo: bpy.props.EnumProperty( name='Type', items=[('0','boards',''), - ('1','character','')] ) + ('1','character',''), + ('2','world','')] ) mark_rack: bpy.props.PointerProperty( \ type=bpy.types.Object, name="Board Rack", \ poll=lambda self,obj: sr_filter_ent_type(obj,['ent_marker'])) @@ -3070,6 +3084,11 @@ class SR_MATERIAL_PROPERTIES(bpy.types.PropertyGroup): default=False,\ description = "Spawn grass sprites on this surface?" \ ) + preview_visibile: bpy.props.BoolProperty( \ + name="Preview visibile", \ + default=True,\ + description = "Show this material in preview models?" \ + ) blend_offset: bpy.props.FloatVectorProperty( \ name="Blend Offset", \ size=2, \ @@ -3942,6 +3961,15 @@ def cv_draw(): info_cu = Vector((1.2,0.01,0.3))*0.5 info_co = Vector((0.0,0.0,0.0))*0.5 #} + elif data.tipo == '2':#{ + rack = None + cc1 = (1.0,0.0,0.0) + cc2 = (1.0,0.5,0.0) + display_cu = Vector((1.0,1.0,0.5))*0.5 + display_co = Vector((0.0,0.0,0.5))*0.5 + info_cu = Vector((1.2,0.01,0.3))*0.5 + info_co = Vector((0.0,0.0,0.0))*0.5 + #} if rack: cv_draw_ucube( rack.matrix_world, cc, rack_cu, rack_co ) diff --git a/build.c b/build.c index ae1ff0f..d5b09c2 100644 --- a/build.c +++ b/build.c @@ -137,6 +137,9 @@ void build_shaders(void) _S( "model_gate", "model_gate.vs", "model_gate_lq.fs" ); _S( "model_font", "model_font.vs", "model_font.fs" ); + /* Pointcloud */ + _S( "point_map", "cloud.vs", "cloud.fs" ); + /* 2D */ _S( "blit", "blit.vs", "blit.fs" ); _S( "blitblur", "blit.vs", "blitblur.fs" ); diff --git a/ent_skateshop.c b/ent_skateshop.c index 9438c00..b47dacf 100644 --- a/ent_skateshop.c +++ b/ent_skateshop.c @@ -9,6 +9,7 @@ #include "player.h" #include "gui.h" #include "menu.h" +#include "pointcloud.h" /* * Checks string equality but does a hash check first @@ -474,7 +475,8 @@ VG_STATIC void global_skateshop_preupdate(void) player_vector_angles( localplayer.cam_override_angles, dir, 1.0f, 0.0f ); v3f lookat; - if( shop->type == k_skateshop_type_boardshop ){ + if( shop->type == k_skateshop_type_boardshop || + shop->type == k_skateshop_type_worldshop ){ ent_marker *display = mdl_arritm( &world->ent_marker, mdl_entity_id_id(shop->boards.id_display) ); @@ -570,6 +572,25 @@ VG_STATIC void global_skateshop_preupdate(void) global_skateshop_exit(); } } + else if( shop->type == k_skateshop_type_worldshop ){ + gui_helper_action( axis_display_string( k_sraxis_mbrowse_h ), "browse" ); + + v2f input; + joystick_state( k_srjoystick_steer, input ); + pointcloud.control[0] += input[0] * vg.time_delta; + pointcloud.control[2] += input[1] * vg.time_delta; + + pointcloud.control[0] = vg_clampf( pointcloud.control[0], -10.0f, 10.0f ); + pointcloud.control[2] = vg_clampf( pointcloud.control[2], -10.0f, 10.0f ); + + if( button_press( k_srbind_trick1 ) ){ + pointcloud.control[3] += vg.time_delta*0.2f; + } + if( button_press( k_srbind_trick0 ) ){ + pointcloud.control[3] -= vg.time_delta*0.2f; +} + pointcloud.control[3] = vg_clampf( pointcloud.control[3], 0.001f, 10.0f ); + } else{ vg_fatal_error( "Unknown store (%u)\n", shop->type ); } @@ -717,6 +738,55 @@ VG_STATIC void skateshop_render_charshop(void) { } +VG_STATIC void skateshop_render_worldshop(void) +{ + world_instance *world = get_active_world(); + + m4x3f mmdl; + ent_skateshop *shop = global_skateshop.ptr_ent; + ent_marker *mark_display = mdl_arritm( &world->ent_marker, + mdl_entity_id_id(shop->worlds.id_display)); + mdl_transform_m4x3( &mark_display->transform, mmdl ); + + /* TODO? ... */ + v3f vol; + v3_sub( world->scene_geo.bbx[1], world->scene_geo.bbx[0], vol ); + + v2f rect = { 1.0f, 1.0f }, + map = { vol[0], vol[2] }, + result; + + f32 rp = rect[0] * map[1], + rc = rect[1] * map[0]; + + u32 axis, other; + if( rc > rp ) axis = 0; + else axis = 1; + other = axis ^ 0x1; + + result[axis] = rect[axis]; + result[other] = (rect[axis] * map[other]) / map[axis]; + + m4x3f mlocal, mx; + m4x3_identity( mlocal ); + + mlocal[0][0] = result[0]; + mlocal[2][2] = result[1]; + mlocal[1][1] = (vol[1]/vol[0]) * mlocal[0][0]; + mlocal[3][0] = (rect[0]-result[0])*0.5f - rect[0]*0.5f; /* sea level? */ + mlocal[3][2] = (rect[1]-result[1])*0.5f - rect[1]*0.5f; + m4x3_mul( mmdl, mlocal, mx ); + +#if 1 + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE); + glDisable(GL_DEPTH_TEST); +#endif + pointcloud_render( world, &main_camera, mx ); + glDisable(GL_BLEND); + glEnable(GL_DEPTH_TEST); +} + /* * World: render event */ @@ -732,6 +802,9 @@ VG_STATIC void skateshop_render(void) else if( shop->type == k_skateshop_type_charshop ){ skateshop_render_charshop(); } + else if( shop->type == k_skateshop_type_worldshop ){ + skateshop_render_worldshop(); + } else{ vg_fatal_error( "Unknown store (%u)\n", shop->type ); } diff --git a/entity.h b/entity.h index 867c74c..998557e 100644 --- a/entity.h +++ b/entity.h @@ -220,7 +220,8 @@ struct ent_marker{ enum skateshop_type{ k_skateshop_type_boardshop, - k_skateshop_type_charshop + k_skateshop_type_charshop, + k_skateshop_type_worldshop }; struct ent_skateshop{ @@ -240,6 +241,12 @@ struct ent_skateshop{ id_info; } character; + + struct{ + u32 id_display, + id_info; + } + worlds; }; }; diff --git a/maps_src/mp_mtzero.mdl b/maps_src/mp_mtzero.mdl index 7de53a9..ddd7d6d 100644 Binary files a/maps_src/mp_mtzero.mdl and b/maps_src/mp_mtzero.mdl differ diff --git a/maps_src/mp_spawn.mdl b/maps_src/mp_spawn.mdl index 8e3042a..2c01527 100644 Binary files a/maps_src/mp_spawn.mdl and b/maps_src/mp_spawn.mdl differ diff --git a/model.h b/model.h index 80ab7cb..686a428 100644 --- a/model.h +++ b/model.h @@ -36,7 +36,8 @@ enum material_flag k_material_flag_grow_grass = 0x00000004, k_material_flag_grindable = 0x00000008, k_material_flag_invisible = 0x00000010, - k_material_flag_boundary = 0x00000020 + k_material_flag_boundary = 0x00000020, + k_material_flag_preview_visibile = 0x00000040 }; #pragma pack(push,1) diff --git a/pointcloud.h b/pointcloud.h new file mode 100644 index 0000000..b303973 --- /dev/null +++ b/pointcloud.h @@ -0,0 +1,121 @@ +#ifndef POINTCLOUD_H +#define POINTCLOUD_H + +#include "common.h" +#include "world.h" +#include "shaders/point_map.h" + +#define POINTCLOUD_POINTS 250000 + +struct pointcloud{ + GLuint vao, vbo; + u32 count; + + v4f control; +} +static pointcloud = { .control = {0.0f,0.0f,0.0f,1.0f} }; + +#pragma pack(push,1) +struct pointcloud_vert{ + u16 pos[4]; /* float[ 0 -> 1 ] */ + i8 norm[4]; /* float[ -1 -> 1 ] */ + u8 colour[4]; /* float[ 0 -> 1 ] */ +}; +#pragma pack(pop) + +static void async_pointcloud_sub( void *payload, u32 size ) +{ + + glBindVertexArray( pointcloud.vao ); + glBindBuffer( GL_ARRAY_BUFFER, pointcloud.vbo ); + glBufferSubData( GL_ARRAY_BUFFER, 0, + sizeof(struct pointcloud_vert)*size, payload ); + pointcloud.count = size; +} + +static void async_pointcloud_alloc( void *payload, u32 size ) +{ + glGenVertexArrays( 1, &pointcloud.vao ); + glGenBuffers( 1, &pointcloud.vbo ); + glBindVertexArray( pointcloud.vao ); + + size_t stride = sizeof( struct pointcloud_vert ); + + glBindBuffer( GL_ARRAY_BUFFER, pointcloud.vbo ); + glBufferData( GL_ARRAY_BUFFER, stride * POINTCLOUD_POINTS, + payload, GL_DYNAMIC_DRAW ); + + /* 0: coordinates */ + glVertexAttribPointer( 0, 4, GL_UNSIGNED_SHORT, GL_TRUE, stride, (void*)0 ); + glEnableVertexAttribArray( 0 ); + + /* 1: normal */ + glVertexAttribPointer( 1, 4, GL_BYTE, GL_TRUE, + stride, (void *)offsetof(struct pointcloud_vert, norm) ); + glEnableVertexAttribArray( 1 ); + + /* 2: colour */ + glVertexAttribPointer( 2, 4, GL_UNSIGNED_BYTE, GL_TRUE, + stride, (void *)offsetof(struct pointcloud_vert, colour) ); + glEnableVertexAttribArray( 2 ); + VG_CHECK_GL_ERR(); + pointcloud.count = size; +} + +static void pointcloud_init(void) +{ + vg_info( "Generating random test point cloud\n" ); + + vg_rand_seed( 2000 ); + vg_async_item *call = + vg_async_alloc( sizeof(struct pointcloud_vert)*POINTCLOUD_POINTS ); + struct pointcloud_vert *test_data = call->payload; + call->size = POINTCLOUD_POINTS; + + for( u32 i=0; imtx_prev.pv, upvmprev, upvmprev ); + + shader_point_map_use(); + shader_point_map_uPv( cam->mtx.pv ); + shader_point_map_uPvmPrev( upvmprev ); + shader_point_map_uMdl( model ); + shader_point_map_uCamera( cam->pos ); + shader_point_map_uTime( (v2f){ vg.time, sinf(vg.time) } ); + shader_point_map_uTransform( pointcloud.control ); + + m3x3f mnorm; + m3x3_inv( model, mnorm ); + m3x3_transpose( mnorm, mnorm ); + shader_point_map_uNormMtx( mnorm ); + + glBindVertexArray( pointcloud.vao ); + glEnable( GL_PROGRAM_POINT_SIZE ); + glDrawArrays( GL_POINTS, 0, pointcloud.count ); +} + +#endif /* POINTCLOUD_H */ diff --git a/shaders/cloud.fs b/shaders/cloud.fs new file mode 100644 index 0000000..a7f4802 --- /dev/null +++ b/shaders/cloud.fs @@ -0,0 +1,24 @@ +out vec4 FragColor; + +#include "motion_vectors_fs.glsl" + +uniform vec3 uCamera; + +in vec4 aColour; +in vec3 aNorm; +in vec3 aCo; +in vec3 aWorldCo; + +void main() +{ + vec2 ssuv = gl_FragCoord.xy; + vec3 vDither = vec3( dot( vec2( 171.0, 231.0 ), ssuv) ); + float dither = fract( vDither.g / 71.0 ) - 0.5; + + float diff = length(gl_PointCoord.xy-vec2(0.5)); + if( diff+dither>0.5 ) + discard; + + compute_motion_vectors(); + FragColor = aColour; +} diff --git a/shaders/cloud.vs b/shaders/cloud.vs new file mode 100644 index 0000000..9bac346 --- /dev/null +++ b/shaders/cloud.vs @@ -0,0 +1,61 @@ +layout (location=0) in vec4 a_co; +layout (location=1) in vec4 a_norm; +layout (location=2) in vec4 a_colour; + +#include "motion_vectors_vs.glsl" + +uniform mat4x3 uMdl; +uniform mat3 uNormMtx; +uniform mat4 uPv; +uniform mat4 uPvmPrev; +uniform vec2 uTime; +uniform vec4 uTransform; + +out vec4 aColour; +out vec3 aNorm; +out vec3 aWorldCo; +out vec3 aCo; + +vec2 rand_hash22( vec2 p ) +{ + vec3 p3 = fract(vec3(p.xyx) * 213.8976123); + p3 += dot(p3, p3.yzx+19.19); + return fract(vec2((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y)); +} + +vec3 mapP( vec3 p ) +{ + return p; + float t = max(0.0,uTime.y); + + vec3 lco = p * 20.0; + vec3 grid = vec3(floor(lco.x),lco.y,floor(lco.z));//fract(p); + + return mix(p,grid * (1.0/20.0), t)*vec3(1.0+t,1.0-t,1.0+t); +} + +void main() +{ + vec3 mco = a_co.xyz * uTransform.w + uTransform.xyz; + + + vec3 center = vec3(0.5); + vec3 lco = mapP(mco-center); + mco = lco + center; + + vec3 world_pos0 = uMdl * vec4( mco, 1.0 ); + vec4 vproj0 = uPv * vec4( world_pos0, 1.0 ); + vec4 vproj1 = uPvmPrev * vec4( mco, 1.0 ); + + float t = max(0.0,uTime.y); + float scaler = smoothstep(0.6,0.58,length(lco.xz*vec2(0.7,1.0))); + + vs_motion_out( vproj0, vproj1 ); + + gl_Position = vproj0; + gl_PointSize = (8.0*uTransform.w*scaler) / (gl_Position.z + 0.01); + aWorldCo = world_pos0; + aColour = a_colour*scaler*(0.3+a_co.y)+pow(1.0-a_co.y,16.0); + aCo = mco; + aNorm = uNormMtx * a_norm.xyz; +} diff --git a/shaders/point_map.h b/shaders/point_map.h new file mode 100644 index 0000000..533b0dd --- /dev/null +++ b/shaders/point_map.h @@ -0,0 +1,183 @@ +#ifndef SHADER_point_map_H +#define SHADER_point_map_H +static void shader_point_map_link(void); +static void shader_point_map_register(void); +static struct vg_shader _shader_point_map = { + .name = "point_map", + .link = shader_point_map_link, + .vs = +{ +.orig_file = "shaders/cloud.vs", +.static_src = +"layout (location=0) in vec4 a_co;\n" +"layout (location=1) in vec4 a_norm;\n" +"layout (location=2) in vec4 a_colour;\n" +"\n" +"#line 1 1 \n" +"const float k_motion_lerp_amount = 0.01;\n" +"\n" +"#line 2 0 \n" +"\n" +"out vec3 aMotionVec0;\n" +"out vec3 aMotionVec1;\n" +"\n" +"void vs_motion_out( vec4 vproj0, vec4 vproj1 )\n" +"{\n" +" // This magically solves some artifacting errors!\n" +" //\n" +" vproj1 = vproj0*(1.0-k_motion_lerp_amount) + vproj1*k_motion_lerp_amount;\n" +"\n" +" aMotionVec0 = vec3( vproj0.xy, vproj0.w );\n" +" aMotionVec1 = vec3( vproj1.xy, vproj1.w );\n" +"}\n" +"\n" +"#line 6 0 \n" +"\n" +"uniform mat4x3 uMdl;\n" +"uniform mat3 uNormMtx;\n" +"uniform mat4 uPv;\n" +"uniform mat4 uPvmPrev;\n" +"uniform vec2 uTime;\n" +"uniform vec4 uTransform;\n" +"\n" +"out vec4 aColour;\n" +"out vec3 aNorm;\n" +"out vec3 aWorldCo;\n" +"out vec3 aCo;\n" +"\n" +"vec2 rand_hash22( vec2 p )\n" +"{\n" +" vec3 p3 = fract(vec3(p.xyx) * 213.8976123);\n" +" p3 += dot(p3, p3.yzx+19.19);\n" +" return fract(vec2((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y));\n" +"}\n" +"\n" +"vec3 mapP( vec3 p )\n" +"{\n" +" return p;\n" +" float t = max(0.0,uTime.y);\n" +"\n" +" vec3 lco = p * 20.0;\n" +" vec3 grid = vec3(floor(lco.x),lco.y,floor(lco.z));//fract(p);\n" +"\n" +" return mix(p,grid * (1.0/20.0), t)*vec3(1.0+t,1.0-t,1.0+t);\n" +"}\n" +"\n" +"void main()\n" +"{\n" +" vec3 mco = a_co.xyz * uTransform.w + uTransform.xyz;\n" +"\n" +"\n" +" vec3 center = vec3(0.5);\n" +" vec3 lco = mapP(mco-center);\n" +" mco = lco + center;\n" +"\n" +" vec3 world_pos0 = uMdl * vec4( mco, 1.0 );\n" +" vec4 vproj0 = uPv * vec4( world_pos0, 1.0 );\n" +" vec4 vproj1 = uPvmPrev * vec4( mco, 1.0 );\n" +"\n" +" float t = max(0.0,uTime.y);\n" +" float scaler = smoothstep(0.6,0.58,length(lco.xz*vec2(0.7,1.0)));\n" +"\n" +" vs_motion_out( vproj0, vproj1 );\n" +"\n" +" gl_Position = vproj0;\n" +" gl_PointSize = (8.0*uTransform.w*scaler) / (gl_Position.z + 0.01);\n" +" aWorldCo = world_pos0;\n" +" aColour = a_colour*scaler*(0.3+a_co.y);\n" +" aCo = mco;\n" +" aNorm = uNormMtx * a_norm.xyz;\n" +"}\n" +""}, + .fs = +{ +.orig_file = "shaders/cloud.fs", +.static_src = +"out vec4 FragColor;\n" +"\n" +"#line 1 1 \n" +"const float k_motion_lerp_amount = 0.01;\n" +"\n" +"#line 2 0 \n" +"\n" +"layout (location = 1) out vec2 oMotionVec;\n" +"\n" +"in vec3 aMotionVec0;\n" +"in vec3 aMotionVec1;\n" +"\n" +"void compute_motion_vectors()\n" +"{\n" +" // Write motion vectors\n" +" vec2 vmotion0 = aMotionVec0.xy / aMotionVec0.z;\n" +" vec2 vmotion1 = aMotionVec1.xy / aMotionVec1.z;\n" +"\n" +" oMotionVec = (vmotion1-vmotion0) * (1.0/k_motion_lerp_amount);\n" +"}\n" +"\n" +"#line 4 0 \n" +"\n" +"uniform vec3 uCamera;\n" +"\n" +"in vec4 aColour;\n" +"in vec3 aNorm;\n" +"in vec3 aCo;\n" +"in vec3 aWorldCo;\n" +"\n" +"void main()\n" +"{\n" +" vec2 ssuv = gl_FragCoord.xy;\n" +" vec3 vDither = vec3( dot( vec2( 171.0, 231.0 ), ssuv) );\n" +" float dither = fract( vDither.g / 71.0 ) - 0.5;\n" +"\n" +" float diff = length(gl_PointCoord.xy-vec2(0.5));\n" +" if( diff>0.5 )\n" +" discard;\n" +"\n" +" compute_motion_vectors();\n" +" FragColor = aColour;\n" +"}\n" +""}, +}; + +static GLuint _uniform_point_map_uMdl; +static GLuint _uniform_point_map_uNormMtx; +static GLuint _uniform_point_map_uPv; +static GLuint _uniform_point_map_uPvmPrev; +static GLuint _uniform_point_map_uTime; +static GLuint _uniform_point_map_uTransform; +static GLuint _uniform_point_map_uCamera; +static void shader_point_map_uMdl(m4x3f m){ + glUniformMatrix4x3fv(_uniform_point_map_uMdl,1,GL_FALSE,(float*)m); +} +static void shader_point_map_uNormMtx(m3x3f m){ + glUniformMatrix3fv(_uniform_point_map_uNormMtx,1,GL_FALSE,(float*)m); +} +static void shader_point_map_uPv(m4x4f m){ + glUniformMatrix4fv(_uniform_point_map_uPv,1,GL_FALSE,(float*)m); +} +static void shader_point_map_uPvmPrev(m4x4f m){ + glUniformMatrix4fv(_uniform_point_map_uPvmPrev,1,GL_FALSE,(float*)m); +} +static void shader_point_map_uTime(v2f v){ + glUniform2fv(_uniform_point_map_uTime,1,v); +} +static void shader_point_map_uTransform(v4f v){ + glUniform4fv(_uniform_point_map_uTransform,1,v); +} +static void shader_point_map_uCamera(v3f v){ + glUniform3fv(_uniform_point_map_uCamera,1,v); +} +static void shader_point_map_register(void){ + vg_shader_register( &_shader_point_map ); +} +static void shader_point_map_use(void){ glUseProgram(_shader_point_map.id); } +static void shader_point_map_link(void){ + _uniform_point_map_uMdl = glGetUniformLocation( _shader_point_map.id, "uMdl" ); + _uniform_point_map_uNormMtx = glGetUniformLocation( _shader_point_map.id, "uNormMtx" ); + _uniform_point_map_uPv = glGetUniformLocation( _shader_point_map.id, "uPv" ); + _uniform_point_map_uPvmPrev = glGetUniformLocation( _shader_point_map.id, "uPvmPrev" ); + _uniform_point_map_uTime = glGetUniformLocation( _shader_point_map.id, "uTime" ); + _uniform_point_map_uTransform = glGetUniformLocation( _shader_point_map.id, "uTransform" ); + _uniform_point_map_uCamera = glGetUniformLocation( _shader_point_map.id, "uCamera" ); +} +#endif /* SHADER_point_map_H */ diff --git a/skaterift.c b/skaterift.c index 2edd7dc..daac040 100644 --- a/skaterift.c +++ b/skaterift.c @@ -31,6 +31,7 @@ #include "network.h" #include "menu.h" #include "vehicle.h" +#include "pointcloud.h" static struct player_avatar localplayer_avatar; static struct player_model localplayer_models[3]; @@ -106,6 +107,7 @@ VG_STATIC void vg_load(void) vg_loader_step( render_init, NULL ); vg_loader_step( menu_init, NULL ); + vg_loader_step( pointcloud_init, NULL ); vg_loader_step( world_init, NULL ); vg_loader_step( vehicle_init, NULL ); vg_loader_step( font3d_init, NULL ); diff --git a/skaterift.h b/skaterift.h index b2d208c..b76fd1d 100644 --- a/skaterift.h +++ b/skaterift.h @@ -9,6 +9,7 @@ struct{ k_async_op_clientloading, k_async_op_world_preloading, k_async_op_world_loading, + k_async_op_cloud_loading, k_workshop_form_op_loading_model, k_workshop_form_op_downloading_submission, k_workshop_form_op_publishing_update, @@ -19,16 +20,10 @@ struct{ } static skaterift = { .async_op = k_async_op_clientloading }; - /* Skaterift api */ - static void skaterift_change_world( const char *world_path ); static int skaterift_change_world_command( int argc, const char *argv[] ); - - - - /* * Start a new operation or crash if we are already running one. you can avoid * crashing the game by checking the async status yourself before calling. diff --git a/world_gen.h b/world_gen.h index 6cae853..b5b06e5 100644 --- a/world_gen.h +++ b/world_gen.h @@ -104,6 +104,7 @@ VG_STATIC void world_apply_procedural_foliage( world_instance *world, float area = volume[0]*volume[2]; u32 particles = 0.08f * area; + /* TODO: Quasirandom? */ vg_info( "Map area: %f. Max particles: %u\n", area, particles ); for( u32 i=0; igeo_bh, sample, pcpoint, 10.0f ) == -1 ){ + v3_copy( sample, pcpoint ); + } + + v3f pos, vol; + v3_sub( world->scene_geo.bbx[1], world->scene_geo.bbx[0], vol ); + v3_sub( pcpoint, world->scene_geo.bbx[0], pos ); + v3_div( pos, vol, pos ); + + for( u32 i=0; i<3; i++ ){ + vert->pos[i] = vg_clampf(pos[i], 0.0f,1.0f) * 65535.0f; + vert->norm[i] = ha.normal[i] * 127.0f; + } + + float dist = 1.0f-(v3_length(jitter)); + + for( u32 i=0; i<4; i++ ){ + vert->colour[i] = colour[i] * 255.0f * dist*dist; + } + } + } if( resa && resb ){ struct world_surface *surfa = ray_hit_surface( world, &ha ), @@ -346,9 +380,17 @@ void world_routes_place_curve( world_instance *world, VG_STATIC void world_routes_create_mesh( world_instance *world, u32 route_id, - scene_context *sc ) + scene_context *sc, + struct pointcloud_vert *points, + u32 *point_count ) { ent_route *route = mdl_arritm( &world->ent_route, route_id ); + u8 colour[4]; + colour[0] = route->colour[0] * 255.0f; + colour[1] = route->colour[1] * 255.0f; + colour[2] = route->colour[2] * 255.0f; + colour[3] = route->colour[3] * 255.0f; + u32 last_valid = 0; for( int i=0; icheckpoints_count; i++ ){ @@ -451,7 +493,8 @@ void world_routes_create_mesh( world_instance *world, u32 route_id, v3_normalize( n0 ); v3_normalize( n2 ); - world_routes_place_curve( world, p, n0, n2, sc ); + world_routes_place_curve( world, p, n0, n2, sc, points, point_count, + route->colour ); /* --- */ v4_copy( p[2], p[0] ); @@ -461,15 +504,25 @@ void world_routes_create_mesh( world_instance *world, u32 route_id, scene_copy_slice( sc, &route->sm ); } +VG_STATIC +struct world_surface *world_tri_index_surface( world_instance *world, + u32 index ); /* * Create the strips of colour that run through the world along course paths */ VG_STATIC void world_routes_generate( world_instance *world ) { vg_info( "Generating route meshes\n" ); + vg_async_stall(); + + vg_rand_seed( 2000 ); vg_async_item *call = scene_alloc_async( &world->scene_lines, &world->mesh_route_lines, 200000, 300000 ); + vg_async_item *call1 = + vg_async_alloc( sizeof(struct pointcloud_vert)*POINTCLOUD_POINTS ); + u32 generated_points = 0; + struct pointcloud_vert *cloud_data = call1->payload; for( u32 i=0; ient_gate); i++ ){ ent_gate *gate = mdl_arritm( &world->ent_gate, i ); @@ -510,10 +563,118 @@ VG_STATIC void world_routes_generate( world_instance *world ) } } - for( u32 i=0; ient_route); i++ ) - world_routes_create_mesh( world, i, &world->scene_lines ); + for( u32 i=0; ient_route); i++ ){ + world_routes_create_mesh( world, i, &world->scene_lines, + cloud_data, &generated_points ); + } + + + { + vg_info( "Executing awesome algorithm!\n" ); + + f32 accum = 0.0f; + + v3f vol; + v3_sub( world->scene_geo.bbx[1], world->scene_geo.bbx[0], vol ); + v3_div( (v3f){1.0f,1.0f,1.0f}, vol, vol ); + + u8 colour[] = { 80,80,80,255 }; + v3f light_dir = {0.3f,0.8f,0.1f}; + v3_normalize( light_dir ); + + for( u32 k=1; k<=10; k++ ){ + f32 rate = 50.0f * (1.0f/(float)k); + + for( u32 i=0; iscene_geo.indice_count/3; i++ ){ + u32 *tri = &world->scene_geo.arrindices[i*3]; + struct world_surface *surf = world_tri_index_surface( world, tri[0] ); + + if( surf->info.shader == k_shader_boundary || + surf->info.shader == k_shader_invisible ) continue; + + if( !(surf->info.flags & k_material_flag_preview_visibile) ) continue; + + scene_vert *va = &world->scene_geo.arrvertices[tri[0]], + *vb = &world->scene_geo.arrvertices[tri[1]], + *vc = &world->scene_geo.arrvertices[tri[2]]; + + v3f v0, v1, vn; + v3_sub( vb->co, va->co, v0 ); + v3_sub( vc->co, va->co, v1 ); + v3_cross( v0, v1, vn ); + if( vn[1] < 0.0f ) continue; + + accum += v3_length(vn)*0.5f; + v3_normalize( vn ); + + while( accum > rate ){ + accum -= rate; + + if( generated_points >= POINTCLOUD_POINTS ){ + goto too_many_points; + } + + v2f co = { vg_randf64(), vg_randf64() }; + if( v2_length2(co) > 0.5f ){ + co[0] = 1.0f-co[0]; + co[1] = 1.0f-co[1]; + } + + v3f pt; + v3_muls( v0, co[0], pt ); + v3_muladds( pt, v1, co[1], pt ); + v3_add( va->co, pt, pt ); + + if( pt[1] < world->water.height ) continue; + struct pointcloud_vert *vert = &cloud_data[generated_points ++]; + + v3f pos; + v3_sub( pt, world->scene_geo.bbx[0], pos ); + v3_mul( pos, vol, pos ); + + for( u32 j=0; j<3; j++ ){ + vert->pos[j] = vg_clampf(pos[j],0.0f,1.0f) * 65535.0f; + vert->norm[j] = vg_clampf(vn[j],-1.0f,1.0f) * 127.0f; + } + + f32 brightness = vg_clampf( v3_dot( vn, light_dir ), 0.0f, 1.0f ); + + v4f col = {0.0f,0.0f,0.0f,0.0f}; + if( surf->info.surface_prop == k_surface_prop_wood ){ + v4_copy( (v4f){0.66f,0.6f,0.5f}, col ); + } + else if( surf->info.surface_prop == k_surface_prop_grass ){ + v4_copy( (v4f){0.42f,0.5f,0.33f}, col ); + } + else if( surf->info.surface_prop == k_surface_prop_concrete ){ + v4_copy( (v4f){0.57f,0.57f,0.55f}, col ); + } + else if( surf->info.surface_prop == k_surface_prop_metal ){ + v4_copy( (v4f){0.76f,0.76f,0.75f}, col ); + } + else{ + v4_copy( (v4f){0.2f,0.2f,0.2f}, col ); + } + + v4_copy( (v4f){0.2f,0.2f,0.26f}, col ); + v3_muls( col, brightness*0.25f, col ); + + for( u32 j=0; j<4; j++ ){ + vert->colour[j] = col[j] * 255.0f; + } + } + } + } + +too_many_points: + vg_info( "finished awesome algorithm! yipee (%u)!\n", generated_points ); + } + + call1->size = generated_points; vg_async_dispatch( call, async_scene_upload ); + vg_async_dispatch( call1, async_pointcloud_sub ); + world_routes_clear( world ); }