From c3801d46e51be8292dad0655d9994acc7996040d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 17 May 2012 15:58:29 +0900 Subject: [PATCH] Render iqm models in GL. There are still many issues to sort out, but the basics are working. Problems: rendered fullbright (no lighting done) normals are ignored extra textures (glow etc) not used/loaded 4 models on the screen don't seem to be a problem. --- include/QF/GL/qf_iqm.h | 8 ++ libs/models/iqm/gl_model_iqm.c | 13 +++ libs/video/renderer/gl/Makefile.am | 4 +- libs/video/renderer/gl/gl_mod_iqm.c | 130 ++++++++++++++++++++++++++++ libs/video/renderer/gl/gl_rmain.c | 14 ++- 5 files changed, 165 insertions(+), 4 deletions(-) create mode 100644 libs/video/renderer/gl/gl_mod_iqm.c diff --git a/include/QF/GL/qf_iqm.h b/include/QF/GL/qf_iqm.h index 8c6b3e11c..47a77d6da 100644 --- a/include/QF/GL/qf_iqm.h +++ b/include/QF/GL/qf_iqm.h @@ -31,11 +31,19 @@ #define __QF_GL_qf_iqm_h #include "QF/iqm.h" +#include "QF/render.h" typedef struct glsliqm_s { int *textures; iqmblend_t *blend_palette; // includes base data from iqm int palette_size; // includes base data from iqm + iqmvertexarray *position; + iqmvertexarray *texcoord; + iqmvertexarray *normal; + iqmvertexarray *bindices; + iqmvertexarray *color; } gliqm_t; +void gl_R_DrawIQMModel (entity_t *ent); + #endif//__QF_GL_qf_iqm_h diff --git a/libs/models/iqm/gl_model_iqm.c b/libs/models/iqm/gl_model_iqm.c index a93ab09f1..e2e877d1d 100644 --- a/libs/models/iqm/gl_model_iqm.c +++ b/libs/models/iqm/gl_model_iqm.c @@ -98,9 +98,22 @@ gl_Mod_IQMFinish (model_t *mod) { iqm_t *iqm = (iqm_t *) mod->aliashdr; gliqm_t *gl; + int i; mod->clear = gl_iqm_clear; iqm->extra_data = gl = calloc (1, sizeof (gliqm_t)); gl_iqm_load_textures (iqm); gl->blend_palette = Mod_IQMBuildBlendPalette (iqm, &gl->palette_size); + for (i = 0; i < iqm->num_arrays; i++) { + if (iqm->vertexarrays[i].type == IQM_POSITION) + gl->position = &iqm->vertexarrays[i]; + if (iqm->vertexarrays[i].type == IQM_TEXCOORD) + gl->texcoord = &iqm->vertexarrays[i]; + if (iqm->vertexarrays[i].type == IQM_NORMAL) + gl->normal = &iqm->vertexarrays[i]; + if (iqm->vertexarrays[i].type == IQM_BLENDINDEXES) + gl->bindices = &iqm->vertexarrays[i]; + if (iqm->vertexarrays[i].type == IQM_COLOR) + gl->color = &iqm->vertexarrays[i]; + } } diff --git a/libs/video/renderer/gl/Makefile.am b/libs/video/renderer/gl/Makefile.am index 4298d8bf0..c50e9ab60 100644 --- a/libs/video/renderer/gl/Makefile.am +++ b/libs/video/renderer/gl/Makefile.am @@ -7,8 +7,8 @@ noinst_LTLIBRARIES= libgl.la gl_src = \ gl_draw.c gl_dyn_lights.c gl_dyn_part.c gl_dyn_textures.c \ - gl_fog.c gl_graph.c gl_lightmap.c gl_mod_alias.c gl_mod_sprite.c \ - gl_rmain.c gl_rmisc.c gl_rsurf.c gl_screen.c gl_sky.c \ + gl_fog.c gl_graph.c gl_lightmap.c gl_mod_alias.c gl_mod_iqm.c \ + gl_mod_sprite.c gl_rmain.c gl_rmisc.c gl_rsurf.c gl_screen.c gl_sky.c \ gl_sky_clip.c gl_textures.c gl_warp.c qfgl_ext.c vid_common_gl.c vtxarray.c libgl_la_SOURCES= $(gl_src) diff --git a/libs/video/renderer/gl/gl_mod_iqm.c b/libs/video/renderer/gl/gl_mod_iqm.c new file mode 100644 index 000000000..c47220e30 --- /dev/null +++ b/libs/video/renderer/gl/gl_mod_iqm.c @@ -0,0 +1,130 @@ +/* + gl_mod_iqm.c + + GL IQM rendering + + Copyright (C) 2012 Bill Currie + + Author: Bill Currie + Date: 2012/5/17 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#define NH_DEFINE +#include "namehack.h" + +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#include "QF/cvar.h" +#include "QF/render.h" +#include "QF/skin.h" +#include "QF/sys.h" + +#include "QF/GL/defines.h" +#include "QF/GL/funcs.h" +#include "QF/GL/qf_iqm.h" +#include "QF/GL/qf_rmain.h" +#include "QF/GL/qf_vid.h" + +#include "r_internal.h" + +//FIXME this is really lame: normals are ignored. also, it could be +//faster +static void +gl_draw_iqm_frame (iqm_t *iqm, gliqm_t *gl, iqmframe_t *frame, iqmmesh *mesh) +{ + byte *vert; + uint32_t i, j; + + qfglBegin (GL_TRIANGLES); + for (i = 0; i < mesh->num_triangles; i++) { + int vind = (mesh->first_triangle + i) * 3; + for (j = 0; j < 3; j++) { + vert = iqm->vertices + iqm->elements[vind + j] * iqm->stride; + if (gl->texcoord) + qfglTexCoord2fv ((float *) (vert + gl->texcoord->offset)); + if (gl->color) + qfglColor4bv ((GLbyte *) (vert + gl->color->offset)); + if (gl->bindices) { + vec3_t position; + uint32_t bind = *(uint32_t *) (vert + gl->bindices->offset); + vec_t *f = (vec_t *) &frame[bind]; + float *v = (float *) (vert + gl->position->offset); + Mat4MultVec (f, v, position); + VectorScale (position, 8, position); + qfglVertex3fv (position); + } else { + qfglVertex3fv ((float *) (vert + gl->position->offset)); + } + } + } + qfglEnd (); +} + +void +gl_R_DrawIQMModel (entity_t *ent) +{ + model_t *model = ent->model; + iqm_t *iqm = (iqm_t *) model->aliashdr; + gliqm_t *gl = (gliqm_t *) iqm->extra_data; + int data_size; + float blend; + iqmframe_t *frame; + int i, j; + + model = ent->model; + data_size = (gl->palette_size - iqm->num_joints) * sizeof (iqmframe_t); + blend = R_IQMGetLerpedFrames (ent, iqm); + frame = R_IQMBlendFrames (iqm, ent->pose1, ent->pose2, blend, data_size); + for (i = iqm->num_joints; i < gl->palette_size; i++) { + vec_t *mat = (vec_t *) &frame[i]; + iqmblend_t *blend = &gl->blend_palette[i]; + vec_t *f; + + f = (vec_t *) &frame[blend->indices[0]]; + Mat4Scale (f, blend->weights[0] / 255.0, mat); + for (j = 1; j < 4; j++) { + if (!blend->weights[j]) + break; + f = (vec_t *) &frame[blend->indices[j]]; + Mat4MultAdd (mat, blend->weights[j] / 255.0, f, mat); + } + } + + qfglPushMatrix (); + gl_R_RotateForEntity (ent); + qfglScalef (ent->scale, ent->scale, ent->scale); + + for (i = 0; i < iqm->num_meshes; i++) { + qfglBindTexture (GL_TEXTURE_2D, gl->textures[i]); + gl_draw_iqm_frame (iqm, gl, frame, &iqm->meshes[i]); + } + qfglPopMatrix (); +} diff --git a/libs/video/renderer/gl/gl_rmain.c b/libs/video/renderer/gl/gl_rmain.c index b28b7cb49..f3c7ba9cf 100644 --- a/libs/video/renderer/gl/gl_rmain.c +++ b/libs/video/renderer/gl/gl_rmain.c @@ -55,6 +55,7 @@ #include "QF/GL/defines.h" #include "QF/GL/funcs.h" #include "QF/GL/qf_draw.h" +#include "QF/GL/qf_iqm.h" #include "QF/GL/qf_rlight.h" #include "QF/GL/qf_rmain.h" #include "QF/GL/qf_rsurf.h" @@ -214,7 +215,7 @@ R_DrawEntitiesOnList (void) } else if (gl_tess) { qfglEnable (GL_NORMALIZE); } - + for (ent = r_ent_queue; ent; ent = ent->next) { if (ent->model->type != mod_alias) continue; @@ -227,7 +228,6 @@ R_DrawEntitiesOnList (void) qfglDisable (GL_NORMALIZE); qfglDisable (GL_LIGHTING); - qfglDisable (GL_CULL_FACE); if (gl_tess) qfglDisable (GL_PN_TRIANGLES_ATI); if (gl_affinemodels->int_val) @@ -248,6 +248,16 @@ R_DrawEntitiesOnList (void) qglActiveTexture (gl_mtex_enum + 0); } + for (ent = r_ent_queue; ent; ent = ent->next) { + if (ent->model->type != mod_iqm) + continue; + currententity = ent; + + gl_R_DrawIQMModel (currententity); + } + qfglColor3ubv (color_white); + + qfglDisable (GL_CULL_FACE); qfglEnable (GL_ALPHA_TEST); if (gl_va_capable) qfglInterleavedArrays (GL_T2F_C4UB_V3F, 0, gl_spriteVertexArray);