void Gui_FillBackgroundBuffer() { GLfloat x0 = 0.0f; GLfloat y0 = 0.0f; GLfloat x1 = screen_info.w; GLfloat y1 = screen_info.h; GLfloat *v, backgroundArray[32]; GLfloat color[4] = {0.0f, 0.0f, 0.0f, 0.5f}; v = backgroundArray; *v++ = x0; *v++ = y0; vec4_copy(v, color); v += 4; *v++ = 0.0f; *v++ = 0.0f; *v++ = x1; *v++ = y0; vec4_copy(v, color); v += 4; *v++ = 1.0f; *v++ = 0.0f; *v++ = x1; *v++ = y1; vec4_copy(v, color); v += 4; *v++ = 1.0f; *v++ = 1.0f; *v++ = x0; *v++ = y1; vec4_copy(v, color); v += 4; *v++ = 0.0f; *v++ = 1.0f; qglBindBufferARB(GL_ARRAY_BUFFER, backgroundBuffer); qglBufferDataARB(GL_ARRAY_BUFFER, sizeof(GLfloat[32]), backgroundArray, GL_STATIC_DRAW); }
void Gui_FillCrosshairBuffer() { GLfloat x = (GLfloat)screen_info.w / 2.0f; GLfloat y = (GLfloat)screen_info.h / 2.0f; GLfloat *v, crosshairArray[32]; const GLfloat size = 8.0f; const GLfloat color[4] = {1.0f, 0.0f, 0.0f, 1.0f}; v = crosshairArray; *v++ = x; *v++ = y - size; vec4_copy(v, color); v += 4; *v++ = 0.0; *v++ = 0.0; *v++ = x; *v++ = y + size; vec4_copy(v, color); v += 4; *v++ = 0.0; *v++ = 0.0; *v++ = x - size; *v++ = y; vec4_copy(v, color); v += 4; *v++ = 0.0; *v++ = 0.0; *v++ = x + size; *v++ = y; vec4_copy(v, color); v += 4; *v++ = 0.0; *v++ = 0.0; // copy vertices into GL buffer qglBindBufferARB(GL_ARRAY_BUFFER, crosshairBuffer); qglBufferDataARB(GL_ARRAY_BUFFER, sizeof(GLfloat[32]), crosshairArray, GL_STATIC_DRAW); }
void SSBoneFrame_TargetBoneToSlerp(struct ss_bone_frame_s *bf, struct ss_animation_s *ss_anim) { extern float engine_frame_time; if(ss_anim->anim_ext_flags & ANIM_EXT_TARGET_TO) { ss_bone_tag_p b_tag = bf->bone_tags + ss_anim->targeting_bone; float clamped_q[4], q[4], target_dir[3], target_local[3], bone_dir[3]; Mat4_vec3_mul_inv(target_local, bf->transform, ss_anim->target); if(b_tag->parent) { Mat4_vec3_mul_inv(target_local, b_tag->parent->full_transform, target_local); } vec3_sub(target_dir, target_local, b_tag->transform + 12); if(ss_anim->targeting_flags & ANIM_TARGET_OWERRIDE_ANIM) { Mat4_vec3_rot_macro(bone_dir, b_tag->transform, ss_anim->bone_direction); } else { vec3_copy(bone_dir, ss_anim->bone_direction); } vec4_GetQuaternionRotation(q, bone_dir, target_dir); if(ss_anim->targeting_flags & ANIM_TARGET_USE_AXIS_MOD) { q[0] *= ss_anim->targeting_axis_mod[0]; q[1] *= ss_anim->targeting_axis_mod[1]; q[2] *= ss_anim->targeting_axis_mod[2]; q[3] = 1.0f - vec3_sqabs(q); q[3] = sqrtf(q[3]); } if(q[3] < ss_anim->targeting_limit[3]) { vec4_clampw(q, ss_anim->targeting_limit[3]); } vec4_slerp_to(clamped_q, ss_anim->current_mod, q, engine_frame_time * M_PI / 1.3f); vec4_copy(ss_anim->current_mod, clamped_q); SSBoneFrame_RotateBone(bf, ss_anim->current_mod, ss_anim->targeting_bone); } else if(ss_anim->current_mod[3] < 1.0f) { if(ss_anim->current_mod[3] < 0.99f) { float zero_ang[4] = {0.0f, 0.0f, 0.0f, 1.0f}; float clamped_q[4]; vec4_slerp_to(clamped_q, ss_anim->current_mod, zero_ang, engine_frame_time * M_PI / 1.3f); vec4_copy(ss_anim->current_mod, clamped_q); SSBoneFrame_RotateBone(bf, ss_anim->current_mod, ss_anim->targeting_bone); } else { vec4_set_zero_angle(ss_anim->current_mod); } } }
void SSBoneFrame_TargetBoneToSlerp(struct ss_bone_frame_s *bf, struct ss_bone_tag_s *b_tag, float time) { b_tag->mod.current_slerp = 1.0f; if(b_tag->is_targeted) { float clamped_q[4], q[4], target_dir[3], target_local[3], bone_dir[3]; Mat4_vec3_mul_inv(target_local, bf->transform->M4x4, b_tag->mod.target_pos); if(b_tag->parent) { Mat4_vec3_mul_inv(target_local, b_tag->parent->current_transform, target_local); } vec3_sub(target_dir, target_local, b_tag->local_transform + 12); vec3_copy(bone_dir, b_tag->mod.bone_local_direction); vec4_GetQuaternionRotation(q, bone_dir, target_dir); if(q[3] < b_tag->mod.limit[3]) { vec4_clampw(q, b_tag->mod.limit[3]); } if(b_tag->is_axis_modded) { q[0] *= b_tag->mod.axis_mod[0]; q[1] *= b_tag->mod.axis_mod[1]; q[2] *= b_tag->mod.axis_mod[2]; q[3] = 1.0f - vec3_sqabs(q); q[3] = sqrtf(q[3]); } b_tag->mod.current_slerp = vec4_slerp_to(clamped_q, b_tag->mod.current_q, q, time * M_PI / 1.3f); vec4_copy(b_tag->mod.current_q, clamped_q); SSBoneFrame_RotateBone(bf, b_tag->mod.current_q, b_tag->index); } else if(b_tag->mod.current_q[3] < 1.0f) { if(b_tag->mod.current_q[3] < 0.99f) { float zero_ang[4] = {0.0f, 0.0f, 0.0f, 1.0f}; float clamped_q[4]; vec4_slerp_to(clamped_q, b_tag->mod.current_q, zero_ang, time * M_PI / 1.3f); vec4_copy(b_tag->mod.current_q, clamped_q); SSBoneFrame_RotateBone(bf, b_tag->mod.current_q, b_tag->index); } else { vec4_set_zero_angle(b_tag->mod.current_q); } } }
void SSBoneFrame_SetTargetingLimit(struct ss_animation_s *ss_anim, const float limit[4]) { if(limit) { vec4_copy(ss_anim->targeting_limit, limit); } else { ss_anim->targeting_limit[3] = -1.0f; } }
int gesture_update(int nb, gesture_t *gestures[], const inputs_t *inputs, const float viewport[4], void *user) { int i, j, mask = 0; bool allup = true; // Set if all the mouse buttons are up. gesture_t *gest, *triggered = NULL; for (i = 0; allup && i < ARRAY_SIZE(inputs->touches); i++) { for (j = 0; allup && j < ARRAY_SIZE(inputs->touches[i].down); j++) { if (inputs->touches[i].down[j]) { allup = false; break; } } } for (i = 0; i < nb; i++) { gest = gestures[i]; if (gest->state == GESTURE_POSSIBLE) mask |= gest->type; } for (i = 0; i < nb; i++) { gest = gestures[i]; vec4_copy(viewport, gest->viewport); if ((gest->state == GESTURE_FAILED) && allup) { gest->state = GESTURE_POSSIBLE; } if (gest->state == GESTURE_END || gest->state == GESTURE_TRIGGERED) gest->state = GESTURE_POSSIBLE; update(gest, inputs, mask); if ( gest->state == GESTURE_BEGIN || gest->state == GESTURE_UPDATE || gest->state == GESTURE_END || gest->state == GESTURE_TRIGGERED) { gest->callback(gest, user); triggered = gest; break; } } // If one gesture started, fail all the other gestures. if (triggered && triggered->state == GESTURE_BEGIN) { for (i = 0; i < nb; i++) { gest = gestures[i]; if (gest != triggered) gest->state = GESTURE_FAILED; } } return triggered ? 1 : 0; }
void SSBoneFrame_SetTargetingLimit(struct ss_bone_tag_s *b_tag, const float limit[4]) { if(limit) { vec4_copy(b_tag->mod.limit, limit); } else { b_tag->mod.limit[0] = 0.0f; b_tag->mod.limit[1] = 0.0f; b_tag->mod.limit[2] = 0.0f; b_tag->mod.limit[3] = -1.0f; } }
void SSBoneFrame_RotateBone(struct ss_bone_frame_s *bf, const float q_rotate[4], int bone) { float tr[16], q[4]; ss_bone_tag_p b_tag = b_tag = bf->bone_tags + bone; vec4_copy(q, q_rotate); Mat4_E(tr); Mat4_RotateQuaternion(tr, q); vec4_copy(q, b_tag->transform + 12); Mat4_Mat4_mul(b_tag->transform, tr, b_tag->transform); vec4_copy(b_tag->transform + 12, q); for(uint16_t i = bone; i < bf->bone_tag_count; i++) { ss_bone_tag_p btag = bf->bone_tags + i; if(btag->parent) { Mat4_Mat4_mul(btag->full_transform, btag->parent->full_transform, btag->transform); } else { Mat4_Copy(btag->full_transform, btag->transform); } } }
void vec4_transform(struct vec4 *dst, const struct vec4 *v, const struct matrix4 *m) { struct vec4 temp; struct matrix4 transpose; matrix4_transpose(&transpose, m); temp.x = vec4_dot(&transpose.x, v); temp.y = vec4_dot(&transpose.y, v); temp.z = vec4_dot(&transpose.z, v); temp.w = vec4_dot(&transpose.t, v); vec4_copy(dst, &temp); }
void BoneFrame_Copy(bone_frame_p dst, bone_frame_p src) { if(dst->bone_tag_count < src->bone_tag_count) { dst->bone_tags = (bone_tag_p)realloc(dst->bone_tags, src->bone_tag_count * sizeof(bone_tag_t)); } dst->bone_tag_count = src->bone_tag_count; vec3_copy(dst->pos, src->pos); vec3_copy(dst->centre, src->centre); vec3_copy(dst->bb_max, src->bb_max); vec3_copy(dst->bb_min, src->bb_min); for(uint16_t i = 0; i < dst->bone_tag_count; i++) { vec4_copy(dst->bone_tags[i].qrotate, src->bone_tags[i].qrotate); vec3_copy(dst->bone_tags[i].offset, src->bone_tags[i].offset); } }
/* * We made independent copy of src; */ void Polygon_Copy(polygon_p dst, polygon_p src) { if(dst->vertex_count != src->vertex_count) { Polygon_Resize(dst, src->vertex_count); } dst->anim_id = src->anim_id; dst->frame_offset = src->frame_offset; dst->double_side = src->double_side; dst->texture_index = src->texture_index; dst->transparency = src->transparency; vec4_copy(dst->plane, src->plane); for(uint16_t i = 0; i < src->vertex_count; i++) { dst->vertices[i] = src->vertices[i]; } }
void SkeletalModel_InterpolateFrames(skeletal_model_p model) { uint16_t new_frames_count; animation_frame_p anim = model->animations; bone_frame_p bf, new_bone_frames; float lerp, t; for(uint16_t i = 0; i < model->animation_count; i++, anim++) { if(anim->frames_count > 1 && anim->original_frame_rate > 1) // we can't interpolate one frame or rate < 2! { new_frames_count = (uint16_t)anim->original_frame_rate * (anim->frames_count - 1) + 1; bf = new_bone_frames = (bone_frame_p)malloc(new_frames_count * sizeof(bone_frame_t)); /* * the first frame does not changes */ bf->bone_tags = (bone_tag_p)malloc(model->mesh_count * sizeof(bone_tag_t)); bf->bone_tag_count = model->mesh_count; vec3_set_zero(bf->pos); vec3_set_zero(bf->move); bf->command = 0x00; vec3_copy(bf->centre, anim->frames[0].centre); vec3_copy(bf->pos, anim->frames[0].pos); vec3_copy(bf->bb_max, anim->frames[0].bb_max); vec3_copy(bf->bb_min, anim->frames[0].bb_min); for(uint16_t k = 0; k < model->mesh_count; k++) { vec3_copy(bf->bone_tags[k].offset, anim->frames[0].bone_tags[k].offset); vec4_copy(bf->bone_tags[k].qrotate, anim->frames[0].bone_tags[k].qrotate); } bf++; for(uint16_t j = 1; j < anim->frames_count; j++) { for(uint16_t lerp_index = 1; lerp_index <= anim->original_frame_rate; lerp_index++) { vec3_set_zero(bf->pos); vec3_set_zero(bf->move); bf->command = 0x00; lerp = ((float)lerp_index) / (float)anim->original_frame_rate; t = 1.0 - lerp; bf->bone_tags = (bone_tag_p)malloc(model->mesh_count * sizeof(bone_tag_t)); bf->bone_tag_count = model->mesh_count; bf->centre[0] = t * anim->frames[j-1].centre[0] + lerp * anim->frames[j].centre[0]; bf->centre[1] = t * anim->frames[j-1].centre[1] + lerp * anim->frames[j].centre[1]; bf->centre[2] = t * anim->frames[j-1].centre[2] + lerp * anim->frames[j].centre[2]; bf->pos[0] = t * anim->frames[j-1].pos[0] + lerp * anim->frames[j].pos[0]; bf->pos[1] = t * anim->frames[j-1].pos[1] + lerp * anim->frames[j].pos[1]; bf->pos[2] = t * anim->frames[j-1].pos[2] + lerp * anim->frames[j].pos[2]; bf->bb_max[0] = t * anim->frames[j-1].bb_max[0] + lerp * anim->frames[j].bb_max[0]; bf->bb_max[1] = t * anim->frames[j-1].bb_max[1] + lerp * anim->frames[j].bb_max[1]; bf->bb_max[2] = t * anim->frames[j-1].bb_max[2] + lerp * anim->frames[j].bb_max[2]; bf->bb_min[0] = t * anim->frames[j-1].bb_min[0] + lerp * anim->frames[j].bb_min[0]; bf->bb_min[1] = t * anim->frames[j-1].bb_min[1] + lerp * anim->frames[j].bb_min[1]; bf->bb_min[2] = t * anim->frames[j-1].bb_min[2] + lerp * anim->frames[j].bb_min[2]; for(uint16_t k = 0; k < model->mesh_count; k++) { bf->bone_tags[k].offset[0] = t * anim->frames[j-1].bone_tags[k].offset[0] + lerp * anim->frames[j].bone_tags[k].offset[0]; bf->bone_tags[k].offset[1] = t * anim->frames[j-1].bone_tags[k].offset[1] + lerp * anim->frames[j].bone_tags[k].offset[1]; bf->bone_tags[k].offset[2] = t * anim->frames[j-1].bone_tags[k].offset[2] + lerp * anim->frames[j].bone_tags[k].offset[2]; vec4_slerp(bf->bone_tags[k].qrotate, anim->frames[j-1].bone_tags[k].qrotate, anim->frames[j].bone_tags[k].qrotate, lerp); } bf++; } } /* * swap old and new animation bone brames * free old bone frames; */ for(uint16_t j = 0; j < anim->frames_count; j++) { if(anim->frames[j].bone_tag_count) { anim->frames[j].bone_tag_count = 0; free(anim->frames[j].bone_tags); anim->frames[j].bone_tags = NULL; } } free(anim->frames); anim->frames = new_bone_frames; anim->frames_count = new_frames_count; } } }
/** * Draws simple colored rectangle with given parameters. */ void Gui_DrawRect(const GLfloat &x, const GLfloat &y, const GLfloat &width, const GLfloat &height, const float colorUpperLeft[], const float colorUpperRight[], const float colorLowerLeft[], const float colorLowerRight[], const int &blendMode, const GLuint texture) { switch(blendMode) { case BM_HIDE: return; case BM_MULTIPLY: qglBlendFunc(GL_SRC_ALPHA, GL_ONE); break; case BM_SIMPLE_SHADE: qglBlendFunc(GL_ONE_MINUS_SRC_COLOR, GL_ONE_MINUS_SRC_ALPHA); break; case BM_SCREEN: qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); break; default: case BM_OPAQUE: qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); break; }; GLfloat x0 = x; GLfloat y0 = y + height; GLfloat x1 = x + width; GLfloat y1 = y; GLfloat *v, rectArray[32]; v = rectArray; *v++ = x0; *v++ = y0; *v++ = 0.0f; *v++ = 0.0f; vec4_copy(v, colorUpperLeft); v += 4; *v++ = x1; *v++ = y0; *v++ = 1.0f; *v++ = 0.0f; vec4_copy(v, colorUpperRight); v += 4; *v++ = x1; *v++ = y1; *v++ = 1.0f; *v++ = 1.0f; vec4_copy(v, colorLowerRight); v += 4; *v++ = x0; *v++ = y1; *v++ = 0.0f; *v++ = 1.0f; vec4_copy(v, colorLowerLeft); if(qglIsTexture(texture)) { qglBindTexture(GL_TEXTURE_2D, texture); } else { BindWhiteTexture(); } qglBindBufferARB(GL_ARRAY_BUFFER, rectBuffer); qglBufferDataARB(GL_ARRAY_BUFFER, sizeof(GLfloat[32]), rectArray, GL_DYNAMIC_DRAW); qglVertexPointer(2, GL_FLOAT, 8 * sizeof(GLfloat), (void *)0); qglTexCoordPointer(2, GL_FLOAT, 8 * sizeof(GLfloat), (void *)sizeof(GLfloat[2])); qglColorPointer(4, GL_FLOAT, 8 * sizeof(GLfloat), (void *)sizeof(GLfloat[4])); qglDrawArrays(GL_TRIANGLE_FAN, 0, 4); }
/* * animated textures coordinates splits too! */ void Polygon_Split(polygon_p src, float n[4], polygon_p front, polygon_p back) { float t, tmp, dir[3]; vertex_t *curr_v, *prev_v, tv; float dist[2]; vec4_copy(front->plane, src->plane); front->anim_id = src->anim_id; front->frame_offset = src->frame_offset; front->double_side = src->double_side; front->texture_index = src->texture_index; front->transparency = src->transparency; vec4_copy(back->plane, src->plane); back->anim_id = src->anim_id; back->frame_offset = src->frame_offset; back->double_side = src->double_side; back->texture_index = src->texture_index; back->transparency = src->transparency; curr_v = src->vertices; prev_v = src->vertices + src->vertex_count - 1; dist[0] = vec3_plane_dist(n, prev_v->position); for(uint16_t i = 0; i < src->vertex_count; i++) { dist[1] = vec3_plane_dist(n, curr_v->position); if(dist[1] > SPLIT_EPSILON) { if(dist[0] < -SPLIT_EPSILON) { vec3_sub(dir, curr_v->position, prev_v->position); vec3_ray_plane_intersect(prev_v->position, dir, n, tv.position, t); tv.normal[0] = prev_v->normal[0] + t * (curr_v->normal[0] - prev_v->normal[0]); tv.normal[1] = prev_v->normal[1] + t * (curr_v->normal[1] - prev_v->normal[1]); tv.normal[2] = prev_v->normal[2] + t * (curr_v->normal[2] - prev_v->normal[2]); vec3_norm(tv.normal, tmp); tv.color[0] = prev_v->color[0] + t * (curr_v->color[0] - prev_v->color[0]); tv.color[1] = prev_v->color[1] + t * (curr_v->color[1] - prev_v->color[1]); tv.color[2] = prev_v->color[2] + t * (curr_v->color[2] - prev_v->color[2]); tv.color[3] = prev_v->color[3] + t * (curr_v->color[3] - prev_v->color[3]); tv.tex_coord[0] = prev_v->tex_coord[0] + t * (curr_v->tex_coord[0] - prev_v->tex_coord[0]); tv.tex_coord[1] = prev_v->tex_coord[1] + t * (curr_v->tex_coord[1] - prev_v->tex_coord[1]); front->vertices[front->vertex_count++] = tv; back->vertices[back->vertex_count++] = tv; } front->vertices[front->vertex_count++] = *curr_v; } else if(dist[1] < -SPLIT_EPSILON) { if(dist[0] > SPLIT_EPSILON) { vec3_sub(dir, curr_v->position, prev_v->position); vec3_ray_plane_intersect(prev_v->position, dir, n, tv.position, t); tv.normal[0] = prev_v->normal[0] + t * (curr_v->normal[0] - prev_v->normal[0]); tv.normal[1] = prev_v->normal[1] + t * (curr_v->normal[1] - prev_v->normal[1]); tv.normal[2] = prev_v->normal[2] + t * (curr_v->normal[2] - prev_v->normal[2]); vec3_norm(tv.normal, tmp); tv.color[0] = prev_v->color[0] + t * (curr_v->color[0] - prev_v->color[0]); tv.color[1] = prev_v->color[1] + t * (curr_v->color[1] - prev_v->color[1]); tv.color[2] = prev_v->color[2] + t * (curr_v->color[2] - prev_v->color[2]); tv.color[3] = prev_v->color[3] + t * (curr_v->color[3] - prev_v->color[3]); tv.tex_coord[0] = prev_v->tex_coord[0] + t * (curr_v->tex_coord[0] - prev_v->tex_coord[0]); tv.tex_coord[1] = prev_v->tex_coord[1] + t * (curr_v->tex_coord[1] - prev_v->tex_coord[1]); front->vertices[front->vertex_count++] = tv; back->vertices[back->vertex_count++] = tv; } back->vertices[back->vertex_count++] = *curr_v; } else { front->vertices[front->vertex_count++] = *curr_v; back->vertices[back->vertex_count++] = *curr_v; } prev_v = curr_v; curr_v ++; dist[0] = dist[1]; } }
void CDynamicBSP::AddPolygon(struct bsp_node_s *root, struct polygon_s *p) { if(m_realloc_state) { return; } if(m_tree_allocated + 1024 > m_tree_buffer_size) { m_realloc_state = NEED_REALLOC_TREE_BUFF; return; } if(m_temp_allocated + 1024 > m_temp_buffer_size) { m_realloc_state = NEED_REALLOC_TEMP_BUFF; return; } if(root->polygons_front == NULL) { // we though root->front == NULL and root->back == NULL vec4_copy(root->plane, p->plane); p->next = NULL; this->AddBSPPolygon(root, p); return; } uint16_t positive = 0; uint16_t negative = 0; uint16_t in_plane = 0; float dist; vertex_p v = p->vertices; for(uint16_t i = 0; i < p->vertex_count; i++, v++) { dist = vec3_plane_dist(root->plane, v->position); if (dist > SPLIT_EPSILON) { positive++; } else if (dist < -SPLIT_EPSILON) { negative++; } else { in_plane++; } } if ((positive > 0) && (negative == 0)) // SPLIT_FRONT { if (root->front == NULL) { root->front = this->CreateBSPNode(); } this->AddPolygon(root->front, p); } else if ((positive == 0) && (negative > 0)) // SPLIT_BACK { if (root->back == NULL) { root->back = this->CreateBSPNode(); } this->AddPolygon(root->back, p); } else if ((positive == 0) && (negative == 0)) // SPLIT_IN_PLANE { this->AddBSPPolygon(root, p); } else // SPLIT_IN_BOTH { polygon_p front, back; front = this->CreatePolygon(p->vertex_count + 2); front->vertex_count = 0; back = this->CreatePolygon(p->vertex_count + 2); back->vertex_count = 0; Polygon_Split(p, root->plane, front, back); if(root->front == NULL) { root->front = this->CreateBSPNode(); } this->AddPolygon(root->front, front); if(root->back == NULL) { root->back = this->CreateBSPNode(); } this->AddPolygon(root->back, back); } }
void CDynamicBSP::AddNewPolygonList(struct polygon_s *p, float transform[16], struct frustum_s *f) { for( ; p && (!m_realloc_state); p = p->next) { m_temp_allocated = 0; polygon_p np = this->CreatePolygon(p->vertex_count); bool visible = (f == NULL); vertex_p src_v, dst_v; np->anim_id = p->anim_id; np->frame_offset = p->frame_offset; np->double_side = p->double_side; np->transparency = p->transparency; Mat4_vec3_rot_macro(np->plane, transform, p->plane); for(uint16_t i = 0; i < p->vertex_count; i++) { src_v = p->vertices + i; dst_v = np->vertices + i; Mat4_vec3_mul_macro(dst_v->position, transform, src_v->position); } np->plane[3] = -vec3_dot(np->plane, np->vertices[0].position); for(frustum_p ff = f; (!visible) && ff; ff = ff->next) { if(Frustum_IsPolyVisible(np, ff, false)) { visible = true; break; } } if(visible) { if(p->anim_id > 0) { anim_seq_p seq = m_anim_seq + p->anim_id - 1; uint16_t frame = (seq->current_frame + p->frame_offset) % seq->frames_count; tex_frame_p tf = seq->frames + frame; np->texture_index = tf->texture_index; for(uint16_t i = 0; i < p->vertex_count; i++) { src_v = p->vertices + i; dst_v = np->vertices + i; Mat4_vec3_rot_macro(dst_v->normal, transform, src_v->normal); vec4_copy(dst_v->color, src_v->color); ApplyAnimTextureTransformation(dst_v->tex_coord, src_v->tex_coord, tf); } } else { np->texture_index = p->texture_index; for(uint16_t i = 0; i < p->vertex_count; i++) { src_v = p->vertices + i; dst_v = np->vertices + i; Mat4_vec3_rot_macro(dst_v->normal, transform, src_v->normal); vec4_copy(dst_v->color, src_v->color); dst_v->tex_coord[0] = src_v->tex_coord[0]; dst_v->tex_coord[1] = src_v->tex_coord[1]; } } m_input_polygons++; this->AddPolygon(m_root, np); } } }
void glf_render_str(gl_tex_font_p glf, GLfloat x, GLfloat y, const char *text, int32_t n_sym) { if(glf && glf->ft_face && text && (text[0] != 0)) { uint8_t *nch, *ch = (uint8_t*)text; FT_Vector kern; int32_t x_pt = 0; int32_t y_pt = 0; if(glf->gl_real_tex_indexes_count == 1) { GLuint elements_count = 0; uint32_t curr_utf32, next_utf32; GLfloat *p, *buffer; buffer = (GLfloat*)malloc(48 * utf8_strlen(text) * sizeof(GLfloat)); nch = utf8_to_utf32(ch, &curr_utf32); curr_utf32 = FT_Get_Char_Index(glf->ft_face, curr_utf32); qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); for(p = buffer; *ch && n_sym--;) { char_info_p g; uint8_t *nch2 = utf8_to_utf32(nch, &next_utf32); next_utf32 = FT_Get_Char_Index(glf->ft_face, next_utf32); ch = nch; nch = nch2; g = glf->glyphs + curr_utf32; FT_Get_Kerning(glf->ft_face, curr_utf32, next_utf32, FT_KERNING_UNSCALED, &kern); // kern in 1/64 pixel curr_utf32 = next_utf32; if(g->tex_index != 0) { GLfloat x0 = x + g->left + x_pt / 64.0f; GLfloat x1 = x0 + g->width; GLfloat y0 = y + g->top + y_pt / 64.0f; GLfloat y1 = y0 - g->height; *p = x0; p++; *p = y0; p++; *p = g->tex_x0; p++; *p = g->tex_y0; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x1; p++; *p = y0; p++; *p = g->tex_x1; p++; *p = g->tex_y0; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x1; p++; *p = y1; p++; *p = g->tex_x1; p++; *p = g->tex_y1; p++; vec4_copy(p, glf->gl_font_color); p += 4; elements_count++; *p = x0; p++; *p = y0; p++; *p = g->tex_x0; p++; *p = g->tex_y0; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x1; p++; *p = y1; p++; *p = g->tex_x1; p++; *p = g->tex_y1; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x0; p++; *p = y1; p++; *p = g->tex_x0; p++; *p = g->tex_y1; p++; vec4_copy(p, glf->gl_font_color); p += 4; elements_count++; } x_pt += kern.x + g->advance_x_pt; y_pt += kern.y + g->advance_y_pt; } ///RENDER if(elements_count != 0) { qglBindTexture(GL_TEXTURE_2D, glf->gl_tex_indexes[0]); qglVertexPointer(2, GL_FLOAT, 8 * sizeof(GLfloat), buffer+0); qglTexCoordPointer(2, GL_FLOAT, 8 * sizeof(GLfloat), buffer+2); qglColorPointer(4, GL_FLOAT, 8 * sizeof(GLfloat), buffer+4); qglDrawArrays(GL_TRIANGLES, 0, elements_count * 3); } qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); free(buffer); } else { GLfloat *p, buffer[32]; GLuint active_texture = 0; uint32_t curr_utf32, next_utf32; nch = utf8_to_utf32(ch, &curr_utf32); curr_utf32 = FT_Get_Char_Index(glf->ft_face, curr_utf32); qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); for(; *ch && n_sym--;) { char_info_p g; uint8_t *nch2 = utf8_to_utf32(nch, &next_utf32); next_utf32 = FT_Get_Char_Index(glf->ft_face, next_utf32); ch = nch; nch = nch2; g = glf->glyphs + curr_utf32; FT_Get_Kerning(glf->ft_face, curr_utf32, next_utf32, FT_KERNING_UNSCALED, &kern); // kern in 1/64 pixel curr_utf32 = next_utf32; if(g->tex_index != 0) { ///RENDER GLfloat x0 = x + g->left + x_pt / 64.0f; GLfloat x1 = x0 + g->width; GLfloat y0 = y + g->top + y_pt / 64.0f; GLfloat y1 = y0 - g->height; p = buffer; *p = x0; p++; *p = y0; p++; *p = g->tex_x0; p++; *p = g->tex_y0; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x1; p++; *p = y0; p++; *p = g->tex_x1; p++; *p = g->tex_y0; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x1; p++; *p = y1; p++; *p = g->tex_x1; p++; *p = g->tex_y1; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x0; p++; *p = y1; p++; *p = g->tex_x0; p++; *p = g->tex_y1; p++; vec4_copy(p, glf->gl_font_color); if(active_texture != g->tex_index) { qglBindTexture(GL_TEXTURE_2D, g->tex_index); active_texture = g->tex_index; } qglVertexPointer(2, GL_FLOAT, 8 * sizeof(GLfloat), buffer+0); qglTexCoordPointer(2, GL_FLOAT, 8 * sizeof(GLfloat), buffer+2); qglColorPointer(4, GL_FLOAT, 8 * sizeof(GLfloat), buffer+4); qglDrawArrays(GL_TRIANGLE_FAN, 0, 4); } x_pt += kern.x + g->advance_x_pt; y_pt += kern.y + g->advance_y_pt; } } } }
void glf_render_str(gl_tex_font_p glf, GLfloat x, GLfloat y, const char *text) { uint8_t *nch; uint8_t *ch = (uint8_t*)text; FT_Vector kern; if((glf == nullptr) || (glf->ft_face == nullptr) || (text == nullptr) || (text[0] == '\0')) { return; } FontBuffer_Bind(); if(glf->gl_real_tex_indexes_count == 1) { GLfloat *p = FontBuffer_ResizeAndMap(48 * utf8_strlen(text) * sizeof(GLfloat)); GLuint elements_count = 0; uint32_t curr_utf32, next_utf32; nch = utf8_to_utf32(ch, &curr_utf32); curr_utf32 = FT_Get_Char_Index(glf->ft_face, curr_utf32); while(*ch) { char_info_p g; uint8_t *nch2 = utf8_to_utf32(nch, &next_utf32); next_utf32 = FT_Get_Char_Index(glf->ft_face, next_utf32); ch = nch; nch = nch2; g = glf->glyphs + curr_utf32; FT_Get_Kerning(glf->ft_face, curr_utf32, next_utf32, FT_KERNING_UNSCALED, &kern); // kern in 1/64 pixel curr_utf32 = next_utf32; if(g->tex_index != 0) { GLfloat x0 = x + g->left; GLfloat x1 = x0 + g->width; GLfloat y0 = y + g->top; GLfloat y1 = y0 - g->height; *p = x0; p++; *p = y0; p++; *p = g->tex_x0; p++; *p = g->tex_y0; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x1; p++; *p = y0; p++; *p = g->tex_x1; p++; *p = g->tex_y0; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x1; p++; *p = y1; p++; *p = g->tex_x1; p++; *p = g->tex_y1; p++; vec4_copy(p, glf->gl_font_color); p += 4; elements_count++; *p = x0; p++; *p = y0; p++; *p = g->tex_x0; p++; *p = g->tex_y0; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x1; p++; *p = y1; p++; *p = g->tex_x1; p++; *p = g->tex_y1; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x0; p++; *p = y1; p++; *p = g->tex_x0; p++; *p = g->tex_y1; p++; vec4_copy(p, glf->gl_font_color); p += 4; elements_count++; } x += static_cast<GLfloat>(kern.x + g->advance_x) / 64.0; y += static_cast<GLfloat>(kern.y + g->advance_y) / 64.0; } FontBuffer_Unmap(); ///RENDER if(elements_count != 0) { glBindTexture(GL_TEXTURE_2D, glf->gl_tex_indexes[0]); glDrawArrays(GL_TRIANGLES, 0, elements_count * 3); } } else { GLuint active_texture = 0; uint32_t curr_utf32, next_utf32; nch = utf8_to_utf32(ch, &curr_utf32); curr_utf32 = FT_Get_Char_Index(glf->ft_face, curr_utf32); for(; *ch;) { GLfloat *p = FontBuffer_ResizeAndMap(sizeof(GLfloat[32])); char_info_p g; uint8_t *nch2 = utf8_to_utf32(nch, &next_utf32); next_utf32 = FT_Get_Char_Index(glf->ft_face, next_utf32); ch = nch; nch = nch2; g = glf->glyphs + curr_utf32; FT_Get_Kerning(glf->ft_face, curr_utf32, next_utf32, FT_KERNING_UNSCALED, &kern); // kern in 1/64 pixel curr_utf32 = next_utf32; if(g->tex_index != 0) { if(active_texture != g->tex_index) { glBindTexture(GL_TEXTURE_2D, g->tex_index); active_texture = g->tex_index; } ///RENDER GLfloat x0 = x + g->left; GLfloat x1 = x0 + g->width; GLfloat y0 = y + g->top; GLfloat y1 = y0 - g->height; *p = x0; p++; *p = y0; p++; *p = g->tex_x0; p++; *p = g->tex_y0; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x1; p++; *p = y0; p++; *p = g->tex_x1; p++; *p = g->tex_y0; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x1; p++; *p = y1; p++; *p = g->tex_x1; p++; *p = g->tex_y1; p++; vec4_copy(p, glf->gl_font_color); p += 4; *p = x0; p++; *p = y1; p++; *p = g->tex_x0; p++; *p = g->tex_y1; p++; vec4_copy(p, glf->gl_font_color); FontBuffer_Unmap(); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } x += static_cast<GLfloat>(kern.x + g->advance_x) / 64.0; y += static_cast<GLfloat>(kern.y + g->advance_y) / 64.0; } } }