//***************************************************************************** void rvec_2_R(const float rvec[3], // rotation vector [rad] float R[3][3]) // rotation matrix { float q[4]; float angle = vector_magnitude(rvec); if (angle <= 0.00048828125f) { // angle < sqrt(2*machine_epsilon(float)), so flush cos(x) to 1.0f q[0] = 1.0f; // and flush sin(x/2)/x to 0.5 q[1] = 0.5f*rvec[0]; q[2] = 0.5f*rvec[1]; q[3] = 0.5f*rvec[2]; // This prevents division by zero, while retaining full accuracy } else { q[0] = cosf(angle*0.5f); float scale = sinf(angle*0.5f) / angle; q[1] = scale*rvec[0]; q[2] = scale*rvec[1]; q[3] = scale*rvec[2]; } quaternion_2_R(q, R); }
t_bool intersect_cone(t_ray ray, t_cone *obj, float *t) { float a; float b; float c; float tmp; t_vector3 ec; ec = vector_substract(ray.pos, obj->pos); tmp = (1 + obj->radius * obj->radius); a = vector_dotproduct(ray.dir, ray.dir); a = a - (tmp * SQUARE(vector_dotproduct(ray.dir, obj->dir))); b = vector_dotproduct(ray.dir, obj->dir) * vector_dotproduct(ec, obj->dir); b = 2 * (vector_dotproduct(ray.dir, ec) - b * tmp); c = vector_dotproduct(ec, ec); c -= tmp * SQUARE(vector_dotproduct(ec, obj->dir)); if ((*t = compute_len(a, b, c)) > 0.) { ec = vector_substract(create_intersect(ray, *t), obj->pos); if (obj->height == 0 || obj->dir.x > 0) return (TRUE); else if (obj->height > 0. && vector_dotproduct(obj->dir, ec) > 0.) if ((obj->height / cos(atan(obj->radius)) > vector_magnitude(ec))) return (TRUE); } return (FALSE); }
void vector_normalize(float v[3]) { float length = vector_magnitude(v); v[0] /= length; v[1] /= length; v[2] /= length; }
static int collision_native__make_polygon(lua_State *L) { int vertex_count = lua_objlen(L, 1) / 2; polygon_s *poly = (polygon_s *)lua_newuserdata( L, sizeof(polygon_s) + (vertex_count - 1) * sizeof(vector_s)); luaL_getmetatable(L, POLY_MT); lua_setmetatable(L, -2); poly->vertex_count = vertex_count; poly->bounding_radius = 0; int i; for(i = 0; i < vertex_count; i++) { lua_rawgeti(L, 1, i*2+1); poly->vertices[i].x = lua_tonumber(L, -1); lua_rawgeti(L, 1, i*2+2); poly->vertices[i].y = lua_tonumber(L, -1); lua_pop(L, 2); lua_Number mag = vector_magnitude(poly->vertices[i]); if(poly->bounding_radius < mag) poly->bounding_radius = mag; } return 1; }
static void movement_calc(void *o) { struct missile *m = o; float target_dist = FLT_MAX; if (m->target != NULL) { target_dist = vector_magnitude(m->pos, m->target->pos); target_dist -= m->hb[0].rad; target_dist -= m->target->hb[0].rad; } if ( (m->life_time != 0 && get_tick_count() - m->init_time > m->life_time) || (m->frag && target_dist < 0.05*world_scale) ) { if (m->frag) { missile_frag(m); } if (m->target != NULL) { remove_reset_ptr((void*)m->target, &m->target); } m->is_alive = false; explode(m); return; } if (m->target == NULL) { remove_reset_ptr((void*)m->target, &m->target); if (!m->dumb) { m->target = acquire_target(m->firer); if (m->target != NULL) { puts("required target"); } } return; } if ( !m->target->is_alive || !timed_out_r(&m->last_ctrl_tick, CTRL_RATE)) { return; } float dx = -m->target->pos.x + m->pos.x; float dy = +m->target->pos.y - m->pos.y; float old_rot = m->rotation; m->rotation = rad_to_degd(atan2(dx, dy)); const float MAX_ROT = 10; if (old_rot > m->rotation) { if (old_rot - m->rotation > MAX_ROT || fmod(360 + old_rot - m->rotation, 360) > MAX_ROT) { m->rotation = old_rot - MAX_ROT; } } else { if (m->rotation - old_rot > MAX_ROT || fmod(360 + m->rotation - old_rot, 360) > MAX_ROT) { m->rotation = old_rot + MAX_ROT; } } float mag = xy_magnitude(m->vel.x, m->vel.y); m->vel.x = vector_x(mag, 180 + m->rotation); m->vel.y = vector_y(mag, m->rotation); m->accel = 0; }
void vector_normalize(vector* v) { float magnitude = vector_magnitude(v), z = 0; if(magnitude > 0) { z = powf(magnitude, 0.5f); vector_div_scalar(v, z); } }
void vector_normalize(vector* v) { float magnitude = vector_magnitude(v); if(magnitude > 0) { v->x /= magnitude; v->y /= magnitude; v->z /= magnitude; } }
vector_t calculate_gravitation(object_t* a,object_t* b) { //Get distance and direction vector_t displacement=vector_subtract(a->position,b->position); double distance=vector_magnitude(displacement); vector_t direction=vector_multiply(1/distance,displacement); //Calculate gravity double gravity=GRAVITATIONAL_CONSTANT*(a->mass*b->mass)/(distance*distance); return vector_multiply(gravity,direction); }
void GameScene::update(float dt) { for (Entity* d : decorations_) { d->update(dt); } for (Entity* p : platforms_) { p->update(dt); } for (Entity* g : goalflags_) { g->update(dt); } update_effects(dt); for (Entity* c : collectibles_) { c->update(dt); sf::FloatRect bbox(c->collision_area()); if (!c->animation().hidden() && bbox.Intersects(player_.collision_area())) { explode(c,true); collectsnd_.Play(); } } update_player(dt); bool out_of_bounds = true; for (Entity* p : platforms_) { if (vector_magnitude( p->position() - player_.position()) < 1000) { out_of_bounds = false; } } if (out_of_bounds) { init_world(); } update_camera(dt); }
vector3d ahrs_drift_correction(dataexchange_t *data) { vector3d corr_vector, acc_g; corr_vector.x = 0.0; corr_vector.y = 0.0; corr_vector.z = 0.0; //do correction only then acceleration is close to 1G (unreliable if greater) acc_g = adxl345_raw_to_g(data, SCALE_2G_10B); double acc_magnitude = vector_magnitude(acc_g); if (fabs(acc_magnitude - 1.0) <= 0.15) { float corr_strength = 0.15; //vectors for rotation matrix vector3d acc_v, mag_v; acc_v.x = (*data).acc_x; acc_v.y = (*data).acc_y; acc_v.z = (*data).acc_z; mag_v.x = (*data).mag_x; mag_v.y = (*data).mag_y; mag_v.z = (*data).mag_z; hmc5883l_applyCalibration(&mag_v, calib_ptr); vector3d down = vector_inv(acc_v); vector3d east = vector_cross(down, mag_v); vector3d north = vector_cross(east, down); //normalize vectors vector_norm(&down); vector_norm(&east); vector_norm(&north); //matrix from rotation quaternion matrix3x3d rot_matrix = quaternion_to_matrix((*data).qr); //correction vector calculation vector3d sum1 = vector_sum(vector_cross(north, matrix_row_to_vector(&rot_matrix, 1)), vector_cross(east, matrix_row_to_vector(&rot_matrix, 2))); vector3d sum2 = vector_sum(sum1, vector_cross(down, matrix_row_to_vector(&rot_matrix, 3))); corr_vector = vector_scale(sum2, corr_strength); } return corr_vector; }
fp_t cosine_of_angle_diff(const vector_3_t v1, const vector_3_t v2) { int64_t dotproduct; int64_t denominator; /* * Angle between two vectors is acos(A dot B / |A|*|B|). To return * cosine of angle between vectors, then don't do acos operation. */ dotproduct = (int64_t)v1[0] * v2[0] + (int64_t)v1[1] * v2[1] + (int64_t)v1[2] * v2[2]; denominator = (int64_t)vector_magnitude(v1) * vector_magnitude(v2); /* Check for divide by 0 although extremely unlikely. */ if (!denominator) return 0; /* * We must shift the dot product first, so that we can represent * fractions. The answer is always a number with magnitude < 1.0, so * if we don't shift, it will always round down to 0. * * Note that overflow is possible if the dot product is large (that is, * if the vector components are of size (31 - FP_BITS/2) bits. If that * ever becomes a problem, we could detect this by counting the leading * zeroes of the dot product and shifting the denominator down * partially instead of shifting the dot product up. With the current * FP_BITS=16, that happens if the vector components are ~2^23. Which * we're a long way away from; the vector components used in * accelerometer calculations are ~2^11. */ return (dotproduct << FP_BITS) / denominator; }
void spacecraft_collision(simulation_t* sim,spacecraft_t* spacecraft) { vector_t displacement=vector_subtract(spacecraft->base.position,spacecraft->orbit.primary->base.position); double distance=vector_magnitude(displacement); double penetration=spacecraft->orbit.primary->radius-distance; if(penetration>0) { displacement=vector_multiply((distance+penetration)/distance,displacement); spacecraft->base.position=vector_add(spacecraft->orbit.primary->base.position,displacement); spacecraft->base.velocity=spacecraft->orbit.primary->base.velocity; spacecraft->base.velocity.x+=spacecraft->orbit.primary->base.delta_rot*displacement.y; spacecraft->base.velocity.y+=-spacecraft->orbit.primary->base.delta_rot*displacement.x; spacecraft->base.rotation=atan2(-displacement.y,displacement.x)+M_PI/2; spacecraft->base.delta_rot=0; } }
static t_color3 getfinalcolor(t_object *arr, t_intersect inter, t_env env) { t_color3 color; t_color3 color_tmp; float dist[2]; t_ray newray; float shade; t_vector3 l; int i; int k; int a; color_tmp = color_new(0, 0, 0); a = 0; if (inter.obj) { i = -1; while(arr[i].type != DEFAULT) { shade = 1.0; if (arr[i].light == TRUE) { l = vector_substract(arr[i].pos, inter.pos); dist[0] = vector_magnitude(l); newray.pos = vector_substract(inter.pos, vector_mul(inter.v_normal, 1e-4f)); newray.dir = vector_unit(l); k = -1; while (++k < 16 && arr[k].type != DEFAULT) if (env.fctinter[arr[k].type](newray, arr + k, &dist[1])) { if (arr[k].light != TRUE && dist[1] <= dist[0]) shade -= 0.3; } color_tmp = vector_sum(color_tmp, iter_light(inter, &arr[i], shade)); ++a; } ++i; } return (vector_div(color_tmp, a)); } return (color_new(17, 25, 37)); }
void spacecraft_calculate_orbit(simulation_t* sim,spacecraft_t* spacecraft) { //Determine smallest s.o.i that the spacecraft lies within celestial_body_t* primary=sim->primary; double smallest_soi=vector_magnitude(vector_subtract(sim->primary->base.position,spacecraft->base.position)); int i; for(i=0;i<sim->num_celestial_bodies;i++) { celestial_body_t* body=&sim->celestial_bodies[i]; if(body->orbit.primary!=NULL&&body->sphere_of_influence<smallest_soi&&body->sphere_of_influence>vector_magnitude(vector_subtract(body->base.position,spacecraft->base.position))) { primary=body; smallest_soi=body->sphere_of_influence; } } //Calculate spacecraft orbit spacecraft->orbit=orbit_calculate(primary,vector_subtract(spacecraft->base.position,primary->base.position),vector_subtract(spacecraft->base.velocity,primary->base.velocity)); }
void animate_particles(particle *particles, int particle_count, float time_delta){ int i; vector target = vector_make(0,-40,500); time_delta *= 500; for(i=0;i<particle_count;i++){ vector to = vector_sub(target,particles[i].pos); float len = vector_magnitude(to); if(len>1.f){ vector dir = vector_normalize(to); particles[i].pos = vector_add(particles[i].pos, vector_scale(dir,time_delta*(1.f/(len*0.1f) ) )); if(particles[i].pos.z>500){ particles[i].pos = target; len = 0; } particles[i].alpha = (len-1)*0.005f; }else{ particles[i].size = 0; particles[i].alpha = 0; } } }
quaternion ahrs_orientation_from_gyro(dataexchange_t *data) { //angle component vector3d gyr_rad_s = l3g4200d_raw_to_rad(data); double angle = vector_magnitude(gyr_rad_s) * (*data).time_period; //axis, normalized vector_norm(&gyr_rad_s); //quaternion from axis/angle quaternion q = quaternion_from_axis_angle(gyr_rad_s, angle); //normalize quaternion_norm(&q); (*data).qr = quaternion_product((*data).qr, q); return q; }
//***************************************************************************** uint8_t R_from_two_vectors(const float v1b[3], // v1 in b, will be nornalized const float v1e[3], // v1 in e, will be normalized const float v2b[3], // v2 in b, will be normalized const float v2e[3], // v2 in e, will be normlized float Rbe[3][3]) // rotation matrix { float Rib[3][3], Rie[3][3]; float mag; uint8_t i,j,k; // identity rotation in case of error for (i=0;i<3;i++) { for (j=0;j<3;j++) Rbe[i][j]=0; Rbe[i][i]=1; } // The first rows of rot matrices chosen in direction of v1 mag = vector_magnitude(v1b); if (fabsf(mag) < 1e-30) return (0); for (i=0;i<3;i++) Rib[0][i]=v1b[i]/mag; mag = vector_magnitude(v1e); if (fabs(mag) < 1e-30) return (0); for (i=0;i<3;i++) Rie[0][i]=v1e[i]/mag; // The second rows of rot matrices chosen in direction of v1xv2 cross_product(v1b,v2b,&Rib[1][0]); mag = vector_magnitude(&Rib[1][0]); if (fabsf(mag) < 1e-30) return (0); for (i=0;i<3;i++) Rib[1][i]=Rib[1][i]/mag; cross_product(v1e,v2e,&Rie[1][0]); mag = vector_magnitude(&Rie[1][0]); if (fabsf(mag) < 1e-30) return (0); for (i=0;i<3;i++) Rie[1][i]=Rie[1][i]/mag; // The third rows of rot matrices are XxY (Row1xRow2) cross_product(&Rib[0][0],&Rib[1][0],&Rib[2][0]); cross_product(&Rie[0][0],&Rie[1][0],&Rie[2][0]); // Rbe = Rbi*Rie = Rib'*Rie for (i=0;i<3;i++) for(j=0;j<3;j++) { Rbe[i][j]=0; for(k=0;k<3;k++) Rbe[i][j] += Rib[k][i]*Rie[k][j]; } return 1; }
void test_vector() { Vector *v = vector_new(1,2,3); CU_ASSERT(v->x == 1); CU_ASSERT(v->y == 2); CU_ASSERT(v->z == 3); Vector *vc = vector_copy(v); CU_ASSERT(vc->x == 1); CU_ASSERT(vc->y == 2); CU_ASSERT(vc->z == 3); Vector *u = vector_new(4,5,6); vector_add(v,u); CU_ASSERT(v->x == 5); CU_ASSERT(v->y == 7); CU_ASSERT(v->z == 9); vector_subtract(v,u); CU_ASSERT(v->x == 1); CU_ASSERT(v->y == 2); CU_ASSERT(v->z == 3); vector_multiply(v,2); CU_ASSERT(v->x == 2); CU_ASSERT(v->y == 4); CU_ASSERT(v->z == 6); Vector *w = vector_cross(v,u); CU_ASSERT(w->x == -6); CU_ASSERT(w->y == 12); CU_ASSERT(w->z == -6); vector_free(v); vector_free(u); vector_free(w); v = vector_new(3,4,0); u = vector_new(0,3,4); CU_ASSERT(v->x==u->y); CU_ASSERT(v->y==u->z); w = vector_cross(v,u); CU_ASSERT(w->x == 16); CU_ASSERT(w->y == -12); CU_ASSERT(w->z == 9); CU_ASSERT(within_tol(vector_magnitude(v),5)); CU_ASSERT(within_tol(vector_magnitude(u),5)); vector_free(v); vector_free(u); vector_free(w); v = vector_new(1,0,0); u = vector_new(0,0,1); double a = vector_angle(v,u)/D2R; CU_ASSERT(within_tol(a,90)); CU_ASSERT(within_tol(vector_angle(u,v),90.*D2R)); w = vector_cross(v,u); CU_ASSERT(within_tol(vector_magnitude(w),1)); CU_ASSERT(w->x==0); CU_ASSERT(w->y==-1); CU_ASSERT(w->z==0); }
int main(void) { ALmatrix *m1 = _alMatrixAlloc(3, 3); ALmatrix *m2 = _alMatrixAlloc(3, 3); ALmatrix *m3 = _alMatrixAlloc(3, 3); ALfloat axis[3] = { 0.0, 0.0, 1.0 }; ALfloat point[3] = { 15.0, 0.0, 0.0 }; ALfloat point1[3] = { 15.0, 0.0, 0.0 }; ALfloat point2[3] = { 15.0, 0.0, 0.0 }; ALfloat origin[3] = { 0.0, 0.0, 0.0 }; ALfloat vab; ALfloat xaxis[3] = { 1.0, 0.0, 0.0 }; ALfloat yaxis[3] = { 0.0, 1.0, 0.0 }; ALfloat zaxis[3] = { 0.0, 0.0, 1.0 }; ALfloat mxaxis[3] = { -1.0, 0.0, 0.0 }; ALfloat myaxis[3] = { 0.0, -1.0, 0.0 }; ALfloat mzaxis[3] = { 0.0, 0.0, -1.0 }; int i; int j; ALfloat vec1[3], vec2[3], d[3]; for(i = 0; i < 3; i++) { for(j = 0; j < 3; j++) { m3->data[i][j] = 0.0; if(i == j) { m1->data[i][j] = 3.0; m2->data[i][j] = 1.0; } else { m1->data[i][j] = 2.0; m2->data[i][j] = 0.0; } } } #if 0 fprintf(stderr, "m1:\n[%f][%f][%f]\n[%f][%f][%f]\n[%f][%f][%f]\n\n", m1->data[0][0], m1->data[0][1], m1->data[0][2], m1->data[1][0], m1->data[1][1], m1->data[1][2], m1->data[2][0], m1->data[2][1], m1->data[2][2]); fprintf(stderr, "m2:\n[%f][%f][%f]\n[%f][%f][%f]\n[%f][%f][%f]\n\n", m2->data[0][0], m2->data[0][1], m2->data[0][2], m2->data[1][0], m2->data[1][1], m2->data[1][2], m2->data[2][0], m2->data[2][1], m2->data[2][2]); _alMatrixMul(m3, m2, m1); fprintf(stderr, "[%f][%f][%f]\n[%f][%f][%f]\n[%f][%f][%f]\n", m3->data[0][0], m3->data[0][1], m3->data[0][2], m3->data[1][0], m3->data[1][1], m3->data[1][2], m3->data[2][0], m3->data[2][1], m3->data[2][2]); rotate_point_about_axis(1.00, point, axis); fprintf(stderr, "point [%f][%f][%f]\n", point[0], point[1], point[2]); vab = vector_angle_between(origin, origin, origin); fprintf(stderr, "origin should be 0.0, is %f\n", vab); vab = vector_angle_between(origin, xaxis, yaxis); fprintf(stderr, "xaxis/yaxis: should be %f, is %f\n", M_PI_2, vab); vab = vector_angle_between(origin, xaxis, zaxis); fprintf(stderr, "xaxis/zaxis: should be %f, is %f\n", M_PI_2, vab); vab = vector_angle_between(origin, origin, point); fprintf(stderr, "origin/point: should be %f, is %f\n", 0.0, vab); vab = vector_angle_between(origin, point1, point2); fprintf(stderr, "point1/point2: should be %f, is %f\n", 0.0, vab); for(i = 0; i < 32; i++) { if(ISPOWEROFTWO(i) == AL_TRUE) { fprintf(stderr, "ISPOWEROFTWO %d = AL_TRUE\n", i); } } for(i = 0; i < 32; i++) { fprintf(stderr, "nextPowerOfTwo(%d) = %d\n", i, nextPowerOfTwo(i)); } /* vector distance */ vec1[0] = -20.0; vec1[1] = 0.0; vec1[2] = 0.0; vec2[0] = -22.0; vec2[1] = 0.0; vec2[2] = 0.0; vector_distance(vec1, vec2, d); fprintf(stderr, "\n\t %f %f %f \n\t+ (%f %f %f)\n\t= (%f %f %f)\n", vec1[0], vec1[1], vec1[2], vec2[0], vec2[1], vec2[2], d[0], d[1], d[2]); /* vector magnitude */ vec1[0] = -31.0; vec1[1] = 0.0; vec1[2] = 0.0; vec2[0] = 30.0; vec2[1] = 0.0; vec2[2] = 0.0; fprintf(stderr, "\n\t %f %f %f \n\t~~ (%f %f %f)\n\t= %f\n", vec1[0], vec1[1], vec1[2], vec2[0], vec2[1], vec2[2], vector_magnitude(vec1, vec2)); /* vector magnitude again */ vec1[0] = 5.0; vec1[1] = 0.0; vec1[2] = 0.0; vec2[0] = 0.0; vec2[1] = 5.0; vec2[2] = 0.0; fprintf(stderr, "\n\t %f %f %f \n\t~~ (%f %f %f)\n\t= %f\n", vec1[0], vec1[1], vec1[2], vec2[0], vec2[1], vec2[2], vector_magnitude(vec1, vec2)); /* vector intersect angle */ vec1[0] = 0.0; point1[0] = 4.0; vec1[1] = 0.0; point1[1] = 0.0; vec1[2] = 0.0; point1[2] = 0.0; vec2[0] = 0.0; point2[0] = 0.0; vec2[1] = 0.0; point2[1] = 4.0; vec2[2] = 0.0; point2[2] = 0.0; fprintf(stderr, "\n\t ---- VECTOR ANGLE INTERSECT PERPENDICULAR -----\n" "\t1: (%f %f %f) -> (%f %f %f)\n" "\t2: (%f %f %f) -> (%f %f %f)\n" "\t=== %f\n", vec1[0], vec1[1], vec1[2], point1[0], point1[1], point1[2], vec2[0], vec2[1], vec2[2], point2[0], point2[1], point2[2], vector_intersect_angle(vec1, point1, vec2, point2)); /* vector intersect angle */ vec1[0] = 0.0; point1[0] = 4.0; vec1[1] = 0.0; point1[1] = 0.0; vec1[2] = 0.0; point1[2] = 0.0; vec2[0] = 2.0; point2[0] = 6.0; vec2[1] = 0.0; point2[1] = 0.0; vec2[2] = 0.0; point2[2] = 0.0; fprintf(stderr, "\n\t ---- VECTOR ANGLE INTERSECT PARALLEL -----\n" "\t1: (%f %f %f) -> (%f %f %f)\n" "\t2: (%f %f %f) -> (%f %f %f)\n" "\t=== %f\n", vec1[0], vec1[1], vec1[2], point1[0], point1[1], point1[2], vec2[0], vec2[1], vec2[2], point2[0], point2[1], point2[2], vector_intersect_angle(vec1, point1, vec2, point2)); /* vector intersect angle */ vec1[0] = -2.0; point1[0] = 4.0; vec1[1] = 0.0; point1[1] = 0.0; vec1[2] = 0.0; point1[2] = 0.0; vec2[0] = 0.0; point2[0] = -4.0; vec2[1] = 0.0; point2[1] = 0.0; vec2[2] = 0.0; point2[2] = 10.0; fprintf(stderr, "\n\t ---- VECTOR ANGLE INTERSECT OBTUSE -----\n" "\t1: (%f %f %f) -> (%f %f %f)\n" "\t2: (%f %f %f) -> (%f %f %f)\n" "\t=== %f\n", vec1[0], vec1[1], vec1[2], point1[0], point1[1], point1[2], vec2[0], vec2[1], vec2[2], point2[0], point2[1], point2[2], vector_intersect_angle(vec1, point1, vec2, point2)); /* vector intersect angle */ vec1[0] = 0.0; point1[0] = 0.0; vec1[1] = 4.0; point1[1] = 0.0; vec1[2] = 0.0; point1[2] = 0.0; vec2[0] = 0.0; point2[0] = 0.0; vec2[1] = 0.0; point2[1] = 0.0; vec2[2] = 4.0; point2[2] = 0.0; fprintf(stderr, "\n\t ---- VECTOR ANGLE INTERSECT INTERSECTING -----\n" "\t1: (%f %f %f) -> (%f %f %f)\n" "\t2: (%f %f %f) -> (%f %f %f)\n" "\t=== %f\n", vec1[0], vec1[1], vec1[2], point1[0], point1[1], point1[2], vec2[0], vec2[1], vec2[2], point2[0], point2[1], point2[2], vector_intersect_angle(vec1, point1, vec2, point2)); #endif return 0; }
vector_t vector_normalize(vector_t v) { return vector_scale(v, 1.0 / vector_magnitude(v)); }
float vector_distance(vector_t a, vector_t b) { return vector_magnitude(vector_sub(a, b)); }