("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):
#{
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)
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)
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" )
#}
#}
#{
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']))
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, \
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 )
_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" );
#include "player.h"
#include "gui.h"
#include "menu.h"
+#include "pointcloud.h"
/*
* Checks string equality but does a hash check first
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) );
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 );
}
{
}
+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
*/
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 );
}
enum skateshop_type{
k_skateshop_type_boardshop,
- k_skateshop_type_charshop
+ k_skateshop_type_charshop,
+ k_skateshop_type_worldshop
};
struct ent_skateshop{
id_info;
}
character;
+
+ struct{
+ u32 id_display,
+ id_info;
+ }
+ worlds;
};
};
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)
--- /dev/null
+#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; i<POINTCLOUD_POINTS; i++ ){
+ test_data[i].pos[0] = vg_randf64() * 65535.0f;
+ test_data[i].pos[1] = vg_randf64() * 65535.0f;
+ test_data[i].pos[2] = vg_randf64() * 65535.0f;
+
+ v3f norm;
+ vg_rand_dir( norm );
+
+ test_data[i].norm[0] = norm[0] * 127.0f;
+ test_data[i].norm[1] = norm[1] * 127.0f;
+ test_data[i].norm[2] = norm[2] * 127.0f;
+
+ test_data[i].colour[0] = 90;
+ test_data[i].colour[1] = 90;
+ test_data[i].colour[2] = 90;
+ test_data[i].colour[3] = 255;
+ }
+
+ vg_async_dispatch( call, async_pointcloud_alloc );
+ shader_point_map_register();
+}
+
+static void pointcloud_render( world_instance *world, camera *cam, m4x3f model )
+{
+ m4x4f upvmprev;
+ m4x3_expand( model, upvmprev );
+ m4x4_mul( cam->mtx_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 */
--- /dev/null
+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;
+}
--- /dev/null
+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;
+}
--- /dev/null
+#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 */
#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];
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 );
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,
}
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.
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; i<particles; i++ ){
#include "world.h"
#include "world_gate.h"
#include "font.h"
+#include "pointcloud.h"
#if 0
#include "shaders/vblend.h"
VG_STATIC
void world_routes_place_curve( world_instance *world,
- v4f h[3], v3f n0, v3f n2, scene_context *scene )
+ v4f h[3], v3f n0, v3f n2, scene_context *scene,
+ struct pointcloud_vert *points,
+ u32 *point_count, v4f colour )
{
float t;
v3f p, pd;
int resa = ray_world( world, sa, down, &ha ),
resb = ray_world( world, sb, down, &hb );
+
+ for( u32 j=0; j<10; j++ ){
+ if( *point_count < POINTCLOUD_POINTS ){
+ struct pointcloud_vert *vert = &points[*point_count];
+ *point_count = (*point_count) + 1;
+
+ v3f sample, jitter, pcpoint;
+ vg_rand_sphere( jitter );
+ v3_muladds( ha.pos, jitter, 8.0f, sample );
+
+ if( bh_closest_point( world->geo_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 ),
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; i<route->checkpoints_count; i++ ){
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] );
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; i<mdl_arrcount(&world->ent_gate); i++ ){
ent_gate *gate = mdl_arritm( &world->ent_gate, i );
}
}
- for( u32 i=0; i<mdl_arrcount(&world->ent_route); i++ )
- world_routes_create_mesh( world, i, &world->scene_lines );
+ for( u32 i=0; i<mdl_arrcount(&world->ent_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; i<world->scene_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 );
}