GLuint vao, vbo;
u32 count;
- v4f control;
+ f64 anim_start;
+ f32 visibility;
+ enum pointcloud_anim{
+ k_pointcloud_anim_opening,
+ k_pointcloud_anim_hiding,
+ k_pointcloud_anim_idle_any,
+ k_pointcloud_anim_idle_open,
+ k_pointcloud_anim_idle_closed,
+ }
+ anim;
}
-static pointcloud = { .control = {0.0f,0.0f,0.0f,1.0f} };
+static pointcloud;
#pragma pack(push,1)
struct pointcloud_vert{
- u16 pos[4]; /* float[ 0 -> 1 ] */
- i8 norm[4]; /* float[ -1 -> 1 ] */
+ i16 pos[4]; /* float[ -1 -> 1 ] */
u8 colour[4]; /* float[ 0 -> 1 ] */
};
#pragma pack(pop)
-static void async_pointcloud_sub( void *payload, u32 size )
-{
+typedef struct pointcloud_vert pointcloud_vert;
+typedef struct pointcloud_buffer pointcloud_buffer;
+
+struct pointcloud_buffer{
+ u32 max, count;
+ boxf boundary;
+ enum pointcloud_op{
+ k_pointcloud_op_clear,
+ k_pointcloud_op_append
+ }
+ op;
+ pointcloud_vert buf[];
+};
+
+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;
+
+ pointcloud_buffer *buf = payload;
+
+ u32 start,end,count;
+ if( buf->op == k_pointcloud_op_append ){
+ start = pointcloud.count;
+ end = pointcloud.count + buf->count;
+ }
+ else{
+ start = 0;
+ end = buf->count;
+ }
+
+ end = VG_MIN(POINTCLOUD_POINTS,end);
+ count = end-start;
+
+ if( count ){
+ u32 size = count * sizeof(pointcloud_vert),
+ offset = start * sizeof(pointcloud_vert);
+
+ glBufferSubData( GL_ARRAY_BUFFER, offset, size, buf->buf );
+ pointcloud.count = end;
+ }
}
-static void async_pointcloud_alloc( void *payload, u32 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 );
+ size_t stride = sizeof( pointcloud_vert );
glBindBuffer( GL_ARRAY_BUFFER, pointcloud.vbo );
glBufferData( GL_ARRAY_BUFFER, stride * POINTCLOUD_POINTS,
- payload, GL_DYNAMIC_DRAW );
+ NULL, GL_DYNAMIC_DRAW );
/* 0: coordinates */
- glVertexAttribPointer( 0, 4, GL_UNSIGNED_SHORT, GL_TRUE, stride, (void*)0 );
+ glVertexAttribPointer( 0, 4, GL_SHORT, GL_TRUE, stride, (void*)0 );
glEnableVertexAttribArray( 0 );
- /* 1: normal */
- glVertexAttribPointer( 1, 4, GL_BYTE, GL_TRUE,
- stride, (void *)offsetof(struct pointcloud_vert, norm) );
+ /* 1: colour */
+ glVertexAttribPointer( 1, 4, GL_UNSIGNED_BYTE, GL_TRUE,
+ stride, (void *)offsetof(pointcloud_vert, colour) );
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;
+static void pointcloud_init(void){
+ vg_async_call( async_pointcloud_alloc, NULL, 0 );
+ shader_point_map_register();
+}
- v3f norm;
- vg_rand_dir( norm );
+static void pointcloud_animate( enum pointcloud_anim anim ){
+ pointcloud.anim = anim;
+ pointcloud.anim_start = vg.time;
+}
- 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;
+static int pointcloud_idle(void){
+ if( pointcloud.anim >= k_pointcloud_anim_idle_any ) return 1;
+ else return 0;
+}
- test_data[i].colour[0] = 90;
- test_data[i].colour[1] = 90;
- test_data[i].colour[2] = 90;
- test_data[i].colour[3] = 255;
+static
+void pointcloud_render( world_instance *world, camera *cam, m4x3f model ){
+ if( pointcloud.anim < k_pointcloud_anim_idle_any ){
+ f32 const k_transition = 0.6f;
+ f32 t = (vg.time - pointcloud.anim_start) / k_transition;
+
+ if( pointcloud.anim == k_pointcloud_anim_hiding ){
+ if( t > 1.0f ){
+ pointcloud.visibility = 0.0f;
+ pointcloud.anim = k_pointcloud_anim_idle_closed;
+ }
+ else pointcloud.visibility = 1.0f-t;
+ }
+ else if( pointcloud.anim == k_pointcloud_anim_opening ){
+ if( t > 1.0f ){
+ pointcloud.visibility = 1.0f;
+ pointcloud.anim = k_pointcloud_anim_idle_open;
+ }
+ else pointcloud.visibility = t;
+ }
}
- vg_async_dispatch( call, async_pointcloud_alloc );
- shader_point_map_register();
-}
+ if( pointcloud.visibility == 0.0f ) return;
-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_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 );
+ shader_point_map_uAnim( (v4f){ 32, 1.0f-pointcloud.visibility,
+ 0.0f, vg.time } );
glBindVertexArray( pointcloud.vao );
glEnable( GL_PROGRAM_POINT_SIZE );
glDrawArrays( GL_POINTS, 0, pointcloud.count );
}
+static void pointcloud_packvert( pointcloud_vert *vert, v3f pos, v4f colour ){
+ for( u32 i=0; i<3; i++ )
+ vert->pos[i] = (pos[i]-0.5f) * 32767.0f;
+
+ for( u32 i=0; i<4; i++ )
+ vert->colour[i] = colour[i] * 255.0f;
+}
+
#endif /* POINTCLOUD_H */