mission is possible 2
[carveJwlIkooP6JGAAIwe30JlM.git] / pointcloud.h
1 #ifndef POINTCLOUD_H
2 #define POINTCLOUD_H
3
4 #include "common.h"
5 #include "world.h"
6 #include "shaders/point_map.h"
7
8 #define POINTCLOUD_POINTS 250000
9
10 struct pointcloud{
11 GLuint vao, vbo;
12 u32 count;
13
14 f64 anim_start;
15 f32 visibility;
16 enum pointcloud_anim{
17 k_pointcloud_anim_opening,
18 k_pointcloud_anim_hiding,
19 k_pointcloud_anim_idle_any,
20 k_pointcloud_anim_idle_open,
21 k_pointcloud_anim_idle_closed,
22 }
23 anim;
24 }
25 static pointcloud;
26
27 #pragma pack(push,1)
28 struct pointcloud_vert{
29 i16 pos[4]; /* float[ -1 -> 1 ] */
30 u8 colour[4]; /* float[ 0 -> 1 ] */
31 };
32 #pragma pack(pop)
33
34 typedef struct pointcloud_vert pointcloud_vert;
35 typedef struct pointcloud_buffer pointcloud_buffer;
36
37 struct pointcloud_buffer{
38 u32 max, count;
39 boxf boundary;
40
41 enum pointcloud_op{
42 k_pointcloud_op_clear,
43 k_pointcloud_op_append
44 }
45 op;
46 pointcloud_vert buf[];
47 };
48
49 static void async_pointcloud_sub( void *payload, u32 size )
50 {
51 glBindVertexArray( pointcloud.vao );
52 glBindBuffer( GL_ARRAY_BUFFER, pointcloud.vbo );
53
54 pointcloud_buffer *buf = payload;
55
56 u32 start,end,count;
57 if( buf->op == k_pointcloud_op_append ){
58 start = pointcloud.count;
59 end = pointcloud.count + buf->count;
60 }
61 else{
62 start = 0;
63 end = buf->count;
64 }
65
66 end = VG_MIN(POINTCLOUD_POINTS,end);
67 count = end-start;
68
69 if( count ){
70 u32 size = count * sizeof(pointcloud_vert),
71 offset = start * sizeof(pointcloud_vert);
72
73 glBufferSubData( GL_ARRAY_BUFFER, offset, size, buf->buf );
74 pointcloud.count = end;
75 }
76 }
77
78 static void async_pointcloud_alloc( void *payload, u32 size )
79 {
80 glGenVertexArrays( 1, &pointcloud.vao );
81 glGenBuffers( 1, &pointcloud.vbo );
82 glBindVertexArray( pointcloud.vao );
83
84 size_t stride = sizeof( pointcloud_vert );
85
86 glBindBuffer( GL_ARRAY_BUFFER, pointcloud.vbo );
87 glBufferData( GL_ARRAY_BUFFER, stride * POINTCLOUD_POINTS,
88 NULL, GL_DYNAMIC_DRAW );
89
90 /* 0: coordinates */
91 glVertexAttribPointer( 0, 4, GL_SHORT, GL_TRUE, stride, (void*)0 );
92 glEnableVertexAttribArray( 0 );
93
94 /* 1: colour */
95 glVertexAttribPointer( 1, 4, GL_UNSIGNED_BYTE, GL_TRUE,
96 stride, (void *)offsetof(pointcloud_vert, colour) );
97 glEnableVertexAttribArray( 1 );
98 VG_CHECK_GL_ERR();
99 }
100
101 static void pointcloud_init(void)
102 {
103 vg_async_call( async_pointcloud_alloc, NULL, 0 );
104 shader_point_map_register();
105 }
106
107 static void pointcloud_animate( enum pointcloud_anim anim )
108 {
109 pointcloud.anim = anim;
110 pointcloud.anim_start = vg.time;
111 }
112
113 static int pointcloud_idle(void)
114 {
115 if( pointcloud.anim >= k_pointcloud_anim_idle_any ) return 1;
116 else return 0;
117 }
118
119 static void pointcloud_render( world_instance *world, camera *cam, m4x3f model )
120 {
121 if( pointcloud.anim < k_pointcloud_anim_idle_any ){
122 f32 const k_transition = 0.6f;
123 f32 t = (vg.time - pointcloud.anim_start) / k_transition;
124
125 if( pointcloud.anim == k_pointcloud_anim_hiding ){
126 if( t > 1.0f ){
127 pointcloud.visibility = 0.0f;
128 pointcloud.anim = k_pointcloud_anim_idle_closed;
129 }
130 else pointcloud.visibility = 1.0f-t;
131 }
132 else if( pointcloud.anim == k_pointcloud_anim_opening ){
133 if( t > 1.0f ){
134 pointcloud.visibility = 1.0f;
135 pointcloud.anim = k_pointcloud_anim_idle_open;
136 }
137 else pointcloud.visibility = t;
138 }
139 }
140
141 if( pointcloud.visibility == 0.0f ) return;
142
143 m4x4f upvmprev;
144 m4x3_expand( model, upvmprev );
145 m4x4_mul( cam->mtx_prev.pv, upvmprev, upvmprev );
146
147 shader_point_map_use();
148 shader_point_map_uPv( cam->mtx.pv );
149 shader_point_map_uPvmPrev( upvmprev );
150 shader_point_map_uMdl( model );
151 shader_point_map_uCamera( cam->pos );
152 shader_point_map_uAnim( (v4f){ 32, 1.0f-pointcloud.visibility,
153 0.0f, vg.time } );
154
155 glBindVertexArray( pointcloud.vao );
156 glEnable( GL_PROGRAM_POINT_SIZE );
157 glDrawArrays( GL_POINTS, 0, pointcloud.count );
158 }
159
160 #endif /* POINTCLOUD_H */