static void spherical_lerp(float *v1, float *v2, float d, float *vout) { float v1xv2[3]; float v3[3]; float v1_norm = vec3_norm(v1); float v2_norm = vec3_norm(v2); vec3_normalize(v1); vec3_normalize(v2); vec3_cross(v1, v2, v1xv2); double theta; float dot = vec3_dot(v1, v2); if (dot > 1) dot = 1; theta = acosf(dot); if (theta < 0.05) { lerp(v1, v2, d, vout); return; } double phi = d * theta; vec3_normalize(v1xv2); vec3_cross(v1xv2, v1, v3); int i = 0; float cos_phi = cos(phi); float sin_phi = sin(phi); for (i = 0; i < 3; i++) { vout[i] = (cos_phi * v1[i] + sin_phi * v3[i]) * (v1_norm * (1-d) + v2_norm * d); } }
Camera::Camera(vec3 u, vec3 loc, vec3 la, float a, int width, int height): angle(a){ up = u; location = loc; lookat = la; camz = vec3_norm(vec3_sub(lookat, location)); camx = vec3_norm(vec3_mul_cross(up, camz)); camy = vec3_mul_cross(camx, vec3_sub((vec3) {0., 0., 0.}, camz)); camy = vec3_norm(camy); tax = tan(angle); tay = tan(((float) height / (float) width) * angle); }
static int player_in_fov(vec3_t viewangle, vec3_t ppos, vec3_t opos) { float yaw, pitch, cos_angle; vec3_t dir, los; VectorSubtract(opos, ppos, los); // Check if the two players are roughly on the same X/Y plane // and skip the test if not. We only want to eliminate info that // would reveal the position of opponents behind the player on // the same X/Y plane (e.g. on the same floor in a room). if (vec3_length(los) < 5 * fabs(opos[2] - ppos[2])) { return 1; } // calculate unit vector of the direction the player looks at yaw = viewangle[YAW] * (M_PI * 2 / 360); pitch = viewangle[PITCH] * (M_PI * 2 / 360); dir[0] = cos(yaw) * cos(pitch); dir[1] = sin(yaw); dir[2] = cos(yaw) * sin(pitch); // calculate unit vector corresponding to line of sight to opponent vec3_norm(los); // calculate and test the angle between the two vectors cos_angle = DotProduct(dir, los); if (cos_angle > 0) // +/- 90 degrees (fov = 180) { return 1; } return 0; }
static t_rgb compute_gradient(double *grad, t_obj *obj) { t_vec3 color; double diffx; double diffy; double scale; scale = obj->mat.texture.normal_strength; diffx = grad[1] - grad[2]; diffy = grad[0] - grad[3]; color.x = vec3_norm(vec3(1, diffx * scale, 0)).y; color.y = vec3_norm(vec3(1, diffy * scale, 0)).y; color.z = sqrt(1 - ft_clampf(color.x * color.x + color.y * color.y, 0, 1)); vec3_normalize(&color); return (vec3_to_rgb(vec3_add(vec3_fmul(color, 0.5), vec3(0.5, 0.5, 0.5)))); }
void set_light(t_vec3 hit, t_obj *obj, t_lgt *light) { double theta; double epsilon; light->ray.pos = hit; if (light->type == DIRECTIONAL) { light->ray.dir = vec3_fmul(light->dir, -1); obj->dist_attenuation = 1.0; } else { light->ray.dir = vec3_sub(light->pos, hit); obj->t = vec3_magnitude(light->ray.dir); obj->dist_attenuation = (1.0 + obj->t * obj->t * light->attenuation); } if (light->type == SPOT) { theta = vec3_dot(light->dir, vec3_norm(vec3_fmul(light->ray.dir, -1))); epsilon = light->cutoff - light->cutoff_outer; light->cutoff_intensity = ft_clampf((theta - light->cutoff_outer) / epsilon, 0, 1); } vec3_normalize(&light->ray.dir); }
static inline void _setup_camera(game *g) { if (g->d.ortho) { mat4x4_ortho(g->d.proj, -g->aspect, g->aspect, -1, 1, 0.001, 1000); } else { mat4x4_perspective(g->d.proj, 45.0, g->aspect, 0.001, 1000.0); } vec3_sub(g->d.view_f, g->d.center, g->d.eye); vec3_norm(g->d.view_f, g->d.view_f); vec3_mul_cross(g->d.view_r, g->d.view_f, g->d.up); vec3_norm(g->d.view_r, g->d.view_r); vec3_mul_cross(g->d.view_u, g->d.view_r, g->d.view_f); _calc_zoom(g, 0); // Update zoom for this view type }
void vec3_normalize(float *v) { int i; float norm = vec3_norm(v); if (norm > 0) { for (i = 0; i < 3; i++) { v[i] *= 1.0/norm; } } }
void plane_transform(struct plane *dst, const struct plane *p, const struct matrix3 *m) { struct vec3 temp; vec3_transform(&dst->dir, &p->dir, m); vec3_norm(&dst->dir, &dst->dir); vec3_transform(&temp, &m->t, m); dst->dist = p->dist - vec3_dot(&dst->dir, &temp); }
void GetRotationbyVector(mat33_t *R, const vec3_t *v1, const vec3_t *v2) { vec3_t diff; vec3_sub_vec2(&diff, v1, v2); if( vec3_norm(&diff) < 1e-3 ){ mat33_assign(R,1,0,0,0,1,0,0,0,1); }else { if( fabs((vec3_norm(&diff)-2)) < 1e-3 ){ mat33_assign(R,1,0,0 ,0,-1,0, 0,0,-1); }else { real_t winkel = _acos(vec3_dot(v1,v2)); quat_t QU; vec3_t vc; vec3_cross(&vc,v2,v1); Quaternion_byAngleAndVector(&QU,winkel,&vc); mat33_from_quat(R,&QU); } } }
t_vec3 set_specular(t_obj *obj, t_cam *cam, t_lgt *light) { t_vec3 halfdir; float theta; float res; halfdir = vec3_norm(vec3_sub(light->ray.dir, cam->ray.dir)); theta = ft_clampf(vec3_dot(obj->mat.texture.normal, halfdir), 0, 1); res = pow(theta, obj->mat.shininess); res = res * obj->mat.specular * light->intensity / obj->dist_attenuation; light->type == SPOT ? res *= light->cutoff_intensity : 0; return (vec3_fmul(light->color, res)); }
void plane_from_tri(struct plane *dst, const struct vec3 *v1, const struct vec3 *v2, const struct vec3 *v3) { struct vec3 temp; vec3_sub(&temp, v2, v1); vec3_sub(&dst->dir, v3, v1); vec3_cross(&dst->dir, &temp, &dst->dir); vec3_norm(&dst->dir, &dst->dir); dst->dist = vec3_dot(v1, &dst->dir); }
void Camera_update(Camera* const camera, Input* const input) { Camera_offset_orientation( camera, toRadians((-input->mouse_dx * input->mouse_sensitivity)), toRadians((-input->mouse_dy * input->mouse_sensitivity)) ); // TODO: Delta time vec3 dir = {0.0f, 0.0f, 0.0f}; float vel = 0.2f; vec3 forward, backward, left, right; Camera_relative_directions(camera, forward, backward, left, right); if (input->forward_key) { vec3 f = {forward[0], 0.0f, forward[2]}; vec3_norm(f, f); vec3_add(dir, dir, f); } if (input->back_key) { vec3 b = {backward[0], 0.0f, backward[2]}; vec3_norm(b, b); vec3_add(dir, dir, b); } if (input->left_key) { vec3_add(dir, dir, left); } if (input->right_key) { vec3_add(dir, dir, right); } if (vec3_len(dir) > 0.0f) { vec3_norm(dir, dir); } vec3 movement; vec3_scale(movement, dir, vel); vec3_add(camera->transform.position, camera->transform.position, movement); }
/** * @brief CM_PlaneFromPoints * @details The normal will point out of the clock for clockwise ordered points * @param[in,out] plane * @param[in] a * @param[in] b * @param[in] c * @return false if the triangle is degenrate. */ static qboolean CM_PlaneFromPoints(vec4_t plane, vec3_t a, vec3_t b, vec3_t c) { vec3_t d1, d2; VectorSubtract(b, a, d1); VectorSubtract(c, a, d2); vec3_cross(d2, d1, plane); if (vec3_norm(plane) == 0.f) { return qfalse; } plane[3] = DotProduct(a, plane); return qtrue; }
vec3 *vec3_get_surface_normal(const vec3 *v1, const vec3 *v2, const vec3 *v3) { vec3 u, v; u.x = v2->x - v1->x; u.y = v2->y - v1->y; u.z = v2->z - v1->z; v.x = v3->x - v1->x; v.y = v3->y - v1->y; v.z = v3->z - v1->z; vec3 *normal = vec3_create(0, 0, 0); normal->x = u.x * v.x - u.z * v.z; normal->y = u.z * v.x - u.x * v.z; normal->z = u.x * v.y - u.y * v.x; vec3_norm(normal); return normal; }
void cubeUpdate(CubeRenderPacket* cube, vec3 rot, float angle, float x, float y, float z, float* view, float* proj) { static mat4x4 temp; memcpy(cube->transforms.view, view, 16 * sizeof(float)); memcpy(cube->transforms.proj, proj, 16 * sizeof(float)); vec3_norm(rot, rot); mat4x4_identity(cube->transforms.world); mat4x4_translate_in_place(cube->transforms.world, x, y, z); mat4x4_rotate(cube->transforms.world, cube->transforms.world, rot[0], rot[1], rot[2], angle); mat4x4_mul(temp, cube->transforms.view, cube->transforms.world); mat4x4_mul(cube->transforms.proj_view_world, cube->transforms.proj, temp); gfxBindUniformBuffer(cube->ubo, &cube->transforms, sizeof(struct Transforms), 0); }
void Camera_offset_orientation(Camera* const camera, float yaw, float pitch) { quat pitch_rotation, yaw_rotation; quat_rotate(yaw_rotation, yaw, G_UP); vec3 right; quat_mul_vec3(right, camera->transform.orientation, G_RIGHT); vec3_norm(right, right); quat_rotate(pitch_rotation, pitch, right); quat orientation; quat_mul(orientation, yaw_rotation, pitch_rotation); quat_mul( camera->transform.orientation, orientation, camera->transform.orientation ); quat_norm(camera->transform.orientation, camera->transform.orientation); }
void point_calc_normal(Point *point, distance_func sdf) { float eps = 0.1e-4; vec4 pos = {point->pos[0], point->pos[1], point->pos[2], 1.0}; vec4 epsX = {eps, 0.f, 0.f, 0.0f}; vec4 epsY = {0.f, eps, 0.f, 0.0f}; vec4 epsZ = {0.f, 0.f, eps, 0.0f}; vec4 ppx, psx, ppy, psy, ppz, psz; vec4_add(ppx, pos, epsX); vec4_add(ppy, pos, epsY); vec4_add(ppz, pos, epsZ); vec4_sub(psx, pos, epsX); vec4_sub(psy, pos, epsY); vec4_sub(psz, pos, epsZ); point->norm[0] = sdf(ppx) - sdf(psx); point->norm[1] = sdf(ppy) - sdf(psy); point->norm[2] = sdf(ppz) - sdf(psz); vec3_norm(point->norm, point->norm); }
int SSBoneFrame_CheckTargetBoneLimit(struct ss_bone_frame_s *bf, struct ss_bone_tag_s *b_tag, float target[3]) { float target_dir[3], target_local[3], limit_dir[3], t; Mat4_vec3_mul_inv(target_local, bf->transform->M4x4, target); 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_norm(target_dir, t); vec3_copy(limit_dir, b_tag->mod.limit); if((b_tag->mod.limit[3] == -1.0f) || (vec3_dot(limit_dir, target_dir) > b_tag->mod.limit[3])) { return 1; } return 0; }
int SSBoneFrame_CheckTargetBoneLimit(struct ss_bone_frame_s *bf, struct ss_animation_s *ss_anim) { ss_bone_tag_p b_tag = b_tag = bf->bone_tags + ss_anim->targeting_bone; float target_dir[3], target_local[3], limit_dir[3], t; 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); vec3_norm(target_dir, t); vec3_copy(limit_dir, ss_anim->targeting_limit); if((ss_anim->targeting_limit[3] == -1.0f) || (vec3_dot(limit_dir, target_dir) > ss_anim->targeting_limit[3])) { return 1; } return 0; }
t_vec3 bump_normal(t_obj *obj, t_ray *ray) { t_vec3 normal; t_vec3 tangent; t_vec3 binormal; t_vec3 bump; t_vec3 c[2]; normal = obj->normal; bump = texture_mapping(obj, obj->mat.texture.bump, ray->hit); bump = vec3_sub(vec3_fmul(bump, 2), vec3(1, 1, 1)); c[0] = vec3_cross(normal, vec3(0, 0, 1)); c[1] = vec3_cross(normal, vec3(0, 1, 0)); tangent = (vec3_magnitude(c[0]) > vec3_magnitude(c[1]) ? c[0] : c[1]); tangent = vec3_sub(tangent, vec3_fmul(normal, vec3_dot(tangent, normal))); vec3_normalize(&tangent); binormal = vec3_norm(vec3_cross(normal, tangent)); normal.x = vec3_dot(bump, vec3(tangent.x, binormal.x, normal.x)); normal.y = vec3_dot(bump, vec3(tangent.y, binormal.y, normal.y)); normal.z = vec3_dot(bump, vec3(tangent.z, binormal.z, normal.z)); vec3_normalize(&normal); return (normal); }
static int predict_slide_move(sharedEntity_t *ent, float frametime, trajectory_t *tr, vec3_t result) { int count, numplanes = 0, i, j, k; float d, time_left = frametime, into; vec3_t planes[MAX_CLIP_PLANES], velocity, origin, clipVelocity, endVelocity, endClipVelocity, dir, end; trace_t trace; VectorCopy(tr->trBase, origin); origin[2] += Z_ADJUST; // move it off the floor VectorCopy(tr->trDelta, velocity); VectorCopy(tr->trDelta, endVelocity); for (count = 0; count < NUMBUMPS; count++) { // calculate position we are trying to move to VectorMA(origin, time_left, velocity, end); // see if we can make it there SV_Trace(&trace, origin, ent->r.mins, ent->r.maxs, end, ent->s.number, CONTENTS_SOLID, qfalse); if (trace.allsolid) { // entity is completely trapped in another solid VectorCopy(origin, result); return 0; } if (trace.fraction > 0.99) // moved the entire distance { VectorCopy(trace.endpos, result); return 1; } if (trace.fraction > 0) // covered some distance { VectorCopy(trace.endpos, origin); } time_left -= time_left * trace.fraction; if (numplanes >= MAX_CLIP_PLANES) { // this shouldn't really happen VectorCopy(origin, result); return 0; } // if this is the same plane we hit before, nudge velocity // out along it, which fixes some epsilon issues with // non-axial planes for (i = 0; i < numplanes; i++) { if (DotProduct(trace.plane.normal, planes[i]) > 0.99) { VectorAdd(trace.plane.normal, velocity, velocity); break; } } if (i < numplanes) { continue; } VectorCopy(trace.plane.normal, planes[numplanes]); numplanes++; // modify velocity so it parallels all of the clip planes // find a plane that it enters for (i = 0; i < numplanes; i++) { into = DotProduct(velocity, planes[i]); if (into >= 0.1) // move doesn't interact with the plane { continue; } // slide along the plane predict_clip_velocity(velocity, planes[i], clipVelocity); // slide along the plane predict_clip_velocity(endVelocity, planes[i], endClipVelocity); // see if there is a second plane that the new move enters for (j = 0; j < numplanes; j++) { if (j == i) { continue; } if (DotProduct(clipVelocity, planes[j]) >= 0.1) // move doesn't interact with the plane { continue; } // try clipping the move to the plane predict_clip_velocity(clipVelocity, planes[j], clipVelocity); predict_clip_velocity(endClipVelocity, planes[j], endClipVelocity); // see if it goes back into the first clip plane if (DotProduct(clipVelocity, planes[i]) >= 0) { continue; } // slide the original velocity along the crease vec3_cross(planes[i], planes[j], dir); vec3_norm(dir); d = DotProduct(dir, velocity); VectorScale(dir, d, clipVelocity); vec3_cross(planes[i], planes[j], dir); vec3_norm(dir); d = DotProduct(dir, endVelocity); VectorScale(dir, d, endClipVelocity); // see if there is a third plane the new move enters for (k = 0; k < numplanes; k++) { if (k == i || k == j) { continue; } if (DotProduct(clipVelocity, planes[k]) >= 0.1) // move doesn't interact with the plane { continue; } // stop dead at a tripple plane interaction VectorCopy(origin, result); return 1; } } // if we have fixed all interactions, try another move VectorCopy(clipVelocity, velocity); VectorCopy(endClipVelocity, endVelocity); break; } } VectorCopy(origin, result); if (count == 0) { return 1; } return 0; }
void gfx_csm_prepare(const struct gfx_view_params* params, const struct vec3f* light_dir, const struct aabb* world_bounds) { static const float tolerance = 10.0f; struct vec3f dir; vec3_setv(&dir, light_dir); float texoffset_x = 0.5f + (0.5f/g_csm->shadowmap_size); float texoffset_y = 0.5f + (0.5f/g_csm->shadowmap_size); struct mat3f view_inv; struct mat4f tex_mat; struct mat4f tmp_mat; float splits[CSM_CASCADE_CNT+1]; mat3_setf(&view_inv, params->view.m11, params->view.m21, params->view.m31, params->view.m12, params->view.m22, params->view.m32, params->view.m13, params->view.m23, params->view.m33, params->cam_pos.x, params->cam_pos.y, params->cam_pos.z); mat4_setf(&tex_mat, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, texoffset_x, texoffset_y, 0.0f, 1.0f); float csm_far = minf(CSM_FAR_MAX, params->cam->ffar); csm_split_range(params->cam->fnear, csm_far, splits); /* calculate cascades */ struct frustum f; /* frustum points for cascades */ struct plane vp_planes[6]; for (uint i = 0; i < CSM_CASCADE_CNT; i++) { cam_calc_frustumcorners(params->cam, (struct vec3f*)f.points, &splits[i], &splits[i+1]); csm_calc_minsphere(&g_csm->cascades[i].bounds, &f, ¶ms->view, &view_inv); memcpy(&g_csm->cascade_frusts[i], &f, sizeof(f)); /* cascade matrixes: first we find two extreme points of the world, related to cascade */ struct vec3f scenter; struct ray r; struct plane upper_plane; struct plane lower_plane; struct vec3f upper_pt; struct vec3f lower_pt; struct vec3f xaxis; struct vec3f yaxis; struct vec3f viewpos; struct vec3f tmp; struct vec3f lowerpt_vs; float sr = g_csm->cascades[i].bounds.r; vec3_setf(&scenter, g_csm->cascades[i].bounds.x, g_csm->cascades[i].bounds.y, g_csm->cascades[i].bounds.z); ray_setv(&r, &scenter, &dir); plane_setv(&upper_plane, &g_vec3_unity_neg, fabs(world_bounds->maxpt.y)); plane_setv(&lower_plane, &g_vec3_unity, fabs(world_bounds->minpt.y)); vec3_sub(&upper_pt, &r.pt, vec3_muls(&tmp, &dir, fabs(ray_intersect_plane(&r, &upper_plane)) + tolerance)); vec3_add(&lower_pt, &r.pt, vec3_muls(&tmp, &dir, fabs(ray_intersect_plane(&r, &lower_plane)) + tolerance)); /* view matrix of light view for the cascade : * dir = light_dir * up = (1, 0, 0) * pos = sphere center */ vec3_norm(&xaxis, vec3_cross(&tmp, &g_vec3_unitx, &dir)); vec3_cross(&yaxis, &dir, &xaxis); vec3_sub(&viewpos, &upper_pt, vec3_muls(&tmp, &dir, tolerance)); mat3_setf(&g_csm->cascades[i].view, xaxis.x, yaxis.x, dir.x, xaxis.y, yaxis.y, dir.y, xaxis.z, yaxis.z, dir.z, -vec3_dot(&xaxis, &viewpos), -vec3_dot(&yaxis, &viewpos), -vec3_dot(&dir, &viewpos)); /* orthographic projection matrix for cascade */ vec3_transformsrt(&lowerpt_vs, &lower_pt, &g_csm->cascades[i].view); float nnear = tolerance*0.5f; float nfar = lowerpt_vs.z + sr; csm_calc_orthoproj(&g_csm->cascades[i].proj, sr*2.0f + 1.0f/g_csm->shadowmap_size, sr*2.0f + 1.0f/g_csm->shadowmap_size, nnear, nfar); g_csm->cascades[i].nnear = nnear; g_csm->cascades[i].nfar = nfar; /* calculate final matrix */ mat3_mul4(&g_csm->cascade_vps[i], &g_csm->cascades[i].view, &g_csm->cascades[i].proj); cam_calc_frustumplanes(vp_planes, &g_csm->cascade_vps[i]); csm_calc_cascadeplanes(&g_csm->cascade_planes[i*4], vp_planes, &g_csm->cascade_vps[i]); csm_round_mat(&g_csm->cascade_vps[i], &g_csm->cascade_vps[i], g_csm->shadowmap_size); mat4_mul(&g_csm->shadow_mats[i], mat3_mul4(&tmp_mat, &view_inv, &g_csm->cascade_vps[i]), &tex_mat); } /* caculate shadow area bounds (aabb) */ struct aabb cascade_near; struct aabb cascade_far; aabb_setzero(&g_csm->frustum_bounds); aabb_from_sphere(&cascade_near, &g_csm->cascades[0].bounds); aabb_from_sphere(&cascade_far, &g_csm->cascades[CSM_CASCADE_CNT-1].bounds); aabb_merge(&g_csm->frustum_bounds, &cascade_near, &cascade_far); vec3_setv(&g_csm->light_dir, &dir); }
/** * @brief CM_AddFacetBevels * @param[in,out] facet */ void CM_AddFacetBevels(facet_t *facet) { int i, j, k, l; int axis, dir, flipped; float plane[4], d, minBack, newplane[4]; winding_t *w, *w2; vec3_t mins, maxs, vec, vec2; #ifndef ADDBEVELS return; #endif Vector4Copy(planes[facet->surfacePlane].plane, plane); w = BaseWindingForPlane(plane, plane[3]); for (j = 0 ; j < facet->numBorders && w ; j++) { if (facet->borderPlanes[j] == facet->surfacePlane) { continue; } Vector4Copy(planes[facet->borderPlanes[j]].plane, plane); if (!facet->borderInward[j]) { VectorSubtract(vec3_origin, plane, plane); plane[3] = -plane[3]; } ChopWindingInPlace(&w, plane, plane[3], 0.1f); } if (!w) { return; } WindingBounds(w, mins, maxs); // add the axial planes for (axis = 0; axis < 3; axis++) { for (dir = -1; dir <= 1; dir += 2) { VectorClear(plane); plane[axis] = dir; if (dir == 1) { plane[3] = maxs[axis]; } else { plane[3] = -mins[axis]; } // if it's the surface plane if (CM_PlaneEqual(&planes[facet->surfacePlane], plane, &flipped)) { continue; } // see if the plane is already present for (i = 0; i < facet->numBorders; i++) { if (CM_PlaneEqual(&planes[facet->borderPlanes[i]], plane, &flipped)) { break; } } if (i == facet->numBorders) { if (facet->numBorders >= 4 + 6 + 16) { Com_Printf("CM_AddFacetBevels: ERROR - too many bevels\n"); continue; } facet->borderPlanes[facet->numBorders] = CM_FindPlane2(plane, &flipped); facet->borderNoAdjust[facet->numBorders] = 0; facet->borderInward[facet->numBorders] = flipped; facet->numBorders++; } } } // add the edge bevels // test the non-axial plane edges for (j = 0; j < w->numpoints; j++) { k = (j + 1) % w->numpoints; VectorSubtract(w->p[j], w->p[k], vec); // if it's a degenerate edge if (vec3_norm(vec) < 0.5f) { continue; } CM_SnapVector(vec); for (k = 0; k < 3; k++) { if (vec[k] == -1.0f || vec[k] == 1.0f || (vec[k] == 0.0f && vec[(k + 1) % 3] == 0.0f)) { break; // axial } } if (k < 3) { continue; // only test non-axial edges } // try the six possible slanted axials from this edge for (axis = 0 ; axis < 3 ; axis++) { for (dir = -1 ; dir <= 1 ; dir += 2) { // construct a plane VectorClear(vec2); vec2[axis] = dir; vec3_cross(vec, vec2, plane); if (vec3_norm(plane) < 0.5f) { continue; } plane[3] = DotProduct(w->p[j], plane); // if all the points of the facet winding are // behind this plane, it is a proper edge bevel minBack = 0.0f; for (l = 0; l < w->numpoints; l++) { d = DotProduct(w->p[l], plane) - plane[3]; if (d > 0.1f) { break; // point in front } if (d < minBack) { minBack = d; } } // if some point was at the front if (l < w->numpoints) { continue; } // if no points at the back then the winding is on the bevel plane if (minBack > -0.1f) { break; } // if it's the surface plane if (CM_PlaneEqual(&planes[facet->surfacePlane], plane, &flipped)) { continue; } // see if the plane is already present for (i = 0; i < facet->numBorders; i++) { if (CM_PlaneEqual(&planes[facet->borderPlanes[i]], plane, &flipped)) { break; } } if (i == facet->numBorders) { if (facet->numBorders >= 4 + 6 + 16) { Com_Printf("CM_AddFacetBevels: ERROR - too many bevels\n"); continue; } facet->borderPlanes[facet->numBorders] = CM_FindPlane2(plane, &flipped); for (k = 0; k < facet->numBorders; k++) { if (facet->borderPlanes[facet->numBorders] == facet->borderPlanes[k]) { Com_Printf("CM_AddFacetBevels: WARNING - bevel plane already used\n"); } } facet->borderNoAdjust[facet->numBorders] = 0; facet->borderInward[facet->numBorders] = flipped; // w2 = CopyWinding(w); Vector4Copy(planes[facet->borderPlanes[facet->numBorders]].plane, newplane); if (!facet->borderInward[facet->numBorders]) { VectorNegate(newplane, newplane); newplane[3] = -newplane[3]; } ChopWindingInPlace(&w2, newplane, newplane[3], 0.1f); if (!w2) { // any map load spams with this error .. don't print it anymore //Com_DPrintf("WARNING: CM_AddFacetBevels... invalid bevel\n"); continue; } else { FreeWinding(w2); } facet->numBorders++; // already got a bevel //break; } } } } FreeWinding(w); // add opposite plane if (facet->numBorders >= 4 + 6 + 16) { Com_Printf("CM_AddFacetBevels: ERROR - too many bevels at end\n"); return; } facet->borderPlanes[facet->numBorders] = facet->surfacePlane; facet->borderNoAdjust[facet->numBorders] = 0; facet->borderInward[facet->numBorders] = qtrue; facet->numBorders++; }
void render_screen_area(void *args) { ray3 ray; float t = 0; screen_area *c = (screen_area *)args; int width = c->width; int height = c->height; int stride = c->stride; vec3 planeXPosition; vec3 dcol, drow, ro, rd, normal, o; dcol = c->dcol; drow = c->drow; ro = c->ro; uint8_t *data = c->data; ray_packet3 packet; packet.origin[0] = vec3f(ro[0]); packet.origin[1] = vec3f(ro[1]); packet.origin[2] = vec3f(ro[2]); vec3 planeYPosition = dcol * vec3f(c->y) + c->pos; vec3 invdir[4], dir[4]; vec3 m; float r = VOXEL_BRICK_HALF_SIZE * 0.99f; int result; int x, y; aabb_packet bounds; bounds[0] = _mm_sub_ps(c->brick->bounds_packet[0], vec3f(ro[0])); bounds[1] = _mm_sub_ps(c->brick->bounds_packet[1], vec3f(ro[1])); bounds[2] = _mm_sub_ps(c->brick->bounds_packet[2], vec3f(ro[2])); bounds[3] = _mm_sub_ps(c->brick->bounds_packet[3], vec3f(ro[0])); bounds[4] = _mm_sub_ps(c->brick->bounds_packet[4], vec3f(ro[1])); bounds[5] = _mm_sub_ps(c->brick->bounds_packet[5], vec3f(ro[2])); for (y=c->y; y<height; ++y) { planeXPosition = planeYPosition; for (x=0; x<width; x+=4) { for (int i=0; i<4; i++) { planeXPosition += drow; rd = planeXPosition - ro; dir[i] = rd; invdir[i] = vec3_reciprocal(rd); packet.invdir[0][i] = invdir[i][0]; packet.invdir[1][i] = invdir[i][1]; packet.invdir[2][i] = invdir[i][2]; } result = ray_isect_packet(packet, bounds, &m); for (int j=0; j<4; j++) { unsigned long where = y * width * stride + (x + j) * stride; int cr = floor(((x+j)/(float)width) * 255); int cg = floor((y/(float)c->screen_height) * 255); int cb = 0; if (result & (1<<j)) { vec3 isect = ro + dir[j] * vec3f(m[j]); o = isect - c->brick->center; for (int k=0; k<3; k++) { if (fabsf(o[k]) >= r) { normal[k] = o[k] > 0.0f ? 1.0f : -1.0f; } else { normal[k] = 0.0f; } } float sum = fabsf(normal[0]) + fabsf(normal[1]) + fabsf(normal[2]); int voxel_pos[3] = { 0, 0, 0 }; int found = voxel_brick_traverse( c->brick, isect, vec3_norm(dir[j]), 1.0f, voxel_pos ); if (found) { cr = (int)((voxel_pos[0] / (float)VOXEL_BRICK_WIDTH) * 255.0f); cg = (int)((voxel_pos[1] / (float)VOXEL_BRICK_WIDTH) * 255.0f); cb = (int)((voxel_pos[2] / (float)VOXEL_BRICK_WIDTH) * 255.0f); } else { cr = fmaxf(0, cr - 20); cg = fmaxf(0, cg - 20); cb = fmaxf(0, cb - 20); } if (sum >= 2) { cr = fmaxf(0, cr - 20); cg = fmaxf(0, cg - 20); cb = fmaxf(0, cb - 20); } } data[where+0] = cr; data[where+1] = cg; data[where+2] = cb; } } planeYPosition += dcol; } }
int main(int argc, char** argv) { Settings settings; ConstructSettings(&settings); LoadSettingsFile(&settings, "settings.ini"); if(Init(&settings) < 0) return -1; GLuint program; if(SetupProgram(&program) < 0) return -2; GLuint grid_vbuf = CreateGridVertexBuffer(settings.graphics.viewdistance); int grid_icount; GLuint grid_ibuf = CreateGridIndexBuffer(&grid_icount, settings.graphics.viewdistance); glUseProgram(program); GLint grid_pos_loc = glGetAttribLocation(program, "grid_pos"); GLint grid_world_mat_loc = glGetUniformLocation(program, "world_mat"); GLint grid_view_mat_loc = glGetUniformLocation(program, "view_mat"); GLint grid_proj_mat_loc = glGetUniformLocation(program, "proj_mat"); GLint grid_color_loc = glGetUniformLocation(program, "color"); GLint grid_viewdistance_loc = glGetUniformLocation(program, "viewdistance"); glUniform3f(grid_color_loc, 0.f, 0.6f, 0.f); glUniform1f(grid_viewdistance_loc, settings.graphics.viewdistance); GLuint grid_vao; glGenVertexArrays(1, &grid_vao); glBindVertexArray(grid_vao); glBindBuffer(GL_ARRAY_BUFFER, grid_vbuf); glEnableVertexAttribArray(grid_pos_loc); glVertexAttribPointer(grid_pos_loc, 2, GL_FLOAT, GL_FALSE, 0, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, grid_ibuf); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glClearColor(0.5f, 0.5f, 0.5f, 1.f); glViewport(0, 0, settings.video.width, settings.video.height); Node grid_node; ConstructNode(&grid_node); Camera camera; ConstructCamera(&camera); mat4x4 projection_matrix; mat4x4_perspective(projection_matrix, settings.video.pfov, settings.video.width/(float)settings.video.height, settings.video.pnear, settings.video.pfar); glUniformMatrix4fv(grid_proj_mat_loc, 1, GL_FALSE, (const float*)projection_matrix); float speed = 10.f; Uint32 ticks = SDL_GetTicks(); State state = STATE_RUNNING | (settings.video.fullscreen ? STATE_FULLSCREEN : 0); while(state & STATE_RUNNING) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUseProgram(program); glUniformMatrix4fv(grid_world_mat_loc, 1, GL_FALSE, (const float*)grid_node.world_matrix); glUniformMatrix4fv(grid_view_mat_loc, 1, GL_FALSE, (const float*)camera.view_matrix); glBindVertexArray(grid_vao); glDrawElements(GL_TRIANGLE_STRIP, grid_icount, GL_UNSIGNED_INT, NULL); SDL_GL_SwapWindow(window); SDL_Event event; while(SDL_PollEvent(&event)) { switch(event.type) { case SDL_QUIT: state &= ~STATE_RUNNING; break; case SDL_KEYUP: switch(event.key.keysym.scancode) { case SDL_SCANCODE_F11: state ^= STATE_FULLSCREEN; SDL_SetWindowFullscreen ( window, state & STATE_FULLSCREEN ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0 ); break; case SDL_SCANCODE_ESCAPE: state ^= STATE_MOUSE_GRABBED; SDL_SetRelativeMouseMode(state & STATE_MOUSE_GRABBED); break; case SDL_SCANCODE_LSHIFT: speed = settings.controls.speed1; break; default: break; } break; case SDL_KEYDOWN: switch(event.key.keysym.scancode) { case SDL_SCANCODE_LSHIFT: speed = settings.controls.speed2; break; default: break; } break; case SDL_WINDOWEVENT: if(event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) { int w = event.window.data1; int h = event.window.data2; glViewport(0, 0, w, h); mat4x4_perspective(projection_matrix, settings.video.pfov, w/(float)h, settings.video.pnear, settings.video.pfar); glUniformMatrix4fv(grid_proj_mat_loc, 1, GL_FALSE, (const float*)projection_matrix); } break; case SDL_MOUSEMOTION: if(state & STATE_MOUSE_GRABBED) { camera.yaw -= settings.controls.xsensitivity * event.motion.xrel; camera.pitch -= settings.controls.xsensitivity * event.motion.yrel; } break; default: break; } } Uint32 nticks = SDL_GetTicks(); float delta = (nticks - ticks)/1000.f; ticks = nticks; const Uint8* keys = SDL_GetKeyboardState(NULL); vec3 movement; int i; for(i = 0; i < 3; i++) movement[i] = 0.f; SDL_bool moved = SDL_FALSE; if(keys[SDL_SCANCODE_W] && !keys[SDL_SCANCODE_S]) { vec3_add(movement, movement, camera.direction); moved = SDL_TRUE; } else if(keys[SDL_SCANCODE_S] && !keys[SDL_SCANCODE_W]) { vec3_sub(movement, movement, camera.direction); moved = SDL_TRUE; } if(keys[SDL_SCANCODE_A] && !keys[SDL_SCANCODE_D]) { vec3_sub(movement, movement, camera.right); moved = SDL_TRUE; } else if(keys[SDL_SCANCODE_D] && !keys[SDL_SCANCODE_A]) { vec3_add(movement, movement, camera.right); moved = SDL_TRUE; } if(keys[SDL_SCANCODE_Q] && !keys[SDL_SCANCODE_E]) { vec3_sub(movement, movement, camera.up); moved = SDL_TRUE; } else if(keys[SDL_SCANCODE_E] && !keys[SDL_SCANCODE_Q]) { vec3_add(movement, movement, camera.up); moved = SDL_TRUE; } if(moved) { vec3_norm(movement, movement); vec3_scale(movement, movement, delta * speed); vec3_add(camera.node.translation, camera.node.translation, movement); } UpdateCamera(&camera); if(moved) { vec2 tmp1; tmp1[0] = camera.node.position[0]; tmp1[1] = camera.node.position[2]; vec2 tmp2; tmp2[0] = grid_node.position[0]; tmp2[1] = grid_node.position[2]; vec2_sub(tmp1, tmp1, tmp2); tmp1[0] = floor(tmp1[0]); tmp1[1] = floor(tmp1[1]); grid_node.translation[0] += tmp1[0]; grid_node.translation[2] += tmp1[1]; UpdateNode(&grid_node); } } glDeleteVertexArrays(1, &grid_vao); glDeleteBuffers(1, &grid_vbuf); glDeleteBuffers(1, &grid_ibuf); glDeleteProgram(program); return 0; }
void Vector::normalize() { vec3_norm(&v_, &v_); }
void vec3_normalize(Vec3* v) { float norm = vec3_norm(v); v->x /= norm; v->y /= norm; v->z /= norm; }
/* * 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]; } }