X42_EXPORT bool X42_CALL x42_ApplyBoneOffsets( x42animLerp_t *lerp, const x42data_t *x42, const x42boneOffset_t *offsets, uint numOffsets, x42opts_t *opts ) { uint i, j; REF_PARAM( opts ); #ifndef LIBX42_NO_PARAM_VALIDATION demand_rf( lerp != NULL, X42_ERR_BADPTR, "lerp is NULL" ); demand_rf( x42 != NULL, X42_ERR_BADPTR, "x42 is NULL" ); demand_rf( x42_ValidateHeader( &x42->header ), X42_ERR_BADDATA, "invalid x42 header data" ); demand_rf( offsets != NULL, X42_ERR_BADPTR, "offsets is NULL" ); #endif for( i = 0; i < numOffsets; i++ ) { for( j = 0; j < x42->header.numBones; j++ ) { if( x42name_eq2( x42, x42->bones[j].name, offsets[i].boneName ) ) break; } if( j == x42->header.numBones ) continue; vec3_add( lerp->p[j], lerp->p[j], offsets[i].pos_offset ); vec3_add( lerp->s[j], lerp->s[j], offsets[i].scale_offset ); quat_mul( lerp->r[j], offsets[i].rot_offset, lerp->r[j] ); } return true; }
void object3d_render(screen_buffer *screen, object3d *obj) { vec3 a, b, c; int i; for (i = 0; i < obj->vertex_cnt; i+=3) { a = obj->vertices[i][0]; b = obj->vertices[i+1][0]; c = obj->vertices[i+2][0]; vec3_rotate(&a, &obj->rotation); vec3_mul(&a, &obj->scale); vec3_add(&a, &obj->position); vec3_rotate(&b, &obj->rotation); vec3_mul(&b, &obj->scale); vec3_add(&b, &obj->position); vec3_rotate(&c, &obj->rotation); vec3_mul(&c, &obj->scale); vec3_add(&c, &obj->position); rasterize_vertex(screen, &a, &b, &c); //line(screen, a.x, a.y, b.x, b.y, '+'); //line(screen, b.x, b.y, c.x, c.y, '+'); //line(screen, c.x, c.y, a.x, a.y, '+'); } }
void collision_response_slide(void* x, vec3* position, vec3* velocity, collision (*colfunc)(void* x, vec3* pos, vec3* vel) ) { collision col = colfunc(x, position, velocity); int count = 0; while (col.collided) { //renderer_add(x, render_object_line(*position, vec3_add(*position, col.norm), vec3_red(), count+1)); if (count++ == 100) { *velocity = vec3_zero(); break; } vec3 fwrd = vec3_mul(*velocity, col.time); float len = max(vec3_length(fwrd) - 0.001, 0.0) / vec3_length(fwrd); vec3 move = vec3_add(*position, vec3_mul(fwrd, len)); vec3 proj = vec3_project(vec3_mul(*velocity, (1.0-col.time)), col.norm); //renderer_add(x, render_object_line(*position, vec3_add(*position, vec3_normalize(proj)), vec3_green(), count+1)); *position = move; *velocity = proj; col = colfunc(x, position, velocity); } *position = vec3_add(*position, *velocity); }
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); }
collision sphere_collide_face(sphere s, vec3 v, ctri ct) { //if (unlikely(sphere_intersects_face(s, ct.a, ct.b, ct.c, ct.norm))) { error("Collision Sphere Inside Mesh Face!"); } float angle = vec3_dot(ct.norm, v); float dist = vec3_dot(ct.norm, vec3_sub(s.center, ct.a)); float t0 = ( s.radius - dist) / angle; float t1 = (-s.radius - dist) / angle; float t = FLT_MAX; 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(); } vec3 cpoint = vec3_add(s.center, vec3_mul(v, t)); vec3 spoint = vec3_add(cpoint, vec3_mul(ct.norm, -s.radius)); if (!point_inside_triangle(spoint, ct.a, ct.b, ct.c)) { return collision_none(); } else { return collision_new(t, spoint, ct.norm); } }
void _set_collision_point() { if (this->type == HITSCAN_TARGET_NONE) { const Vec3 away = vec3_scalar_mult(this->direction, this->range); this->collision_point = vec3_add(this->start_position, away); } else if (this->type == HITSCAN_TARGET_BLOCK) { const Vec3 away = vec3_scalar_mult(this->direction, this->block_distance); this->collision_point = vec3_add(this->start_position, away); } else if (this->type == HITSCAN_TARGET_MECH) { const Vec3 away = vec3_scalar_mult(this->direction, this->mech_distance); this->collision_point = vec3_add(this->start_position, away); } else if (this->type == HITSCAN_TARGET_SPRITE_MOB) { this->collision_point = this->sprite_mob_collision_point; } else if (this->type == HITSCAN_TARGET_VOXEL) { this->collision_point = this->voxel_collision_point; } else { GS_ASSERT(false); } }
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); }
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); }
static Ray cam_ray_internal(Camera *cam, int i, int j, float offx, float offy, double near) { Ray r; float d, u, v; double bottom, left, width, height; const int nx = config->width, ny = config->height; width = 2*near*tan(cam->fov*M_TWO_PI/360./2.); left = -width/2; height = width * ny/(double) nx; bottom = -height/2; d = near; u = left + width *(i + offx)/nx; v = bottom + height*(j + offy)/ny; r.origin = cam->position; r.direction = vec3_normalize(vec3_add( vec3_scale(-d, cam->w), vec3_add( vec3_scale( u, cam->u), vec3_scale( v, cam->v)))); r.near = 0; r.far = HUGE_VAL; return r; }
static int ray_sphere_intersect(Ray r, Sphere sph, float t[2], Vec3 normal[2]) { Vec3 v; float dd, vd, vv, discriminant; float radius = sph.radius; v = r.origin; vv = vec3_dot(v, v); vd = vec3_dot(v, r.direction); dd = vec3_dot(r.direction, r.direction); discriminant = vd*vd - dd*(vv - radius*radius); if (discriminant < 0) return 0; else if (discriminant == 0) { t[0] = -vd/dd; normal[0] = vec3_normalize(vec3_add(r.origin, vec3_scale(t[0], r.direction))); return 1; } else { t[0] = (-vd - sqrtf(discriminant))/dd; t[1] = (-vd + sqrtf(discriminant))/dd; normal[0] = vec3_add(r.origin, vec3_scale(t[0], r.direction)); normal[1] = vec3_add(r.origin, vec3_scale(t[1], r.direction)); return 2; } }
static void _control_camera(Game* G, float delta_time) { if(G->num_points == 1) { Vec2 curr = G->points[0].pos; Vec2 delta = vec2_sub(curr, G->prev_single); /* L-R rotation */ Quaternion q = quat_from_axis_anglef(0, 1, 0, delta_time*delta.x*0.2f); G->camera.orientation = quat_multiply(G->camera.orientation, q); /* U-D rotation */ q = quat_from_axis_anglef(1, 0, 0, delta_time*delta.y*0.2f); G->camera.orientation = quat_multiply(q, G->camera.orientation); G->prev_single = curr; } else if(G->num_points == 2) { float camera_speed = 0.1f; Vec3 look = quat_get_z_axis(G->camera.orientation); Vec3 right = quat_get_x_axis(G->camera.orientation); Vec2 avg = vec2_add(G->points[0].pos, G->points[1].pos); Vec2 delta; avg = vec2_mul_scalar(avg, 0.5f); delta = vec2_sub(avg, G->prev_double); look = vec3_mul_scalar(look, -delta.y*camera_speed); right = vec3_mul_scalar(right, delta.x*camera_speed); G->camera.position = vec3_add(G->camera.position, look); G->camera.position = vec3_add(G->camera.position, right); G->prev_double = avg; } }
/* 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); }
/** * Component of the support function for a cylinder collider. **/ static void object_support_component_cylinder(object_t *object, float direction[3], float out[3]) { float top[3] = { 0, object->h / 2, 0 }; float bottom[3] = { 0, -object->h / 2, 0 }; float axis[3]; float dir_perp[3]; float trans[16]; float dot_top; object_get_transform_mat(object, trans); /* Top and bottom are set to points in the middle of the top and the * bottom faces of the cylinder respectively. We transform them to * their worldspace positions. */ matrix_vec3_mul(trans, top, 1.0, top); matrix_vec3_mul(trans, bottom, 1.0, bottom); /* We get an axis vector that runs down the middle of the cylinder. */ vec3_subtract(top, bottom, axis); /* Part of another process, but useful now for a reason... */ vec3_cross(axis, direction, dir_perp); /* If the cross product is zero, our direction is aligned with the * cylinder and top and bottom are our two final candidates. */ if (vec3_magnitude(dir_perp) > 0) { /* This completes what we started with the last cross product. * dir_perp is now a vector perpendicular to the cylinder's * axis, but as close to our selected direction as possible. */ vec3_cross(dir_perp, axis, dir_perp); /* Scale dir_perp to be the radius of our cylinder. */ vec3_normalize(dir_perp, dir_perp); vec3_scale(dir_perp, dir_perp, object->r); /* Finally, move top and bottom to the edges of our cylinder in * the appropriate direction. We now have our two final * candidates. */ vec3_add(dir_perp, top, top); vec3_add(dir_perp, bottom, bottom); } /* We now have two candidates, top and bottom. We can just use largest * dot product to determine which is furthest. */ dot_top = vec3_dot(top, direction); if (dot_top > vec3_dot(bottom, direction)) memcpy(out, top, 3 * sizeof(float)); else memcpy(out, bottom, 3 * sizeof(float)); }
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()); }
t_bool lambertian(t_material *material, const t_ray *r, const t_hit_record *h, t_vec3 *attenuation, t_ray *scattered) { (void)r; t_vec3 target; t_vec3 random; random = random_in_unit_sphere(1.0f); vec3_add(&target, vec3_add(&target, &h->normal, &h->pos), &random); ray_assign(scattered, &h->pos, vec3_sub(&target, &target, &h->pos)); material->texture.value(&material->texture, h, attenuation); return (TRUE); }
void RailTrailEffect::draw_quad(const Vec3& p, float r, float theta, float phi) // quadratic radius { // with no rotation modifications, it faces upwards static const float tx_min = 0.0f; static const float tx_max = 1.0f; static const float ty_min = 0.0f; static const float ty_max = 1.0f; Vec3 bl, tl, tr, br; bl = tl = tr = br = vec3_init(0.0f); // FIXME: MOVE SHIT LIKE THIS TO BE CALC'ED ONLY ONCE then applied to all the interpolated points // rotate the y & z (pitch) .... prob need to reverse/mirror the y float radian = phi*PI; // first setup up-facing quad with correct PITCH // bottom edge bl.y = br.y = -r*sinf(radian); bl.z = br.z = r*cosf(radian); //printf("bl.y: %8.2f bl.z: %8.2f \n", bl.y, bl.z); // top edge tl.y = tr.y = r*sinf(radian); tl.z = tr.z = -r*cosf(radian); //printf("tl.y: %8.2f tl.z: %8.2f \n", tl.y, tl.z); // sides bl.x = tl.x = -r; br.x = tr.x = r; // do YAW bl = vec3_euler_rotation(bl, theta-0.5f, 0, 0); tl = vec3_euler_rotation(tl, theta-0.5f, 0, 0); tr = vec3_euler_rotation(tr, theta-0.5f, 0, 0); br = vec3_euler_rotation(br, theta-0.5f, 0, 0); // translate to world space bl = vec3_add(p, bl); tl = vec3_add(p, tl); tr = vec3_add(p, tr); br = vec3_add(p, br); // draw glTexCoord2f(tx_max, ty_max); glVertex3f(bl.x, bl.y, bl.z); // Bottom left glTexCoord2f(tx_min, ty_max); glVertex3f(tl.x, tl.y, tl.z); // Top left glTexCoord2f(tx_min, ty_min); glVertex3f(tr.x, tr.y, tr.z); // Top right glTexCoord2f(tx_max, ty_min); glVertex3f(br.x, br.y, br.z); // Bottom right }
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; }
// NB. Proportional x and y Ray Camera::getRay(float x, float y){ vec3 xdir; vec3 ydir; vec3 dest; xdir = vec3_scale(camx, (x-0.5) * tax); ydir = vec3_scale(camy, (y-0.5) * tay); dest = vec3_add(camz, vec3_add(xdir, ydir)); Ray r; r.ro = location; r.rd = dest; return r; }
/* Various intersection routines. The sphere and cylinder routines are the most * mature. */ static int ray_plane_intersect(Ray ray, Plane plane, float t[1], Vec3 normal[1]) { float test_t, alpha, beta, det; Vec3 a = plane.edge1, b = plane.edge2, d = ray.direction, o = ray.origin; Vec3 n, axn, bxn, pos; /* This is basically Cramer's rule with vector calculus */ n = vec3_cross(a, b); test_t = -vec3_dot(o, n)/vec3_dot(d, n); pos = vec3_add(o, vec3_scale(test_t, d)); axn = vec3_cross(a, n); bxn = vec3_cross(b, n); det = vec3_dot(a, bxn); alpha = vec3_dot(pos, bxn)/det; beta = -vec3_dot(pos, axn)/det; if (alpha < 0 || alpha > 1 || beta < 0 || beta > 1) return 0; t[0] = test_t; if (vec3_dot(d, n) < 0) normal[0] = n; else normal[0] = vec3_scale(-1, n); return 1; }
void generate_debug_geometry(vector_buffer *vertices, vector_buffer *normals, geometry* out) { float temp[3]; vector_buffer debug; vector_init(&debug); for(int i = 0; i < out->vertex_count; ++i) { vec3_scale(vector_get(normals, i), 0.05f, temp); vec3_add(vector_get(vertices, i), temp, temp); vector_append(&debug, vector_get(vertices, i)); vector_append(&debug, temp); } out->debug_geometry.attributes.position = 3; make_buffer(out->debug_geometry.attributes.position, &out->debug_geometry.vertex_buffer, debug.data , (GLsizei) (out->vertex_count * 3 * 2 * sizeof(float))); out->debug_geometry.vertex_shader = make_shader(GL_VERTEX_SHADER, "shaders/debug_shader.v.glsl"); out->debug_geometry.fragment_shader = make_shader(GL_FRAGMENT_SHADER, "shaders/debug_shader.f.glsl"); out->debug_geometry.program = make_program(out->debug_geometry.vertex_shader, out->debug_geometry.fragment_shader); glBindAttribLocation(out->debug_geometry.program, out->debug_geometry.attributes.position, "position"); glLinkProgram(out->debug_geometry.program); out->debug_geometry.uniform.mvp_matrix = glGetUniformLocation(out->program, "mvp_matrix"); }
static vec4_t fragment_shader(const vs_to_fs_t *in) { vec3_t result = { 0, 0, 0 }; //eye position const vec3_t E = { 0, 0, 1 }; const float ambient = 0.05f; float diffuse, specular; vec3_t N = vec3_normalize(in->normal); int i; for(i=0; i<sizeof(lights)/sizeof(light_t); i++){ vec3_t H = vec3_normalize(vec3_add(E, lights[i].position)); diffuse = vec3_dot(N, lights[i].position); specular = vec3_dot(N, H); specular *= specular; specular *= specular; specular *= specular; specular *= specular; specular *= specular; specular *= specular * 0.6f; vec3_t c = r3d_texture_nearest(textures[mesh], in->uv); // read texel result.r += diffuse * c.r * lights[i].color.r + specular; result.g += diffuse * c.g * lights[i].color.g + specular; result.b += diffuse * c.b * lights[i].color.b + specular; } return vec4(ambient + result.r, ambient + result.g, ambient + result.b, 1.0f); }
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); } } }
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))); } }
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))); } }
static int _llfunc_vec3_add(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_add(a, b, r); return 1; }
void trace_image(int width, int height, float aspect, unsigned char *image, const world* world, const vec3& light_dir) { #pragma omp parallel for schedule(dynamic) for(int yloop = 0; yloop < height; yloop++) { unsigned char *row = image + (height - yloop - 1) * (((width * 3) + 3) & ~3); for(int xloop = 0; xloop < width; xloop++) { // printf("%d, %d\n", xloop, yloop); int cols = 0; vec3 color(0, 0, 0); for(int qky = 0; qky < world->ysub; qky++) { for(int qkx = 0; qkx < world->xsub; qkx++) { float u = ((xloop + qkx / (float)world->xsub) + .5) / width; float v = ((yloop + qky / (float)world->ysub) + .5) / height; ray eye_ray; eye_ray.d = make_eye_ray(u, v, aspect, world->cam.fov); eye_ray.o = vec3(0, 0, 0); ray world_ray = transform_ray(eye_ray, world->camera_matrix, world->camera_normal_matrix); vec3 sample = trace(world_ray, world, light_dir); color = vec3_add(color, sample); ++cols; } } vec3 final_color = vec3_divide(color, cols); unsigned char *pixel = row + xloop * 3; pixel[0] = final_color.x * 255; pixel[1] = final_color.y * 255; pixel[2] = final_color.z * 255; } } }
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 */ } }
void foreach_block_in_hiearchy( struct group *group, struct vec3 const *parentpos, void (*proc)(struct blockref*, struct vec3 const *pos, void*), void *data) { vec3 pos; vec3_add(&pos, parentpos, &group->position); struct groupdata *groupdata = group->data; struct ptrarray *blocks = groupdata->blocks; size_t blockcount = ptrarray_count(blocks); struct blockref ref = {NULL, group}; for (size_t i = 0; i < blockcount; ++i) { ref.block = get_ptrarray(blocks, i); proc(&ref, &pos, data); } struct ptrarray *groups = groupdata->groups; size_t groupcount = ptrarray_count(groups); for (size_t i = 0; i < groupcount; ++i) { struct group *child = get_ptrarray(groups, i); foreach_block_in_hiearchy(child, &pos, proc, data); } }
int collision_test_sphere(t_ray_result *r, t_sphere *sphere) { t_real a; t_real b; t_real c; t_real det; a = collision_test_sphere_a(&r->ray.direction); b = collision_test_sphere_b(&r->ray, &sphere->position); c = collision_test_sphere_c(&r->ray, sphere); det = ft_pow(b, 2) - (4 * a * c); if (!det) r->distance = -(b / 2 * a); else if (det > 0) r->distance = FT_MIN((-b - sqrt(det)) / (2 * a), (-b + sqrt(det)) / (2 * a)); else return (0); r->hit = OT_SPHERE; r->contact.point = vec3_add(r->ray.origin, vec3_scale(r->ray.direction, r->distance)); return (1); }