-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathpoki.h
More file actions
400 lines (305 loc) · 10.4 KB
/
poki.h
File metadata and controls
400 lines (305 loc) · 10.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
/*
Poki - minimal creative coding framework
Copyright (c) 2025, Arne Koenig
Redistribution and use in source and binary forms, with or without modification, are permitted.
THIS SOFTWARE IS PROVIDED 'AS-IS', WITHOUT ANY EXPRESS OR IMPLIED WARRANTY. IN NO EVENT WILL THE AUTHORS BE HELD LIABLE FOR ANY DAMAGES ARISING FROM THE USE OF THIS SOFTWARE.
*/
#ifndef POKI_H
#define POKI_H
#include "deps/sokol_gfx.h"
#include "deps/sokol_fetch.h"
#include "deps/hmm.h"
#include "shaders/shaders.glsl.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef pk_assert
#include <assert.h>
#define pk_assert(x) assert(x)
#endif
#ifndef pk_printf
#include <stdio.h>
#define pk_printf printf
#endif
#if defined(_WIN32) && !defined(SOKOL_GLES3)
#define PK_REQUEST_DEDICATED_DEVICE \
_declspec(dllexport) unsigned long NvOptimusEnablement = 1; \
_declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
#else
#define PK_REQUEST_DEDICATED_DEVICE
#endif
//--FORWARD--------------
typedef struct m3d_t m3d_t;
typedef struct cgltf_data cgltf_data;
#ifndef PK_NO_SAPP
typedef struct sapp_event sapp_event;
#endif
//--ALLOCATOR--------------------------------------------
//TODO: Hook to dependencies.
typedef void* (*pk_alloc_fn)(size_t size, void* udata);
typedef void (*pk_free_fn)(void* ptr, void* udata);
typedef struct pk_allocator {
pk_alloc_fn alloc;
pk_free_fn free;
void* udata;
} pk_allocator;
void* pk_alloc(pk_allocator* alloc, size_t size);
void pk_free(pk_allocator* alloc, void* ptr);
//returns an allocator which just uses malloc and free.
pk_allocator pk_default_allocator(void);
//--INIT&SHUTDOWN----------------------------------------
typedef struct pk_desc {
sg_desc gfx;
sfetch_desc_t fetch;
} pk_desc;
void pk_setup(const pk_desc* desc);
void pk_shutdown(void);
//--CAMERA------------------------------------------------------------
//modified from https://github.com/floooh/sokol-samples
typedef struct pk_cam_desc {
float mindist;
float maxdist;
float minlat;
float maxlat;
float distance;
float latitude;
float longitude;
float aspect;
float nearz;
float farz;
float sensitivity;
HMM_Vec3 center;
} pk_cam_desc;
typedef struct pk_cam {
float mindist;
float maxdist;
float minlat;
float maxlat;
float distance;
float latitude;
float longitude;
float aspect;
float nearz;
float farz;
float sensitivity;
HMM_Vec3 center;
HMM_Vec3 eyepos;
HMM_Mat4 view;
HMM_Mat4 proj;
HMM_Mat4 viewproj;
} pk_cam;
void pk_init_cam(pk_cam* cam, const pk_cam_desc* desc);
void pk_orbit_cam(pk_cam* cam, float dx, float dy);
void pk_zoom_cam(pk_cam* cam, float d);
void pk_update_cam(pk_cam* cam, int fb_width, int fb_height);
#ifndef PK_NO_SAPP
void pk_cam_input(pk_cam* cam, const sapp_event* ev);
#endif //PK_NO_SAPP
//--TEXTURES&IMAGES---------------------------------------------------
//Generate mips on gpu. Not supported on GLES backend.
sg_image pk_gen_mipmaps_gpu(sg_image src, int width, int height, int mip_levels);
//Generate mips on cpu. Assumes RGBA8 format for now.
sg_image_desc pk_gen_mipmaps_cpu(pk_allocator* allocator, const sg_image_desc* src, int mip_levels);
typedef struct pk_texture {
sg_image image;
sg_sampler sampler;
} pk_texture;
#ifdef __cplusplus
#define PK_TEXTURE(img, smp) pk_texture{ img, smp }
#else
#define PK_TEXTURE(img, smp) (pk_texture){ .image = img, .sampler = smp }
#endif
void pk_checker_texture(pk_texture* tex);
void pk_release_texture(pk_texture* tex);
//--RENDERTARGET-------------------------------------------------------
typedef struct pk_rendertarget_desc {
int width, height;
sg_pixel_format color_format;
uint16_t color_attachment_count;
sg_pixel_format depth_format;
sg_pass_action action;
} pk_rendertarget_desc;
typedef struct pk_rendertarget {
sg_pass pass;
sg_image color_images[SG_MAX_COLOR_ATTACHMENTS];
sg_image depth_image;
} pk_rendertarget;
void pk_init_rendertarget(pk_rendertarget* rt, const pk_rendertarget_desc* desc);
void pk_release_rendertarget(pk_rendertarget* rt);
void pk_begin_rendertarget(const pk_rendertarget* rt);
void pk_end_rendertarget(void);
//--NODE-----------------------------------------------------------------
#define PK_MAX_NAME_LEN 32
typedef struct pk_node {
char name[PK_MAX_NAME_LEN];
struct pk_node* parent;
HMM_Vec3 position;
HMM_Vec3 scale;
HMM_Quat rotation;
} pk_node;
void pk_init_node(pk_node* node);
HMM_Mat4 pk_node_transform(const pk_node* node);
//--PRIMITIVE--------------------------------------------------------------
typedef struct pk_vertex_pnt {
HMM_Vec3 pos;
HMM_Vec3 nrm;
HMM_Vec2 uv;
} pk_vertex_pnt;
sg_vertex_layout_state pk_pnt_layout(void);
typedef struct pk_vertex_skin {
uint8_t indices[4];
float weights[4];
} pk_vertex_skin;
sg_vertex_layout_state pk_skinned_layout(void);
typedef struct {
sg_range vertices;
sg_range indices;
int num_elements;
bool is_mutable;
} pk_primitive_desc;
typedef struct pk_primitive {
sg_bindings bindings;
int base_element;
int num_elements;
} pk_primitive;
void pk_alloc_primitive(pk_primitive* primitive, uint16_t vubf_count, uint16_t view_count);
void pk_init_primitive(pk_primitive* primitive, const pk_primitive_desc* desc);
bool pk_load_m3d(pk_allocator* allocator, pk_primitive* mesh, pk_node* node, m3d_t* m3d);
void pk_release_primitive(pk_primitive* primitive);
void pk_texture_primitive(pk_primitive* primitive, const pk_texture* tex, int slot);
void pk_draw_primitive(const pk_primitive* primitive, int num_instances);
//--MESH------------------------------------------------------------------
typedef struct pk_mesh {
pk_primitive* primitives;
uint16_t primitive_count;
pk_node* node;
} pk_mesh;
void pk_draw_mesh(pk_mesh* mesh, pk_vs_params_t* vs_params);
void pk_release_mesh(pk_mesh* mesh);
//--MODEL-----------------------------------------------------------------
typedef struct pk_model {
pk_mesh* meshes;
pk_node* nodes;
uint16_t mesh_count;
uint16_t node_count;
} pk_model;
bool pk_load_gltf(pk_allocator* allocator, pk_model* model, cgltf_data* data);
void pk_release_model(pk_allocator* allocator, pk_model* model);
pk_node* pk_find_model_node(const pk_model*, const char* name);
void pk_set_model_texture(pk_model* model, const pk_texture* tex, int slot);
void pk_draw_model(pk_model* model, pk_vs_params_t* vs_params);
//--ANIMATION-------------------------------------------------------------
//--GLTF---------------------------
typedef enum {
PK_ANIM_PATH_UNDEFINED,
PK_ANIM_PATH_TRANSLATION,
PK_ANIM_PATH_ROTATION,
PK_ANIM_PATH_SCALE,
} pk_gltf_anim_path_type;
typedef enum {
PK_ANIM_INTERP_UNDEFINED,
PK_ANIM_INTERP_LINEAR,
PK_ANIM_INTERP_STEP,
PK_ANIM_INTERP_CUBIC, //not used - atm we force cubic to linear
} pk_gltf_anim_interp_type;
typedef struct pk_gltf_keyframe {
float time;
float* value;
} pk_gltf_keyframe;
typedef struct pk_gltf_anim_channel {
pk_node* target_node;
pk_gltf_keyframe* keyframes;
int num_keyframes;
pk_gltf_anim_path_type path;
pk_gltf_anim_interp_type interpolation;
} pk_gltf_anim_channel;
typedef struct pk_gltf_anim {
pk_gltf_anim_channel* channels;
int num_channels;
float duration;
float elapsed_time;
bool loop;
bool ready;
} pk_gltf_anim;
bool pk_load_gltf_anim(pk_allocator* allocator, pk_gltf_anim* anim, pk_model* model, cgltf_data* data);
void pk_release_gltf_anim(pk_allocator* allocator, pk_gltf_anim* anim);
void pk_play_gltf_anim(pk_gltf_anim* anim, float delta_time);
//--M3D------------------------------
#define PK_MAX_BONES 32
typedef struct pk_bone {
char name[PK_MAX_NAME_LEN];
int parent;
} pk_bone;
typedef struct pk_transform {
HMM_Quat rot;
HMM_Vec3 pos;
HMM_Vec3 scale;
} pk_transform;
typedef struct pk_bone_keyframe {
pk_transform* pose;
float time;
} pk_bone_keyframe;
typedef struct pk_bone_anim {
pk_bone_keyframe* keyframes;
int keyframe_count;
} pk_bone_anim;
typedef struct pk_bone_anim_set {
HMM_Mat4* inv_bind_matrices;
pk_bone* bones;
pk_bone_anim* anims;
int bone_count;
int anim_count;
} pk_bone_anim_set;
typedef struct pk_bone_anim_state {
int anim;
float time;
bool loop;
} pk_bone_anim_state;
bool pk_load_bone_anims(pk_allocator* allocator, pk_bone_anim_set* set, m3d_t* m3d);
void pk_sample_bone_anim(pk_transform* pose, pk_bone_anim_set* set, pk_bone_anim_state* state, float dt);
void pk_blend_poses(pk_transform* pose_a, const pk_transform* pose_b, float weight, int bone_count);
void pk_local_to_model_pose(pk_transform* model_pose, const pk_transform* local_pose, pk_bone_anim_set* set);
void pk_apply_pose(HMM_Mat4* trs, const pk_transform* pose, pk_bone_anim_set* set);
void pk_play_bone_anim(HMM_Mat4* trs, pk_bone_anim_set* set, pk_bone_anim_state* state, float dt);
void pk_release_bone_anims(pk_allocator* allocator, pk_bone_anim_set* set);
//--IO---------------------------------------------------------------------------
//Maybe add optional automatic texture loading for models.
typedef void(*pk_fail_callback)(const sfetch_response_t* response, void* udata);
//--IMAGE-LOADING----------
void pk_release_image_desc(pk_allocator* allocator, sg_image_desc* desc);
typedef void(*pk_image_loaded_callback)(sg_image_desc* desc, void* udata);
typedef struct pk_image_request {
const char* path;
sfetch_range_t buffer;
pk_image_loaded_callback loaded_cb;
pk_fail_callback fail_cb;
void* udata;
} pk_image_request;
//Supports qoi, png, webp and dds. Will generate a 4x4 checker texture on fail, if no fail callback is provided.
sfetch_handle_t pk_load_image_data(const pk_image_request* req);
//--M3D-LOADING----------------
typedef void(*pk_m3d_loaded_callback)(m3d_t* m3d, void* udata);
typedef struct pk_m3d_request {
const char* path;
sfetch_range_t buffer;
pk_m3d_loaded_callback loaded_cb;
pk_fail_callback fail_cb;
void* udata;
} pk_m3d_request;
sfetch_handle_t pk_load_m3d_data(const pk_m3d_request* req);
void pk_release_m3d_data(m3d_t* m3d);
//--GLTF-LOADING---------------
typedef void(*pk_gltf_loaded_callback)(cgltf_data* gltf, void* udata);
typedef struct pk_gltf_request {
const char* path;
sfetch_range_t buffer;
pk_gltf_loaded_callback loaded_cb;
pk_fail_callback fail_cb;
void* udata;
} pk_gltf_request;
sfetch_handle_t pk_load_gltf_data(const pk_gltf_request* req);
void pk_release_gltf_data(cgltf_data* data);
#ifdef __cplusplus
} //extern "C"
#endif
#endif // POKI_H