/** * @brief Draws the field marker entity is specified in CL_AddTargeting * @sa CL_AddTargeting * @sa RF_BOX */ static void R_DrawBox (const entity_t* e) { const vec4_t color = {e->color[0], e->color[1], e->color[2], e->alpha}; if (e->texture) { R_Color(color); R_BindTexture(e->texture->texnum); if (VectorNotEmpty(e->eBox.mins) && VectorNotEmpty(e->eBox.maxs)) { R_DrawTexturedBox(e->eBox.mins, e->eBox.maxs); } else { R_DrawTexturedBox(e->oldorigin, e->origin); } R_Color(nullptr); return; } glDisable(GL_TEXTURE_2D); R_Color(color); if (VectorNotEmpty(e->eBox.mins) && VectorNotEmpty(e->eBox.maxs)) { R_DrawBoundingBox(e->eBox); } else { vec3_t points[] = { { e->oldorigin[0], e->oldorigin[1], e->oldorigin[2] }, { e->oldorigin[0], e->origin[1], e->oldorigin[2] }, { e->origin[0], e->origin[1], e->oldorigin[2] }, { e->origin[0], e->oldorigin[1], e->oldorigin[2] } }; glLineWidth(2.0f); R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, points); /** @todo fill one array */ glDrawArrays(GL_LINE_LOOP, 0, 4); refdef.batchCount++; points[0][2] = e->origin[2]; points[1][2] = e->origin[2]; points[2][2] = e->origin[2]; points[3][2] = e->origin[2]; glDrawArrays(GL_LINE_LOOP, 0, 4); refdef.batchCount++; points[0][2] = e->oldorigin[2]; points[1][1] = e->oldorigin[1]; points[2][2] = e->oldorigin[2]; points[3][1] = e->origin[1]; glDrawArrays(GL_LINES, 0, 4); refdef.batchCount++; points[0][0] = e->origin[0]; points[1][0] = e->origin[0]; points[2][0] = e->oldorigin[0]; points[3][0] = e->oldorigin[0]; glDrawArrays(GL_LINES, 0, 4); refdef.batchCount++; R_BindDefaultArray(GL_VERTEX_ARRAY); } glEnable(GL_TEXTURE_2D); R_Color(nullptr); }
/** * @brief Use the vertex, texture and normal arrays to draw a surface * @sa R_DrawSurfaces */ static inline void R_DrawSurface (const mBspSurface_t *surf) { glDrawArrays(GL_TRIANGLE_FAN, surf->index, surf->numedges); refdef.batchCount++; if (r_showbox->integer == 2) R_DrawBoundingBox(surf->mins, surf->maxs); refdef.brushCount++; }
/** * @param[in] drawFunc The function pointer to the surface draw function * @param[in] surfType The primary rendering type of the surface */ static void R_RenderBspRRefs (drawSurfaceFunc drawFunc, surfaceArrayType_t surfType) { glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); /* our triangles are backwards to what OpenGL expects, so tell it to render only back faces */ for (int i = 0; i < numBspRRefs; i++) { const bspRenderRef_t* const bspRR = &bspRRefs[i]; const mBspModel_t* const bsp = bspRR->bsp; const mBspModel_t* const tile = &r_mapTiles[bsp->maptile]->bsp; /* This is required to find the tile (world) bsp model to which arrays belong (submodels do not own arrays, but use world model ones) */ glElementIndex_t* indexPtr; if (!bsp->sorted_surfaces[surfType]->count) continue; R_SetArrayState(tile); /* Vertex buffers are nullptr-based, arrays are not */ if (qglBindBuffer && r_vertexbuffers->integer) indexPtr = nullptr; else indexPtr = tile->indexes; glPushMatrix(); glTranslatef(bspRR->origin[0], bspRR->origin[1], bspRR->origin[2]); glRotatef(bspRR->angles[YAW], 0, 0, 1); glRotatef(bspRR->angles[PITCH], 0, 1, 0); glRotatef(bspRR->angles[ROLL], 1, 0, 0); drawFunc(bsp->sorted_surfaces[surfType], indexPtr); /** @todo make it work again; also reimplement r_showbox 2 */ #if 0 /* show model bounding box */ if (r_showbox->integer) { const model_t* model = bspRR->bsp; R_DrawBoundingBox(model->mins, model->maxs); } #endif glPopMatrix(); } /* and restore array pointers */ R_ResetArrayState(); glCullFace(GL_BACK); glDisable(GL_CULL_FACE); }
/** * @brief Renders a particle model for the battlescape * @param[in,out] mi The model information that is used to render the particle model. * @sa R_DrawPtlModel */ void R_DrawModelParticle (modelInfo_t * mi) { image_t *skin; mAliasMesh_t *mesh; /* check if the model exists */ if (!mi->model) return; skin = R_AliasModelState(mi->model, &mi->mesh, &mi->frame, &mi->oldframe, &mi->skin); if (skin == NULL) { Com_Printf("Model '%s' is broken\n", mi->name); return; } R_Color(mi->color); glPushMatrix(); glTranslatef(mi->origin[0], mi->origin[1], mi->origin[2]); glRotatef(mi->angles[YAW], 0, 0, 1); glRotatef(mi->angles[PITCH], 0, 1, 0); glRotatef(-mi->angles[ROLL], 1, 0, 0); /* draw it */ R_BindTexture(skin->texnum); /* draw the model */ mesh = &mi->model->alias.meshes[0]; refdef.aliasCount += mesh->num_tris; if (mi->model->alias.num_frames == 1) R_DrawAliasStaticWithReset(mesh, vec4_origin); else R_DrawAliasFrameLerp(&mi->model->alias, mesh, mi->backlerp, mi->frame, mi->oldframe, vec4_origin); /* show model bounding box */ if (r_showbox->integer) R_DrawBoundingBox(mi->model->alias.frames[mi->frame].mins, mi->model->alias.frames[mi->frame].maxs); glPopMatrix(); R_Color(NULL); }
/** * @brief Draw a model from the battlescape entity list * @sa R_GetEntityLists */ void R_DrawAliasModel (entity_t *e) { mAliasModel_t *mod = &e->model->alias; /* the values are sane here already - see R_GetEntityLists */ const image_t *skin = mod->meshes[e->as.mesh].skins[e->skinnum].skin; int i; float g; vec4_t color = {0.8, 0.8, 0.8, 1.0}; mAliasMesh_t *mesh; /* IR goggles override color for entities that are affected */ if ((refdef.rendererFlags & RDF_IRGOGGLES) && (e->flags & RF_IRGOGGLES)) Vector4Set(e->shell, 1.0, 0.3, 0.3, 1.0); if (e->flags & RF_PULSE) { /* and then adding in a pulse */ const float f = 1.0 + sin((refdef.time + (e->model->alias.meshes[0].num_tris)) * 6.0) * 0.33; VectorScale(color, 1.0 + f, color); } g = 0.0; /* find brightest component */ for (i = 0; i < 3; i++) { if (color[i] > g) /* keep it */ g = color[i]; } /* scale it back to 1.0 */ if (g > 1.0) VectorScale(color, 1.0 / g, color); R_Color(color); assert(skin->texnum > 0); R_BindTexture(skin->texnum); R_EnableGlowMap(skin->glowmap); R_UpdateLightList(e); R_EnableModelLights(e->lights, e->numLights, e->inShadow, true); /** @todo this breaks the encapsulation - don't call CL_* functions from within the renderer code */ if (r_debug_lights->integer) { for (i = 0; i < e->numLights && i < r_dynamic_lights->integer; i++) CL_ParticleSpawn("lightTracerDebug", 0, e->transform.matrix + 12, e->lights[i]->origin); } if (skin->normalmap) R_EnableBumpmap(skin->normalmap); if (skin->specularmap) R_EnableSpecularMap(skin->specularmap, true); if (skin->roughnessmap) R_EnableRoughnessMap(skin->roughnessmap, true); glPushMatrix(); glMultMatrixf(e->transform.matrix); if (VectorNotEmpty(e->scale)) glScalef(e->scale[0], e->scale[1], e->scale[2]); mesh = R_DrawAliasModelBuffer(e); if (r_state.specularmap_enabled) R_EnableSpecularMap(NULL, false); if (r_state.roughnessmap_enabled) R_EnableRoughnessMap(NULL, false); R_EnableModelLights(NULL, 0, false, false); R_EnableGlowMap(NULL); if (r_state.active_normalmap) R_EnableBumpmap(NULL); R_DrawMeshShadow(e, mesh); if (mod->num_frames == 1) R_ResetArraysAfterStaticMeshRender(); glPopMatrix(); /* show model bounding box */ if (r_showbox->integer) R_DrawBoundingBox(mod->frames[e->as.frame].mins, mod->frames[e->as.frame].maxs); R_Color(NULL); }
/** * @brief Draws a model in 2d mode (for rendering model data from the ui) * @param[in,out] mi All the needed model information to render the model * @param[in,out] pmi The model information of the parent model. This is used * in those cases, where the model that should get rendered here is placed relativly * to an already existing model in the world. * @param[in] tagname If a parent model is given, a @c tagname is given in most cases, too. It's used * to transform the model location relative to the parent model location again. E.g. a * @c tagname of tag_rweapon will transform the location to the right hand of an actor. * @sa R_DrawAliasModel */ void R_DrawModelDirect (modelInfo_t * mi, modelInfo_t * pmi, const char *tagname) { image_t *skin; mAliasMesh_t *mesh; if (Q_strnull(mi->name)) return; /* register the model */ mi->model = R_FindModel(mi->name); /* check if the model exists */ if (!mi->model) { Com_Printf("No model found for '%s'\n", mi->name); return; } skin = R_AliasModelState(mi->model, &mi->mesh, &mi->frame, &mi->oldframe, &mi->skin); if (skin == NULL) { Com_Printf("Model '%s' is broken\n", mi->name); return; } glPushMatrix(); glScalef(viddef.rx, viddef.ry, (viddef.rx + viddef.ry) / 2); R_Color(mi->color); if (pmi) { /* register the parent model */ pmi->model = R_FindModel(pmi->name); /* transform - the next transform for the child model will be relative from the * parent model location now */ R_TransformModelDirect(pmi); /* tag transformation */ if (tagname) { const mAliasTagOrientation_t *current = NULL; const mAliasTagOrientation_t *old = NULL; R_GetTags(pmi->model, tagname, pmi->frame, pmi->oldframe, ¤t, &old); if (current != NULL && old != NULL) { float interpolated[16]; /* do interpolation */ R_InterpolateTransform(pmi->backlerp, pmi->model->alias.num_frames, current, old, interpolated); /* transform */ glMultMatrixf(interpolated); R_CheckError(); } } } /* transform */ R_TransformModelDirect(mi); /* we have to reenable this here - we are in 2d mode here already */ glEnable(GL_DEPTH_TEST); /* draw it */ R_BindTexture(skin->texnum); /* draw the model */ mesh = &mi->model->alias.meshes[0]; refdef.aliasCount += mesh->num_tris; if (mi->model->alias.num_frames == 1) R_DrawAliasStaticWithReset(mesh, vec4_origin); else R_DrawAliasFrameLerp(&mi->model->alias, mesh, mi->backlerp, mi->frame, mi->oldframe, vec4_origin); /* show model bounding box */ if (r_showbox->integer) R_DrawBoundingBox(mi->model->alias.frames[mi->frame].mins, mi->model->alias.frames[mi->frame].maxs); glDisable(GL_DEPTH_TEST); glPopMatrix(); R_Color(NULL); }