float rayIntersectDisk(ShadeRec* sr, Disk* disk, const Ray ray) { vec3 displacement; vec3_sub(displacement, disk->center, ray.origin); float t = vec3_dot(displacement, disk->normal) / vec3_dot(ray.direction, disk->normal); if(t > K_EPSILON) { vec3 hit_point; getPointOnRay(hit_point, ray, t); vec3_sub(displacement, hit_point, disk->center); if(vec3_length(displacement) <= disk->radius) { vec3_negate(sr->wo, ray.direction); if(vec3_dot(sr->wo, disk->normal) < 0) { vec3_negate(sr->wo, disk->normal); }else { vec3_copy(sr->normal, disk->normal); } vec3_copy(sr->hit_point, hit_point); sr->mat = *(disk->mat); return t; } } return TMAX; }
/* See "Real Time Collision Detection", by Christer Ericson, p. 224 */ int moving_spheres_intersection(union vec3 *s1, float r1, union vec3 *v1, union vec3 *s2, float r2, union vec3 *v2, float time_horizon, float *time) { union vec3 s, v; float r, c, t; vec3_sub(&s, s2, s1); /* vector between sphere centers */ vec3_sub(&v, v2, v1); /* relative velocity of s2 wrt stationary s1 */ r = r1 + r2; c = vec3_dot(&s, &s) - r * r; if (c < 0.0f) { *time = 0.0f; /* already touching */ return 1; } float a = vec3_dot(&v, &v); if (a < ZERO_TOLERANCE) return 0; /* spheres not moving relative to each other */ float b = vec3_dot(&v, &s); if (b >= 0.0f) return 0; /* spheres not moving towards each other */ float d = b * b - a * c; if (d < 0.0f) return 0; /* No real-valued root, spheres do not intersect */ t = (-b - sqrtf(d)) / a; if (time_horizon < 0 || t < time_horizon) { *time = t; return 1; } return 0; }
void camera_control_joyorbit(camera* c, float timestep) { if (joystick_count() == 0) return; SDL_Joystick* mainstick = joystick_get(0); int x_move = SDL_JoystickGetAxis(mainstick, 0); int y_move = SDL_JoystickGetAxis(mainstick, 1); /* Dead Zone */ if (abs(x_move) < 10000) { x_move = 0; }; if (abs(y_move) < 10000) { y_move = 0; }; float a1 = (x_move / 32768.0) * -0.05; float a2 = (y_move / 32768.0) * 0.05; vec3 translation = c->target; c->position = vec3_sub(c->position, translation); c->target = vec3_sub(c->target, translation); c->position = mat3_mul_vec3(mat3_rotation_y( a1 ), c->position ); vec3 axis = vec3_normalize(vec3_cross( vec3_sub(c->position, c->target) , vec3_new(0,1,0) )); c->position = mat3_mul_vec3(mat3_rotation_axis_angle(axis, a2 ), c->position ); c->position = vec3_add(c->position, translation); c->target = vec3_add(c->target, translation); }
/* calculate sphere that goes through 4 points */ struct sphere* sphere_circum(struct sphere* rs, const struct vec4f* v0, const struct vec4f* v1, const struct vec4f* v2, const struct vec4f* v3) { struct vec4f a; vec3_sub(&a, v1, v0); struct vec4f b; vec3_sub(&b, v2, v0); struct vec4f c; vec3_sub(&c, v3, v0); struct vec4f o; struct vec4f tmp; struct mat3f m; mat3_setf(&m, a.x, a.y, a.z, b.x, b.y, b.z, c.x, c.y, c.z, 0.0f, 0.0f, 0.0f); float denom = 2.0f * mat3_det(&m); vec3_muls(&o, vec3_cross(&tmp, &a, &b), vec3_dot(&c, &c)); vec3_add(&o, &o, vec3_muls(&tmp, vec3_cross(&tmp, &c, &a), vec3_dot(&b, &b))); vec3_add(&o, &o, vec3_muls(&tmp, vec3_cross(&tmp, &b, &c), vec3_dot(&a, &a))); vec3_muls(&o, &o, 1.0f/denom); return sphere_setf(rs, v0->x + o.x, v0->y + o.y, v0->z + o.z, vec3_len(&o) + EPSILON); }
collision point_collide_edge(vec3 p, vec3 v, vec3 e0, vec3 e1) { vec3 x0 = vec3_sub(e0, p); vec3 x1 = vec3_sub(e1, p); vec3 d = vec3_sub(x1, x0); float dlen = vec3_length_sqrd(d); float vlen = vec3_length_sqrd(v); float xlen = vec3_length_sqrd(x0); float A = dlen * -vlen + vec3_dot(d, v) * vec3_dot(d, v); float B = dlen * 2 * vec3_dot(v, x0) - 2 * vec3_dot(d, v) * vec3_dot(d, x0); float C = dlen * - xlen + vec3_dot(d, x0) * vec3_dot(d, x0); float t0, t1, t; if (!quadratic(A, B, C, &t0, &t1)) { return collision_none(); } if (between_or(t0, 0, 1) && between_or(t1, 0, 1)) { t = min(t0, t1); } else if (between_or(t0, 0, 1)) { t = t0; } else if (between_or(t1, 0, 1)) { t = t1; } else { return collision_none(); } float range = (vec3_dot(d, v) * t - vec3_dot(d, x0)) / dlen; if (!between_or(range, 0, 1)) { return collision_none(); } else { vec3 spoint = vec3_add(e0, vec3_mul(d, range)); return collision_new(t, spoint, vec3_normalize(vec3_sub(p, spoint))); } }
/* This is basically Cramer's rule, but with vector calculus. */ static bool ray_triangle_intersect(Ray ray, Vec3 u, Vec3 v, Vec3 w, struct TriangleHit *tri_hit) { Vec3 edge1, edge2, tvec, pvec, qvec; float det; float aa, bb, cc; edge1 = vec3_sub(v, u); edge2 = vec3_sub(w, u); pvec = vec3_cross(ray.direction, edge2); det = vec3_dot(edge1, pvec); tvec = vec3_sub(ray.origin, u); bb = vec3_dot(tvec, pvec) / det; if (bb < 0.0 || bb > 1.0) return false; qvec = vec3_cross(tvec, edge1); cc = vec3_dot(ray.direction, qvec) / det; if (cc < 0.0 || cc + bb > 1.0) return false; aa = 1.0 - bb - cc; tri_hit->a = aa; tri_hit->b = bb; tri_hit->c = cc; tri_hit->t = vec3_dot(edge2, qvec) / det; return true; }
collision sphere_collide_edge(sphere s, vec3 v, vec3 e0, vec3 e1) { //Wif (unlikely(!line_outside_sphere(s, e0, e1))) { error("Collision Sphere Inside Mesh Edge!"); } vec3 x0 = vec3_sub(e0, s.center); vec3 x1 = vec3_sub(e1, s.center); vec3 d = vec3_sub(x1, x0); float dlen = vec3_length_sqrd(d); float vlen = vec3_length_sqrd(v); float xlen = vec3_length_sqrd(x0); float A = dlen * -vlen + vec3_dot(d, v) * vec3_dot(d, v); float B = dlen * 2 * vec3_dot(v, x0) - 2 * vec3_dot(d, v) * vec3_dot(d, x0); float C = dlen * (s.radius * s.radius - xlen) + vec3_dot(d, x0) * vec3_dot(d, x0); float t0, t1, t; if (!quadratic(A, B, C, &t0, &t1)) { return collision_none(); } if (between_or(t0, 0, 1) && between_or(t1, 0, 1)) { t = min(t0, t1); } else if (between_or(t0, 0, 1)) { t = t0; } else if (between_or(t1, 0, 1)) { t = t1; } else { return collision_none(); } float range = (vec3_dot(d, v) * t - vec3_dot(d, x0)) / dlen; if (!between_or(range, 0, 1)) { return collision_none(); } else { vec3 spoint = vec3_add(e0, vec3_mul(d, range)); return collision_new(t, spoint, vec3_normalize(vec3_sub(s.center, spoint))); } }
void camera_control_orbit(camera* c, SDL_Event e) { float a1 = 0; float a2 = 0; vec3 axis; vec3 translation = c->target; c->position = vec3_sub(c->position, translation); c->target = vec3_sub(c->target, translation); switch(e.type) { case SDL_MOUSEMOTION: if (e.motion.state & SDL_BUTTON(1)) { a1 = e.motion.xrel * -0.005; a2 = e.motion.yrel * 0.005; c->position = mat3_mul_vec3(mat3_rotation_y( a1 ), c->position ); axis = vec3_normalize(vec3_cross( vec3_sub(c->position, c->target) , vec3_new(0,1,0) )); c->position = mat3_mul_vec3(mat3_rotation_angle_axis(a2, axis), c->position ); } break; case SDL_MOUSEWHEEL: c->position = vec3_add(c->position, vec3_mul(vec3_normalize(c->position), -e.wheel.y)); break; } c->position = vec3_add(c->position, translation); c->target = vec3_add(c->target, translation); }
void SSBoneFrame_UpdateMoveCommand(struct ss_animation_s *ss_anim, float move[3]) { vec3_sub(ss_anim->prev_bf.pos, ss_anim->prev_bf.pos, move); vec3_sub(ss_anim->prev_bf.centre, ss_anim->prev_bf.centre, move); vec3_sub(ss_anim->prev_bf.bb_min, ss_anim->prev_bf.bb_min, move); vec3_sub(ss_anim->prev_bf.bb_max, ss_anim->prev_bf.bb_max, move); }
void BillboardSprite::draw(Vec3 v) { v = quadrant_translate_position(current_camera_position, v); if (!point_fulstrum_test(v.x, v.y, v.z)) return; Vec3 up = vec3_init(model_view_matrix[0]*this->scale, model_view_matrix[4]*this->scale, model_view_matrix[8]*this->scale); Vec3 right = vec3_init(model_view_matrix[1]*this->scale, model_view_matrix[5]*this->scale, model_view_matrix[9]*this->scale); float tx_min, tx_max, ty_min, ty_max; tx_min = (float)(this->texture_index%16)* (1.0f/16.0f); tx_max = tx_min + (1.0f/16.0f); ty_min = (float)(this->texture_index/16)* (1.0f/16.0f); ty_max = ty_min + (1.0f/16.0f); Vec3 p = vec3_sub(v, vec3_add(right, up)); glTexCoord2f(tx_min,ty_max); glVertex3f(p.x, p.y, p.z); p = vec3_add(v, vec3_sub(up, right)); glTexCoord2f(tx_max,ty_max); glVertex3f(p.x, p.y, p.z); p = vec3_add(v, vec3_add(up, right)); glTexCoord2f(tx_max,ty_min); glVertex3f(p.x, p.y, p.z); p = vec3_add(v, vec3_sub(right, up)); glTexCoord2f(tx_min,ty_min); glVertex3f(p.x, p.y, p.z); }
void MeshData::generateTangents() { int pos_attr, uv_attr, len, n; float r, *pos, *uv, *tan, *bitan; vec3 pos_d1, pos_d2, uv_d1, uv_d2; pos_attr = getAttributeIndex("position"); uv_attr = getAttributeIndex("texcoord"); if (pos_attr < 0) { #ifndef PLG_RELEASE dprintf(2, "error: can't generateTangents() without position attribute\n"); #endif return; } if (uv_attr < 0) { #ifndef PLG_RELEASE dprintf(2, "error: can't generateTangents() without texcoord attribute\n"); #endif return; } pos = getVertex(pos_attr, 0); uv = getVertex(uv_attr, 0); len = getVertexCount() / 3; tan = (float *) malloc(len * 9 * sizeof(float)); bitan = (float *) malloc(len * 9 * sizeof(float)); for (n = 0; n < len; n ++) { vec3_sub(&pos_d1, (vec3 *) (pos + n * 9 + 3), (vec3 *) (pos + n * 9)); vec3_sub(&pos_d2, (vec3 *) (pos + n * 9 + 6), (vec3 *) (pos + n * 9)); uv_d1.d[0] = uv[n * 6 + 2] - uv[n * 6 + 0]; uv_d1.d[1] = uv[n * 6 + 3] - uv[n * 6 + 1]; uv_d2.d[0] = uv[n * 6 + 4] - uv[n * 6 + 0]; uv_d2.d[1] = uv[n * 6 + 5] - uv[n * 6 + 1]; r = 1.0f / (uv_d1.d[0] * uv_d2.d[1] - uv_d1.d[1] * uv_d2.d[0]); tan[n * 9 + 0] = (pos_d1.d[0] * uv_d2.d[1] - pos_d2.d[0] * uv_d1.d[1]) * r; tan[n * 9 + 1] = (pos_d1.d[1] * uv_d2.d[1] - pos_d2.d[1] * uv_d1.d[1]) * r; tan[n * 9 + 2] = (pos_d1.d[2] * uv_d2.d[1] - pos_d2.d[2] * uv_d1.d[1]) * r; tan[n * 9 + 6] = tan[n * 9 + 3] = tan[n * 9 + 0]; tan[n * 9 + 7] = tan[n * 9 + 4] = tan[n * 9 + 1]; tan[n * 9 + 8] = tan[n * 9 + 5] = tan[n * 9 + 2]; bitan[n * 9 + 0] = (pos_d2.d[0] * uv_d1.d[0] - pos_d1.d[0] * uv_d2.d[0]) * r; bitan[n * 9 + 1] = (pos_d2.d[1] * uv_d1.d[0] - pos_d1.d[1] * uv_d2.d[0]) * r; bitan[n * 9 + 2] = (pos_d2.d[2] * uv_d1.d[0] - pos_d1.d[2] * uv_d2.d[0]) * r; bitan[n * 9 + 6] = bitan[n * 9 + 3] = bitan[n * 9 + 0]; bitan[n * 9 + 7] = bitan[n * 9 + 4] = bitan[n * 9 + 1]; bitan[n * 9 + 8] = bitan[n * 9 + 5] = bitan[n * 9 + 2]; } addTangents(tan, len * 9); addBitangents(bitan, len * 9); }
static int on_move(gesture3d_t *gest, void *user) { float face_plane[4][4]; cursor_t *curs = gest->cursor; tool_move_t *tool = user; float n[3], pos[3], d[3], ofs[3], v[3]; layer_t *layer = goxel->image->active_layer; float mat[4][4]; if (box_is_null(tool->box)) return GESTURE_FAILED; if (gest->type == GESTURE_HOVER) { goxel_set_help_text(goxel, "Drag to move face"); if (curs->snaped != SNAP_LAYER_OUT) return GESTURE_FAILED; tool->snap_face = get_face(curs->normal); curs->snap_offset = 0; curs->snap_mask &= ~SNAP_ROUNDED; mat4_mul(tool->box, FACES_MATS[tool->snap_face], face_plane); render_img(&goxel->rend, NULL, face_plane, EFFECT_NO_SHADING); if (curs->flags & CURSOR_PRESSED) { gest->type = GESTURE_DRAG; vec3_normalize(face_plane[0], v); plane_from_vectors(goxel->tool_plane, curs->pos, curs->normal, v); image_history_push(goxel->image); } return 0; } if (gest->type == GESTURE_DRAG) { goxel_set_help_text(goxel, "Drag to move face"); curs->snap_offset = 0; curs->snap_mask &= ~SNAP_ROUNDED; mat4_mul(tool->box, FACES_MATS[tool->snap_face], face_plane); vec3_normalize(face_plane[2], n); vec3_sub(curs->pos, goxel->tool_plane[3], v); vec3_project(v, n, v); vec3_add(goxel->tool_plane[3], v, pos); pos[0] = round(pos[0]); pos[1] = round(pos[1]); pos[2] = round(pos[2]); vec3_add(tool->box[3], face_plane[2], d); vec3_sub(pos, d, ofs); vec3_project(ofs, n, ofs); mat4_set_identity(mat); mat4_itranslate(mat, ofs[0], ofs[1], ofs[2]); do_move(layer, mat); if (gest->state == GESTURE_END) { gest->type = GESTURE_HOVER; mat4_copy(plane_null, goxel->tool_plane); } return 0; } return 0; }
void scotland_update() { camera* cam = entity_get("camera"); light* sun = entity_get("sun"); static_object* skydome = entity_get("skydome"); landscape* world = entity_get("world"); sun_orbit += frame_time() * 0.01; sun->position.x = 512 + sin(sun_orbit) * 512; sun->position.y = cos(sun_orbit) * 512; sun->position.z = 512; sun->target = vec3_new(512, 0, 512); if (w_held || s_held) { vec3 cam_dir = vec3_normalize(vec3_sub(cam->target, cam->position)); float speed = 0.5; if (!freecam) speed = 0.05; if (w_held) { cam->position = vec3_add(cam->position, vec3_mul(cam_dir, speed)); } if (s_held) { cam->position = vec3_sub(cam->position, vec3_mul(cam_dir, speed)); } if (!freecam) { float height = terrain_height(asset_hndl_ptr(world->terrain), vec2_new(cam->position.x, cam->position.z)); cam->position.y = height + 1; } cam->target = vec3_add(cam->position, cam_dir); } Uint8 keystate = SDL_GetMouseState(NULL, NULL); if(keystate & SDL_BUTTON(1)){ float a1 = -(float)mouse_x * 0.005; float a2 = (float)mouse_y * 0.005; vec3 cam_dir = vec3_normalize(vec3_sub(cam->target, cam->position)); cam_dir.y += -a2; vec3 side_dir = vec3_normalize(vec3_cross(cam_dir, vec3_new(0,1,0))); cam_dir = vec3_add(cam_dir, vec3_mul(side_dir, -a1)); cam_dir = vec3_normalize(cam_dir); cam->target = vec3_add(cam->position, cam_dir); } mouse_x = 0; mouse_y = 0; ui_button* framerate = ui_elem_get("framerate"); ui_button_set_label(framerate, frame_rate_string()); }
void Polygon_FindNormale(polygon_p p) { float v1[3], v2[3]; vec3_sub(v1, p->vertices[1].position, p->vertices[0].position); vec3_sub(v2, p->vertices[2].position, p->vertices[1].position); vec3_cross(p->plane, v1, v2); p->plane[3] = -vec3_abs(p->plane); vec3_norm_plane(p->plane, p->vertices[0].position, p->plane[3]); }
/* Create a new buffer object from an array of vec3s for pts, and vec3s for texture coordinates. Faces is an array of 3 shorts for each face. */ BUFFER_T *buffer_new(float pts[][3], float tex[][3], short faces[][3], int numpts, int numfaces) { int i; float normals[numpts][3]; BUFFER_T *buf; NEW(buf); for(i=0; i<numpts; i++) { normals[i][0]=0; normals[i][1]=0; normals[i][2]=1; } for(i=0; i<numfaces; i++) { int a = faces[i][0]; int b = faces[i][1]; int c = faces[i][2]; float tmp[3]; float tmp2[3]; float n[3]; vec3_sub(tmp,pts[b],pts[a]); vec3_sub(tmp2,pts[c],pts[a]); vec3_cross(n,tmp,tmp2); vec3_normal(n,n); vec3_copy(normals[a],n); vec3_copy(normals[b],n); vec3_copy(normals[c],n); } float B[3*3*numpts]; for(i=0; i<numpts; i++) { for(int j=0; j<3; j++) { B[i*3*3+j]=pts[i][j]; B[i*3*3+3+j]=tex[i][j]; B[i*3*3+6+j]=normals[i][j]; } } buf->ntris=numfaces; glGenBuffers(1,&buf->vbuf); glBindBuffer(GL_ARRAY_BUFFER, buf->vbuf); glBufferData(GL_ARRAY_BUFFER, 36*numpts, B, GL_STATIC_DRAW); buf->vbuf_num = numpts; glGenBuffers(1,&buf->ebuf); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf->ebuf); glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6*numfaces, faces, GL_STATIC_DRAW); buf->ebuf_num = numfaces*3; return buf; }
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); }
static void vertex_shader(const vertex_t *in, vs_to_fs_t *out) { // decode vertex const vec3_t pc = { 0.5f, 0.5f, 0.5f }, nc = { 1.0f, 1.0f, 1.0f }; const float pi = 1.0f / 65535.0f, ni = 2.0f / 255.0f, uvi = 1.0f / 255.0f; vec3_t position = vec3_sub(vec3_mul(vec3(in->x, in->y, in->z), pi), pc); vec3_t normal = vec3_sub(vec3_mul(vec3(in->nx, in->ny, in->nz), ni), nc); vec2_t uv = vec2_mul(vec2(in->u, in->v), uvi); // transform vertex out->position = mat4_transform_position(mvp, position); out->normal = mat4_transform_vector(mv, normal); out->uv = uv; }
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); }
CollisionResult collision_ray_scene_union(const Ray* ray, const Scene* scene) { const Scene* scene1 = ((ScenePair*)scene->data)->scene1; const Scene* scene2 = ((ScenePair*)scene->data)->scene2; const int max_iterations = 10; CollisionResult r1; { Ray ray2 = *ray; Vec3 p; for (int i = 0; i < max_iterations; ++i) { r1 = collision_ray_scene(&ray2, scene1); if (r1.type == None) { break; } p = ray_point(&ray2, r1.time); if (!scene_is_point_in_solid(scene2, &p)) { break; } Vec3 ro = ray_point(&ray2, r1.time+0.1); ray2 = ray_init(&ro, &ray2.direction); } if (r1.type != None) { Vec3 v = vec3_sub(&p, &ray->origin); r1.time = vec3_dot(&ray->direction, &v); } } CollisionResult r2; { Ray ray2 = *ray; Vec3 p; for (int i = 0; i < max_iterations; ++i) { r2 = collision_ray_scene(&ray2, scene2); if (r2.type == None) { break; } p = ray_point(&ray2, r2.time); if (!scene_is_point_in_solid(scene1, &p)) { break; } Vec3 ro = ray_point(&ray2, r2.time+0.1); ray2 = ray_init(&ro, &ray2.direction); } if (r2.type != None) { Vec3 v = vec3_sub(&p, &ray->origin); r2.time = vec3_dot(&ray->direction, &v); } } if (r1.type == None) { if (r2.type == None) { return (CollisionResult){.type=None}; } else { return r2; } } else {
static void compute_normal (char clockwise, vec3 p1, vec3 p2, vec3 p3, vec3* n) { vec3 v1, v2; if (!clockwise) { vec3_sub (p3, p2, &v1); vec3_sub (p1, p2, &v2); } else { vec3_sub (p1, p2, &v1); vec3_sub (p3, p2, &v2); } cross (v1, v2, n); }
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); }
void OBSBasicPreview::SnapStretchingToScreen(vec3 &tl, vec3 &br) { uint32_t stretchFlags = (uint32_t)stretchHandle; vec3 newTL = GetTransformedPos(tl.x, tl.y, itemToScreen); vec3 newTR = GetTransformedPos(br.x, tl.y, itemToScreen); vec3 newBL = GetTransformedPos(tl.x, br.y, itemToScreen); vec3 newBR = GetTransformedPos(br.x, br.y, itemToScreen); vec3 boundingTL; vec3 boundingBR; vec3_copy(&boundingTL, &newTL); vec3_min(&boundingTL, &boundingTL, &newTR); vec3_min(&boundingTL, &boundingTL, &newBL); vec3_min(&boundingTL, &boundingTL, &newBR); vec3_copy(&boundingBR, &newTL); vec3_max(&boundingBR, &boundingBR, &newTR); vec3_max(&boundingBR, &boundingBR, &newBL); vec3_max(&boundingBR, &boundingBR, &newBR); vec3 offset = GetScreenSnapOffset(boundingTL, boundingBR); vec3_add(&offset, &offset, &newTL); vec3_transform(&offset, &offset, &screenToItem); vec3_sub(&offset, &offset, &tl); if (stretchFlags & ITEM_LEFT) tl.x += offset.x; else if (stretchFlags & ITEM_RIGHT) br.x += offset.x; if (stretchFlags & ITEM_TOP) tl.y += offset.y; else if (stretchFlags & ITEM_BOTTOM) br.y += offset.y; }
inline t_vec3 *vec3_reflect(t_vec3 *v, const t_vec3 *v1, const t_vec3 *v2) { t_vec3 tmp; vec3_mul_f(&tmp, v2, 2 * vec3_dot(v1, v2)); return (vec3_sub(v, v1, &tmp)); }
t_mat4 mat4_view_lookat(t_vec3 eye, t_vec3 targ, t_vec3 up) { t_mat4 out; t_vec3 zaxis; t_vec3 xaxis; t_vec3 yaxis; zaxis = vec3_normal(vec3_sub(eye, targ)); xaxis = vec3_normal(vec3_cross(up, zaxis)); yaxis = vec3_cross(zaxis, xaxis); out = mat4_ident(); out.m[0] = xaxis.x; out.m[1] = yaxis.x; out.m[2] = zaxis.x; out.m[4] = xaxis.y; out.m[5] = yaxis.y; out.m[6] = zaxis.y; out.m[8] = xaxis.z; out.m[9] = yaxis.z; out.m[10] = zaxis.z; out.m[12] = -vec3_dot(xaxis, eye); out.m[13] = -vec3_dot(yaxis, eye); out.m[14] = -vec3_dot(zaxis, eye); return (out); }
int raycast_to_sphere(t_hit *hit, const t_ray *ray, const t_sphere *sphere) { t_vec3 distance_to_center; float tca; float d2; float thc; vec3_copy(&distance_to_center, &sphere->position); vec3_sub(&distance_to_center, &ray->origin); tca = vec3_dot(&distance_to_center, &ray->direction); if (tca < 0) return (0); d2 = vec3_dot(&distance_to_center, &distance_to_center) - tca * tca; if (d2 > sphere->radius * sphere->radius) return (0); thc = sqrt(sphere->radius * sphere->radius - d2); hit->distance = select_closest_hit(tca - thc, tca + thc); update_hit_from_ray(hit, ray, &sphere->material->ambient); return (1); }
static void toggle_freecam(ui_button* b, SDL_Event event) { if (event.type == SDL_MOUSEBUTTONDOWN) { if (ui_button_contains_position(b, vec2_new(event.motion.x, event.motion.y))) { b->pressed = true; } } else if (event.type == SDL_MOUSEBUTTONUP) { if (b->pressed) { b->pressed = false; freecam = !freecam; camera* cam = entity_get("camera"); landscape* world = entity_get("world"); vec3 cam_dir = vec3_normalize(vec3_sub(cam->target, cam->position)); float height = terrain_height(asset_hndl_ptr(world->terrain), vec2_new(cam->position.x, cam->position.z)); cam->position.y = height + 1; cam->target = vec3_add(cam->position, cam_dir); } } }
/* See TestRaySphere() in "Real Time Collision Detection", p. 179, by Christer Ericson. */ int ray_intersects_sphere(const union vec3 *ray_origin, const union vec3 *ray_direction, const union vec3 *sphere_origin, const float radius) { union vec3 m; float c, b, disc; vec3_sub(&m, ray_origin, sphere_origin); c = vec3_dot(&m, &m) - radius * radius; /* If there is definitely at least one real root, there must be an intersection */ if (c <= 0.0f) return 1; b = vec3_dot(&m, ray_direction); /* Early exit if ray origin outside sphere and ray pointing away from sphere */ if (b > 0.0f) return 0; disc = b * b - c; /* A negative discriminant corresponds to ray missing sphere */ if (disc < 0.0f) return 0; /* Now ray must hit sphere */ return 1; }
void calc_torque(struct vec3 *dst, const struct vec3 *v1, const struct vec3 *v2, float torque, float min_adjust, float t) { struct vec3 line, dir; float orig_dist, torque_dist, adjust_dist; if (vec3_close(v1, v2, EPSILON)) { vec3_copy(dst, v1); return; } vec3_sub(&line, v2, v1); orig_dist = vec3_len(&line); vec3_mulf(&dir, &line, 1.0f/orig_dist); torque_dist = orig_dist*torque; /* use distance to determine speed */ if (torque_dist < min_adjust) /* prevent from going too slow */ torque_dist = min_adjust; adjust_dist = torque_dist*t; if (adjust_dist <= (orig_dist-LARGE_EPSILON)) { vec3_mulf(dst, &dir, adjust_dist); vec3_add(dst, dst, v1); /* add torque */ } else { vec3_copy(dst, v2); /* clamp if overshoot */ } }
static int _llfunc_vec3_sub(lua_State *L) { vec3 *a = (vec3*)userdata_get_or_die(L, 1); vec3 *b = (vec3*)userdata_get_or_die(L, 2); vec3 *r = (vec3*)userdata_get_or_new(L, 3, sizeof(vec3)); vec3_sub(a, b, r); return 1; }
static box_t get_box(const vec3_t *p0, const vec3_t *p1, const vec3_t *n, float r, const plane_t *plane) { mat4_t rot; box_t box; if (p1 == NULL) { box = bbox_from_extents(*p0, r, r, r); box = box_swap_axis(box, 2, 0, 1); return box; } if (r == 0) { box = bbox_grow(bbox_from_points(*p0, *p1), 0.5, 0.5, 0.5); // Apply the plane rotation. rot = plane->mat; rot.vecs[3] = vec4(0, 0, 0, 1); mat4_imul(&box.mat, rot); return box; } // Create a box for a line: int i; const vec3_t AXES[] = {vec3(1, 0, 0), vec3(0, 1, 0), vec3(0, 0, 1)}; box.mat = mat4_identity; box.p = vec3_mix(*p0, *p1, 0.5); box.d = vec3_sub(*p1, box.p); for (i = 0; i < 3; i++) { box.w = vec3_cross(box.d, AXES[i]); if (vec3_norm2(box.w) > 0) break; } if (i == 3) return box; box.w = vec3_mul(vec3_normalized(box.w), r); box.h = vec3_mul(vec3_normalized(vec3_cross(box.d, box.w)), r); return box; }