font: fix linedist calc + add font_print_rect
parent
ee9bf54d43
commit
295a9d932d
|
@ -674,11 +674,13 @@ typedef struct font_metrics_t {
|
||||||
} font_metrics_t;
|
} font_metrics_t;
|
||||||
void font_face(const char *face_tag, const char *filename_ttf, float font_size, unsigned flags);
|
void font_face(const char *face_tag, const char *filename_ttf, float font_size, unsigned flags);
|
||||||
void font_face_from_mem(const char *tag, const void *ttf_buffer, unsigned ttf_len, float font_size, unsigned flags);
|
void font_face_from_mem(const char *tag, const void *ttf_buffer, unsigned ttf_len, float font_size, unsigned flags);
|
||||||
|
void font_scale(const char *face_tag, int scale_index, float value);
|
||||||
void font_scales(const char *face_tag, float h1, float h2, float h3, float h4, float h5, float h6);
|
void font_scales(const char *face_tag, float h1, float h2, float h3, float h4, float h5, float h6);
|
||||||
void font_color(const char *color_tag, uint32_t color);
|
void font_color(const char *color_tag, uint32_t color);
|
||||||
vec2 font_xy();
|
vec2 font_xy();
|
||||||
void font_goto(float x, float y);
|
void font_goto(float x, float y);
|
||||||
vec2 font_print(const char *text);
|
vec2 font_print(const char *text);
|
||||||
|
vec2 font_print_rect(const char *text, vec4 rect);
|
||||||
vec2 font_rect(const char *text);
|
vec2 font_rect(const char *text);
|
||||||
font_metrics_t font_metrics(const char *text);
|
font_metrics_t font_metrics(const char *text);
|
||||||
void* font_colorize(const char *text, const char *comma_types, const char *comma_keywords);
|
void* font_colorize(const char *text, const char *comma_types, const char *comma_keywords);
|
||||||
|
@ -1295,6 +1297,7 @@ typedef struct anim_t {
|
||||||
} anim_t;
|
} anim_t;
|
||||||
anim_t clip(float minframe, float maxframe, float blendtime, unsigned flags);
|
anim_t clip(float minframe, float maxframe, float blendtime, unsigned flags);
|
||||||
anim_t loop(float minframe, float maxframe, float blendtime, unsigned flags);
|
anim_t loop(float minframe, float maxframe, float blendtime, unsigned flags);
|
||||||
|
anim_t* animlist(const char *filename);
|
||||||
enum MODEL_FLAGS {
|
enum MODEL_FLAGS {
|
||||||
MODEL_NO_ANIMATIONS = 1,
|
MODEL_NO_ANIMATIONS = 1,
|
||||||
MODEL_NO_MESHES = 2,
|
MODEL_NO_MESHES = 2,
|
||||||
|
@ -1481,6 +1484,8 @@ typedef struct object_t {
|
||||||
vec3 sca, pos, euler, pivot;
|
vec3 sca, pos, euler, pivot;
|
||||||
handle* textures;
|
handle* textures;
|
||||||
model_t model;
|
model_t model;
|
||||||
|
anim_t anim;
|
||||||
|
float anim_speed;
|
||||||
aabb bounds;
|
aabb bounds;
|
||||||
unsigned billboard;
|
unsigned billboard;
|
||||||
bool light_cached;
|
bool light_cached;
|
||||||
|
@ -1493,6 +1498,7 @@ typedef struct object_t {
|
||||||
vec3 object_position(object_t *obj);
|
vec3 object_position(object_t *obj);
|
||||||
void object_scale(object_t *obj, vec3 sca);
|
void object_scale(object_t *obj, vec3 sca);
|
||||||
void object_model(object_t *obj, model_t model);
|
void object_model(object_t *obj, model_t model);
|
||||||
|
void object_anim(object_t *obj, anim_t anim, float speed);
|
||||||
void object_diffuse(object_t *obj, texture_t tex);
|
void object_diffuse(object_t *obj, texture_t tex);
|
||||||
void object_diffuse_push(object_t *obj, texture_t tex);
|
void object_diffuse_push(object_t *obj, texture_t tex);
|
||||||
void object_diffuse_pop(object_t *obj);
|
void object_diffuse_pop(object_t *obj);
|
||||||
|
|
|
@ -102,14 +102,15 @@ int main() {
|
||||||
//font_print(FONT_LEFT "Left" FONT_CENTER "Center" FONT_RIGHT "Right\n");
|
//font_print(FONT_LEFT "Left" FONT_CENTER "Center" FONT_RIGHT "Right\n");
|
||||||
|
|
||||||
// ... alignment must be the first tag in a string for now. this is a temporary hack.
|
// ... alignment must be the first tag in a string for now. this is a temporary hack.
|
||||||
|
font_goto(0, window_height()*3/4.);
|
||||||
font_print(FONT_LEFT "left");
|
font_print(FONT_LEFT "left");
|
||||||
font_print(FONT_CENTER "center");
|
font_print(FONT_CENTER "center");
|
||||||
font_print(FONT_RIGHT "right");
|
font_print(FONT_RIGHT "right");
|
||||||
|
|
||||||
font_print(FONT_TOP FONT_CENTER "top\n");
|
font_print(FONT_TOP FONT_CENTER "top");
|
||||||
font_print(FONT_MIDDLE FONT_RIGHT "middle\n");
|
font_print(FONT_MIDDLE FONT_RIGHT "middle");
|
||||||
font_print(FONT_BASELINE FONT_RIGHT "baseline\n");
|
font_print(FONT_BASELINE FONT_RIGHT "baseline");
|
||||||
font_print(FONT_BOTTOM FONT_CENTER "bottom\n");
|
font_print(FONT_BOTTOM FONT_CENTER "bottom");
|
||||||
|
|
||||||
{
|
{
|
||||||
vec2 pos = vec2(1290,120);
|
vec2 pos = vec2(1290,120);
|
||||||
|
@ -126,7 +127,7 @@ int main() {
|
||||||
{
|
{
|
||||||
vec2 pos = vec2(830,80);
|
vec2 pos = vec2(830,80);
|
||||||
ddraw_push_2d();
|
ddraw_push_2d();
|
||||||
char *txt = "Very iffy global text.";
|
char *txt = "Very iffy global text.";
|
||||||
font_goto(pos.x, pos.y);
|
font_goto(pos.x, pos.y);
|
||||||
vec2 size=font_rect(txt);
|
vec2 size=font_rect(txt);
|
||||||
|
|
||||||
|
@ -138,7 +139,19 @@ int main() {
|
||||||
{
|
{
|
||||||
vec2 pos = vec2(830,160);
|
vec2 pos = vec2(830,160);
|
||||||
ddraw_push_2d();
|
ddraw_push_2d();
|
||||||
char *txt = FONT_H1 "Very iffy global text.";
|
char *txt = FONT_H1 "Very iffy global text.";
|
||||||
|
font_goto(pos.x, pos.y);
|
||||||
|
vec2 size=font_rect(txt);
|
||||||
|
|
||||||
|
ddraw_aabb(vec3(pos.x,pos.y,0), vec3(pos.x+size.x,pos.y+size.y,0));
|
||||||
|
font_print(txt);
|
||||||
|
ddraw_pop_2d();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i <= 6; i++) {
|
||||||
|
vec2 pos = vec2(830,550 + 55*(i+1));
|
||||||
|
ddraw_push_2d();
|
||||||
|
char *txt = va("%cTest line %d", i, i);
|
||||||
font_goto(pos.x, pos.y);
|
font_goto(pos.x, pos.y);
|
||||||
vec2 size=font_rect(txt);
|
vec2 size=font_rect(txt);
|
||||||
|
|
||||||
|
|
|
@ -16130,13 +16130,14 @@ enum FONT_FLAGS {
|
||||||
typedef struct font_metrics_t {
|
typedef struct font_metrics_t {
|
||||||
float ascent; // max distance above baseline for all glyphs
|
float ascent; // max distance above baseline for all glyphs
|
||||||
float descent; // max distance below baseline for all glyphs
|
float descent; // max distance below baseline for all glyphs
|
||||||
float linegap; // distance betwen ascent of next line and descent of current line
|
float linegap; // distance between ascent of next line and descent of current line
|
||||||
float linedist; // distance between the baseline of two lines (ascent - descent + linegap)
|
float linedist; // distance between the baseline of two lines (ascent - descent + linegap)
|
||||||
} font_metrics_t;
|
} font_metrics_t;
|
||||||
|
|
||||||
// configures
|
// configures
|
||||||
API void font_face(const char *face_tag, const char *filename_ttf, float font_size, unsigned flags);
|
API void font_face(const char *face_tag, const char *filename_ttf, float font_size, unsigned flags);
|
||||||
API void font_face_from_mem(const char *tag, const void *ttf_buffer, unsigned ttf_len, float font_size, unsigned flags);
|
API void font_face_from_mem(const char *tag, const void *ttf_buffer, unsigned ttf_len, float font_size, unsigned flags);
|
||||||
|
API void font_scale(const char *face_tag, int scale_index, float value);
|
||||||
API void font_scales(const char *face_tag, float h1, float h2, float h3, float h4, float h5, float h6);
|
API void font_scales(const char *face_tag, float h1, float h2, float h3, float h4, float h5, float h6);
|
||||||
API void font_color(const char *color_tag, uint32_t color);
|
API void font_color(const char *color_tag, uint32_t color);
|
||||||
|
|
||||||
|
@ -16144,6 +16145,7 @@ API void font_color(const char *color_tag, uint32_t color);
|
||||||
API vec2 font_xy();
|
API vec2 font_xy();
|
||||||
API void font_goto(float x, float y);
|
API void font_goto(float x, float y);
|
||||||
API vec2 font_print(const char *text);
|
API vec2 font_print(const char *text);
|
||||||
|
API vec2 font_print_rect(const char *text, vec4 rect);
|
||||||
API vec2 font_rect(const char *text);
|
API vec2 font_rect(const char *text);
|
||||||
API font_metrics_t font_metrics(const char *text);
|
API font_metrics_t font_metrics(const char *text);
|
||||||
// void font_clip(vec2 topleft, vec2 bottomright);
|
// void font_clip(vec2 topleft, vec2 bottomright);
|
||||||
|
@ -17509,7 +17511,7 @@ typedef struct anim_t {
|
||||||
|
|
||||||
API anim_t clip(float minframe, float maxframe, float blendtime, unsigned flags);
|
API anim_t clip(float minframe, float maxframe, float blendtime, unsigned flags);
|
||||||
API anim_t loop(float minframe, float maxframe, float blendtime, unsigned flags);
|
API anim_t loop(float minframe, float maxframe, float blendtime, unsigned flags);
|
||||||
//API array(anim_t) animlist(const char *filename); // @todo
|
API array(anim_t) animlist(const char *filename);
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// models
|
// models
|
||||||
|
@ -17789,6 +17791,8 @@ typedef struct object_t {
|
||||||
vec3 sca, pos, euler, pivot;
|
vec3 sca, pos, euler, pivot;
|
||||||
array(handle) textures;
|
array(handle) textures;
|
||||||
model_t model;
|
model_t model;
|
||||||
|
anim_t anim;
|
||||||
|
float anim_speed;
|
||||||
aabb bounds;
|
aabb bounds;
|
||||||
unsigned billboard; // [0..7] x(4),y(2),z(1) masks
|
unsigned billboard; // [0..7] x(4),y(2),z(1) masks
|
||||||
bool light_cached; //< used by scene to update light data
|
bool light_cached; //< used by scene to update light data
|
||||||
|
@ -17803,6 +17807,7 @@ API vec3 object_position(object_t *obj);
|
||||||
API void object_scale(object_t *obj, vec3 sca);
|
API void object_scale(object_t *obj, vec3 sca);
|
||||||
//
|
//
|
||||||
API void object_model(object_t *obj, model_t model);
|
API void object_model(object_t *obj, model_t model);
|
||||||
|
API void object_anim(object_t *obj, anim_t anim, float speed);
|
||||||
API void object_diffuse(object_t *obj, texture_t tex);
|
API void object_diffuse(object_t *obj, texture_t tex);
|
||||||
API void object_diffuse_push(object_t *obj, texture_t tex);
|
API void object_diffuse_push(object_t *obj, texture_t tex);
|
||||||
API void object_diffuse_pop(object_t *obj);
|
API void object_diffuse_pop(object_t *obj);
|
||||||
|
@ -363053,7 +363058,7 @@ in vec4 instanceGlyph;\n\
|
||||||
uniform sampler2D sampler_font;\n\
|
uniform sampler2D sampler_font;\n\
|
||||||
uniform sampler2D sampler_meta;\n\
|
uniform sampler2D sampler_meta;\n\
|
||||||
\n\
|
\n\
|
||||||
uniform float offset_firstline; // ascent - descent - linegap/2\n\
|
uniform float offset_firstline; // ascent\n\
|
||||||
uniform float scale_factor; // scaling factor proportional to font size\n\
|
uniform float scale_factor; // scaling factor proportional to font size\n\
|
||||||
uniform vec2 string_offset; // offset of upper-left corner\n\
|
uniform vec2 string_offset; // offset of upper-left corner\n\
|
||||||
\n\
|
\n\
|
||||||
|
@ -363218,6 +363223,20 @@ void ui_font() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void font_scale(const char *tag, int s, float v) {
|
||||||
|
font_init();
|
||||||
|
|
||||||
|
if (s < 0 || s >= 10) return;
|
||||||
|
|
||||||
|
unsigned index = *tag - FONT_FACE1[0];
|
||||||
|
if( index > FONTS_MAX ) return;
|
||||||
|
|
||||||
|
font_t *f = &fonts[index];
|
||||||
|
if (!f->initialized) return;
|
||||||
|
|
||||||
|
f->scale[s] = v / f->font_size;
|
||||||
|
}
|
||||||
|
|
||||||
void font_scales(const char *tag, float h1, float h2, float h3, float h4, float h5, float h6) {
|
void font_scales(const char *tag, float h1, float h2, float h3, float h4, float h5, float h6) {
|
||||||
font_init();
|
font_init();
|
||||||
|
|
||||||
|
@ -363600,7 +363619,7 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm
|
||||||
font_t *f = &fonts[0];
|
font_t *f = &fonts[0];
|
||||||
int S = 3;
|
int S = 3;
|
||||||
uint32_t color = 0;
|
uint32_t color = 0;
|
||||||
float X = 0, Y = 0, W = 0, L = f->ascent*f->factor*f->scale[S], LL = L; // LL=largest linedist
|
float X = 0, Y = 0, W = 0, L = f->ascent*f->factor*f->scale[S], LL = 0; // LL=largest linedist
|
||||||
offset.y = -offset.y; // invert y polarity
|
offset.y = -offset.y; // invert y polarity
|
||||||
|
|
||||||
// utf8 to utf32
|
// utf8 to utf32
|
||||||
|
@ -363632,6 +363651,7 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm
|
||||||
|
|
||||||
// change size
|
// change size
|
||||||
S = ch;
|
S = ch;
|
||||||
|
//@hack: use descent when we use >H4
|
||||||
L = f->ascent*f->factor*f->scale[S];
|
L = f->ascent*f->factor*f->scale[S];
|
||||||
if(L > LL) LL = L;
|
if(L > LL) LL = L;
|
||||||
continue;
|
continue;
|
||||||
|
@ -363648,10 +363668,27 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm
|
||||||
|
|
||||||
// change face
|
// change face
|
||||||
f = &fonts[ ch - 0x10 ];
|
f = &fonts[ ch - 0x10 ];
|
||||||
|
L = f->ascent*f->factor*f->scale[S];
|
||||||
|
if(L > LL) LL = L;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!LL)
|
||||||
|
LL = L;
|
||||||
|
|
||||||
|
if (ch == FONT_LEFT[0] && (
|
||||||
|
(unicode[i+1]) == FONT_LEFT[1] ||
|
||||||
|
(unicode[i+1]) == FONT_CENTER[1] ||
|
||||||
|
(unicode[i+1]) == FONT_RIGHT[1] ||
|
||||||
|
(unicode[i+1]) == FONT_TOP[1] ||
|
||||||
|
(unicode[i+1]) == FONT_MIDDLE[1] ||
|
||||||
|
(unicode[i+1]) == FONT_BASELINE[1] ||
|
||||||
|
(unicode[i+1]) == FONT_BOTTOM[1]
|
||||||
|
)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// convert to vbo data
|
// convert to vbo data
|
||||||
int cp = ch - f->begin; // f->cp2iter[ch - f->begin];
|
int cp = ch - f->begin; // f->cp2iter[ch - f->begin];
|
||||||
//if(cp == 0xFFFD) continue;
|
//if(cp == 0xFFFD) continue;
|
||||||
|
@ -363906,25 +363943,25 @@ void font_goto(float x, float y) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print and linefeed. Text may include markup code
|
// Print and linefeed. Text may include markup code
|
||||||
vec2 font_print(const char *text) {
|
vec2 font_print_rect(const char *text, vec4 rect) {
|
||||||
// @fixme: remove this hack
|
// @fixme: remove this hack
|
||||||
if( text[0] == FONT_LEFT[0] ) {
|
if( text[0] == FONT_LEFT[0] ) {
|
||||||
int l = text[1] == FONT_LEFT[1];
|
int l = text[1] == FONT_LEFT[1];
|
||||||
int c = text[1] == FONT_CENTER[1];
|
int c = text[1] == FONT_CENTER[1];
|
||||||
int r = text[1] == FONT_RIGHT[1];
|
int r = text[1] == FONT_RIGHT[1];
|
||||||
if( l || c || r ) {
|
if( l || c || r ) {
|
||||||
vec2 rect = font_rect(text + 2);
|
vec2 text_rect = font_rect(text + 2);
|
||||||
gotoxy.x = l ? 0 : r ? (window_width() - rect.x) : window_width()/2 - rect.x/2;
|
gotoxy.x = l ? rect.x : r ? ((rect.x+rect.z) - text_rect.x) : rect.x+rect.z/2. - text_rect.x/2.;
|
||||||
return font_print(text + 2);
|
return font_print_rect(text + 2, rect);
|
||||||
}
|
}
|
||||||
int t = text[1] == FONT_TOP[1];
|
int t = text[1] == FONT_TOP[1];
|
||||||
int b = text[1] == FONT_BOTTOM[1];
|
int b = text[1] == FONT_BOTTOM[1];
|
||||||
int m = text[1] == FONT_MIDDLE[1];
|
int m = text[1] == FONT_MIDDLE[1];
|
||||||
int B = text[1] == FONT_BASELINE[1];
|
int B = text[1] == FONT_BASELINE[1];
|
||||||
if( t || b || m || B ) {
|
if( t || b || m || B ) {
|
||||||
vec2 rect = font_rect(text + 2);
|
vec2 text_rect = font_rect(text + 2);
|
||||||
gotoxy.y = t ? 0 : b ? (window_height() - rect.y) : m ? window_height()/2-rect.y/2 : window_height()/2-rect.y/1;
|
gotoxy.y = t ? rect.y : b ? ((rect.y+rect.w) - text_rect.y) : m ? rect.y+rect.w/2.-text_rect.y/2. : rect.y+rect.w/2.-text_rect.y/1;
|
||||||
return font_print(text + 2);
|
return font_print_rect(text + 2, rect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363934,6 +363971,11 @@ vec2 font_print(const char *text) {
|
||||||
return dims;
|
return dims;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vec2 font_print(const char *text) {
|
||||||
|
vec4 dims = {0, 0, window_width(), window_height()};
|
||||||
|
return font_print_rect(text, dims);
|
||||||
|
}
|
||||||
|
|
||||||
// Print a code snippet with syntax highlighting
|
// Print a code snippet with syntax highlighting
|
||||||
vec2 font_highlight(const char *text, const void *colors) {
|
vec2 font_highlight(const char *text, const void *colors) {
|
||||||
vec2 dims = font_draw_ex(text, gotoxy, (const char *)colors, font_draw_cmd);
|
vec2 dims = font_draw_ex(text, gotoxy, (const char *)colors, font_draw_cmd);
|
||||||
|
@ -372697,37 +372739,12 @@ typedef struct iqm_t {
|
||||||
vec4 *colormaps;
|
vec4 *colormaps;
|
||||||
} iqm_t;
|
} iqm_t;
|
||||||
|
|
||||||
#define meshdata (q->meshdata)
|
|
||||||
#define animdata (q->animdata)
|
|
||||||
#define nummeshes (q->nummeshes)
|
|
||||||
#define numtris (q->numtris)
|
|
||||||
#define numverts (q->numverts)
|
|
||||||
#define numjoints (q->numjoints)
|
|
||||||
#define numframes (q->numframes)
|
|
||||||
#define numanims (q->numanims)
|
|
||||||
#define meshes (q->meshes)
|
|
||||||
#define textures (q->textures)
|
|
||||||
#define joints (q->joints)
|
|
||||||
#define poses (q->poses)
|
|
||||||
#define anims (q->anims)
|
|
||||||
#define baseframe (q->baseframe)
|
|
||||||
#define inversebaseframe (q->inversebaseframe)
|
|
||||||
#define outframe (q->outframe)
|
|
||||||
#define frames (q->frames)
|
|
||||||
#define vao (q->vao)
|
|
||||||
#define ibo (q->ibo)
|
|
||||||
#define vbo (q->vbo)
|
|
||||||
#define bonematsoffset (q->bonematsoffset)
|
|
||||||
#define buf (q->buf)
|
|
||||||
#define bounds (q->bounds)
|
|
||||||
#define colormaps (q->colormaps)
|
|
||||||
|
|
||||||
void model_set_texture(model_t m, texture_t t) {
|
void model_set_texture(model_t m, texture_t t) {
|
||||||
if(!m.iqm) return;
|
if(!m.iqm) return;
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
for( int i = 0; i < nummeshes; ++i) { // assume 1 texture per mesh
|
for( int i = 0; i < q->nummeshes; ++i) { // assume 1 texture per mesh
|
||||||
textures[i] = t.id;
|
q->textures[i] = t.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372820,9 +372837,9 @@ void model_set_uniforms(model_t m, int shader, mat44 mv, mat44 proj, mat44 view,
|
||||||
if ((loc = glGetUniformLocation(shader, "proj")) >= 0) {
|
if ((loc = glGetUniformLocation(shader, "proj")) >= 0) {
|
||||||
glUniformMatrix4fv(loc, 1, GL_FALSE, proj);
|
glUniformMatrix4fv(loc, 1, GL_FALSE, proj);
|
||||||
}
|
}
|
||||||
if( (loc = glGetUniformLocation(shader, "SKINNED")) >= 0 ) glUniform1i( loc, numanims ? GL_TRUE : GL_FALSE);
|
if( (loc = glGetUniformLocation(shader, "SKINNED")) >= 0 ) glUniform1i( loc, q->numanims ? GL_TRUE : GL_FALSE);
|
||||||
if( numanims )
|
if( q->numanims )
|
||||||
if( (loc = glGetUniformLocation(shader, "vsBoneMatrix")) >= 0 ) glUniformMatrix3x4fv( loc, numjoints, GL_FALSE, outframe[0]);
|
if( (loc = glGetUniformLocation(shader, "vsBoneMatrix")) >= 0 ) glUniformMatrix3x4fv( loc, q->numjoints, GL_FALSE, q->outframe[0]);
|
||||||
|
|
||||||
if ((loc = glGetUniformLocation(shader, "u_matcaps")) >= 0) {
|
if ((loc = glGetUniformLocation(shader, "u_matcaps")) >= 0) {
|
||||||
glUniform1i(loc, m.flags & MODEL_MATCAPS ? GL_TRUE:GL_FALSE);
|
glUniform1i(loc, m.flags & MODEL_MATCAPS ? GL_TRUE:GL_FALSE);
|
||||||
|
@ -372833,10 +372850,10 @@ void model_set_state(model_t m) {
|
||||||
if(!m.iqm) return;
|
if(!m.iqm) return;
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
glBindVertexArray( vao );
|
glBindVertexArray( q->vao );
|
||||||
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, q->ibo);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
glBindBuffer(GL_ARRAY_BUFFER, q->vbo);
|
||||||
|
|
||||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, position) );
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, position) );
|
||||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, texcoord) );
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, texcoord) );
|
||||||
|
@ -372857,7 +372874,7 @@ void model_set_state(model_t m) {
|
||||||
glEnableVertexAttribArray(12);
|
glEnableVertexAttribArray(12);
|
||||||
|
|
||||||
// animation
|
// animation
|
||||||
if(numframes > 0) {
|
if(q->numframes > 0) {
|
||||||
glVertexAttribPointer( 8, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,blendindexes) );
|
glVertexAttribPointer( 8, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,blendindexes) );
|
||||||
glVertexAttribPointer( 9, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,blendweights) );
|
glVertexAttribPointer( 9, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,blendweights) );
|
||||||
glVertexAttribPointer(10, 1, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, blendvertexindex) );
|
glVertexAttribPointer(10, 1, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, blendvertexindex) );
|
||||||
|
@ -372898,71 +372915,71 @@ void model_set_state(model_t m) {
|
||||||
|
|
||||||
static
|
static
|
||||||
bool model_load_meshes(iqm_t *q, const struct iqmheader *hdr, model_t *m) {
|
bool model_load_meshes(iqm_t *q, const struct iqmheader *hdr, model_t *m) {
|
||||||
if(meshdata) return false;
|
if(q->meshdata) return false;
|
||||||
|
|
||||||
lil32p(&buf[hdr->ofs_vertexarrays], hdr->num_vertexarrays*sizeof(struct iqmvertexarray)/sizeof(uint32_t));
|
lil32p(&q->buf[hdr->ofs_vertexarrays], hdr->num_vertexarrays*sizeof(struct iqmvertexarray)/sizeof(uint32_t));
|
||||||
lil32p(&buf[hdr->ofs_triangles], hdr->num_triangles*sizeof(struct iqmtriangle)/sizeof(uint32_t));
|
lil32p(&q->buf[hdr->ofs_triangles], hdr->num_triangles*sizeof(struct iqmtriangle)/sizeof(uint32_t));
|
||||||
lil32p(&buf[hdr->ofs_meshes], hdr->num_meshes*sizeof(struct iqmmesh)/sizeof(uint32_t));
|
lil32p(&q->buf[hdr->ofs_meshes], hdr->num_meshes*sizeof(struct iqmmesh)/sizeof(uint32_t));
|
||||||
lil32p(&buf[hdr->ofs_joints], hdr->num_joints*sizeof(struct iqmjoint)/sizeof(uint32_t));
|
lil32p(&q->buf[hdr->ofs_joints], hdr->num_joints*sizeof(struct iqmjoint)/sizeof(uint32_t));
|
||||||
|
|
||||||
meshdata = buf;
|
q->meshdata = q->buf;
|
||||||
nummeshes = hdr->num_meshes;
|
q->nummeshes = hdr->num_meshes;
|
||||||
numtris = hdr->num_triangles;
|
q->numtris = hdr->num_triangles;
|
||||||
numverts = hdr->num_vertexes;
|
q->numverts = hdr->num_vertexes;
|
||||||
numjoints = hdr->num_joints;
|
q->numjoints = hdr->num_joints;
|
||||||
outframe = CALLOC(hdr->num_joints, sizeof(mat34));
|
q->outframe = CALLOC(hdr->num_joints, sizeof(mat34));
|
||||||
|
|
||||||
float *inposition = NULL, *innormal = NULL, *intangent = NULL, *intexcoord = NULL, *invertexindex = NULL;
|
float *inposition = NULL, *innormal = NULL, *intangent = NULL, *intexcoord = NULL, *invertexindex = NULL;
|
||||||
uint8_t *inblendindex8 = NULL, *inblendweight8 = NULL;
|
uint8_t *inblendindex8 = NULL, *inblendweight8 = NULL;
|
||||||
int *inblendindexi = NULL; float *inblendweightf = NULL;
|
int *inblendindexi = NULL; float *inblendweightf = NULL;
|
||||||
uint8_t *invertexcolor8 = NULL;
|
uint8_t *invertexcolor8 = NULL;
|
||||||
struct iqmvertexarray *vas = (struct iqmvertexarray *)&buf[hdr->ofs_vertexarrays];
|
struct iqmvertexarray *vas = (struct iqmvertexarray *)&q->buf[hdr->ofs_vertexarrays];
|
||||||
for(int i = 0; i < (int)hdr->num_vertexarrays; i++) {
|
for(int i = 0; i < (int)hdr->num_vertexarrays; i++) {
|
||||||
struct iqmvertexarray *va = &vas[i];
|
struct iqmvertexarray *va = &vas[i];
|
||||||
switch(va->type) {
|
switch(va->type) {
|
||||||
default: continue; // return PANIC("unknown iqm vertex type (%d)", va->type), false;
|
default: continue; // return PANIC("unknown iqm vertex type (%d)", va->type), false;
|
||||||
break; case IQM_POSITION: ASSERT(va->format == IQM_FLOAT && va->size == 3); inposition = (float *)&buf[va->offset]; lil32pf(inposition, 3*hdr->num_vertexes);
|
break; case IQM_POSITION: ASSERT(va->format == IQM_FLOAT && va->size == 3); inposition = (float *)&q->buf[va->offset]; lil32pf(inposition, 3*hdr->num_vertexes);
|
||||||
break; case IQM_NORMAL: ASSERT(va->format == IQM_FLOAT && va->size == 3); innormal = (float *)&buf[va->offset]; lil32pf(innormal, 3*hdr->num_vertexes);
|
break; case IQM_NORMAL: ASSERT(va->format == IQM_FLOAT && va->size == 3); innormal = (float *)&q->buf[va->offset]; lil32pf(innormal, 3*hdr->num_vertexes);
|
||||||
break; case IQM_TANGENT: ASSERT(va->format == IQM_FLOAT && va->size == 4); intangent = (float *)&buf[va->offset]; lil32pf(intangent, 4*hdr->num_vertexes);
|
break; case IQM_TANGENT: ASSERT(va->format == IQM_FLOAT && va->size == 4); intangent = (float *)&q->buf[va->offset]; lil32pf(intangent, 4*hdr->num_vertexes);
|
||||||
break; case IQM_TEXCOORD: ASSERT(va->format == IQM_FLOAT && va->size == 2); intexcoord = (float *)&buf[va->offset]; lil32pf(intexcoord, 2*hdr->num_vertexes);
|
break; case IQM_TEXCOORD: ASSERT(va->format == IQM_FLOAT && va->size == 2); intexcoord = (float *)&q->buf[va->offset]; lil32pf(intexcoord, 2*hdr->num_vertexes);
|
||||||
break; case IQM_COLOR: ASSERT(va->size == 4); ASSERT(va->format == IQM_UBYTE); invertexcolor8 = (uint8_t *)&buf[va->offset];
|
break; case IQM_COLOR: ASSERT(va->size == 4); ASSERT(va->format == IQM_UBYTE); invertexcolor8 = (uint8_t *)&q->buf[va->offset];
|
||||||
break; case IQM_BLENDINDEXES: ASSERT(va->size == 4); ASSERT(va->format == IQM_UBYTE || va->format == IQM_INT);
|
break; case IQM_BLENDINDEXES: ASSERT(va->size == 4); ASSERT(va->format == IQM_UBYTE || va->format == IQM_INT);
|
||||||
if(va->format == IQM_UBYTE) inblendindex8 = (uint8_t *)&buf[va->offset];
|
if(va->format == IQM_UBYTE) inblendindex8 = (uint8_t *)&q->buf[va->offset];
|
||||||
else inblendindexi = (int *)&buf[va->offset];
|
else inblendindexi = (int *)&q->buf[va->offset];
|
||||||
break; case IQM_BLENDWEIGHTS: ASSERT(va->size == 4); ASSERT(va->format == IQM_UBYTE || va->format == IQM_FLOAT);
|
break; case IQM_BLENDWEIGHTS: ASSERT(va->size == 4); ASSERT(va->format == IQM_UBYTE || va->format == IQM_FLOAT);
|
||||||
if(va->format == IQM_UBYTE) inblendweight8 = (uint8_t *)&buf[va->offset];
|
if(va->format == IQM_UBYTE) inblendweight8 = (uint8_t *)&q->buf[va->offset];
|
||||||
else inblendweightf = (float *)&buf[va->offset];
|
else inblendweightf = (float *)&q->buf[va->offset];
|
||||||
invertexindex = (inblendweight8 ? (float*)(inblendweight8 + 4) : inblendweightf + 4 );
|
invertexindex = (inblendweight8 ? (float*)(inblendweight8 + 4) : inblendweightf + 4 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hdr->ofs_bounds) lil32p(buf + hdr->ofs_bounds, hdr->num_frames * sizeof(struct iqmbounds));
|
if (hdr->ofs_bounds) lil32p(q->buf + hdr->ofs_bounds, hdr->num_frames * sizeof(struct iqmbounds));
|
||||||
if (hdr->ofs_bounds) bounds = (struct iqmbounds *) &buf[hdr->ofs_bounds];
|
if (hdr->ofs_bounds) q->bounds = (struct iqmbounds *) &q->buf[hdr->ofs_bounds];
|
||||||
|
|
||||||
meshes = (struct iqmmesh *)&buf[hdr->ofs_meshes];
|
q->meshes = (struct iqmmesh *)&q->buf[hdr->ofs_meshes];
|
||||||
joints = (struct iqmjoint *)&buf[hdr->ofs_joints];
|
q->joints = (struct iqmjoint *)&q->buf[hdr->ofs_joints];
|
||||||
|
|
||||||
baseframe = CALLOC(hdr->num_joints, sizeof(mat34));
|
q->baseframe = CALLOC(hdr->num_joints, sizeof(mat34));
|
||||||
inversebaseframe = CALLOC(hdr->num_joints, sizeof(mat34));
|
q->inversebaseframe = CALLOC(hdr->num_joints, sizeof(mat34));
|
||||||
for(int i = 0; i < (int)hdr->num_joints; i++) {
|
for(int i = 0; i < (int)hdr->num_joints; i++) {
|
||||||
struct iqmjoint *j = &joints[i];
|
struct iqmjoint *j = &q->joints[i];
|
||||||
compose34(baseframe[i], ptr3(j->translate), normq(ptrq(j->rotate)), ptr3(j->scale));
|
compose34(q->baseframe[i], ptr3(j->translate), normq(ptrq(j->rotate)), ptr3(j->scale));
|
||||||
invert34(inversebaseframe[i], baseframe[i]);
|
invert34(q->inversebaseframe[i], q->baseframe[i]);
|
||||||
if(j->parent >= 0) {
|
if(j->parent >= 0) {
|
||||||
multiply34x2(baseframe[i], baseframe[j->parent], baseframe[i]);
|
multiply34x2(q->baseframe[i], q->baseframe[j->parent], q->baseframe[i]);
|
||||||
multiply34(inversebaseframe[i], inversebaseframe[j->parent]);
|
multiply34(q->inversebaseframe[i], q->inversebaseframe[j->parent]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct iqmtriangle *tris = (struct iqmtriangle *)&buf[hdr->ofs_triangles];
|
struct iqmtriangle *tris = (struct iqmtriangle *)&q->buf[hdr->ofs_triangles];
|
||||||
m->num_tris = hdr->num_triangles;
|
m->num_tris = hdr->num_triangles;
|
||||||
m->tris = (void*)tris;
|
m->tris = (void*)tris;
|
||||||
|
|
||||||
glGenVertexArrays(1, &vao);
|
glGenVertexArrays(1, &q->vao);
|
||||||
glBindVertexArray(vao);
|
glBindVertexArray(q->vao);
|
||||||
|
|
||||||
if(!ibo) glGenBuffers(1, &ibo);
|
if(!q->ibo) glGenBuffers(1, &q->ibo);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, q->ibo);
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, hdr->num_triangles*sizeof(struct iqmtriangle), tris, GL_STATIC_DRAW);
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, hdr->num_triangles*sizeof(struct iqmtriangle), tris, GL_STATIC_DRAW);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
@ -372993,8 +373010,8 @@ bool model_load_meshes(iqm_t *q, const struct iqmheader *hdr, model_t *m) {
|
||||||
if(invertexcolor8) memcpy(v->color, &invertexcolor8[i*4], sizeof(v->color));
|
if(invertexcolor8) memcpy(v->color, &invertexcolor8[i*4], sizeof(v->color));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!vbo) glGenBuffers(1, &vbo);
|
if(!q->vbo) glGenBuffers(1, &q->vbo);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
glBindBuffer(GL_ARRAY_BUFFER, q->vbo);
|
||||||
glBufferData(GL_ARRAY_BUFFER, hdr->num_vertexes*sizeof(iqm_vertex), verts, GL_STATIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, hdr->num_vertexes*sizeof(iqm_vertex), verts, GL_STATIC_DRAW);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
@ -373015,16 +373032,16 @@ bool model_load_meshes(iqm_t *q, const struct iqmheader *hdr, model_t *m) {
|
||||||
m->verts = verts;
|
m->verts = verts;
|
||||||
/*m->verts = 0; FREE(verts);*/
|
/*m->verts = 0; FREE(verts);*/
|
||||||
|
|
||||||
textures = CALLOC(hdr->num_meshes * 8, sizeof(GLuint));
|
q->textures = CALLOC(hdr->num_meshes * 8, sizeof(GLuint));
|
||||||
colormaps = CALLOC(hdr->num_meshes * 8, sizeof(vec4));
|
q->colormaps = CALLOC(hdr->num_meshes * 8, sizeof(vec4));
|
||||||
for(int i = 0; i < (int)hdr->num_meshes; i++) {
|
for(int i = 0; i < (int)hdr->num_meshes; i++) {
|
||||||
int invalid = texture_checker().id;
|
int invalid = texture_checker().id;
|
||||||
textures[i] = invalid;
|
q->textures[i] = invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *str = hdr->ofs_text ? (char *)&buf[hdr->ofs_text] : "";
|
const char *str = hdr->ofs_text ? (char *)&q->buf[hdr->ofs_text] : "";
|
||||||
for(int i = 0; i < (int)hdr->num_meshes; i++) {
|
for(int i = 0; i < (int)hdr->num_meshes; i++) {
|
||||||
struct iqmmesh *m = &meshes[i];
|
struct iqmmesh *m = &q->meshes[i];
|
||||||
PRINTF("loaded mesh: %s\n", &str[m->name]);
|
PRINTF("loaded mesh: %s\n", &str[m->name]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373033,34 +373050,34 @@ bool model_load_meshes(iqm_t *q, const struct iqmheader *hdr, model_t *m) {
|
||||||
|
|
||||||
static
|
static
|
||||||
bool model_load_anims(iqm_t *q, const struct iqmheader *hdr) {
|
bool model_load_anims(iqm_t *q, const struct iqmheader *hdr) {
|
||||||
if((int)hdr->num_poses != numjoints) return false;
|
if((int)hdr->num_poses != q->numjoints) return false;
|
||||||
|
|
||||||
if(animdata) {
|
if(q->animdata) {
|
||||||
if(animdata != meshdata) FREE(animdata);
|
if(q->animdata != q->meshdata) FREE(q->animdata);
|
||||||
FREE(frames);
|
FREE(q->frames);
|
||||||
animdata = NULL;
|
q->animdata = NULL;
|
||||||
anims = NULL;
|
q->anims = NULL;
|
||||||
frames = 0;
|
q->frames = 0;
|
||||||
numframes = 0;
|
q->numframes = 0;
|
||||||
numanims = 0;
|
q->numanims = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
lil32p(&buf[hdr->ofs_poses], hdr->num_poses*sizeof(struct iqmpose)/sizeof(uint32_t));
|
lil32p(&q->buf[hdr->ofs_poses], hdr->num_poses*sizeof(struct iqmpose)/sizeof(uint32_t));
|
||||||
lil32p(&buf[hdr->ofs_anims], hdr->num_anims*sizeof(struct iqmanim)/sizeof(uint32_t));
|
lil32p(&q->buf[hdr->ofs_anims], hdr->num_anims*sizeof(struct iqmanim)/sizeof(uint32_t));
|
||||||
lil16p((uint16_t *)&buf[hdr->ofs_frames], hdr->num_frames*hdr->num_framechannels);
|
lil16p((uint16_t *)&q->buf[hdr->ofs_frames], hdr->num_frames*hdr->num_framechannels);
|
||||||
|
|
||||||
animdata = buf;
|
q->animdata = q->buf;
|
||||||
numanims = hdr->num_anims;
|
q->numanims = hdr->num_anims;
|
||||||
numframes = hdr->num_frames;
|
q->numframes = hdr->num_frames;
|
||||||
|
|
||||||
anims = (struct iqmanim *)&buf[hdr->ofs_anims];
|
q->anims = (struct iqmanim *)&q->buf[hdr->ofs_anims];
|
||||||
poses = (struct iqmpose *)&buf[hdr->ofs_poses];
|
q->poses = (struct iqmpose *)&q->buf[hdr->ofs_poses];
|
||||||
frames = CALLOC(hdr->num_frames * hdr->num_poses, sizeof(mat34));
|
q->frames = CALLOC(hdr->num_frames * hdr->num_poses, sizeof(mat34));
|
||||||
uint16_t *framedata = (uint16_t *)&buf[hdr->ofs_frames];
|
uint16_t *framedata = (uint16_t *)&q->buf[hdr->ofs_frames];
|
||||||
|
|
||||||
for(int i = 0; i < (int)hdr->num_frames; i++) {
|
for(int i = 0; i < (int)hdr->num_frames; i++) {
|
||||||
for(int j = 0; j < (int)hdr->num_poses; j++) {
|
for(int j = 0; j < (int)hdr->num_poses; j++) {
|
||||||
struct iqmpose *p = &poses[j];
|
struct iqmpose *p = &q->poses[j];
|
||||||
quat rotate;
|
quat rotate;
|
||||||
vec3 translate, scale;
|
vec3 translate, scale;
|
||||||
translate.x = p->channeloffset[0]; if(p->mask&0x01) translate.x += *framedata++ * p->channelscale[0];
|
translate.x = p->channeloffset[0]; if(p->mask&0x01) translate.x += *framedata++ * p->channelscale[0];
|
||||||
|
@ -373084,16 +373101,16 @@ bool model_load_anims(iqm_t *q, const struct iqmheader *hdr) {
|
||||||
// parentPose * childPose * childInverseBasePose
|
// parentPose * childPose * childInverseBasePose
|
||||||
|
|
||||||
mat34 m; compose34(m, translate, normq(rotate), scale);
|
mat34 m; compose34(m, translate, normq(rotate), scale);
|
||||||
if(p->parent >= 0) multiply34x3(frames[i*hdr->num_poses + j], baseframe[p->parent], m, inversebaseframe[j]);
|
if(p->parent >= 0) multiply34x3(q->frames[i*hdr->num_poses + j], q->baseframe[p->parent], m, q->inversebaseframe[j]);
|
||||||
else multiply34x2(frames[i*hdr->num_poses + j], m, inversebaseframe[j]);
|
else multiply34x2(q->frames[i*hdr->num_poses + j], m, q->inversebaseframe[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *str = hdr->ofs_text ? (char *)&buf[hdr->ofs_text] : "";
|
// const char *str = hdr->ofs_text ? (char *)&q->buf[hdr->ofs_text] : "";
|
||||||
for(int i = 0; i < (int)hdr->num_anims; i++) {
|
// for(int i = 0; i < (int)hdr->num_anims; i++) {
|
||||||
struct iqmanim *a = &anims[i];
|
// struct iqmanim *a = &anims[i];
|
||||||
PRINTF("loaded anim[%d]: %s\n", i, &str[a->name]);
|
// PRINTF("loaded anim[%d]: %s\n", i, &str[a->name]);
|
||||||
}
|
// }
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -373106,14 +373123,14 @@ static char* strcpy_safe(char *d, const char *s) {
|
||||||
|
|
||||||
static
|
static
|
||||||
bool model_load_textures(iqm_t *q, const struct iqmheader *hdr, model_t *model) {
|
bool model_load_textures(iqm_t *q, const struct iqmheader *hdr, model_t *model) {
|
||||||
textures = textures ? textures : CALLOC(hdr->num_meshes * 8, sizeof(GLuint)); // up to 8 textures per mesh
|
q->textures = q->textures ? q->textures : CALLOC(hdr->num_meshes * 8, sizeof(GLuint)); // up to 8 textures per mesh
|
||||||
colormaps = colormaps ? colormaps : CALLOC(hdr->num_meshes * 8, sizeof(vec4)); // up to 8 colormaps per mesh
|
q->colormaps = q->colormaps ? q->colormaps : CALLOC(hdr->num_meshes * 8, sizeof(vec4)); // up to 8 colormaps per mesh
|
||||||
|
|
||||||
GLuint *out = textures;
|
GLuint *out = q->textures;
|
||||||
|
|
||||||
const char *str = hdr->ofs_text ? (char *)&buf[hdr->ofs_text] : "";
|
const char *str = hdr->ofs_text ? (char *)&q->buf[hdr->ofs_text] : "";
|
||||||
for(int i = 0; i < (int)hdr->num_meshes; i++) {
|
for(int i = 0; i < (int)hdr->num_meshes; i++) {
|
||||||
struct iqmmesh *m = &meshes[i];
|
struct iqmmesh *m = &q->meshes[i];
|
||||||
|
|
||||||
// reuse texture+material if already decoded
|
// reuse texture+material if already decoded
|
||||||
bool reused = 0;
|
bool reused = 0;
|
||||||
|
@ -373282,13 +373299,23 @@ model_t model_from_mem(const void *mem, int len, int flags) {
|
||||||
if( !memcmp(hdr.magic, IQM_MAGIC, sizeof(hdr.magic))) {
|
if( !memcmp(hdr.magic, IQM_MAGIC, sizeof(hdr.magic))) {
|
||||||
lil32p(&hdr.version, (sizeof(hdr) - sizeof(hdr.magic))/sizeof(uint32_t));
|
lil32p(&hdr.version, (sizeof(hdr) - sizeof(hdr.magic))/sizeof(uint32_t));
|
||||||
if(hdr.version == IQM_VERSION) {
|
if(hdr.version == IQM_VERSION) {
|
||||||
buf = CALLOC(hdr.filesize, sizeof(uint8_t));
|
q->buf = CALLOC(hdr.filesize, sizeof(uint8_t));
|
||||||
memcpy(buf + sizeof(hdr), ptr, hdr.filesize - sizeof(hdr));
|
memcpy(q->buf + sizeof(hdr), ptr, hdr.filesize - sizeof(hdr));
|
||||||
error = 0;
|
error = 0;
|
||||||
if( hdr.num_meshes > 0 && !(flags & MODEL_NO_MESHES) ) error |= !model_load_meshes(q, &hdr, &m);
|
if( hdr.num_meshes > 0 && !(flags & MODEL_NO_MESHES) ) error |= !model_load_meshes(q, &hdr, &m);
|
||||||
if( hdr.num_meshes > 0 && !(flags & MODEL_NO_TEXTURES) ) error |= !model_load_textures(q, &hdr, &m);
|
if( hdr.num_meshes > 0 && !(flags & MODEL_NO_TEXTURES) ) error |= !model_load_textures(q, &hdr, &m);
|
||||||
|
else {
|
||||||
|
// setup fallback
|
||||||
|
material_t mt = {0};
|
||||||
|
mt.name = "placeholder";
|
||||||
|
mt.count = 1;
|
||||||
|
mt.layer[0].color = vec4(1,1,1,1);
|
||||||
|
mt.layer[0].texture = texture_checker().id;
|
||||||
|
|
||||||
|
array_push(m.materials, mt);
|
||||||
|
}
|
||||||
if( hdr.num_anims > 0 && !(flags & MODEL_NO_ANIMATIONS) ) error |= !model_load_anims(q, &hdr);
|
if( hdr.num_anims > 0 && !(flags & MODEL_NO_ANIMATIONS) ) error |= !model_load_anims(q, &hdr);
|
||||||
if( buf != meshdata && buf != animdata ) FREE(buf);
|
if( q->buf != q->meshdata && q->buf != q->animdata ) FREE(q->buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -373297,31 +373324,23 @@ model_t model_from_mem(const void *mem, int len, int flags) {
|
||||||
PRINTF("Error: cannot load %s", "model");
|
PRINTF("Error: cannot load %s", "model");
|
||||||
FREE(q), q = 0;
|
FREE(q), q = 0;
|
||||||
} else {
|
} else {
|
||||||
#undef vao
|
|
||||||
#undef ibo
|
|
||||||
#undef vbo
|
|
||||||
m.vao = q->vao;
|
m.vao = q->vao;
|
||||||
m.ibo = q->ibo;
|
m.ibo = q->ibo;
|
||||||
m.vbo = q->vbo;
|
m.vbo = q->vbo;
|
||||||
m.num_verts = numverts;
|
m.num_verts = q->numverts;
|
||||||
#define vao (q->vao)
|
|
||||||
#define ibo (q->ibo)
|
|
||||||
#define vbo (q->vbo)
|
|
||||||
|
|
||||||
// m.boxes = bounds; // <@todo
|
// m.boxes = bounds; // <@todo
|
||||||
m.num_meshes = nummeshes;
|
m.num_meshes = q->nummeshes;
|
||||||
m.num_triangles = numtris;
|
m.num_triangles = q->numtris;
|
||||||
m.num_joints = numjoints;
|
m.num_joints = q->numjoints;
|
||||||
//m.num_poses = numposes;
|
//m.num_poses = numposes;
|
||||||
m.num_anims = numanims;
|
m.num_anims = q->numanims;
|
||||||
m.num_frames = numframes;
|
m.num_frames = q->numframes;
|
||||||
m.iqm = q;
|
m.iqm = q;
|
||||||
m.curframe = model_animate(m, 0);
|
m.curframe = model_animate(m, 0);
|
||||||
|
|
||||||
//m.num_textures = nummeshes; // assume 1 texture only per mesh
|
//m.num_textures = q->nummeshes; // assume 1 texture only per mesh
|
||||||
#undef textures
|
|
||||||
m.textures = (q->textures);
|
m.textures = (q->textures);
|
||||||
#define textures (q->textures)
|
|
||||||
|
|
||||||
m.flags = flags;
|
m.flags = flags;
|
||||||
|
|
||||||
|
@ -373345,9 +373364,9 @@ bool model_get_bone_pose(model_t m, unsigned joint, mat34 *out) {
|
||||||
if(!m.iqm) return false;
|
if(!m.iqm) return false;
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
if(joint >= numjoints) return false;
|
if(joint >= q->numjoints) return false;
|
||||||
|
|
||||||
multiply34x2(*out, outframe[joint], baseframe[joint]);
|
multiply34x2(*out, q->outframe[joint], q->baseframe[joint]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373358,6 +373377,26 @@ anim_t loop(float minframe, float maxframe, float blendtime, unsigned flags) {
|
||||||
return clip(minframe, maxframe, blendtime, flags | ANIM_LOOP);
|
return clip(minframe, maxframe, blendtime, flags | ANIM_LOOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
array(anim_t) animlist(const char *pathfile) {
|
||||||
|
anim_t *animlist = 0;
|
||||||
|
char *anim_file = vfs_read(strendi(pathfile,".txt") ? pathfile : va("%s@animlist.txt", pathfile));
|
||||||
|
if( anim_file ) {
|
||||||
|
// deserialize anim
|
||||||
|
for each_substring(anim_file, "\r\n", anim) {
|
||||||
|
int from, to;
|
||||||
|
char anim_name[128] = {0};
|
||||||
|
if( sscanf(anim, "%*s %d-%d %127[^\r\n]", &from, &to, anim_name) != 3) continue;
|
||||||
|
array_push(animlist, !!strstri(anim_name, "loop") || !strcmpi(anim_name, "idle") ? loop(from, to, 0, 0) : clip(from, to, 0, 0)); // [from,to,flags]
|
||||||
|
array_back(animlist)->name = strswap(strswap(strswap(STRDUP(anim_name), "Loop", ""), "loop", ""), "()", ""); // @leak
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// placeholder
|
||||||
|
array_push(animlist, clip(0,1,0,0));
|
||||||
|
array_back(animlist)->name = STRDUP("Error"); // @leak
|
||||||
|
}
|
||||||
|
return animlist;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void anim_tick(anim_t *p, bool is_primary, float delta) { // delta can be negative (reverses anim)
|
void anim_tick(anim_t *p, bool is_primary, float delta) { // delta can be negative (reverses anim)
|
||||||
if( !is_primary ) p->active = 0;
|
if( !is_primary ) p->active = 0;
|
||||||
|
@ -373395,18 +373434,18 @@ float model_animate_blends(model_t m, anim_t *primary, anim_t *secondary, float
|
||||||
unsigned frame4 = secondary->pose.y;
|
unsigned frame4 = secondary->pose.y;
|
||||||
float alphaB = secondary->pose.z;
|
float alphaB = secondary->pose.z;
|
||||||
|
|
||||||
mat34 *mat1 = &frames[frame1 * numjoints];
|
mat34 *mat1 = &q->frames[frame1 * q->numjoints];
|
||||||
mat34 *mat2 = &frames[frame2 * numjoints];
|
mat34 *mat2 = &q->frames[frame2 * q->numjoints];
|
||||||
mat34 *mat3 = &frames[frame3 * numjoints];
|
mat34 *mat3 = &q->frames[frame3 * q->numjoints];
|
||||||
mat34 *mat4 = &frames[frame4 * numjoints];
|
mat34 *mat4 = &q->frames[frame4 * q->numjoints];
|
||||||
|
|
||||||
for(int i = 0; i < numjoints; i++) {
|
for(int i = 0; i < q->numjoints; i++) {
|
||||||
mat34 matA, matB, matF;
|
mat34 matA, matB, matF;
|
||||||
lerp34(matA, mat1[i], mat2[i], alphaA);
|
lerp34(matA, mat1[i], mat2[i], alphaA);
|
||||||
lerp34(matB, mat3[i], mat4[i], alphaB);
|
lerp34(matB, mat3[i], mat4[i], alphaB);
|
||||||
lerp34(matF, matA, matB, alpha );
|
lerp34(matF, matA, matB, alpha );
|
||||||
if(joints[i].parent >= 0) multiply34x2(outframe[i], outframe[joints[i].parent], matF);
|
if(q->joints[i].parent >= 0) multiply34x2(q->outframe[i], q->outframe[q->joints[i].parent], matF);
|
||||||
else copy34(outframe[i], matF);
|
else copy34(q->outframe[i], matF);
|
||||||
}
|
}
|
||||||
|
|
||||||
return frame1 + alpha;
|
return frame1 + alpha;
|
||||||
|
@ -373441,20 +373480,20 @@ float model_animate_clip(model_t m, float curframe, int minframe, int maxframe,
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
float retframe = -1;
|
float retframe = -1;
|
||||||
if( numframes > 0 ) {
|
if( q->numframes > 0 ) {
|
||||||
vec3 p = pose(curframe >= m.curframe, curframe, minframe, maxframe, loop, &retframe);
|
vec3 p = pose(curframe >= m.curframe, curframe, minframe, maxframe, loop, &retframe);
|
||||||
int frame1 = p.x;
|
int frame1 = p.x;
|
||||||
int frame2 = p.y;
|
int frame2 = p.y;
|
||||||
float offset = p.z;
|
float offset = p.z;
|
||||||
|
|
||||||
mat34 *mat1 = &frames[frame1 * numjoints];
|
mat34 *mat1 = &q->frames[frame1 * q->numjoints];
|
||||||
mat34 *mat2 = &frames[frame2 * numjoints];
|
mat34 *mat2 = &q->frames[frame2 * q->numjoints];
|
||||||
|
|
||||||
// @todo: add animation blending and inter-frame blending here
|
// @todo: add animation blending and inter-frame blending here
|
||||||
for(int i = 0; i < numjoints; i++) {
|
for(int i = 0; i < q->numjoints; i++) {
|
||||||
mat34 mat; lerp34(mat, mat1[i], mat2[i], offset);
|
mat34 mat; lerp34(mat, mat1[i], mat2[i], offset);
|
||||||
if(joints[i].parent >= 0) multiply34x2(outframe[i], outframe[joints[i].parent], mat);
|
if(q->joints[i].parent >= 0) multiply34x2(q->outframe[i], q->outframe[q->joints[i].parent], mat);
|
||||||
else copy34(outframe[i], mat);
|
else copy34(q->outframe[i], mat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373465,20 +373504,20 @@ void model_render_skeleton(model_t m, mat44 M) {
|
||||||
if(!m.iqm) return;
|
if(!m.iqm) return;
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
if(!numjoints) return;
|
if(!q->numjoints) return;
|
||||||
|
|
||||||
ddraw_ontop_push(true);
|
ddraw_ontop_push(true);
|
||||||
ddraw_color_push(RED);
|
ddraw_color_push(RED);
|
||||||
|
|
||||||
for( int joint = 0; joint < numjoints; joint++ ) {
|
for( int joint = 0; joint < q->numjoints; joint++ ) {
|
||||||
if( joints[joint].parent < 0) continue;
|
if( q->joints[joint].parent < 0) continue;
|
||||||
|
|
||||||
// bone space...
|
// bone space...
|
||||||
mat34 f;
|
mat34 f;
|
||||||
model_get_bone_pose(m, joint, &f);
|
model_get_bone_pose(m, joint, &f);
|
||||||
vec3 pos = vec3(f[3],f[7],f[11]);
|
vec3 pos = vec3(f[3],f[7],f[11]);
|
||||||
|
|
||||||
model_get_bone_pose(m, joints[joint].parent, &f);
|
model_get_bone_pose(m, q->joints[joint].parent, &f);
|
||||||
vec3 src = vec3(f[3],f[7],f[11]);
|
vec3 src = vec3(f[3],f[7],f[11]);
|
||||||
|
|
||||||
// ...to model space
|
// ...to model space
|
||||||
|
@ -373506,7 +373545,7 @@ void model_render_skeleton(model_t m, mat44 M) {
|
||||||
float model_animate(model_t m, float curframe) {
|
float model_animate(model_t m, float curframe) {
|
||||||
if(!m.iqm) return -1;
|
if(!m.iqm) return -1;
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
return model_animate_clip(m, curframe, 0, numframes-1, true);
|
return model_animate_clip(m, curframe, 0, q->numframes-1, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
|
@ -373514,19 +373553,19 @@ void model_draw_call(model_t m, int shader) {
|
||||||
if(!m.iqm) return;
|
if(!m.iqm) return;
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
glBindVertexArray( vao );
|
glBindVertexArray( q->vao );
|
||||||
|
|
||||||
struct iqmtriangle *tris = NULL;
|
struct iqmtriangle *tris = NULL;
|
||||||
for(int i = 0; i < nummeshes; i++) {
|
for(int i = 0; i < q->nummeshes; i++) {
|
||||||
struct iqmmesh *im = &meshes[i];
|
struct iqmmesh *im = &q->meshes[i];
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, textures[i] );
|
glBindTexture(GL_TEXTURE_2D, q->textures[i] );
|
||||||
glUniform1i(glGetUniformLocation(shader, "u_texture2d"), 0 );
|
glUniform1i(glGetUniformLocation(shader, "u_texture2d"), 0 );
|
||||||
|
|
||||||
int loc;
|
int loc;
|
||||||
if ((loc = glGetUniformLocation(shader, "u_textured")) >= 0) {
|
if ((loc = glGetUniformLocation(shader, "u_textured")) >= 0) {
|
||||||
bool textured = !!textures[i] && textures[i] != texture_checker().id; // m.materials[i].layer[0].texture != texture_checker().id;
|
bool textured = !!q->textures[i] && q->textures[i] != texture_checker().id; // m.materials[i].layer[0].texture != texture_checker().id;
|
||||||
glUniform1i(loc, textured ? GL_TRUE : GL_FALSE);
|
glUniform1i(loc, textured ? GL_TRUE : GL_FALSE);
|
||||||
if ((loc = glGetUniformLocation(shader, "u_diffuse")) >= 0) {
|
if ((loc = glGetUniformLocation(shader, "u_diffuse")) >= 0) {
|
||||||
glUniform4f(loc, m.materials[i].layer[0].color.r, m.materials[i].layer[0].color.g, m.materials[i].layer[0].color.b, m.materials[i].layer[0].color.a);
|
glUniform4f(loc, m.materials[i].layer[0].color.r, m.materials[i].layer[0].color.g, m.materials[i].layer[0].color.b, m.materials[i].layer[0].color.a);
|
||||||
|
@ -373586,10 +373625,10 @@ aabb aabb_transform( aabb A, mat44 M ) {
|
||||||
|
|
||||||
aabb model_aabb(model_t m, mat44 transform) {
|
aabb model_aabb(model_t m, mat44 transform) {
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
if( q && bounds ) {
|
if( q && q->bounds ) {
|
||||||
int f = ( (int)m.curframe ) % (numframes + !numframes);
|
int f = ( (int)m.curframe ) % (q->numframes + !q->numframes);
|
||||||
vec3 bbmin = ptr3(bounds[f].bbmin);
|
vec3 bbmin = ptr3(q->bounds[f].bbmin);
|
||||||
vec3 bbmax = ptr3(bounds[f].bbmax);
|
vec3 bbmax = ptr3(q->bounds[f].bbmax);
|
||||||
return aabb_transform(aabb(bbmin,bbmax), transform);
|
return aabb_transform(aabb(bbmin,bbmax), transform);
|
||||||
}
|
}
|
||||||
return aabb(vec3(0,0,0),vec3(0,0,0));
|
return aabb(vec3(0,0,0),vec3(0,0,0));
|
||||||
|
@ -373604,62 +373643,22 @@ void model_destroy(model_t m) {
|
||||||
|
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
// if(m.mesh) mesh_destroy(m.mesh);
|
// if(m.mesh) mesh_destroy(m.mesh);
|
||||||
FREE(outframe);
|
FREE(q->outframe);
|
||||||
FREE(colormaps);
|
FREE(q->colormaps);
|
||||||
FREE(textures);
|
FREE(q->textures);
|
||||||
FREE(baseframe);
|
FREE(q->baseframe);
|
||||||
FREE(inversebaseframe);
|
FREE(q->inversebaseframe);
|
||||||
if(animdata != meshdata) FREE(animdata);
|
if(q->animdata != q->meshdata) FREE(q->animdata);
|
||||||
//FREE(meshdata);
|
//FREE(q->meshdata);
|
||||||
FREE(frames);
|
FREE(q->frames);
|
||||||
FREE(buf);
|
FREE(q->buf);
|
||||||
FREE(q);
|
FREE(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef program
|
|
||||||
#undef meshdata
|
|
||||||
#undef animdata
|
|
||||||
#undef nummeshes
|
|
||||||
#undef numtris
|
|
||||||
#undef numverts
|
|
||||||
#undef numjoints
|
|
||||||
#undef numframes
|
|
||||||
#undef numanims
|
|
||||||
#undef meshes
|
|
||||||
#undef textures
|
|
||||||
#undef joints
|
|
||||||
#undef poses
|
|
||||||
#undef anims
|
|
||||||
#undef baseframe
|
|
||||||
#undef inversebaseframe
|
|
||||||
#undef outframe
|
|
||||||
#undef frames
|
|
||||||
#undef vao
|
|
||||||
#undef ibo
|
|
||||||
#undef vbo
|
|
||||||
#undef bonematsoffset
|
|
||||||
#undef buf
|
|
||||||
#undef bounds
|
|
||||||
#undef colormaps
|
|
||||||
|
|
||||||
anims_t animations(const char *pathfile, int flags) {
|
anims_t animations(const char *pathfile, int flags) {
|
||||||
anims_t a = {0};
|
anims_t a = {0};
|
||||||
char *anim_file = vfs_read(strendi(pathfile,".txt") ? pathfile : va("%s@animlist.txt", pathfile));
|
a.speed = 1.0;
|
||||||
if( anim_file ) {
|
a.anims = animlist(pathfile);
|
||||||
// deserialize anim
|
|
||||||
a.speed = 1.0;
|
|
||||||
for each_substring(anim_file, "\r\n", anim) {
|
|
||||||
int from, to;
|
|
||||||
char anim_name[128] = {0};
|
|
||||||
if( sscanf(anim, "%*s %d-%d %127[^\r\n]", &from, &to, anim_name) != 3) continue;
|
|
||||||
array_push(a.anims, !!strstri(anim_name, "loop") || !strcmpi(anim_name, "idle") ? loop(from, to, 0, 0) : clip(from, to, 0, 0)); // [from,to,flags]
|
|
||||||
array_back(a.anims)->name = strswap(strswap(strswap(STRDUP(anim_name), "Loop", ""), "loop", ""), "()", ""); // @leak
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// placeholder
|
|
||||||
array_push(a.anims, clip(0,1,0,0));
|
|
||||||
array_back(a.anims)->name = STRDUP("Error"); // @leak
|
|
||||||
}
|
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -374937,6 +374936,8 @@ void object_update(object_t *obj) {
|
||||||
quat p = eulerq(vec3(obj->pivot.x,obj->pivot.y,obj->pivot.z));
|
quat p = eulerq(vec3(obj->pivot.x,obj->pivot.y,obj->pivot.z));
|
||||||
quat e = eulerq(vec3(obj->euler.x,obj->euler.y,obj->euler.z));
|
quat e = eulerq(vec3(obj->euler.x,obj->euler.y,obj->euler.z));
|
||||||
compose44(obj->transform, obj->pos, mulq(e, p), obj->sca);
|
compose44(obj->transform, obj->pos, mulq(e, p), obj->sca);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object_t object() {
|
object_t object() {
|
||||||
|
@ -374986,6 +374987,11 @@ void object_model(object_t *obj, model_t model) {
|
||||||
obj->model = model;
|
obj->model = model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void object_anim(object_t *obj, anim_t anim, float speed) {
|
||||||
|
obj->anim = anim;
|
||||||
|
obj->anim_speed = speed;
|
||||||
|
}
|
||||||
|
|
||||||
void object_push_diffuse(object_t *obj, texture_t tex) {
|
void object_push_diffuse(object_t *obj, texture_t tex) {
|
||||||
array_push(obj->textures, tex.id);
|
array_push(obj->textures, tex.id);
|
||||||
}
|
}
|
||||||
|
@ -375253,6 +375259,7 @@ void scene_render(int flags) {
|
||||||
for(unsigned j = 0, obj_count = scene_count(); j < obj_count; ++j ) {
|
for(unsigned j = 0, obj_count = scene_count(); j < obj_count; ++j ) {
|
||||||
object_t *obj = scene_index(j);
|
object_t *obj = scene_index(j);
|
||||||
model_t *model = &obj->model;
|
model_t *model = &obj->model;
|
||||||
|
anim_t *anim = &obj->anim;
|
||||||
mat44 *views = (mat44*)(&cam->view);
|
mat44 *views = (mat44*)(&cam->view);
|
||||||
|
|
||||||
// @todo: avoid heap allocs here?
|
// @todo: avoid heap allocs here?
|
||||||
|
@ -375277,6 +375284,11 @@ void scene_render(int flags) {
|
||||||
shader_vec3v("u_coefficients_sh", 9, last_scene->skybox.cubemap.sh);
|
shader_vec3v("u_coefficients_sh", 9, last_scene->skybox.cubemap.sh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (anim) {
|
||||||
|
float delta = window_delta() * obj->anim_speed;
|
||||||
|
model->curframe = model_animate_clip(*model, model->curframe + delta, anim->from, anim->to, anim->flags & ANIM_LOOP );
|
||||||
|
}
|
||||||
|
|
||||||
model->billboard = obj->billboard;
|
model->billboard = obj->billboard;
|
||||||
model_render(*model, cam->proj, cam->view, obj->transform, 0);
|
model_render(*model, cam->proj, cam->view, obj->transform, 0);
|
||||||
|
|
||||||
|
|
|
@ -1501,7 +1501,7 @@ in vec4 instanceGlyph;\n\
|
||||||
uniform sampler2D sampler_font;\n\
|
uniform sampler2D sampler_font;\n\
|
||||||
uniform sampler2D sampler_meta;\n\
|
uniform sampler2D sampler_meta;\n\
|
||||||
\n\
|
\n\
|
||||||
uniform float offset_firstline; // ascent - descent - linegap/2\n\
|
uniform float offset_firstline; // ascent\n\
|
||||||
uniform float scale_factor; // scaling factor proportional to font size\n\
|
uniform float scale_factor; // scaling factor proportional to font size\n\
|
||||||
uniform vec2 string_offset; // offset of upper-left corner\n\
|
uniform vec2 string_offset; // offset of upper-left corner\n\
|
||||||
\n\
|
\n\
|
||||||
|
@ -1666,6 +1666,20 @@ void ui_font() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void font_scale(const char *tag, int s, float v) {
|
||||||
|
font_init();
|
||||||
|
|
||||||
|
if (s < 0 || s >= 10) return;
|
||||||
|
|
||||||
|
unsigned index = *tag - FONT_FACE1[0];
|
||||||
|
if( index > FONTS_MAX ) return;
|
||||||
|
|
||||||
|
font_t *f = &fonts[index];
|
||||||
|
if (!f->initialized) return;
|
||||||
|
|
||||||
|
f->scale[s] = v / f->font_size;
|
||||||
|
}
|
||||||
|
|
||||||
void font_scales(const char *tag, float h1, float h2, float h3, float h4, float h5, float h6) {
|
void font_scales(const char *tag, float h1, float h2, float h3, float h4, float h5, float h6) {
|
||||||
font_init();
|
font_init();
|
||||||
|
|
||||||
|
@ -2048,7 +2062,7 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm
|
||||||
font_t *f = &fonts[0];
|
font_t *f = &fonts[0];
|
||||||
int S = 3;
|
int S = 3;
|
||||||
uint32_t color = 0;
|
uint32_t color = 0;
|
||||||
float X = 0, Y = 0, W = 0, L = f->ascent*f->factor*f->scale[S], LL = L; // LL=largest linedist
|
float X = 0, Y = 0, W = 0, L = f->ascent*f->factor*f->scale[S], LL = 0; // LL=largest linedist
|
||||||
offset.y = -offset.y; // invert y polarity
|
offset.y = -offset.y; // invert y polarity
|
||||||
|
|
||||||
// utf8 to utf32
|
// utf8 to utf32
|
||||||
|
@ -2080,6 +2094,7 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm
|
||||||
|
|
||||||
// change size
|
// change size
|
||||||
S = ch;
|
S = ch;
|
||||||
|
//@hack: use descent when we use >H4
|
||||||
L = f->ascent*f->factor*f->scale[S];
|
L = f->ascent*f->factor*f->scale[S];
|
||||||
if(L > LL) LL = L;
|
if(L > LL) LL = L;
|
||||||
continue;
|
continue;
|
||||||
|
@ -2096,10 +2111,27 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm
|
||||||
|
|
||||||
// change face
|
// change face
|
||||||
f = &fonts[ ch - 0x10 ];
|
f = &fonts[ ch - 0x10 ];
|
||||||
|
L = f->ascent*f->factor*f->scale[S];
|
||||||
|
if(L > LL) LL = L;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!LL)
|
||||||
|
LL = L;
|
||||||
|
|
||||||
|
if (ch == FONT_LEFT[0] && (
|
||||||
|
(unicode[i+1]) == FONT_LEFT[1] ||
|
||||||
|
(unicode[i+1]) == FONT_CENTER[1] ||
|
||||||
|
(unicode[i+1]) == FONT_RIGHT[1] ||
|
||||||
|
(unicode[i+1]) == FONT_TOP[1] ||
|
||||||
|
(unicode[i+1]) == FONT_MIDDLE[1] ||
|
||||||
|
(unicode[i+1]) == FONT_BASELINE[1] ||
|
||||||
|
(unicode[i+1]) == FONT_BOTTOM[1]
|
||||||
|
)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// convert to vbo data
|
// convert to vbo data
|
||||||
int cp = ch - f->begin; // f->cp2iter[ch - f->begin];
|
int cp = ch - f->begin; // f->cp2iter[ch - f->begin];
|
||||||
//if(cp == 0xFFFD) continue;
|
//if(cp == 0xFFFD) continue;
|
||||||
|
@ -2354,25 +2386,25 @@ void font_goto(float x, float y) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print and linefeed. Text may include markup code
|
// Print and linefeed. Text may include markup code
|
||||||
vec2 font_print(const char *text) {
|
vec2 font_print_rect(const char *text, vec4 rect) {
|
||||||
// @fixme: remove this hack
|
// @fixme: remove this hack
|
||||||
if( text[0] == FONT_LEFT[0] ) {
|
if( text[0] == FONT_LEFT[0] ) {
|
||||||
int l = text[1] == FONT_LEFT[1];
|
int l = text[1] == FONT_LEFT[1];
|
||||||
int c = text[1] == FONT_CENTER[1];
|
int c = text[1] == FONT_CENTER[1];
|
||||||
int r = text[1] == FONT_RIGHT[1];
|
int r = text[1] == FONT_RIGHT[1];
|
||||||
if( l || c || r ) {
|
if( l || c || r ) {
|
||||||
vec2 rect = font_rect(text + 2);
|
vec2 text_rect = font_rect(text + 2);
|
||||||
gotoxy.x = l ? 0 : r ? (window_width() - rect.x) : window_width()/2 - rect.x/2;
|
gotoxy.x = l ? rect.x : r ? ((rect.x+rect.z) - text_rect.x) : rect.x+rect.z/2. - text_rect.x/2.;
|
||||||
return font_print(text + 2);
|
return font_print_rect(text + 2, rect);
|
||||||
}
|
}
|
||||||
int t = text[1] == FONT_TOP[1];
|
int t = text[1] == FONT_TOP[1];
|
||||||
int b = text[1] == FONT_BOTTOM[1];
|
int b = text[1] == FONT_BOTTOM[1];
|
||||||
int m = text[1] == FONT_MIDDLE[1];
|
int m = text[1] == FONT_MIDDLE[1];
|
||||||
int B = text[1] == FONT_BASELINE[1];
|
int B = text[1] == FONT_BASELINE[1];
|
||||||
if( t || b || m || B ) {
|
if( t || b || m || B ) {
|
||||||
vec2 rect = font_rect(text + 2);
|
vec2 text_rect = font_rect(text + 2);
|
||||||
gotoxy.y = t ? 0 : b ? (window_height() - rect.y) : m ? window_height()/2-rect.y/2 : window_height()/2-rect.y/1;
|
gotoxy.y = t ? rect.y : b ? ((rect.y+rect.w) - text_rect.y) : m ? rect.y+rect.w/2.-text_rect.y/2. : rect.y+rect.w/2.-text_rect.y/1;
|
||||||
return font_print(text + 2);
|
return font_print_rect(text + 2, rect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2382,6 +2414,11 @@ vec2 font_print(const char *text) {
|
||||||
return dims;
|
return dims;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vec2 font_print(const char *text) {
|
||||||
|
vec4 dims = {0, 0, window_width(), window_height()};
|
||||||
|
return font_print_rect(text, dims);
|
||||||
|
}
|
||||||
|
|
||||||
// Print a code snippet with syntax highlighting
|
// Print a code snippet with syntax highlighting
|
||||||
vec2 font_highlight(const char *text, const void *colors) {
|
vec2 font_highlight(const char *text, const void *colors) {
|
||||||
vec2 dims = font_draw_ex(text, gotoxy, (const char *)colors, font_draw_cmd);
|
vec2 dims = font_draw_ex(text, gotoxy, (const char *)colors, font_draw_cmd);
|
||||||
|
|
|
@ -73,13 +73,14 @@ enum FONT_FLAGS {
|
||||||
typedef struct font_metrics_t {
|
typedef struct font_metrics_t {
|
||||||
float ascent; // max distance above baseline for all glyphs
|
float ascent; // max distance above baseline for all glyphs
|
||||||
float descent; // max distance below baseline for all glyphs
|
float descent; // max distance below baseline for all glyphs
|
||||||
float linegap; // distance betwen ascent of next line and descent of current line
|
float linegap; // distance between ascent of next line and descent of current line
|
||||||
float linedist; // distance between the baseline of two lines (ascent - descent + linegap)
|
float linedist; // distance between the baseline of two lines (ascent - descent + linegap)
|
||||||
} font_metrics_t;
|
} font_metrics_t;
|
||||||
|
|
||||||
// configures
|
// configures
|
||||||
API void font_face(const char *face_tag, const char *filename_ttf, float font_size, unsigned flags);
|
API void font_face(const char *face_tag, const char *filename_ttf, float font_size, unsigned flags);
|
||||||
API void font_face_from_mem(const char *tag, const void *ttf_buffer, unsigned ttf_len, float font_size, unsigned flags);
|
API void font_face_from_mem(const char *tag, const void *ttf_buffer, unsigned ttf_len, float font_size, unsigned flags);
|
||||||
|
API void font_scale(const char *face_tag, int scale_index, float value);
|
||||||
API void font_scales(const char *face_tag, float h1, float h2, float h3, float h4, float h5, float h6);
|
API void font_scales(const char *face_tag, float h1, float h2, float h3, float h4, float h5, float h6);
|
||||||
API void font_color(const char *color_tag, uint32_t color);
|
API void font_color(const char *color_tag, uint32_t color);
|
||||||
|
|
||||||
|
@ -87,6 +88,7 @@ API void font_color(const char *color_tag, uint32_t color);
|
||||||
API vec2 font_xy();
|
API vec2 font_xy();
|
||||||
API void font_goto(float x, float y);
|
API void font_goto(float x, float y);
|
||||||
API vec2 font_print(const char *text);
|
API vec2 font_print(const char *text);
|
||||||
|
API vec2 font_print_rect(const char *text, vec4 rect);
|
||||||
API vec2 font_rect(const char *text);
|
API vec2 font_rect(const char *text);
|
||||||
API font_metrics_t font_metrics(const char *text);
|
API font_metrics_t font_metrics(const char *text);
|
||||||
// void font_clip(vec2 topleft, vec2 bottomright);
|
// void font_clip(vec2 topleft, vec2 bottomright);
|
||||||
|
|
|
@ -2797,37 +2797,12 @@ typedef struct iqm_t {
|
||||||
vec4 *colormaps;
|
vec4 *colormaps;
|
||||||
} iqm_t;
|
} iqm_t;
|
||||||
|
|
||||||
#define meshdata (q->meshdata)
|
|
||||||
#define animdata (q->animdata)
|
|
||||||
#define nummeshes (q->nummeshes)
|
|
||||||
#define numtris (q->numtris)
|
|
||||||
#define numverts (q->numverts)
|
|
||||||
#define numjoints (q->numjoints)
|
|
||||||
#define numframes (q->numframes)
|
|
||||||
#define numanims (q->numanims)
|
|
||||||
#define meshes (q->meshes)
|
|
||||||
#define textures (q->textures)
|
|
||||||
#define joints (q->joints)
|
|
||||||
#define poses (q->poses)
|
|
||||||
#define anims (q->anims)
|
|
||||||
#define baseframe (q->baseframe)
|
|
||||||
#define inversebaseframe (q->inversebaseframe)
|
|
||||||
#define outframe (q->outframe)
|
|
||||||
#define frames (q->frames)
|
|
||||||
#define vao (q->vao)
|
|
||||||
#define ibo (q->ibo)
|
|
||||||
#define vbo (q->vbo)
|
|
||||||
#define bonematsoffset (q->bonematsoffset)
|
|
||||||
#define buf (q->buf)
|
|
||||||
#define bounds (q->bounds)
|
|
||||||
#define colormaps (q->colormaps)
|
|
||||||
|
|
||||||
void model_set_texture(model_t m, texture_t t) {
|
void model_set_texture(model_t m, texture_t t) {
|
||||||
if(!m.iqm) return;
|
if(!m.iqm) return;
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
for( int i = 0; i < nummeshes; ++i) { // assume 1 texture per mesh
|
for( int i = 0; i < q->nummeshes; ++i) { // assume 1 texture per mesh
|
||||||
textures[i] = t.id;
|
q->textures[i] = t.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2920,9 +2895,9 @@ void model_set_uniforms(model_t m, int shader, mat44 mv, mat44 proj, mat44 view,
|
||||||
if ((loc = glGetUniformLocation(shader, "proj")) >= 0) {
|
if ((loc = glGetUniformLocation(shader, "proj")) >= 0) {
|
||||||
glUniformMatrix4fv(loc, 1, GL_FALSE, proj);
|
glUniformMatrix4fv(loc, 1, GL_FALSE, proj);
|
||||||
}
|
}
|
||||||
if( (loc = glGetUniformLocation(shader, "SKINNED")) >= 0 ) glUniform1i( loc, numanims ? GL_TRUE : GL_FALSE);
|
if( (loc = glGetUniformLocation(shader, "SKINNED")) >= 0 ) glUniform1i( loc, q->numanims ? GL_TRUE : GL_FALSE);
|
||||||
if( numanims )
|
if( q->numanims )
|
||||||
if( (loc = glGetUniformLocation(shader, "vsBoneMatrix")) >= 0 ) glUniformMatrix3x4fv( loc, numjoints, GL_FALSE, outframe[0]);
|
if( (loc = glGetUniformLocation(shader, "vsBoneMatrix")) >= 0 ) glUniformMatrix3x4fv( loc, q->numjoints, GL_FALSE, q->outframe[0]);
|
||||||
|
|
||||||
if ((loc = glGetUniformLocation(shader, "u_matcaps")) >= 0) {
|
if ((loc = glGetUniformLocation(shader, "u_matcaps")) >= 0) {
|
||||||
glUniform1i(loc, m.flags & MODEL_MATCAPS ? GL_TRUE:GL_FALSE);
|
glUniform1i(loc, m.flags & MODEL_MATCAPS ? GL_TRUE:GL_FALSE);
|
||||||
|
@ -2933,10 +2908,10 @@ void model_set_state(model_t m) {
|
||||||
if(!m.iqm) return;
|
if(!m.iqm) return;
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
glBindVertexArray( vao );
|
glBindVertexArray( q->vao );
|
||||||
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, q->ibo);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
glBindBuffer(GL_ARRAY_BUFFER, q->vbo);
|
||||||
|
|
||||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, position) );
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, position) );
|
||||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, texcoord) );
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, texcoord) );
|
||||||
|
@ -2957,7 +2932,7 @@ void model_set_state(model_t m) {
|
||||||
glEnableVertexAttribArray(12);
|
glEnableVertexAttribArray(12);
|
||||||
|
|
||||||
// animation
|
// animation
|
||||||
if(numframes > 0) {
|
if(q->numframes > 0) {
|
||||||
glVertexAttribPointer( 8, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,blendindexes) );
|
glVertexAttribPointer( 8, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,blendindexes) );
|
||||||
glVertexAttribPointer( 9, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,blendweights) );
|
glVertexAttribPointer( 9, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,blendweights) );
|
||||||
glVertexAttribPointer(10, 1, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, blendvertexindex) );
|
glVertexAttribPointer(10, 1, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, blendvertexindex) );
|
||||||
|
@ -2998,71 +2973,71 @@ void model_set_state(model_t m) {
|
||||||
|
|
||||||
static
|
static
|
||||||
bool model_load_meshes(iqm_t *q, const struct iqmheader *hdr, model_t *m) {
|
bool model_load_meshes(iqm_t *q, const struct iqmheader *hdr, model_t *m) {
|
||||||
if(meshdata) return false;
|
if(q->meshdata) return false;
|
||||||
|
|
||||||
lil32p(&buf[hdr->ofs_vertexarrays], hdr->num_vertexarrays*sizeof(struct iqmvertexarray)/sizeof(uint32_t));
|
lil32p(&q->buf[hdr->ofs_vertexarrays], hdr->num_vertexarrays*sizeof(struct iqmvertexarray)/sizeof(uint32_t));
|
||||||
lil32p(&buf[hdr->ofs_triangles], hdr->num_triangles*sizeof(struct iqmtriangle)/sizeof(uint32_t));
|
lil32p(&q->buf[hdr->ofs_triangles], hdr->num_triangles*sizeof(struct iqmtriangle)/sizeof(uint32_t));
|
||||||
lil32p(&buf[hdr->ofs_meshes], hdr->num_meshes*sizeof(struct iqmmesh)/sizeof(uint32_t));
|
lil32p(&q->buf[hdr->ofs_meshes], hdr->num_meshes*sizeof(struct iqmmesh)/sizeof(uint32_t));
|
||||||
lil32p(&buf[hdr->ofs_joints], hdr->num_joints*sizeof(struct iqmjoint)/sizeof(uint32_t));
|
lil32p(&q->buf[hdr->ofs_joints], hdr->num_joints*sizeof(struct iqmjoint)/sizeof(uint32_t));
|
||||||
|
|
||||||
meshdata = buf;
|
q->meshdata = q->buf;
|
||||||
nummeshes = hdr->num_meshes;
|
q->nummeshes = hdr->num_meshes;
|
||||||
numtris = hdr->num_triangles;
|
q->numtris = hdr->num_triangles;
|
||||||
numverts = hdr->num_vertexes;
|
q->numverts = hdr->num_vertexes;
|
||||||
numjoints = hdr->num_joints;
|
q->numjoints = hdr->num_joints;
|
||||||
outframe = CALLOC(hdr->num_joints, sizeof(mat34));
|
q->outframe = CALLOC(hdr->num_joints, sizeof(mat34));
|
||||||
|
|
||||||
float *inposition = NULL, *innormal = NULL, *intangent = NULL, *intexcoord = NULL, *invertexindex = NULL;
|
float *inposition = NULL, *innormal = NULL, *intangent = NULL, *intexcoord = NULL, *invertexindex = NULL;
|
||||||
uint8_t *inblendindex8 = NULL, *inblendweight8 = NULL;
|
uint8_t *inblendindex8 = NULL, *inblendweight8 = NULL;
|
||||||
int *inblendindexi = NULL; float *inblendweightf = NULL;
|
int *inblendindexi = NULL; float *inblendweightf = NULL;
|
||||||
uint8_t *invertexcolor8 = NULL;
|
uint8_t *invertexcolor8 = NULL;
|
||||||
struct iqmvertexarray *vas = (struct iqmvertexarray *)&buf[hdr->ofs_vertexarrays];
|
struct iqmvertexarray *vas = (struct iqmvertexarray *)&q->buf[hdr->ofs_vertexarrays];
|
||||||
for(int i = 0; i < (int)hdr->num_vertexarrays; i++) {
|
for(int i = 0; i < (int)hdr->num_vertexarrays; i++) {
|
||||||
struct iqmvertexarray *va = &vas[i];
|
struct iqmvertexarray *va = &vas[i];
|
||||||
switch(va->type) {
|
switch(va->type) {
|
||||||
default: continue; // return PANIC("unknown iqm vertex type (%d)", va->type), false;
|
default: continue; // return PANIC("unknown iqm vertex type (%d)", va->type), false;
|
||||||
break; case IQM_POSITION: ASSERT(va->format == IQM_FLOAT && va->size == 3); inposition = (float *)&buf[va->offset]; lil32pf(inposition, 3*hdr->num_vertexes);
|
break; case IQM_POSITION: ASSERT(va->format == IQM_FLOAT && va->size == 3); inposition = (float *)&q->buf[va->offset]; lil32pf(inposition, 3*hdr->num_vertexes);
|
||||||
break; case IQM_NORMAL: ASSERT(va->format == IQM_FLOAT && va->size == 3); innormal = (float *)&buf[va->offset]; lil32pf(innormal, 3*hdr->num_vertexes);
|
break; case IQM_NORMAL: ASSERT(va->format == IQM_FLOAT && va->size == 3); innormal = (float *)&q->buf[va->offset]; lil32pf(innormal, 3*hdr->num_vertexes);
|
||||||
break; case IQM_TANGENT: ASSERT(va->format == IQM_FLOAT && va->size == 4); intangent = (float *)&buf[va->offset]; lil32pf(intangent, 4*hdr->num_vertexes);
|
break; case IQM_TANGENT: ASSERT(va->format == IQM_FLOAT && va->size == 4); intangent = (float *)&q->buf[va->offset]; lil32pf(intangent, 4*hdr->num_vertexes);
|
||||||
break; case IQM_TEXCOORD: ASSERT(va->format == IQM_FLOAT && va->size == 2); intexcoord = (float *)&buf[va->offset]; lil32pf(intexcoord, 2*hdr->num_vertexes);
|
break; case IQM_TEXCOORD: ASSERT(va->format == IQM_FLOAT && va->size == 2); intexcoord = (float *)&q->buf[va->offset]; lil32pf(intexcoord, 2*hdr->num_vertexes);
|
||||||
break; case IQM_COLOR: ASSERT(va->size == 4); ASSERT(va->format == IQM_UBYTE); invertexcolor8 = (uint8_t *)&buf[va->offset];
|
break; case IQM_COLOR: ASSERT(va->size == 4); ASSERT(va->format == IQM_UBYTE); invertexcolor8 = (uint8_t *)&q->buf[va->offset];
|
||||||
break; case IQM_BLENDINDEXES: ASSERT(va->size == 4); ASSERT(va->format == IQM_UBYTE || va->format == IQM_INT);
|
break; case IQM_BLENDINDEXES: ASSERT(va->size == 4); ASSERT(va->format == IQM_UBYTE || va->format == IQM_INT);
|
||||||
if(va->format == IQM_UBYTE) inblendindex8 = (uint8_t *)&buf[va->offset];
|
if(va->format == IQM_UBYTE) inblendindex8 = (uint8_t *)&q->buf[va->offset];
|
||||||
else inblendindexi = (int *)&buf[va->offset];
|
else inblendindexi = (int *)&q->buf[va->offset];
|
||||||
break; case IQM_BLENDWEIGHTS: ASSERT(va->size == 4); ASSERT(va->format == IQM_UBYTE || va->format == IQM_FLOAT);
|
break; case IQM_BLENDWEIGHTS: ASSERT(va->size == 4); ASSERT(va->format == IQM_UBYTE || va->format == IQM_FLOAT);
|
||||||
if(va->format == IQM_UBYTE) inblendweight8 = (uint8_t *)&buf[va->offset];
|
if(va->format == IQM_UBYTE) inblendweight8 = (uint8_t *)&q->buf[va->offset];
|
||||||
else inblendweightf = (float *)&buf[va->offset];
|
else inblendweightf = (float *)&q->buf[va->offset];
|
||||||
invertexindex = (inblendweight8 ? (float*)(inblendweight8 + 4) : inblendweightf + 4 );
|
invertexindex = (inblendweight8 ? (float*)(inblendweight8 + 4) : inblendweightf + 4 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hdr->ofs_bounds) lil32p(buf + hdr->ofs_bounds, hdr->num_frames * sizeof(struct iqmbounds));
|
if (hdr->ofs_bounds) lil32p(q->buf + hdr->ofs_bounds, hdr->num_frames * sizeof(struct iqmbounds));
|
||||||
if (hdr->ofs_bounds) bounds = (struct iqmbounds *) &buf[hdr->ofs_bounds];
|
if (hdr->ofs_bounds) q->bounds = (struct iqmbounds *) &q->buf[hdr->ofs_bounds];
|
||||||
|
|
||||||
meshes = (struct iqmmesh *)&buf[hdr->ofs_meshes];
|
q->meshes = (struct iqmmesh *)&q->buf[hdr->ofs_meshes];
|
||||||
joints = (struct iqmjoint *)&buf[hdr->ofs_joints];
|
q->joints = (struct iqmjoint *)&q->buf[hdr->ofs_joints];
|
||||||
|
|
||||||
baseframe = CALLOC(hdr->num_joints, sizeof(mat34));
|
q->baseframe = CALLOC(hdr->num_joints, sizeof(mat34));
|
||||||
inversebaseframe = CALLOC(hdr->num_joints, sizeof(mat34));
|
q->inversebaseframe = CALLOC(hdr->num_joints, sizeof(mat34));
|
||||||
for(int i = 0; i < (int)hdr->num_joints; i++) {
|
for(int i = 0; i < (int)hdr->num_joints; i++) {
|
||||||
struct iqmjoint *j = &joints[i];
|
struct iqmjoint *j = &q->joints[i];
|
||||||
compose34(baseframe[i], ptr3(j->translate), normq(ptrq(j->rotate)), ptr3(j->scale));
|
compose34(q->baseframe[i], ptr3(j->translate), normq(ptrq(j->rotate)), ptr3(j->scale));
|
||||||
invert34(inversebaseframe[i], baseframe[i]);
|
invert34(q->inversebaseframe[i], q->baseframe[i]);
|
||||||
if(j->parent >= 0) {
|
if(j->parent >= 0) {
|
||||||
multiply34x2(baseframe[i], baseframe[j->parent], baseframe[i]);
|
multiply34x2(q->baseframe[i], q->baseframe[j->parent], q->baseframe[i]);
|
||||||
multiply34(inversebaseframe[i], inversebaseframe[j->parent]);
|
multiply34(q->inversebaseframe[i], q->inversebaseframe[j->parent]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct iqmtriangle *tris = (struct iqmtriangle *)&buf[hdr->ofs_triangles];
|
struct iqmtriangle *tris = (struct iqmtriangle *)&q->buf[hdr->ofs_triangles];
|
||||||
m->num_tris = hdr->num_triangles;
|
m->num_tris = hdr->num_triangles;
|
||||||
m->tris = (void*)tris;
|
m->tris = (void*)tris;
|
||||||
|
|
||||||
glGenVertexArrays(1, &vao);
|
glGenVertexArrays(1, &q->vao);
|
||||||
glBindVertexArray(vao);
|
glBindVertexArray(q->vao);
|
||||||
|
|
||||||
if(!ibo) glGenBuffers(1, &ibo);
|
if(!q->ibo) glGenBuffers(1, &q->ibo);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, q->ibo);
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, hdr->num_triangles*sizeof(struct iqmtriangle), tris, GL_STATIC_DRAW);
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, hdr->num_triangles*sizeof(struct iqmtriangle), tris, GL_STATIC_DRAW);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
@ -3093,8 +3068,8 @@ bool model_load_meshes(iqm_t *q, const struct iqmheader *hdr, model_t *m) {
|
||||||
if(invertexcolor8) memcpy(v->color, &invertexcolor8[i*4], sizeof(v->color));
|
if(invertexcolor8) memcpy(v->color, &invertexcolor8[i*4], sizeof(v->color));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!vbo) glGenBuffers(1, &vbo);
|
if(!q->vbo) glGenBuffers(1, &q->vbo);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
glBindBuffer(GL_ARRAY_BUFFER, q->vbo);
|
||||||
glBufferData(GL_ARRAY_BUFFER, hdr->num_vertexes*sizeof(iqm_vertex), verts, GL_STATIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, hdr->num_vertexes*sizeof(iqm_vertex), verts, GL_STATIC_DRAW);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
@ -3115,16 +3090,16 @@ bool model_load_meshes(iqm_t *q, const struct iqmheader *hdr, model_t *m) {
|
||||||
m->verts = verts;
|
m->verts = verts;
|
||||||
/*m->verts = 0; FREE(verts);*/
|
/*m->verts = 0; FREE(verts);*/
|
||||||
|
|
||||||
textures = CALLOC(hdr->num_meshes * 8, sizeof(GLuint));
|
q->textures = CALLOC(hdr->num_meshes * 8, sizeof(GLuint));
|
||||||
colormaps = CALLOC(hdr->num_meshes * 8, sizeof(vec4));
|
q->colormaps = CALLOC(hdr->num_meshes * 8, sizeof(vec4));
|
||||||
for(int i = 0; i < (int)hdr->num_meshes; i++) {
|
for(int i = 0; i < (int)hdr->num_meshes; i++) {
|
||||||
int invalid = texture_checker().id;
|
int invalid = texture_checker().id;
|
||||||
textures[i] = invalid;
|
q->textures[i] = invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *str = hdr->ofs_text ? (char *)&buf[hdr->ofs_text] : "";
|
const char *str = hdr->ofs_text ? (char *)&q->buf[hdr->ofs_text] : "";
|
||||||
for(int i = 0; i < (int)hdr->num_meshes; i++) {
|
for(int i = 0; i < (int)hdr->num_meshes; i++) {
|
||||||
struct iqmmesh *m = &meshes[i];
|
struct iqmmesh *m = &q->meshes[i];
|
||||||
PRINTF("loaded mesh: %s\n", &str[m->name]);
|
PRINTF("loaded mesh: %s\n", &str[m->name]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3133,34 +3108,34 @@ bool model_load_meshes(iqm_t *q, const struct iqmheader *hdr, model_t *m) {
|
||||||
|
|
||||||
static
|
static
|
||||||
bool model_load_anims(iqm_t *q, const struct iqmheader *hdr) {
|
bool model_load_anims(iqm_t *q, const struct iqmheader *hdr) {
|
||||||
if((int)hdr->num_poses != numjoints) return false;
|
if((int)hdr->num_poses != q->numjoints) return false;
|
||||||
|
|
||||||
if(animdata) {
|
if(q->animdata) {
|
||||||
if(animdata != meshdata) FREE(animdata);
|
if(q->animdata != q->meshdata) FREE(q->animdata);
|
||||||
FREE(frames);
|
FREE(q->frames);
|
||||||
animdata = NULL;
|
q->animdata = NULL;
|
||||||
anims = NULL;
|
q->anims = NULL;
|
||||||
frames = 0;
|
q->frames = 0;
|
||||||
numframes = 0;
|
q->numframes = 0;
|
||||||
numanims = 0;
|
q->numanims = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
lil32p(&buf[hdr->ofs_poses], hdr->num_poses*sizeof(struct iqmpose)/sizeof(uint32_t));
|
lil32p(&q->buf[hdr->ofs_poses], hdr->num_poses*sizeof(struct iqmpose)/sizeof(uint32_t));
|
||||||
lil32p(&buf[hdr->ofs_anims], hdr->num_anims*sizeof(struct iqmanim)/sizeof(uint32_t));
|
lil32p(&q->buf[hdr->ofs_anims], hdr->num_anims*sizeof(struct iqmanim)/sizeof(uint32_t));
|
||||||
lil16p((uint16_t *)&buf[hdr->ofs_frames], hdr->num_frames*hdr->num_framechannels);
|
lil16p((uint16_t *)&q->buf[hdr->ofs_frames], hdr->num_frames*hdr->num_framechannels);
|
||||||
|
|
||||||
animdata = buf;
|
q->animdata = q->buf;
|
||||||
numanims = hdr->num_anims;
|
q->numanims = hdr->num_anims;
|
||||||
numframes = hdr->num_frames;
|
q->numframes = hdr->num_frames;
|
||||||
|
|
||||||
anims = (struct iqmanim *)&buf[hdr->ofs_anims];
|
q->anims = (struct iqmanim *)&q->buf[hdr->ofs_anims];
|
||||||
poses = (struct iqmpose *)&buf[hdr->ofs_poses];
|
q->poses = (struct iqmpose *)&q->buf[hdr->ofs_poses];
|
||||||
frames = CALLOC(hdr->num_frames * hdr->num_poses, sizeof(mat34));
|
q->frames = CALLOC(hdr->num_frames * hdr->num_poses, sizeof(mat34));
|
||||||
uint16_t *framedata = (uint16_t *)&buf[hdr->ofs_frames];
|
uint16_t *framedata = (uint16_t *)&q->buf[hdr->ofs_frames];
|
||||||
|
|
||||||
for(int i = 0; i < (int)hdr->num_frames; i++) {
|
for(int i = 0; i < (int)hdr->num_frames; i++) {
|
||||||
for(int j = 0; j < (int)hdr->num_poses; j++) {
|
for(int j = 0; j < (int)hdr->num_poses; j++) {
|
||||||
struct iqmpose *p = &poses[j];
|
struct iqmpose *p = &q->poses[j];
|
||||||
quat rotate;
|
quat rotate;
|
||||||
vec3 translate, scale;
|
vec3 translate, scale;
|
||||||
translate.x = p->channeloffset[0]; if(p->mask&0x01) translate.x += *framedata++ * p->channelscale[0];
|
translate.x = p->channeloffset[0]; if(p->mask&0x01) translate.x += *framedata++ * p->channelscale[0];
|
||||||
|
@ -3184,16 +3159,16 @@ bool model_load_anims(iqm_t *q, const struct iqmheader *hdr) {
|
||||||
// parentPose * childPose * childInverseBasePose
|
// parentPose * childPose * childInverseBasePose
|
||||||
|
|
||||||
mat34 m; compose34(m, translate, normq(rotate), scale);
|
mat34 m; compose34(m, translate, normq(rotate), scale);
|
||||||
if(p->parent >= 0) multiply34x3(frames[i*hdr->num_poses + j], baseframe[p->parent], m, inversebaseframe[j]);
|
if(p->parent >= 0) multiply34x3(q->frames[i*hdr->num_poses + j], q->baseframe[p->parent], m, q->inversebaseframe[j]);
|
||||||
else multiply34x2(frames[i*hdr->num_poses + j], m, inversebaseframe[j]);
|
else multiply34x2(q->frames[i*hdr->num_poses + j], m, q->inversebaseframe[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *str = hdr->ofs_text ? (char *)&buf[hdr->ofs_text] : "";
|
// const char *str = hdr->ofs_text ? (char *)&q->buf[hdr->ofs_text] : "";
|
||||||
for(int i = 0; i < (int)hdr->num_anims; i++) {
|
// for(int i = 0; i < (int)hdr->num_anims; i++) {
|
||||||
struct iqmanim *a = &anims[i];
|
// struct iqmanim *a = &anims[i];
|
||||||
PRINTF("loaded anim[%d]: %s\n", i, &str[a->name]);
|
// PRINTF("loaded anim[%d]: %s\n", i, &str[a->name]);
|
||||||
}
|
// }
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -3206,14 +3181,14 @@ static char* strcpy_safe(char *d, const char *s) {
|
||||||
|
|
||||||
static
|
static
|
||||||
bool model_load_textures(iqm_t *q, const struct iqmheader *hdr, model_t *model) {
|
bool model_load_textures(iqm_t *q, const struct iqmheader *hdr, model_t *model) {
|
||||||
textures = textures ? textures : CALLOC(hdr->num_meshes * 8, sizeof(GLuint)); // up to 8 textures per mesh
|
q->textures = q->textures ? q->textures : CALLOC(hdr->num_meshes * 8, sizeof(GLuint)); // up to 8 textures per mesh
|
||||||
colormaps = colormaps ? colormaps : CALLOC(hdr->num_meshes * 8, sizeof(vec4)); // up to 8 colormaps per mesh
|
q->colormaps = q->colormaps ? q->colormaps : CALLOC(hdr->num_meshes * 8, sizeof(vec4)); // up to 8 colormaps per mesh
|
||||||
|
|
||||||
GLuint *out = textures;
|
GLuint *out = q->textures;
|
||||||
|
|
||||||
const char *str = hdr->ofs_text ? (char *)&buf[hdr->ofs_text] : "";
|
const char *str = hdr->ofs_text ? (char *)&q->buf[hdr->ofs_text] : "";
|
||||||
for(int i = 0; i < (int)hdr->num_meshes; i++) {
|
for(int i = 0; i < (int)hdr->num_meshes; i++) {
|
||||||
struct iqmmesh *m = &meshes[i];
|
struct iqmmesh *m = &q->meshes[i];
|
||||||
|
|
||||||
// reuse texture+material if already decoded
|
// reuse texture+material if already decoded
|
||||||
bool reused = 0;
|
bool reused = 0;
|
||||||
|
@ -3382,13 +3357,23 @@ model_t model_from_mem(const void *mem, int len, int flags) {
|
||||||
if( !memcmp(hdr.magic, IQM_MAGIC, sizeof(hdr.magic))) {
|
if( !memcmp(hdr.magic, IQM_MAGIC, sizeof(hdr.magic))) {
|
||||||
lil32p(&hdr.version, (sizeof(hdr) - sizeof(hdr.magic))/sizeof(uint32_t));
|
lil32p(&hdr.version, (sizeof(hdr) - sizeof(hdr.magic))/sizeof(uint32_t));
|
||||||
if(hdr.version == IQM_VERSION) {
|
if(hdr.version == IQM_VERSION) {
|
||||||
buf = CALLOC(hdr.filesize, sizeof(uint8_t));
|
q->buf = CALLOC(hdr.filesize, sizeof(uint8_t));
|
||||||
memcpy(buf + sizeof(hdr), ptr, hdr.filesize - sizeof(hdr));
|
memcpy(q->buf + sizeof(hdr), ptr, hdr.filesize - sizeof(hdr));
|
||||||
error = 0;
|
error = 0;
|
||||||
if( hdr.num_meshes > 0 && !(flags & MODEL_NO_MESHES) ) error |= !model_load_meshes(q, &hdr, &m);
|
if( hdr.num_meshes > 0 && !(flags & MODEL_NO_MESHES) ) error |= !model_load_meshes(q, &hdr, &m);
|
||||||
if( hdr.num_meshes > 0 && !(flags & MODEL_NO_TEXTURES) ) error |= !model_load_textures(q, &hdr, &m);
|
if( hdr.num_meshes > 0 && !(flags & MODEL_NO_TEXTURES) ) error |= !model_load_textures(q, &hdr, &m);
|
||||||
|
else {
|
||||||
|
// setup fallback
|
||||||
|
material_t mt = {0};
|
||||||
|
mt.name = "placeholder";
|
||||||
|
mt.count = 1;
|
||||||
|
mt.layer[0].color = vec4(1,1,1,1);
|
||||||
|
mt.layer[0].texture = texture_checker().id;
|
||||||
|
|
||||||
|
array_push(m.materials, mt);
|
||||||
|
}
|
||||||
if( hdr.num_anims > 0 && !(flags & MODEL_NO_ANIMATIONS) ) error |= !model_load_anims(q, &hdr);
|
if( hdr.num_anims > 0 && !(flags & MODEL_NO_ANIMATIONS) ) error |= !model_load_anims(q, &hdr);
|
||||||
if( buf != meshdata && buf != animdata ) FREE(buf);
|
if( q->buf != q->meshdata && q->buf != q->animdata ) FREE(q->buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3397,31 +3382,23 @@ model_t model_from_mem(const void *mem, int len, int flags) {
|
||||||
PRINTF("Error: cannot load %s", "model");
|
PRINTF("Error: cannot load %s", "model");
|
||||||
FREE(q), q = 0;
|
FREE(q), q = 0;
|
||||||
} else {
|
} else {
|
||||||
#undef vao
|
|
||||||
#undef ibo
|
|
||||||
#undef vbo
|
|
||||||
m.vao = q->vao;
|
m.vao = q->vao;
|
||||||
m.ibo = q->ibo;
|
m.ibo = q->ibo;
|
||||||
m.vbo = q->vbo;
|
m.vbo = q->vbo;
|
||||||
m.num_verts = numverts;
|
m.num_verts = q->numverts;
|
||||||
#define vao (q->vao)
|
|
||||||
#define ibo (q->ibo)
|
|
||||||
#define vbo (q->vbo)
|
|
||||||
|
|
||||||
// m.boxes = bounds; // <@todo
|
// m.boxes = bounds; // <@todo
|
||||||
m.num_meshes = nummeshes;
|
m.num_meshes = q->nummeshes;
|
||||||
m.num_triangles = numtris;
|
m.num_triangles = q->numtris;
|
||||||
m.num_joints = numjoints;
|
m.num_joints = q->numjoints;
|
||||||
//m.num_poses = numposes;
|
//m.num_poses = numposes;
|
||||||
m.num_anims = numanims;
|
m.num_anims = q->numanims;
|
||||||
m.num_frames = numframes;
|
m.num_frames = q->numframes;
|
||||||
m.iqm = q;
|
m.iqm = q;
|
||||||
m.curframe = model_animate(m, 0);
|
m.curframe = model_animate(m, 0);
|
||||||
|
|
||||||
//m.num_textures = nummeshes; // assume 1 texture only per mesh
|
//m.num_textures = q->nummeshes; // assume 1 texture only per mesh
|
||||||
#undef textures
|
|
||||||
m.textures = (q->textures);
|
m.textures = (q->textures);
|
||||||
#define textures (q->textures)
|
|
||||||
|
|
||||||
m.flags = flags;
|
m.flags = flags;
|
||||||
|
|
||||||
|
@ -3445,9 +3422,9 @@ bool model_get_bone_pose(model_t m, unsigned joint, mat34 *out) {
|
||||||
if(!m.iqm) return false;
|
if(!m.iqm) return false;
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
if(joint >= numjoints) return false;
|
if(joint >= q->numjoints) return false;
|
||||||
|
|
||||||
multiply34x2(*out, outframe[joint], baseframe[joint]);
|
multiply34x2(*out, q->outframe[joint], q->baseframe[joint]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3458,6 +3435,26 @@ anim_t loop(float minframe, float maxframe, float blendtime, unsigned flags) {
|
||||||
return clip(minframe, maxframe, blendtime, flags | ANIM_LOOP);
|
return clip(minframe, maxframe, blendtime, flags | ANIM_LOOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
array(anim_t) animlist(const char *pathfile) {
|
||||||
|
anim_t *animlist = 0;
|
||||||
|
char *anim_file = vfs_read(strendi(pathfile,".txt") ? pathfile : va("%s@animlist.txt", pathfile));
|
||||||
|
if( anim_file ) {
|
||||||
|
// deserialize anim
|
||||||
|
for each_substring(anim_file, "\r\n", anim) {
|
||||||
|
int from, to;
|
||||||
|
char anim_name[128] = {0};
|
||||||
|
if( sscanf(anim, "%*s %d-%d %127[^\r\n]", &from, &to, anim_name) != 3) continue;
|
||||||
|
array_push(animlist, !!strstri(anim_name, "loop") || !strcmpi(anim_name, "idle") ? loop(from, to, 0, 0) : clip(from, to, 0, 0)); // [from,to,flags]
|
||||||
|
array_back(animlist)->name = strswap(strswap(strswap(STRDUP(anim_name), "Loop", ""), "loop", ""), "()", ""); // @leak
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// placeholder
|
||||||
|
array_push(animlist, clip(0,1,0,0));
|
||||||
|
array_back(animlist)->name = STRDUP("Error"); // @leak
|
||||||
|
}
|
||||||
|
return animlist;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void anim_tick(anim_t *p, bool is_primary, float delta) { // delta can be negative (reverses anim)
|
void anim_tick(anim_t *p, bool is_primary, float delta) { // delta can be negative (reverses anim)
|
||||||
if( !is_primary ) p->active = 0;
|
if( !is_primary ) p->active = 0;
|
||||||
|
@ -3495,18 +3492,18 @@ float model_animate_blends(model_t m, anim_t *primary, anim_t *secondary, float
|
||||||
unsigned frame4 = secondary->pose.y;
|
unsigned frame4 = secondary->pose.y;
|
||||||
float alphaB = secondary->pose.z;
|
float alphaB = secondary->pose.z;
|
||||||
|
|
||||||
mat34 *mat1 = &frames[frame1 * numjoints];
|
mat34 *mat1 = &q->frames[frame1 * q->numjoints];
|
||||||
mat34 *mat2 = &frames[frame2 * numjoints];
|
mat34 *mat2 = &q->frames[frame2 * q->numjoints];
|
||||||
mat34 *mat3 = &frames[frame3 * numjoints];
|
mat34 *mat3 = &q->frames[frame3 * q->numjoints];
|
||||||
mat34 *mat4 = &frames[frame4 * numjoints];
|
mat34 *mat4 = &q->frames[frame4 * q->numjoints];
|
||||||
|
|
||||||
for(int i = 0; i < numjoints; i++) {
|
for(int i = 0; i < q->numjoints; i++) {
|
||||||
mat34 matA, matB, matF;
|
mat34 matA, matB, matF;
|
||||||
lerp34(matA, mat1[i], mat2[i], alphaA);
|
lerp34(matA, mat1[i], mat2[i], alphaA);
|
||||||
lerp34(matB, mat3[i], mat4[i], alphaB);
|
lerp34(matB, mat3[i], mat4[i], alphaB);
|
||||||
lerp34(matF, matA, matB, alpha );
|
lerp34(matF, matA, matB, alpha );
|
||||||
if(joints[i].parent >= 0) multiply34x2(outframe[i], outframe[joints[i].parent], matF);
|
if(q->joints[i].parent >= 0) multiply34x2(q->outframe[i], q->outframe[q->joints[i].parent], matF);
|
||||||
else copy34(outframe[i], matF);
|
else copy34(q->outframe[i], matF);
|
||||||
}
|
}
|
||||||
|
|
||||||
return frame1 + alpha;
|
return frame1 + alpha;
|
||||||
|
@ -3541,20 +3538,20 @@ float model_animate_clip(model_t m, float curframe, int minframe, int maxframe,
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
float retframe = -1;
|
float retframe = -1;
|
||||||
if( numframes > 0 ) {
|
if( q->numframes > 0 ) {
|
||||||
vec3 p = pose(curframe >= m.curframe, curframe, minframe, maxframe, loop, &retframe);
|
vec3 p = pose(curframe >= m.curframe, curframe, minframe, maxframe, loop, &retframe);
|
||||||
int frame1 = p.x;
|
int frame1 = p.x;
|
||||||
int frame2 = p.y;
|
int frame2 = p.y;
|
||||||
float offset = p.z;
|
float offset = p.z;
|
||||||
|
|
||||||
mat34 *mat1 = &frames[frame1 * numjoints];
|
mat34 *mat1 = &q->frames[frame1 * q->numjoints];
|
||||||
mat34 *mat2 = &frames[frame2 * numjoints];
|
mat34 *mat2 = &q->frames[frame2 * q->numjoints];
|
||||||
|
|
||||||
// @todo: add animation blending and inter-frame blending here
|
// @todo: add animation blending and inter-frame blending here
|
||||||
for(int i = 0; i < numjoints; i++) {
|
for(int i = 0; i < q->numjoints; i++) {
|
||||||
mat34 mat; lerp34(mat, mat1[i], mat2[i], offset);
|
mat34 mat; lerp34(mat, mat1[i], mat2[i], offset);
|
||||||
if(joints[i].parent >= 0) multiply34x2(outframe[i], outframe[joints[i].parent], mat);
|
if(q->joints[i].parent >= 0) multiply34x2(q->outframe[i], q->outframe[q->joints[i].parent], mat);
|
||||||
else copy34(outframe[i], mat);
|
else copy34(q->outframe[i], mat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3565,20 +3562,20 @@ void model_render_skeleton(model_t m, mat44 M) {
|
||||||
if(!m.iqm) return;
|
if(!m.iqm) return;
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
if(!numjoints) return;
|
if(!q->numjoints) return;
|
||||||
|
|
||||||
ddraw_ontop_push(true);
|
ddraw_ontop_push(true);
|
||||||
ddraw_color_push(RED);
|
ddraw_color_push(RED);
|
||||||
|
|
||||||
for( int joint = 0; joint < numjoints; joint++ ) {
|
for( int joint = 0; joint < q->numjoints; joint++ ) {
|
||||||
if( joints[joint].parent < 0) continue;
|
if( q->joints[joint].parent < 0) continue;
|
||||||
|
|
||||||
// bone space...
|
// bone space...
|
||||||
mat34 f;
|
mat34 f;
|
||||||
model_get_bone_pose(m, joint, &f);
|
model_get_bone_pose(m, joint, &f);
|
||||||
vec3 pos = vec3(f[3],f[7],f[11]);
|
vec3 pos = vec3(f[3],f[7],f[11]);
|
||||||
|
|
||||||
model_get_bone_pose(m, joints[joint].parent, &f);
|
model_get_bone_pose(m, q->joints[joint].parent, &f);
|
||||||
vec3 src = vec3(f[3],f[7],f[11]);
|
vec3 src = vec3(f[3],f[7],f[11]);
|
||||||
|
|
||||||
// ...to model space
|
// ...to model space
|
||||||
|
@ -3606,7 +3603,7 @@ void model_render_skeleton(model_t m, mat44 M) {
|
||||||
float model_animate(model_t m, float curframe) {
|
float model_animate(model_t m, float curframe) {
|
||||||
if(!m.iqm) return -1;
|
if(!m.iqm) return -1;
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
return model_animate_clip(m, curframe, 0, numframes-1, true);
|
return model_animate_clip(m, curframe, 0, q->numframes-1, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
|
@ -3614,19 +3611,19 @@ void model_draw_call(model_t m, int shader) {
|
||||||
if(!m.iqm) return;
|
if(!m.iqm) return;
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
glBindVertexArray( vao );
|
glBindVertexArray( q->vao );
|
||||||
|
|
||||||
struct iqmtriangle *tris = NULL;
|
struct iqmtriangle *tris = NULL;
|
||||||
for(int i = 0; i < nummeshes; i++) {
|
for(int i = 0; i < q->nummeshes; i++) {
|
||||||
struct iqmmesh *im = &meshes[i];
|
struct iqmmesh *im = &q->meshes[i];
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, textures[i] );
|
glBindTexture(GL_TEXTURE_2D, q->textures[i] );
|
||||||
glUniform1i(glGetUniformLocation(shader, "u_texture2d"), 0 );
|
glUniform1i(glGetUniformLocation(shader, "u_texture2d"), 0 );
|
||||||
|
|
||||||
int loc;
|
int loc;
|
||||||
if ((loc = glGetUniformLocation(shader, "u_textured")) >= 0) {
|
if ((loc = glGetUniformLocation(shader, "u_textured")) >= 0) {
|
||||||
bool textured = !!textures[i] && textures[i] != texture_checker().id; // m.materials[i].layer[0].texture != texture_checker().id;
|
bool textured = !!q->textures[i] && q->textures[i] != texture_checker().id; // m.materials[i].layer[0].texture != texture_checker().id;
|
||||||
glUniform1i(loc, textured ? GL_TRUE : GL_FALSE);
|
glUniform1i(loc, textured ? GL_TRUE : GL_FALSE);
|
||||||
if ((loc = glGetUniformLocation(shader, "u_diffuse")) >= 0) {
|
if ((loc = glGetUniformLocation(shader, "u_diffuse")) >= 0) {
|
||||||
glUniform4f(loc, m.materials[i].layer[0].color.r, m.materials[i].layer[0].color.g, m.materials[i].layer[0].color.b, m.materials[i].layer[0].color.a);
|
glUniform4f(loc, m.materials[i].layer[0].color.r, m.materials[i].layer[0].color.g, m.materials[i].layer[0].color.b, m.materials[i].layer[0].color.a);
|
||||||
|
@ -3686,10 +3683,10 @@ aabb aabb_transform( aabb A, mat44 M ) {
|
||||||
|
|
||||||
aabb model_aabb(model_t m, mat44 transform) {
|
aabb model_aabb(model_t m, mat44 transform) {
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
if( q && bounds ) {
|
if( q && q->bounds ) {
|
||||||
int f = ( (int)m.curframe ) % (numframes + !numframes);
|
int f = ( (int)m.curframe ) % (q->numframes + !q->numframes);
|
||||||
vec3 bbmin = ptr3(bounds[f].bbmin);
|
vec3 bbmin = ptr3(q->bounds[f].bbmin);
|
||||||
vec3 bbmax = ptr3(bounds[f].bbmax);
|
vec3 bbmax = ptr3(q->bounds[f].bbmax);
|
||||||
return aabb_transform(aabb(bbmin,bbmax), transform);
|
return aabb_transform(aabb(bbmin,bbmax), transform);
|
||||||
}
|
}
|
||||||
return aabb(vec3(0,0,0),vec3(0,0,0));
|
return aabb(vec3(0,0,0),vec3(0,0,0));
|
||||||
|
@ -3704,62 +3701,22 @@ void model_destroy(model_t m) {
|
||||||
|
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
// if(m.mesh) mesh_destroy(m.mesh);
|
// if(m.mesh) mesh_destroy(m.mesh);
|
||||||
FREE(outframe);
|
FREE(q->outframe);
|
||||||
FREE(colormaps);
|
FREE(q->colormaps);
|
||||||
FREE(textures);
|
FREE(q->textures);
|
||||||
FREE(baseframe);
|
FREE(q->baseframe);
|
||||||
FREE(inversebaseframe);
|
FREE(q->inversebaseframe);
|
||||||
if(animdata != meshdata) FREE(animdata);
|
if(q->animdata != q->meshdata) FREE(q->animdata);
|
||||||
//FREE(meshdata);
|
//FREE(q->meshdata);
|
||||||
FREE(frames);
|
FREE(q->frames);
|
||||||
FREE(buf);
|
FREE(q->buf);
|
||||||
FREE(q);
|
FREE(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef program
|
|
||||||
#undef meshdata
|
|
||||||
#undef animdata
|
|
||||||
#undef nummeshes
|
|
||||||
#undef numtris
|
|
||||||
#undef numverts
|
|
||||||
#undef numjoints
|
|
||||||
#undef numframes
|
|
||||||
#undef numanims
|
|
||||||
#undef meshes
|
|
||||||
#undef textures
|
|
||||||
#undef joints
|
|
||||||
#undef poses
|
|
||||||
#undef anims
|
|
||||||
#undef baseframe
|
|
||||||
#undef inversebaseframe
|
|
||||||
#undef outframe
|
|
||||||
#undef frames
|
|
||||||
#undef vao
|
|
||||||
#undef ibo
|
|
||||||
#undef vbo
|
|
||||||
#undef bonematsoffset
|
|
||||||
#undef buf
|
|
||||||
#undef bounds
|
|
||||||
#undef colormaps
|
|
||||||
|
|
||||||
anims_t animations(const char *pathfile, int flags) {
|
anims_t animations(const char *pathfile, int flags) {
|
||||||
anims_t a = {0};
|
anims_t a = {0};
|
||||||
char *anim_file = vfs_read(strendi(pathfile,".txt") ? pathfile : va("%s@animlist.txt", pathfile));
|
a.speed = 1.0;
|
||||||
if( anim_file ) {
|
a.anims = animlist(pathfile);
|
||||||
// deserialize anim
|
|
||||||
a.speed = 1.0;
|
|
||||||
for each_substring(anim_file, "\r\n", anim) {
|
|
||||||
int from, to;
|
|
||||||
char anim_name[128] = {0};
|
|
||||||
if( sscanf(anim, "%*s %d-%d %127[^\r\n]", &from, &to, anim_name) != 3) continue;
|
|
||||||
array_push(a.anims, !!strstri(anim_name, "loop") || !strcmpi(anim_name, "idle") ? loop(from, to, 0, 0) : clip(from, to, 0, 0)); // [from,to,flags]
|
|
||||||
array_back(a.anims)->name = strswap(strswap(strswap(STRDUP(anim_name), "Loop", ""), "loop", ""), "()", ""); // @leak
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// placeholder
|
|
||||||
array_push(a.anims, clip(0,1,0,0));
|
|
||||||
array_back(a.anims)->name = STRDUP("Error"); // @leak
|
|
||||||
}
|
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -492,7 +492,7 @@ typedef struct anim_t {
|
||||||
|
|
||||||
API anim_t clip(float minframe, float maxframe, float blendtime, unsigned flags);
|
API anim_t clip(float minframe, float maxframe, float blendtime, unsigned flags);
|
||||||
API anim_t loop(float minframe, float maxframe, float blendtime, unsigned flags);
|
API anim_t loop(float minframe, float maxframe, float blendtime, unsigned flags);
|
||||||
//API array(anim_t) animlist(const char *filename); // @todo
|
API array(anim_t) animlist(const char *filename);
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// models
|
// models
|
||||||
|
|
|
@ -202,6 +202,8 @@ void object_update(object_t *obj) {
|
||||||
quat p = eulerq(vec3(obj->pivot.x,obj->pivot.y,obj->pivot.z));
|
quat p = eulerq(vec3(obj->pivot.x,obj->pivot.y,obj->pivot.z));
|
||||||
quat e = eulerq(vec3(obj->euler.x,obj->euler.y,obj->euler.z));
|
quat e = eulerq(vec3(obj->euler.x,obj->euler.y,obj->euler.z));
|
||||||
compose44(obj->transform, obj->pos, mulq(e, p), obj->sca);
|
compose44(obj->transform, obj->pos, mulq(e, p), obj->sca);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object_t object() {
|
object_t object() {
|
||||||
|
@ -251,6 +253,11 @@ void object_model(object_t *obj, model_t model) {
|
||||||
obj->model = model;
|
obj->model = model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void object_anim(object_t *obj, anim_t anim, float speed) {
|
||||||
|
obj->anim = anim;
|
||||||
|
obj->anim_speed = speed;
|
||||||
|
}
|
||||||
|
|
||||||
void object_push_diffuse(object_t *obj, texture_t tex) {
|
void object_push_diffuse(object_t *obj, texture_t tex) {
|
||||||
array_push(obj->textures, tex.id);
|
array_push(obj->textures, tex.id);
|
||||||
}
|
}
|
||||||
|
@ -518,6 +525,7 @@ void scene_render(int flags) {
|
||||||
for(unsigned j = 0, obj_count = scene_count(); j < obj_count; ++j ) {
|
for(unsigned j = 0, obj_count = scene_count(); j < obj_count; ++j ) {
|
||||||
object_t *obj = scene_index(j);
|
object_t *obj = scene_index(j);
|
||||||
model_t *model = &obj->model;
|
model_t *model = &obj->model;
|
||||||
|
anim_t *anim = &obj->anim;
|
||||||
mat44 *views = (mat44*)(&cam->view);
|
mat44 *views = (mat44*)(&cam->view);
|
||||||
|
|
||||||
// @todo: avoid heap allocs here?
|
// @todo: avoid heap allocs here?
|
||||||
|
@ -542,6 +550,11 @@ void scene_render(int flags) {
|
||||||
shader_vec3v("u_coefficients_sh", 9, last_scene->skybox.cubemap.sh);
|
shader_vec3v("u_coefficients_sh", 9, last_scene->skybox.cubemap.sh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (anim) {
|
||||||
|
float delta = window_delta() * obj->anim_speed;
|
||||||
|
model->curframe = model_animate_clip(*model, model->curframe + delta, anim->from, anim->to, anim->flags & ANIM_LOOP );
|
||||||
|
}
|
||||||
|
|
||||||
model->billboard = obj->billboard;
|
model->billboard = obj->billboard;
|
||||||
model_render(*model, cam->proj, cam->view, obj->transform, 0);
|
model_render(*model, cam->proj, cam->view, obj->transform, 0);
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,8 @@ typedef struct object_t {
|
||||||
vec3 sca, pos, euler, pivot;
|
vec3 sca, pos, euler, pivot;
|
||||||
array(handle) textures;
|
array(handle) textures;
|
||||||
model_t model;
|
model_t model;
|
||||||
|
anim_t anim;
|
||||||
|
float anim_speed;
|
||||||
aabb bounds;
|
aabb bounds;
|
||||||
unsigned billboard; // [0..7] x(4),y(2),z(1) masks
|
unsigned billboard; // [0..7] x(4),y(2),z(1) masks
|
||||||
bool light_cached; //< used by scene to update light data
|
bool light_cached; //< used by scene to update light data
|
||||||
|
@ -57,6 +59,7 @@ API vec3 object_position(object_t *obj);
|
||||||
API void object_scale(object_t *obj, vec3 sca);
|
API void object_scale(object_t *obj, vec3 sca);
|
||||||
//
|
//
|
||||||
API void object_model(object_t *obj, model_t model);
|
API void object_model(object_t *obj, model_t model);
|
||||||
|
API void object_anim(object_t *obj, anim_t anim, float speed);
|
||||||
API void object_diffuse(object_t *obj, texture_t tex);
|
API void object_diffuse(object_t *obj, texture_t tex);
|
||||||
API void object_diffuse_push(object_t *obj, texture_t tex);
|
API void object_diffuse_push(object_t *obj, texture_t tex);
|
||||||
API void object_diffuse_pop(object_t *obj);
|
API void object_diffuse_pop(object_t *obj);
|
||||||
|
|
441
engine/v4k.c
441
engine/v4k.c
|
@ -10199,7 +10199,7 @@ in vec4 instanceGlyph;\n\
|
||||||
uniform sampler2D sampler_font;\n\
|
uniform sampler2D sampler_font;\n\
|
||||||
uniform sampler2D sampler_meta;\n\
|
uniform sampler2D sampler_meta;\n\
|
||||||
\n\
|
\n\
|
||||||
uniform float offset_firstline; // ascent - descent - linegap/2\n\
|
uniform float offset_firstline; // ascent\n\
|
||||||
uniform float scale_factor; // scaling factor proportional to font size\n\
|
uniform float scale_factor; // scaling factor proportional to font size\n\
|
||||||
uniform vec2 string_offset; // offset of upper-left corner\n\
|
uniform vec2 string_offset; // offset of upper-left corner\n\
|
||||||
\n\
|
\n\
|
||||||
|
@ -10364,6 +10364,20 @@ void ui_font() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void font_scale(const char *tag, int s, float v) {
|
||||||
|
font_init();
|
||||||
|
|
||||||
|
if (s < 0 || s >= 10) return;
|
||||||
|
|
||||||
|
unsigned index = *tag - FONT_FACE1[0];
|
||||||
|
if( index > FONTS_MAX ) return;
|
||||||
|
|
||||||
|
font_t *f = &fonts[index];
|
||||||
|
if (!f->initialized) return;
|
||||||
|
|
||||||
|
f->scale[s] = v / f->font_size;
|
||||||
|
}
|
||||||
|
|
||||||
void font_scales(const char *tag, float h1, float h2, float h3, float h4, float h5, float h6) {
|
void font_scales(const char *tag, float h1, float h2, float h3, float h4, float h5, float h6) {
|
||||||
font_init();
|
font_init();
|
||||||
|
|
||||||
|
@ -10746,7 +10760,7 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm
|
||||||
font_t *f = &fonts[0];
|
font_t *f = &fonts[0];
|
||||||
int S = 3;
|
int S = 3;
|
||||||
uint32_t color = 0;
|
uint32_t color = 0;
|
||||||
float X = 0, Y = 0, W = 0, L = f->ascent*f->factor*f->scale[S], LL = L; // LL=largest linedist
|
float X = 0, Y = 0, W = 0, L = f->ascent*f->factor*f->scale[S], LL = 0; // LL=largest linedist
|
||||||
offset.y = -offset.y; // invert y polarity
|
offset.y = -offset.y; // invert y polarity
|
||||||
|
|
||||||
// utf8 to utf32
|
// utf8 to utf32
|
||||||
|
@ -10778,6 +10792,7 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm
|
||||||
|
|
||||||
// change size
|
// change size
|
||||||
S = ch;
|
S = ch;
|
||||||
|
//@hack: use descent when we use >H4
|
||||||
L = f->ascent*f->factor*f->scale[S];
|
L = f->ascent*f->factor*f->scale[S];
|
||||||
if(L > LL) LL = L;
|
if(L > LL) LL = L;
|
||||||
continue;
|
continue;
|
||||||
|
@ -10794,10 +10809,27 @@ vec2 font_draw_ex(const char *text, vec2 offset, const char *col, void (*draw_cm
|
||||||
|
|
||||||
// change face
|
// change face
|
||||||
f = &fonts[ ch - 0x10 ];
|
f = &fonts[ ch - 0x10 ];
|
||||||
|
L = f->ascent*f->factor*f->scale[S];
|
||||||
|
if(L > LL) LL = L;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!LL)
|
||||||
|
LL = L;
|
||||||
|
|
||||||
|
if (ch == FONT_LEFT[0] && (
|
||||||
|
(unicode[i+1]) == FONT_LEFT[1] ||
|
||||||
|
(unicode[i+1]) == FONT_CENTER[1] ||
|
||||||
|
(unicode[i+1]) == FONT_RIGHT[1] ||
|
||||||
|
(unicode[i+1]) == FONT_TOP[1] ||
|
||||||
|
(unicode[i+1]) == FONT_MIDDLE[1] ||
|
||||||
|
(unicode[i+1]) == FONT_BASELINE[1] ||
|
||||||
|
(unicode[i+1]) == FONT_BOTTOM[1]
|
||||||
|
)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// convert to vbo data
|
// convert to vbo data
|
||||||
int cp = ch - f->begin; // f->cp2iter[ch - f->begin];
|
int cp = ch - f->begin; // f->cp2iter[ch - f->begin];
|
||||||
//if(cp == 0xFFFD) continue;
|
//if(cp == 0xFFFD) continue;
|
||||||
|
@ -11052,25 +11084,25 @@ void font_goto(float x, float y) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print and linefeed. Text may include markup code
|
// Print and linefeed. Text may include markup code
|
||||||
vec2 font_print(const char *text) {
|
vec2 font_print_rect(const char *text, vec4 rect) {
|
||||||
// @fixme: remove this hack
|
// @fixme: remove this hack
|
||||||
if( text[0] == FONT_LEFT[0] ) {
|
if( text[0] == FONT_LEFT[0] ) {
|
||||||
int l = text[1] == FONT_LEFT[1];
|
int l = text[1] == FONT_LEFT[1];
|
||||||
int c = text[1] == FONT_CENTER[1];
|
int c = text[1] == FONT_CENTER[1];
|
||||||
int r = text[1] == FONT_RIGHT[1];
|
int r = text[1] == FONT_RIGHT[1];
|
||||||
if( l || c || r ) {
|
if( l || c || r ) {
|
||||||
vec2 rect = font_rect(text + 2);
|
vec2 text_rect = font_rect(text + 2);
|
||||||
gotoxy.x = l ? 0 : r ? (window_width() - rect.x) : window_width()/2 - rect.x/2;
|
gotoxy.x = l ? rect.x : r ? ((rect.x+rect.z) - text_rect.x) : rect.x+rect.z/2. - text_rect.x/2.;
|
||||||
return font_print(text + 2);
|
return font_print_rect(text + 2, rect);
|
||||||
}
|
}
|
||||||
int t = text[1] == FONT_TOP[1];
|
int t = text[1] == FONT_TOP[1];
|
||||||
int b = text[1] == FONT_BOTTOM[1];
|
int b = text[1] == FONT_BOTTOM[1];
|
||||||
int m = text[1] == FONT_MIDDLE[1];
|
int m = text[1] == FONT_MIDDLE[1];
|
||||||
int B = text[1] == FONT_BASELINE[1];
|
int B = text[1] == FONT_BASELINE[1];
|
||||||
if( t || b || m || B ) {
|
if( t || b || m || B ) {
|
||||||
vec2 rect = font_rect(text + 2);
|
vec2 text_rect = font_rect(text + 2);
|
||||||
gotoxy.y = t ? 0 : b ? (window_height() - rect.y) : m ? window_height()/2-rect.y/2 : window_height()/2-rect.y/1;
|
gotoxy.y = t ? rect.y : b ? ((rect.y+rect.w) - text_rect.y) : m ? rect.y+rect.w/2.-text_rect.y/2. : rect.y+rect.w/2.-text_rect.y/1;
|
||||||
return font_print(text + 2);
|
return font_print_rect(text + 2, rect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11080,6 +11112,11 @@ vec2 font_print(const char *text) {
|
||||||
return dims;
|
return dims;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vec2 font_print(const char *text) {
|
||||||
|
vec4 dims = {0, 0, window_width(), window_height()};
|
||||||
|
return font_print_rect(text, dims);
|
||||||
|
}
|
||||||
|
|
||||||
// Print a code snippet with syntax highlighting
|
// Print a code snippet with syntax highlighting
|
||||||
vec2 font_highlight(const char *text, const void *colors) {
|
vec2 font_highlight(const char *text, const void *colors) {
|
||||||
vec2 dims = font_draw_ex(text, gotoxy, (const char *)colors, font_draw_cmd);
|
vec2 dims = font_draw_ex(text, gotoxy, (const char *)colors, font_draw_cmd);
|
||||||
|
@ -19843,37 +19880,12 @@ typedef struct iqm_t {
|
||||||
vec4 *colormaps;
|
vec4 *colormaps;
|
||||||
} iqm_t;
|
} iqm_t;
|
||||||
|
|
||||||
#define meshdata (q->meshdata)
|
|
||||||
#define animdata (q->animdata)
|
|
||||||
#define nummeshes (q->nummeshes)
|
|
||||||
#define numtris (q->numtris)
|
|
||||||
#define numverts (q->numverts)
|
|
||||||
#define numjoints (q->numjoints)
|
|
||||||
#define numframes (q->numframes)
|
|
||||||
#define numanims (q->numanims)
|
|
||||||
#define meshes (q->meshes)
|
|
||||||
#define textures (q->textures)
|
|
||||||
#define joints (q->joints)
|
|
||||||
#define poses (q->poses)
|
|
||||||
#define anims (q->anims)
|
|
||||||
#define baseframe (q->baseframe)
|
|
||||||
#define inversebaseframe (q->inversebaseframe)
|
|
||||||
#define outframe (q->outframe)
|
|
||||||
#define frames (q->frames)
|
|
||||||
#define vao (q->vao)
|
|
||||||
#define ibo (q->ibo)
|
|
||||||
#define vbo (q->vbo)
|
|
||||||
#define bonematsoffset (q->bonematsoffset)
|
|
||||||
#define buf (q->buf)
|
|
||||||
#define bounds (q->bounds)
|
|
||||||
#define colormaps (q->colormaps)
|
|
||||||
|
|
||||||
void model_set_texture(model_t m, texture_t t) {
|
void model_set_texture(model_t m, texture_t t) {
|
||||||
if(!m.iqm) return;
|
if(!m.iqm) return;
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
for( int i = 0; i < nummeshes; ++i) { // assume 1 texture per mesh
|
for( int i = 0; i < q->nummeshes; ++i) { // assume 1 texture per mesh
|
||||||
textures[i] = t.id;
|
q->textures[i] = t.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19966,9 +19978,9 @@ void model_set_uniforms(model_t m, int shader, mat44 mv, mat44 proj, mat44 view,
|
||||||
if ((loc = glGetUniformLocation(shader, "proj")) >= 0) {
|
if ((loc = glGetUniformLocation(shader, "proj")) >= 0) {
|
||||||
glUniformMatrix4fv(loc, 1, GL_FALSE, proj);
|
glUniformMatrix4fv(loc, 1, GL_FALSE, proj);
|
||||||
}
|
}
|
||||||
if( (loc = glGetUniformLocation(shader, "SKINNED")) >= 0 ) glUniform1i( loc, numanims ? GL_TRUE : GL_FALSE);
|
if( (loc = glGetUniformLocation(shader, "SKINNED")) >= 0 ) glUniform1i( loc, q->numanims ? GL_TRUE : GL_FALSE);
|
||||||
if( numanims )
|
if( q->numanims )
|
||||||
if( (loc = glGetUniformLocation(shader, "vsBoneMatrix")) >= 0 ) glUniformMatrix3x4fv( loc, numjoints, GL_FALSE, outframe[0]);
|
if( (loc = glGetUniformLocation(shader, "vsBoneMatrix")) >= 0 ) glUniformMatrix3x4fv( loc, q->numjoints, GL_FALSE, q->outframe[0]);
|
||||||
|
|
||||||
if ((loc = glGetUniformLocation(shader, "u_matcaps")) >= 0) {
|
if ((loc = glGetUniformLocation(shader, "u_matcaps")) >= 0) {
|
||||||
glUniform1i(loc, m.flags & MODEL_MATCAPS ? GL_TRUE:GL_FALSE);
|
glUniform1i(loc, m.flags & MODEL_MATCAPS ? GL_TRUE:GL_FALSE);
|
||||||
|
@ -19979,10 +19991,10 @@ void model_set_state(model_t m) {
|
||||||
if(!m.iqm) return;
|
if(!m.iqm) return;
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
glBindVertexArray( vao );
|
glBindVertexArray( q->vao );
|
||||||
|
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, q->ibo);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
glBindBuffer(GL_ARRAY_BUFFER, q->vbo);
|
||||||
|
|
||||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, position) );
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, position) );
|
||||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, texcoord) );
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, texcoord) );
|
||||||
|
@ -20003,7 +20015,7 @@ void model_set_state(model_t m) {
|
||||||
glEnableVertexAttribArray(12);
|
glEnableVertexAttribArray(12);
|
||||||
|
|
||||||
// animation
|
// animation
|
||||||
if(numframes > 0) {
|
if(q->numframes > 0) {
|
||||||
glVertexAttribPointer( 8, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,blendindexes) );
|
glVertexAttribPointer( 8, 4, GL_UNSIGNED_BYTE, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,blendindexes) );
|
||||||
glVertexAttribPointer( 9, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,blendweights) );
|
glVertexAttribPointer( 9, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex,blendweights) );
|
||||||
glVertexAttribPointer(10, 1, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, blendvertexindex) );
|
glVertexAttribPointer(10, 1, GL_FLOAT, GL_FALSE, sizeof(iqm_vertex), (GLvoid*)offsetof(iqm_vertex, blendvertexindex) );
|
||||||
|
@ -20044,71 +20056,71 @@ void model_set_state(model_t m) {
|
||||||
|
|
||||||
static
|
static
|
||||||
bool model_load_meshes(iqm_t *q, const struct iqmheader *hdr, model_t *m) {
|
bool model_load_meshes(iqm_t *q, const struct iqmheader *hdr, model_t *m) {
|
||||||
if(meshdata) return false;
|
if(q->meshdata) return false;
|
||||||
|
|
||||||
lil32p(&buf[hdr->ofs_vertexarrays], hdr->num_vertexarrays*sizeof(struct iqmvertexarray)/sizeof(uint32_t));
|
lil32p(&q->buf[hdr->ofs_vertexarrays], hdr->num_vertexarrays*sizeof(struct iqmvertexarray)/sizeof(uint32_t));
|
||||||
lil32p(&buf[hdr->ofs_triangles], hdr->num_triangles*sizeof(struct iqmtriangle)/sizeof(uint32_t));
|
lil32p(&q->buf[hdr->ofs_triangles], hdr->num_triangles*sizeof(struct iqmtriangle)/sizeof(uint32_t));
|
||||||
lil32p(&buf[hdr->ofs_meshes], hdr->num_meshes*sizeof(struct iqmmesh)/sizeof(uint32_t));
|
lil32p(&q->buf[hdr->ofs_meshes], hdr->num_meshes*sizeof(struct iqmmesh)/sizeof(uint32_t));
|
||||||
lil32p(&buf[hdr->ofs_joints], hdr->num_joints*sizeof(struct iqmjoint)/sizeof(uint32_t));
|
lil32p(&q->buf[hdr->ofs_joints], hdr->num_joints*sizeof(struct iqmjoint)/sizeof(uint32_t));
|
||||||
|
|
||||||
meshdata = buf;
|
q->meshdata = q->buf;
|
||||||
nummeshes = hdr->num_meshes;
|
q->nummeshes = hdr->num_meshes;
|
||||||
numtris = hdr->num_triangles;
|
q->numtris = hdr->num_triangles;
|
||||||
numverts = hdr->num_vertexes;
|
q->numverts = hdr->num_vertexes;
|
||||||
numjoints = hdr->num_joints;
|
q->numjoints = hdr->num_joints;
|
||||||
outframe = CALLOC(hdr->num_joints, sizeof(mat34));
|
q->outframe = CALLOC(hdr->num_joints, sizeof(mat34));
|
||||||
|
|
||||||
float *inposition = NULL, *innormal = NULL, *intangent = NULL, *intexcoord = NULL, *invertexindex = NULL;
|
float *inposition = NULL, *innormal = NULL, *intangent = NULL, *intexcoord = NULL, *invertexindex = NULL;
|
||||||
uint8_t *inblendindex8 = NULL, *inblendweight8 = NULL;
|
uint8_t *inblendindex8 = NULL, *inblendweight8 = NULL;
|
||||||
int *inblendindexi = NULL; float *inblendweightf = NULL;
|
int *inblendindexi = NULL; float *inblendweightf = NULL;
|
||||||
uint8_t *invertexcolor8 = NULL;
|
uint8_t *invertexcolor8 = NULL;
|
||||||
struct iqmvertexarray *vas = (struct iqmvertexarray *)&buf[hdr->ofs_vertexarrays];
|
struct iqmvertexarray *vas = (struct iqmvertexarray *)&q->buf[hdr->ofs_vertexarrays];
|
||||||
for(int i = 0; i < (int)hdr->num_vertexarrays; i++) {
|
for(int i = 0; i < (int)hdr->num_vertexarrays; i++) {
|
||||||
struct iqmvertexarray *va = &vas[i];
|
struct iqmvertexarray *va = &vas[i];
|
||||||
switch(va->type) {
|
switch(va->type) {
|
||||||
default: continue; // return PANIC("unknown iqm vertex type (%d)", va->type), false;
|
default: continue; // return PANIC("unknown iqm vertex type (%d)", va->type), false;
|
||||||
break; case IQM_POSITION: ASSERT(va->format == IQM_FLOAT && va->size == 3); inposition = (float *)&buf[va->offset]; lil32pf(inposition, 3*hdr->num_vertexes);
|
break; case IQM_POSITION: ASSERT(va->format == IQM_FLOAT && va->size == 3); inposition = (float *)&q->buf[va->offset]; lil32pf(inposition, 3*hdr->num_vertexes);
|
||||||
break; case IQM_NORMAL: ASSERT(va->format == IQM_FLOAT && va->size == 3); innormal = (float *)&buf[va->offset]; lil32pf(innormal, 3*hdr->num_vertexes);
|
break; case IQM_NORMAL: ASSERT(va->format == IQM_FLOAT && va->size == 3); innormal = (float *)&q->buf[va->offset]; lil32pf(innormal, 3*hdr->num_vertexes);
|
||||||
break; case IQM_TANGENT: ASSERT(va->format == IQM_FLOAT && va->size == 4); intangent = (float *)&buf[va->offset]; lil32pf(intangent, 4*hdr->num_vertexes);
|
break; case IQM_TANGENT: ASSERT(va->format == IQM_FLOAT && va->size == 4); intangent = (float *)&q->buf[va->offset]; lil32pf(intangent, 4*hdr->num_vertexes);
|
||||||
break; case IQM_TEXCOORD: ASSERT(va->format == IQM_FLOAT && va->size == 2); intexcoord = (float *)&buf[va->offset]; lil32pf(intexcoord, 2*hdr->num_vertexes);
|
break; case IQM_TEXCOORD: ASSERT(va->format == IQM_FLOAT && va->size == 2); intexcoord = (float *)&q->buf[va->offset]; lil32pf(intexcoord, 2*hdr->num_vertexes);
|
||||||
break; case IQM_COLOR: ASSERT(va->size == 4); ASSERT(va->format == IQM_UBYTE); invertexcolor8 = (uint8_t *)&buf[va->offset];
|
break; case IQM_COLOR: ASSERT(va->size == 4); ASSERT(va->format == IQM_UBYTE); invertexcolor8 = (uint8_t *)&q->buf[va->offset];
|
||||||
break; case IQM_BLENDINDEXES: ASSERT(va->size == 4); ASSERT(va->format == IQM_UBYTE || va->format == IQM_INT);
|
break; case IQM_BLENDINDEXES: ASSERT(va->size == 4); ASSERT(va->format == IQM_UBYTE || va->format == IQM_INT);
|
||||||
if(va->format == IQM_UBYTE) inblendindex8 = (uint8_t *)&buf[va->offset];
|
if(va->format == IQM_UBYTE) inblendindex8 = (uint8_t *)&q->buf[va->offset];
|
||||||
else inblendindexi = (int *)&buf[va->offset];
|
else inblendindexi = (int *)&q->buf[va->offset];
|
||||||
break; case IQM_BLENDWEIGHTS: ASSERT(va->size == 4); ASSERT(va->format == IQM_UBYTE || va->format == IQM_FLOAT);
|
break; case IQM_BLENDWEIGHTS: ASSERT(va->size == 4); ASSERT(va->format == IQM_UBYTE || va->format == IQM_FLOAT);
|
||||||
if(va->format == IQM_UBYTE) inblendweight8 = (uint8_t *)&buf[va->offset];
|
if(va->format == IQM_UBYTE) inblendweight8 = (uint8_t *)&q->buf[va->offset];
|
||||||
else inblendweightf = (float *)&buf[va->offset];
|
else inblendweightf = (float *)&q->buf[va->offset];
|
||||||
invertexindex = (inblendweight8 ? (float*)(inblendweight8 + 4) : inblendweightf + 4 );
|
invertexindex = (inblendweight8 ? (float*)(inblendweight8 + 4) : inblendweightf + 4 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hdr->ofs_bounds) lil32p(buf + hdr->ofs_bounds, hdr->num_frames * sizeof(struct iqmbounds));
|
if (hdr->ofs_bounds) lil32p(q->buf + hdr->ofs_bounds, hdr->num_frames * sizeof(struct iqmbounds));
|
||||||
if (hdr->ofs_bounds) bounds = (struct iqmbounds *) &buf[hdr->ofs_bounds];
|
if (hdr->ofs_bounds) q->bounds = (struct iqmbounds *) &q->buf[hdr->ofs_bounds];
|
||||||
|
|
||||||
meshes = (struct iqmmesh *)&buf[hdr->ofs_meshes];
|
q->meshes = (struct iqmmesh *)&q->buf[hdr->ofs_meshes];
|
||||||
joints = (struct iqmjoint *)&buf[hdr->ofs_joints];
|
q->joints = (struct iqmjoint *)&q->buf[hdr->ofs_joints];
|
||||||
|
|
||||||
baseframe = CALLOC(hdr->num_joints, sizeof(mat34));
|
q->baseframe = CALLOC(hdr->num_joints, sizeof(mat34));
|
||||||
inversebaseframe = CALLOC(hdr->num_joints, sizeof(mat34));
|
q->inversebaseframe = CALLOC(hdr->num_joints, sizeof(mat34));
|
||||||
for(int i = 0; i < (int)hdr->num_joints; i++) {
|
for(int i = 0; i < (int)hdr->num_joints; i++) {
|
||||||
struct iqmjoint *j = &joints[i];
|
struct iqmjoint *j = &q->joints[i];
|
||||||
compose34(baseframe[i], ptr3(j->translate), normq(ptrq(j->rotate)), ptr3(j->scale));
|
compose34(q->baseframe[i], ptr3(j->translate), normq(ptrq(j->rotate)), ptr3(j->scale));
|
||||||
invert34(inversebaseframe[i], baseframe[i]);
|
invert34(q->inversebaseframe[i], q->baseframe[i]);
|
||||||
if(j->parent >= 0) {
|
if(j->parent >= 0) {
|
||||||
multiply34x2(baseframe[i], baseframe[j->parent], baseframe[i]);
|
multiply34x2(q->baseframe[i], q->baseframe[j->parent], q->baseframe[i]);
|
||||||
multiply34(inversebaseframe[i], inversebaseframe[j->parent]);
|
multiply34(q->inversebaseframe[i], q->inversebaseframe[j->parent]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct iqmtriangle *tris = (struct iqmtriangle *)&buf[hdr->ofs_triangles];
|
struct iqmtriangle *tris = (struct iqmtriangle *)&q->buf[hdr->ofs_triangles];
|
||||||
m->num_tris = hdr->num_triangles;
|
m->num_tris = hdr->num_triangles;
|
||||||
m->tris = (void*)tris;
|
m->tris = (void*)tris;
|
||||||
|
|
||||||
glGenVertexArrays(1, &vao);
|
glGenVertexArrays(1, &q->vao);
|
||||||
glBindVertexArray(vao);
|
glBindVertexArray(q->vao);
|
||||||
|
|
||||||
if(!ibo) glGenBuffers(1, &ibo);
|
if(!q->ibo) glGenBuffers(1, &q->ibo);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, q->ibo);
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, hdr->num_triangles*sizeof(struct iqmtriangle), tris, GL_STATIC_DRAW);
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, hdr->num_triangles*sizeof(struct iqmtriangle), tris, GL_STATIC_DRAW);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
@ -20139,8 +20151,8 @@ bool model_load_meshes(iqm_t *q, const struct iqmheader *hdr, model_t *m) {
|
||||||
if(invertexcolor8) memcpy(v->color, &invertexcolor8[i*4], sizeof(v->color));
|
if(invertexcolor8) memcpy(v->color, &invertexcolor8[i*4], sizeof(v->color));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!vbo) glGenBuffers(1, &vbo);
|
if(!q->vbo) glGenBuffers(1, &q->vbo);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
glBindBuffer(GL_ARRAY_BUFFER, q->vbo);
|
||||||
glBufferData(GL_ARRAY_BUFFER, hdr->num_vertexes*sizeof(iqm_vertex), verts, GL_STATIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, hdr->num_vertexes*sizeof(iqm_vertex), verts, GL_STATIC_DRAW);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
@ -20161,16 +20173,16 @@ bool model_load_meshes(iqm_t *q, const struct iqmheader *hdr, model_t *m) {
|
||||||
m->verts = verts;
|
m->verts = verts;
|
||||||
/*m->verts = 0; FREE(verts);*/
|
/*m->verts = 0; FREE(verts);*/
|
||||||
|
|
||||||
textures = CALLOC(hdr->num_meshes * 8, sizeof(GLuint));
|
q->textures = CALLOC(hdr->num_meshes * 8, sizeof(GLuint));
|
||||||
colormaps = CALLOC(hdr->num_meshes * 8, sizeof(vec4));
|
q->colormaps = CALLOC(hdr->num_meshes * 8, sizeof(vec4));
|
||||||
for(int i = 0; i < (int)hdr->num_meshes; i++) {
|
for(int i = 0; i < (int)hdr->num_meshes; i++) {
|
||||||
int invalid = texture_checker().id;
|
int invalid = texture_checker().id;
|
||||||
textures[i] = invalid;
|
q->textures[i] = invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *str = hdr->ofs_text ? (char *)&buf[hdr->ofs_text] : "";
|
const char *str = hdr->ofs_text ? (char *)&q->buf[hdr->ofs_text] : "";
|
||||||
for(int i = 0; i < (int)hdr->num_meshes; i++) {
|
for(int i = 0; i < (int)hdr->num_meshes; i++) {
|
||||||
struct iqmmesh *m = &meshes[i];
|
struct iqmmesh *m = &q->meshes[i];
|
||||||
PRINTF("loaded mesh: %s\n", &str[m->name]);
|
PRINTF("loaded mesh: %s\n", &str[m->name]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20179,34 +20191,34 @@ bool model_load_meshes(iqm_t *q, const struct iqmheader *hdr, model_t *m) {
|
||||||
|
|
||||||
static
|
static
|
||||||
bool model_load_anims(iqm_t *q, const struct iqmheader *hdr) {
|
bool model_load_anims(iqm_t *q, const struct iqmheader *hdr) {
|
||||||
if((int)hdr->num_poses != numjoints) return false;
|
if((int)hdr->num_poses != q->numjoints) return false;
|
||||||
|
|
||||||
if(animdata) {
|
if(q->animdata) {
|
||||||
if(animdata != meshdata) FREE(animdata);
|
if(q->animdata != q->meshdata) FREE(q->animdata);
|
||||||
FREE(frames);
|
FREE(q->frames);
|
||||||
animdata = NULL;
|
q->animdata = NULL;
|
||||||
anims = NULL;
|
q->anims = NULL;
|
||||||
frames = 0;
|
q->frames = 0;
|
||||||
numframes = 0;
|
q->numframes = 0;
|
||||||
numanims = 0;
|
q->numanims = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
lil32p(&buf[hdr->ofs_poses], hdr->num_poses*sizeof(struct iqmpose)/sizeof(uint32_t));
|
lil32p(&q->buf[hdr->ofs_poses], hdr->num_poses*sizeof(struct iqmpose)/sizeof(uint32_t));
|
||||||
lil32p(&buf[hdr->ofs_anims], hdr->num_anims*sizeof(struct iqmanim)/sizeof(uint32_t));
|
lil32p(&q->buf[hdr->ofs_anims], hdr->num_anims*sizeof(struct iqmanim)/sizeof(uint32_t));
|
||||||
lil16p((uint16_t *)&buf[hdr->ofs_frames], hdr->num_frames*hdr->num_framechannels);
|
lil16p((uint16_t *)&q->buf[hdr->ofs_frames], hdr->num_frames*hdr->num_framechannels);
|
||||||
|
|
||||||
animdata = buf;
|
q->animdata = q->buf;
|
||||||
numanims = hdr->num_anims;
|
q->numanims = hdr->num_anims;
|
||||||
numframes = hdr->num_frames;
|
q->numframes = hdr->num_frames;
|
||||||
|
|
||||||
anims = (struct iqmanim *)&buf[hdr->ofs_anims];
|
q->anims = (struct iqmanim *)&q->buf[hdr->ofs_anims];
|
||||||
poses = (struct iqmpose *)&buf[hdr->ofs_poses];
|
q->poses = (struct iqmpose *)&q->buf[hdr->ofs_poses];
|
||||||
frames = CALLOC(hdr->num_frames * hdr->num_poses, sizeof(mat34));
|
q->frames = CALLOC(hdr->num_frames * hdr->num_poses, sizeof(mat34));
|
||||||
uint16_t *framedata = (uint16_t *)&buf[hdr->ofs_frames];
|
uint16_t *framedata = (uint16_t *)&q->buf[hdr->ofs_frames];
|
||||||
|
|
||||||
for(int i = 0; i < (int)hdr->num_frames; i++) {
|
for(int i = 0; i < (int)hdr->num_frames; i++) {
|
||||||
for(int j = 0; j < (int)hdr->num_poses; j++) {
|
for(int j = 0; j < (int)hdr->num_poses; j++) {
|
||||||
struct iqmpose *p = &poses[j];
|
struct iqmpose *p = &q->poses[j];
|
||||||
quat rotate;
|
quat rotate;
|
||||||
vec3 translate, scale;
|
vec3 translate, scale;
|
||||||
translate.x = p->channeloffset[0]; if(p->mask&0x01) translate.x += *framedata++ * p->channelscale[0];
|
translate.x = p->channeloffset[0]; if(p->mask&0x01) translate.x += *framedata++ * p->channelscale[0];
|
||||||
|
@ -20230,16 +20242,16 @@ bool model_load_anims(iqm_t *q, const struct iqmheader *hdr) {
|
||||||
// parentPose * childPose * childInverseBasePose
|
// parentPose * childPose * childInverseBasePose
|
||||||
|
|
||||||
mat34 m; compose34(m, translate, normq(rotate), scale);
|
mat34 m; compose34(m, translate, normq(rotate), scale);
|
||||||
if(p->parent >= 0) multiply34x3(frames[i*hdr->num_poses + j], baseframe[p->parent], m, inversebaseframe[j]);
|
if(p->parent >= 0) multiply34x3(q->frames[i*hdr->num_poses + j], q->baseframe[p->parent], m, q->inversebaseframe[j]);
|
||||||
else multiply34x2(frames[i*hdr->num_poses + j], m, inversebaseframe[j]);
|
else multiply34x2(q->frames[i*hdr->num_poses + j], m, q->inversebaseframe[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *str = hdr->ofs_text ? (char *)&buf[hdr->ofs_text] : "";
|
// const char *str = hdr->ofs_text ? (char *)&q->buf[hdr->ofs_text] : "";
|
||||||
for(int i = 0; i < (int)hdr->num_anims; i++) {
|
// for(int i = 0; i < (int)hdr->num_anims; i++) {
|
||||||
struct iqmanim *a = &anims[i];
|
// struct iqmanim *a = &anims[i];
|
||||||
PRINTF("loaded anim[%d]: %s\n", i, &str[a->name]);
|
// PRINTF("loaded anim[%d]: %s\n", i, &str[a->name]);
|
||||||
}
|
// }
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -20252,14 +20264,14 @@ static char* strcpy_safe(char *d, const char *s) {
|
||||||
|
|
||||||
static
|
static
|
||||||
bool model_load_textures(iqm_t *q, const struct iqmheader *hdr, model_t *model) {
|
bool model_load_textures(iqm_t *q, const struct iqmheader *hdr, model_t *model) {
|
||||||
textures = textures ? textures : CALLOC(hdr->num_meshes * 8, sizeof(GLuint)); // up to 8 textures per mesh
|
q->textures = q->textures ? q->textures : CALLOC(hdr->num_meshes * 8, sizeof(GLuint)); // up to 8 textures per mesh
|
||||||
colormaps = colormaps ? colormaps : CALLOC(hdr->num_meshes * 8, sizeof(vec4)); // up to 8 colormaps per mesh
|
q->colormaps = q->colormaps ? q->colormaps : CALLOC(hdr->num_meshes * 8, sizeof(vec4)); // up to 8 colormaps per mesh
|
||||||
|
|
||||||
GLuint *out = textures;
|
GLuint *out = q->textures;
|
||||||
|
|
||||||
const char *str = hdr->ofs_text ? (char *)&buf[hdr->ofs_text] : "";
|
const char *str = hdr->ofs_text ? (char *)&q->buf[hdr->ofs_text] : "";
|
||||||
for(int i = 0; i < (int)hdr->num_meshes; i++) {
|
for(int i = 0; i < (int)hdr->num_meshes; i++) {
|
||||||
struct iqmmesh *m = &meshes[i];
|
struct iqmmesh *m = &q->meshes[i];
|
||||||
|
|
||||||
// reuse texture+material if already decoded
|
// reuse texture+material if already decoded
|
||||||
bool reused = 0;
|
bool reused = 0;
|
||||||
|
@ -20428,13 +20440,23 @@ model_t model_from_mem(const void *mem, int len, int flags) {
|
||||||
if( !memcmp(hdr.magic, IQM_MAGIC, sizeof(hdr.magic))) {
|
if( !memcmp(hdr.magic, IQM_MAGIC, sizeof(hdr.magic))) {
|
||||||
lil32p(&hdr.version, (sizeof(hdr) - sizeof(hdr.magic))/sizeof(uint32_t));
|
lil32p(&hdr.version, (sizeof(hdr) - sizeof(hdr.magic))/sizeof(uint32_t));
|
||||||
if(hdr.version == IQM_VERSION) {
|
if(hdr.version == IQM_VERSION) {
|
||||||
buf = CALLOC(hdr.filesize, sizeof(uint8_t));
|
q->buf = CALLOC(hdr.filesize, sizeof(uint8_t));
|
||||||
memcpy(buf + sizeof(hdr), ptr, hdr.filesize - sizeof(hdr));
|
memcpy(q->buf + sizeof(hdr), ptr, hdr.filesize - sizeof(hdr));
|
||||||
error = 0;
|
error = 0;
|
||||||
if( hdr.num_meshes > 0 && !(flags & MODEL_NO_MESHES) ) error |= !model_load_meshes(q, &hdr, &m);
|
if( hdr.num_meshes > 0 && !(flags & MODEL_NO_MESHES) ) error |= !model_load_meshes(q, &hdr, &m);
|
||||||
if( hdr.num_meshes > 0 && !(flags & MODEL_NO_TEXTURES) ) error |= !model_load_textures(q, &hdr, &m);
|
if( hdr.num_meshes > 0 && !(flags & MODEL_NO_TEXTURES) ) error |= !model_load_textures(q, &hdr, &m);
|
||||||
|
else {
|
||||||
|
// setup fallback
|
||||||
|
material_t mt = {0};
|
||||||
|
mt.name = "placeholder";
|
||||||
|
mt.count = 1;
|
||||||
|
mt.layer[0].color = vec4(1,1,1,1);
|
||||||
|
mt.layer[0].texture = texture_checker().id;
|
||||||
|
|
||||||
|
array_push(m.materials, mt);
|
||||||
|
}
|
||||||
if( hdr.num_anims > 0 && !(flags & MODEL_NO_ANIMATIONS) ) error |= !model_load_anims(q, &hdr);
|
if( hdr.num_anims > 0 && !(flags & MODEL_NO_ANIMATIONS) ) error |= !model_load_anims(q, &hdr);
|
||||||
if( buf != meshdata && buf != animdata ) FREE(buf);
|
if( q->buf != q->meshdata && q->buf != q->animdata ) FREE(q->buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20443,31 +20465,23 @@ model_t model_from_mem(const void *mem, int len, int flags) {
|
||||||
PRINTF("Error: cannot load %s", "model");
|
PRINTF("Error: cannot load %s", "model");
|
||||||
FREE(q), q = 0;
|
FREE(q), q = 0;
|
||||||
} else {
|
} else {
|
||||||
#undef vao
|
|
||||||
#undef ibo
|
|
||||||
#undef vbo
|
|
||||||
m.vao = q->vao;
|
m.vao = q->vao;
|
||||||
m.ibo = q->ibo;
|
m.ibo = q->ibo;
|
||||||
m.vbo = q->vbo;
|
m.vbo = q->vbo;
|
||||||
m.num_verts = numverts;
|
m.num_verts = q->numverts;
|
||||||
#define vao (q->vao)
|
|
||||||
#define ibo (q->ibo)
|
|
||||||
#define vbo (q->vbo)
|
|
||||||
|
|
||||||
// m.boxes = bounds; // <@todo
|
// m.boxes = bounds; // <@todo
|
||||||
m.num_meshes = nummeshes;
|
m.num_meshes = q->nummeshes;
|
||||||
m.num_triangles = numtris;
|
m.num_triangles = q->numtris;
|
||||||
m.num_joints = numjoints;
|
m.num_joints = q->numjoints;
|
||||||
//m.num_poses = numposes;
|
//m.num_poses = numposes;
|
||||||
m.num_anims = numanims;
|
m.num_anims = q->numanims;
|
||||||
m.num_frames = numframes;
|
m.num_frames = q->numframes;
|
||||||
m.iqm = q;
|
m.iqm = q;
|
||||||
m.curframe = model_animate(m, 0);
|
m.curframe = model_animate(m, 0);
|
||||||
|
|
||||||
//m.num_textures = nummeshes; // assume 1 texture only per mesh
|
//m.num_textures = q->nummeshes; // assume 1 texture only per mesh
|
||||||
#undef textures
|
|
||||||
m.textures = (q->textures);
|
m.textures = (q->textures);
|
||||||
#define textures (q->textures)
|
|
||||||
|
|
||||||
m.flags = flags;
|
m.flags = flags;
|
||||||
|
|
||||||
|
@ -20491,9 +20505,9 @@ bool model_get_bone_pose(model_t m, unsigned joint, mat34 *out) {
|
||||||
if(!m.iqm) return false;
|
if(!m.iqm) return false;
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
if(joint >= numjoints) return false;
|
if(joint >= q->numjoints) return false;
|
||||||
|
|
||||||
multiply34x2(*out, outframe[joint], baseframe[joint]);
|
multiply34x2(*out, q->outframe[joint], q->baseframe[joint]);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20504,6 +20518,26 @@ anim_t loop(float minframe, float maxframe, float blendtime, unsigned flags) {
|
||||||
return clip(minframe, maxframe, blendtime, flags | ANIM_LOOP);
|
return clip(minframe, maxframe, blendtime, flags | ANIM_LOOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
array(anim_t) animlist(const char *pathfile) {
|
||||||
|
anim_t *animlist = 0;
|
||||||
|
char *anim_file = vfs_read(strendi(pathfile,".txt") ? pathfile : va("%s@animlist.txt", pathfile));
|
||||||
|
if( anim_file ) {
|
||||||
|
// deserialize anim
|
||||||
|
for each_substring(anim_file, "\r\n", anim) {
|
||||||
|
int from, to;
|
||||||
|
char anim_name[128] = {0};
|
||||||
|
if( sscanf(anim, "%*s %d-%d %127[^\r\n]", &from, &to, anim_name) != 3) continue;
|
||||||
|
array_push(animlist, !!strstri(anim_name, "loop") || !strcmpi(anim_name, "idle") ? loop(from, to, 0, 0) : clip(from, to, 0, 0)); // [from,to,flags]
|
||||||
|
array_back(animlist)->name = strswap(strswap(strswap(STRDUP(anim_name), "Loop", ""), "loop", ""), "()", ""); // @leak
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// placeholder
|
||||||
|
array_push(animlist, clip(0,1,0,0));
|
||||||
|
array_back(animlist)->name = STRDUP("Error"); // @leak
|
||||||
|
}
|
||||||
|
return animlist;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void anim_tick(anim_t *p, bool is_primary, float delta) { // delta can be negative (reverses anim)
|
void anim_tick(anim_t *p, bool is_primary, float delta) { // delta can be negative (reverses anim)
|
||||||
if( !is_primary ) p->active = 0;
|
if( !is_primary ) p->active = 0;
|
||||||
|
@ -20541,18 +20575,18 @@ float model_animate_blends(model_t m, anim_t *primary, anim_t *secondary, float
|
||||||
unsigned frame4 = secondary->pose.y;
|
unsigned frame4 = secondary->pose.y;
|
||||||
float alphaB = secondary->pose.z;
|
float alphaB = secondary->pose.z;
|
||||||
|
|
||||||
mat34 *mat1 = &frames[frame1 * numjoints];
|
mat34 *mat1 = &q->frames[frame1 * q->numjoints];
|
||||||
mat34 *mat2 = &frames[frame2 * numjoints];
|
mat34 *mat2 = &q->frames[frame2 * q->numjoints];
|
||||||
mat34 *mat3 = &frames[frame3 * numjoints];
|
mat34 *mat3 = &q->frames[frame3 * q->numjoints];
|
||||||
mat34 *mat4 = &frames[frame4 * numjoints];
|
mat34 *mat4 = &q->frames[frame4 * q->numjoints];
|
||||||
|
|
||||||
for(int i = 0; i < numjoints; i++) {
|
for(int i = 0; i < q->numjoints; i++) {
|
||||||
mat34 matA, matB, matF;
|
mat34 matA, matB, matF;
|
||||||
lerp34(matA, mat1[i], mat2[i], alphaA);
|
lerp34(matA, mat1[i], mat2[i], alphaA);
|
||||||
lerp34(matB, mat3[i], mat4[i], alphaB);
|
lerp34(matB, mat3[i], mat4[i], alphaB);
|
||||||
lerp34(matF, matA, matB, alpha );
|
lerp34(matF, matA, matB, alpha );
|
||||||
if(joints[i].parent >= 0) multiply34x2(outframe[i], outframe[joints[i].parent], matF);
|
if(q->joints[i].parent >= 0) multiply34x2(q->outframe[i], q->outframe[q->joints[i].parent], matF);
|
||||||
else copy34(outframe[i], matF);
|
else copy34(q->outframe[i], matF);
|
||||||
}
|
}
|
||||||
|
|
||||||
return frame1 + alpha;
|
return frame1 + alpha;
|
||||||
|
@ -20587,20 +20621,20 @@ float model_animate_clip(model_t m, float curframe, int minframe, int maxframe,
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
float retframe = -1;
|
float retframe = -1;
|
||||||
if( numframes > 0 ) {
|
if( q->numframes > 0 ) {
|
||||||
vec3 p = pose(curframe >= m.curframe, curframe, minframe, maxframe, loop, &retframe);
|
vec3 p = pose(curframe >= m.curframe, curframe, minframe, maxframe, loop, &retframe);
|
||||||
int frame1 = p.x;
|
int frame1 = p.x;
|
||||||
int frame2 = p.y;
|
int frame2 = p.y;
|
||||||
float offset = p.z;
|
float offset = p.z;
|
||||||
|
|
||||||
mat34 *mat1 = &frames[frame1 * numjoints];
|
mat34 *mat1 = &q->frames[frame1 * q->numjoints];
|
||||||
mat34 *mat2 = &frames[frame2 * numjoints];
|
mat34 *mat2 = &q->frames[frame2 * q->numjoints];
|
||||||
|
|
||||||
// @todo: add animation blending and inter-frame blending here
|
// @todo: add animation blending and inter-frame blending here
|
||||||
for(int i = 0; i < numjoints; i++) {
|
for(int i = 0; i < q->numjoints; i++) {
|
||||||
mat34 mat; lerp34(mat, mat1[i], mat2[i], offset);
|
mat34 mat; lerp34(mat, mat1[i], mat2[i], offset);
|
||||||
if(joints[i].parent >= 0) multiply34x2(outframe[i], outframe[joints[i].parent], mat);
|
if(q->joints[i].parent >= 0) multiply34x2(q->outframe[i], q->outframe[q->joints[i].parent], mat);
|
||||||
else copy34(outframe[i], mat);
|
else copy34(q->outframe[i], mat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20611,20 +20645,20 @@ void model_render_skeleton(model_t m, mat44 M) {
|
||||||
if(!m.iqm) return;
|
if(!m.iqm) return;
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
if(!numjoints) return;
|
if(!q->numjoints) return;
|
||||||
|
|
||||||
ddraw_ontop_push(true);
|
ddraw_ontop_push(true);
|
||||||
ddraw_color_push(RED);
|
ddraw_color_push(RED);
|
||||||
|
|
||||||
for( int joint = 0; joint < numjoints; joint++ ) {
|
for( int joint = 0; joint < q->numjoints; joint++ ) {
|
||||||
if( joints[joint].parent < 0) continue;
|
if( q->joints[joint].parent < 0) continue;
|
||||||
|
|
||||||
// bone space...
|
// bone space...
|
||||||
mat34 f;
|
mat34 f;
|
||||||
model_get_bone_pose(m, joint, &f);
|
model_get_bone_pose(m, joint, &f);
|
||||||
vec3 pos = vec3(f[3],f[7],f[11]);
|
vec3 pos = vec3(f[3],f[7],f[11]);
|
||||||
|
|
||||||
model_get_bone_pose(m, joints[joint].parent, &f);
|
model_get_bone_pose(m, q->joints[joint].parent, &f);
|
||||||
vec3 src = vec3(f[3],f[7],f[11]);
|
vec3 src = vec3(f[3],f[7],f[11]);
|
||||||
|
|
||||||
// ...to model space
|
// ...to model space
|
||||||
|
@ -20652,7 +20686,7 @@ void model_render_skeleton(model_t m, mat44 M) {
|
||||||
float model_animate(model_t m, float curframe) {
|
float model_animate(model_t m, float curframe) {
|
||||||
if(!m.iqm) return -1;
|
if(!m.iqm) return -1;
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
return model_animate_clip(m, curframe, 0, numframes-1, true);
|
return model_animate_clip(m, curframe, 0, q->numframes-1, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
|
@ -20660,19 +20694,19 @@ void model_draw_call(model_t m, int shader) {
|
||||||
if(!m.iqm) return;
|
if(!m.iqm) return;
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
|
|
||||||
glBindVertexArray( vao );
|
glBindVertexArray( q->vao );
|
||||||
|
|
||||||
struct iqmtriangle *tris = NULL;
|
struct iqmtriangle *tris = NULL;
|
||||||
for(int i = 0; i < nummeshes; i++) {
|
for(int i = 0; i < q->nummeshes; i++) {
|
||||||
struct iqmmesh *im = &meshes[i];
|
struct iqmmesh *im = &q->meshes[i];
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, textures[i] );
|
glBindTexture(GL_TEXTURE_2D, q->textures[i] );
|
||||||
glUniform1i(glGetUniformLocation(shader, "u_texture2d"), 0 );
|
glUniform1i(glGetUniformLocation(shader, "u_texture2d"), 0 );
|
||||||
|
|
||||||
int loc;
|
int loc;
|
||||||
if ((loc = glGetUniformLocation(shader, "u_textured")) >= 0) {
|
if ((loc = glGetUniformLocation(shader, "u_textured")) >= 0) {
|
||||||
bool textured = !!textures[i] && textures[i] != texture_checker().id; // m.materials[i].layer[0].texture != texture_checker().id;
|
bool textured = !!q->textures[i] && q->textures[i] != texture_checker().id; // m.materials[i].layer[0].texture != texture_checker().id;
|
||||||
glUniform1i(loc, textured ? GL_TRUE : GL_FALSE);
|
glUniform1i(loc, textured ? GL_TRUE : GL_FALSE);
|
||||||
if ((loc = glGetUniformLocation(shader, "u_diffuse")) >= 0) {
|
if ((loc = glGetUniformLocation(shader, "u_diffuse")) >= 0) {
|
||||||
glUniform4f(loc, m.materials[i].layer[0].color.r, m.materials[i].layer[0].color.g, m.materials[i].layer[0].color.b, m.materials[i].layer[0].color.a);
|
glUniform4f(loc, m.materials[i].layer[0].color.r, m.materials[i].layer[0].color.g, m.materials[i].layer[0].color.b, m.materials[i].layer[0].color.a);
|
||||||
|
@ -20732,10 +20766,10 @@ aabb aabb_transform( aabb A, mat44 M ) {
|
||||||
|
|
||||||
aabb model_aabb(model_t m, mat44 transform) {
|
aabb model_aabb(model_t m, mat44 transform) {
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
if( q && bounds ) {
|
if( q && q->bounds ) {
|
||||||
int f = ( (int)m.curframe ) % (numframes + !numframes);
|
int f = ( (int)m.curframe ) % (q->numframes + !q->numframes);
|
||||||
vec3 bbmin = ptr3(bounds[f].bbmin);
|
vec3 bbmin = ptr3(q->bounds[f].bbmin);
|
||||||
vec3 bbmax = ptr3(bounds[f].bbmax);
|
vec3 bbmax = ptr3(q->bounds[f].bbmax);
|
||||||
return aabb_transform(aabb(bbmin,bbmax), transform);
|
return aabb_transform(aabb(bbmin,bbmax), transform);
|
||||||
}
|
}
|
||||||
return aabb(vec3(0,0,0),vec3(0,0,0));
|
return aabb(vec3(0,0,0),vec3(0,0,0));
|
||||||
|
@ -20750,62 +20784,22 @@ void model_destroy(model_t m) {
|
||||||
|
|
||||||
iqm_t *q = m.iqm;
|
iqm_t *q = m.iqm;
|
||||||
// if(m.mesh) mesh_destroy(m.mesh);
|
// if(m.mesh) mesh_destroy(m.mesh);
|
||||||
FREE(outframe);
|
FREE(q->outframe);
|
||||||
FREE(colormaps);
|
FREE(q->colormaps);
|
||||||
FREE(textures);
|
FREE(q->textures);
|
||||||
FREE(baseframe);
|
FREE(q->baseframe);
|
||||||
FREE(inversebaseframe);
|
FREE(q->inversebaseframe);
|
||||||
if(animdata != meshdata) FREE(animdata);
|
if(q->animdata != q->meshdata) FREE(q->animdata);
|
||||||
//FREE(meshdata);
|
//FREE(q->meshdata);
|
||||||
FREE(frames);
|
FREE(q->frames);
|
||||||
FREE(buf);
|
FREE(q->buf);
|
||||||
FREE(q);
|
FREE(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef program
|
|
||||||
#undef meshdata
|
|
||||||
#undef animdata
|
|
||||||
#undef nummeshes
|
|
||||||
#undef numtris
|
|
||||||
#undef numverts
|
|
||||||
#undef numjoints
|
|
||||||
#undef numframes
|
|
||||||
#undef numanims
|
|
||||||
#undef meshes
|
|
||||||
#undef textures
|
|
||||||
#undef joints
|
|
||||||
#undef poses
|
|
||||||
#undef anims
|
|
||||||
#undef baseframe
|
|
||||||
#undef inversebaseframe
|
|
||||||
#undef outframe
|
|
||||||
#undef frames
|
|
||||||
#undef vao
|
|
||||||
#undef ibo
|
|
||||||
#undef vbo
|
|
||||||
#undef bonematsoffset
|
|
||||||
#undef buf
|
|
||||||
#undef bounds
|
|
||||||
#undef colormaps
|
|
||||||
|
|
||||||
anims_t animations(const char *pathfile, int flags) {
|
anims_t animations(const char *pathfile, int flags) {
|
||||||
anims_t a = {0};
|
anims_t a = {0};
|
||||||
char *anim_file = vfs_read(strendi(pathfile,".txt") ? pathfile : va("%s@animlist.txt", pathfile));
|
a.speed = 1.0;
|
||||||
if( anim_file ) {
|
a.anims = animlist(pathfile);
|
||||||
// deserialize anim
|
|
||||||
a.speed = 1.0;
|
|
||||||
for each_substring(anim_file, "\r\n", anim) {
|
|
||||||
int from, to;
|
|
||||||
char anim_name[128] = {0};
|
|
||||||
if( sscanf(anim, "%*s %d-%d %127[^\r\n]", &from, &to, anim_name) != 3) continue;
|
|
||||||
array_push(a.anims, !!strstri(anim_name, "loop") || !strcmpi(anim_name, "idle") ? loop(from, to, 0, 0) : clip(from, to, 0, 0)); // [from,to,flags]
|
|
||||||
array_back(a.anims)->name = strswap(strswap(strswap(STRDUP(anim_name), "Loop", ""), "loop", ""), "()", ""); // @leak
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// placeholder
|
|
||||||
array_push(a.anims, clip(0,1,0,0));
|
|
||||||
array_back(a.anims)->name = STRDUP("Error"); // @leak
|
|
||||||
}
|
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22083,6 +22077,8 @@ void object_update(object_t *obj) {
|
||||||
quat p = eulerq(vec3(obj->pivot.x,obj->pivot.y,obj->pivot.z));
|
quat p = eulerq(vec3(obj->pivot.x,obj->pivot.y,obj->pivot.z));
|
||||||
quat e = eulerq(vec3(obj->euler.x,obj->euler.y,obj->euler.z));
|
quat e = eulerq(vec3(obj->euler.x,obj->euler.y,obj->euler.z));
|
||||||
compose44(obj->transform, obj->pos, mulq(e, p), obj->sca);
|
compose44(obj->transform, obj->pos, mulq(e, p), obj->sca);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object_t object() {
|
object_t object() {
|
||||||
|
@ -22132,6 +22128,11 @@ void object_model(object_t *obj, model_t model) {
|
||||||
obj->model = model;
|
obj->model = model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void object_anim(object_t *obj, anim_t anim, float speed) {
|
||||||
|
obj->anim = anim;
|
||||||
|
obj->anim_speed = speed;
|
||||||
|
}
|
||||||
|
|
||||||
void object_push_diffuse(object_t *obj, texture_t tex) {
|
void object_push_diffuse(object_t *obj, texture_t tex) {
|
||||||
array_push(obj->textures, tex.id);
|
array_push(obj->textures, tex.id);
|
||||||
}
|
}
|
||||||
|
@ -22399,6 +22400,7 @@ void scene_render(int flags) {
|
||||||
for(unsigned j = 0, obj_count = scene_count(); j < obj_count; ++j ) {
|
for(unsigned j = 0, obj_count = scene_count(); j < obj_count; ++j ) {
|
||||||
object_t *obj = scene_index(j);
|
object_t *obj = scene_index(j);
|
||||||
model_t *model = &obj->model;
|
model_t *model = &obj->model;
|
||||||
|
anim_t *anim = &obj->anim;
|
||||||
mat44 *views = (mat44*)(&cam->view);
|
mat44 *views = (mat44*)(&cam->view);
|
||||||
|
|
||||||
// @todo: avoid heap allocs here?
|
// @todo: avoid heap allocs here?
|
||||||
|
@ -22423,6 +22425,11 @@ void scene_render(int flags) {
|
||||||
shader_vec3v("u_coefficients_sh", 9, last_scene->skybox.cubemap.sh);
|
shader_vec3v("u_coefficients_sh", 9, last_scene->skybox.cubemap.sh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (anim) {
|
||||||
|
float delta = window_delta() * obj->anim_speed;
|
||||||
|
model->curframe = model_animate_clip(*model, model->curframe + delta, anim->from, anim->to, anim->flags & ANIM_LOOP );
|
||||||
|
}
|
||||||
|
|
||||||
model->billboard = obj->billboard;
|
model->billboard = obj->billboard;
|
||||||
model_render(*model, cam->proj, cam->view, obj->transform, 0);
|
model_render(*model, cam->proj, cam->view, obj->transform, 0);
|
||||||
|
|
||||||
|
|
|
@ -2197,13 +2197,14 @@ enum FONT_FLAGS {
|
||||||
typedef struct font_metrics_t {
|
typedef struct font_metrics_t {
|
||||||
float ascent; // max distance above baseline for all glyphs
|
float ascent; // max distance above baseline for all glyphs
|
||||||
float descent; // max distance below baseline for all glyphs
|
float descent; // max distance below baseline for all glyphs
|
||||||
float linegap; // distance betwen ascent of next line and descent of current line
|
float linegap; // distance between ascent of next line and descent of current line
|
||||||
float linedist; // distance between the baseline of two lines (ascent - descent + linegap)
|
float linedist; // distance between the baseline of two lines (ascent - descent + linegap)
|
||||||
} font_metrics_t;
|
} font_metrics_t;
|
||||||
|
|
||||||
// configures
|
// configures
|
||||||
API void font_face(const char *face_tag, const char *filename_ttf, float font_size, unsigned flags);
|
API void font_face(const char *face_tag, const char *filename_ttf, float font_size, unsigned flags);
|
||||||
API void font_face_from_mem(const char *tag, const void *ttf_buffer, unsigned ttf_len, float font_size, unsigned flags);
|
API void font_face_from_mem(const char *tag, const void *ttf_buffer, unsigned ttf_len, float font_size, unsigned flags);
|
||||||
|
API void font_scale(const char *face_tag, int scale_index, float value);
|
||||||
API void font_scales(const char *face_tag, float h1, float h2, float h3, float h4, float h5, float h6);
|
API void font_scales(const char *face_tag, float h1, float h2, float h3, float h4, float h5, float h6);
|
||||||
API void font_color(const char *color_tag, uint32_t color);
|
API void font_color(const char *color_tag, uint32_t color);
|
||||||
|
|
||||||
|
@ -2211,6 +2212,7 @@ API void font_color(const char *color_tag, uint32_t color);
|
||||||
API vec2 font_xy();
|
API vec2 font_xy();
|
||||||
API void font_goto(float x, float y);
|
API void font_goto(float x, float y);
|
||||||
API vec2 font_print(const char *text);
|
API vec2 font_print(const char *text);
|
||||||
|
API vec2 font_print_rect(const char *text, vec4 rect);
|
||||||
API vec2 font_rect(const char *text);
|
API vec2 font_rect(const char *text);
|
||||||
API font_metrics_t font_metrics(const char *text);
|
API font_metrics_t font_metrics(const char *text);
|
||||||
// void font_clip(vec2 topleft, vec2 bottomright);
|
// void font_clip(vec2 topleft, vec2 bottomright);
|
||||||
|
@ -3576,7 +3578,7 @@ typedef struct anim_t {
|
||||||
|
|
||||||
API anim_t clip(float minframe, float maxframe, float blendtime, unsigned flags);
|
API anim_t clip(float minframe, float maxframe, float blendtime, unsigned flags);
|
||||||
API anim_t loop(float minframe, float maxframe, float blendtime, unsigned flags);
|
API anim_t loop(float minframe, float maxframe, float blendtime, unsigned flags);
|
||||||
//API array(anim_t) animlist(const char *filename); // @todo
|
API array(anim_t) animlist(const char *filename);
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// models
|
// models
|
||||||
|
@ -3856,6 +3858,8 @@ typedef struct object_t {
|
||||||
vec3 sca, pos, euler, pivot;
|
vec3 sca, pos, euler, pivot;
|
||||||
array(handle) textures;
|
array(handle) textures;
|
||||||
model_t model;
|
model_t model;
|
||||||
|
anim_t anim;
|
||||||
|
float anim_speed;
|
||||||
aabb bounds;
|
aabb bounds;
|
||||||
unsigned billboard; // [0..7] x(4),y(2),z(1) masks
|
unsigned billboard; // [0..7] x(4),y(2),z(1) masks
|
||||||
bool light_cached; //< used by scene to update light data
|
bool light_cached; //< used by scene to update light data
|
||||||
|
@ -3870,6 +3874,7 @@ API vec3 object_position(object_t *obj);
|
||||||
API void object_scale(object_t *obj, vec3 sca);
|
API void object_scale(object_t *obj, vec3 sca);
|
||||||
//
|
//
|
||||||
API void object_model(object_t *obj, model_t model);
|
API void object_model(object_t *obj, model_t model);
|
||||||
|
API void object_anim(object_t *obj, anim_t anim, float speed);
|
||||||
API void object_diffuse(object_t *obj, texture_t tex);
|
API void object_diffuse(object_t *obj, texture_t tex);
|
||||||
API void object_diffuse_push(object_t *obj, texture_t tex);
|
API void object_diffuse_push(object_t *obj, texture_t tex);
|
||||||
API void object_diffuse_pop(object_t *obj);
|
API void object_diffuse_pop(object_t *obj);
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue