t_bool dielectric(t_material *material, const t_ray *r, const t_hit_record *h, t_vec3 *attenuation, t_ray *scattered) { t_vec3 outward_normal; t_vec3 reflected; t_vec3 refracted; float ni_over_nt; float reflect_probe; float cosine; vec3_reflect(&reflected, &RAY_DIRECTION(r), &h->normal); vec3_assign(attenuation, &material->texture.albedo); if (vec3_dot(&RAY_DIRECTION(r), &h->normal) > 0) { vec3_mul_f(&outward_normal, &h->normal, -1.f); //TODO pass idx ni_over_nt = REF_IDX; cosine = REF_IDX * vec3_dot(&RAY_DIRECTION(r), &h->normal) / vec3_length(&RAY_DIRECTION(r)); } else { vec3_assign(&outward_normal, &h->normal); ni_over_nt = 1.0f / REF_IDX; cosine = - vec3_dot(&RAY_DIRECTION(r), &h->normal) / vec3_length(&RAY_DIRECTION(r)); } if (refract(&RAY_DIRECTION(r), &outward_normal, ni_over_nt, &refracted)) reflect_probe = schlick(cosine, REF_IDX); else reflect_probe = 1.0f; if (drand48() < reflect_probe) ray_assign(scattered, &h->pos, &reflected); else ray_assign(scattered, &h->pos, &refracted); return (TRUE); }
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); }
/** * @brief CM_NeedsSubdivision * @param a * @param b * @param c * @return true if the given quadratic curve is not flat enough for our * collision detection purposes */ static qboolean CM_NeedsSubdivision(vec3_t a, vec3_t b, vec3_t c) { vec3_t cmid; vec3_t lmid; vec3_t delta; float dist; int i; // calculate the linear midpoint for (i = 0 ; i < 3 ; i++) { lmid[i] = 0.5f * (a[i] + c[i]); } // calculate the exact curve midpoint for (i = 0 ; i < 3 ; i++) { cmid[i] = 0.5f * (0.5f * (a[i] + b[i]) + 0.5f * (b[i] + c[i])); } // see if the curve is far enough away from the linear mid VectorSubtract(cmid, lmid, delta); dist = vec3_length(delta); return dist >= SUBDIVIDE_DISTANCE; }
static void camOrbit(int dx, int dy) { const double radius = 200; double dist; Vec3 v = cam_position; Quaternion o = cam_orientation; Quaternion q, q2; /* We invert the transformation because we are transforming the camera * and not the scene. */ q = quat_conjugate(quat_trackball(dx, dy, radius)); /* The quaternion q gives us an intrinsic transformation, close to unity. * To make it extrinsic, we compute q2 = o * q * ~o */ q2 = quat_multiply(o, quat_multiply(q, quat_conjugate(o))); q2 = quat_normalize(q2); /* As round-off errors accumulate, the distance between the camera and the * target would normally fluctuate. We take steps to prevent that here. */ dist = vec3_length(v); v = quat_transform(q2, v); v = vec3_normalize(v); v = vec3_scale(v, dist); cam_position = v; cam_orientation = quat_multiply(q2, cam_orientation); }
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; }
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; }
/* Calculates if a position is eclipsed. */ bool is_eclipsed(const double pos[3], const double sol[3], double *depth) { double Rho[3], earth[3]; /* Determine partial eclipse */ double sd_earth = ArcSin(xkmper / vec3_length(pos)); vec3_sub(sol, pos, Rho); double sd_sun = ArcSin(sr / vec3_length(Rho)); vec3_mul_scalar(pos, -1, earth); double delta = ArcCos( vec3_dot(sol, earth) / vec3_length(sol) / vec3_length(earth) ); *depth = sd_earth - sd_sun - delta; if (sd_earth < sd_sun) return false; else if (*depth >= 0) return true; else return false; }
inline t_vec3 *vec3_normalize(t_vec3 *v) { float length; length = vec3_length(v); v = vec3_div_f(v, v, length); return (v); }
vec3 vec3_normalize(const vec3 *v) { float len = vec3_length(v); vec3 u; u.x = v->x / len; u.y = v->y / len; u.z = v->z / len; return u; }
/* ======================================================================================================================================= WindingArea ======================================================================================================================================= */ vec_t WindingArea(winding_t *w) { int i; vec3_t d1, d2, cross; vec_t total = 0; for (i = 2; i < w->numpoints; i++) { VectorSubtract(w->p[i - 1], w->p[0], d1); VectorSubtract(w->p[i], w->p[0], d2); vec3_cross(d1, d2, cross); total += 0.5f * vec3_length(cross); } return total; }
float shadowRayIntersectDisk(const 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) { return t; } } return TMAX; }
quat quat_to_axis(const quat *q) { vec3 axis = {q->x, q->y, q->z}; quat tmp = {0.f, 1.f, 0.f, 0.f}; float length; tmp.w = 2 * acos(q->w); //if ((int)(tmp.w) > 0 || (int)(tmp.w) < 0) { length = vec3_length(&axis); tmp.x = q->x / length; tmp.y = q->y / length; tmp.z = q->z / length; tmp.w = tmp.w * (180.f/M_PI); /* To degrees */ //} return tmp; }
/** * @brief Changes the position of client 'other' so that it is directly * below 'player'. The distance is maintained so that sound scaling * will work correctly. */ void SV_RandomizePos(int player, int other) { sharedEntity_t *pent, *oent; vec3_t los; float dist; pent = SV_GentityNum(player); oent = SV_GentityNum(other); VectorCopy(oent->s.pos.trBase, old_origin[other]); origin_changed[other] = 1; // get distance (we need it for correct sound scaling) VectorSubtract(oent->s.pos.trBase, pent->s.pos.trBase, los); dist = vec3_length(los); // set the opponent's position directly below the player VectorCopy(pent->s.pos.trBase, oent->s.pos.trBase); oent->s.pos.trBase[2] -= dist; }
// ---------------------------------------------------------------------------- void IKSolver::DrawDebugGeometry(DebugRenderer* debug, bool depthTest) { // Draws all scene segments for (auto & it : effectorList_) it->DrawDebugGeometry(debug, depthTest); ORDERED_VECTOR_FOR_EACH(&solver_->effector_nodes_list, ik_node_t*, pnode) ik_effector_t* effector = (*pnode)->effector; // Calculate average length of all segments so we can determine the radius // of the debug spheres to draw int chainLength = effector->chain_length == 0 ? -1 : effector->chain_length; ik_node_t* a = *pnode; ik_node_t* b = a->parent; float averageLength = 0.0f; unsigned numberOfSegments = 0; while (b && chainLength-- != 0) { vec3_t v = a->original_position; vec3_sub_vec3(v.f, b->original_position.f); averageLength += vec3_length(v.f); ++numberOfSegments; a = b; b = b->parent; } averageLength /= numberOfSegments; // connect all chained nodes together with lines chainLength = effector->chain_length == 0 ? -1 : effector->chain_length; a = *pnode; b = a->parent; debug->AddSphere( Sphere(Vec3IK2Urho(&a->original_position), averageLength * 0.1f), Color(0, 0, 255), depthTest ); debug->AddSphere( Sphere(Vec3IK2Urho(&a->position), averageLength * 0.1f), Color(255, 128, 0), depthTest ); while (b && chainLength-- != 0) { debug->AddLine( Vec3IK2Urho(&a->original_position), Vec3IK2Urho(&b->original_position), Color(0, 255, 255), depthTest ); debug->AddSphere( Sphere(Vec3IK2Urho(&b->original_position), averageLength * 0.1f), Color(0, 0, 255), depthTest ); debug->AddLine( Vec3IK2Urho(&a->position), Vec3IK2Urho(&b->position), Color(255, 0, 0), depthTest ); debug->AddSphere( Sphere(Vec3IK2Urho(&b->position), averageLength * 0.1f), Color(255, 128, 0), depthTest ); a = b; b = b->parent; } ORDERED_VECTOR_END_EACH }
/* ======================================================================================================================================= CheckWinding ======================================================================================================================================= */ void CheckWinding(winding_t *w) { int i, j; vec_t *p1, *p2; vec_t d, edgedist; vec3_t dir, edgenormal, facenormal; vec_t area; vec_t facedist; if (w->numpoints < 3) { Com_Error(ERR_DROP, "CheckWinding: %i points", w->numpoints); } area = WindingArea(w); if (area < 1) { Com_Error(ERR_DROP, "CheckWinding: %f area", (double)area); } WindingPlane(w, facenormal, &facedist); for (i = 0; i < w->numpoints; i++) { p1 = w->p[i]; for (j = 0; j < 3; j++) { if (p1[j] > MAX_MAP_BOUNDS || p1[j] < -MAX_MAP_BOUNDS) { Com_Error(ERR_DROP, "CheckWinding: MAX_MAP_BOUNDS: %f", (double)p1[j]); } } j = i + 1 == w->numpoints ? 0 : i + 1; // check the point is on the face plane d = DotProduct(p1, facenormal) - facedist; if (d < -ON_EPSILON || d > ON_EPSILON) { Com_Error(ERR_DROP, "CheckWinding: point off plane"); } // check the edge isn't degenerate p2 = w->p[j]; VectorSubtract(p2, p1, dir); if (vec3_length(dir) < ON_EPSILON) { Com_Error(ERR_DROP, "CheckWinding: degenerate edge"); } vec3_cross(facenormal, dir, edgenormal); vec3_norm2(edgenormal, edgenormal); edgedist = DotProduct(p1, edgenormal); edgedist += ON_EPSILON; // all other points must be on front side for (j = 0; j < w->numpoints; j++) { if (j == i) { continue; } d = DotProduct(w->p[j], edgenormal); if (d > edgedist) { Com_Error(ERR_DROP, "CheckWinding: non-convex"); } } } }
void Calculate_Obs(double time, const double pos[3], const double vel[3], geodetic_t *geodetic, vector_t *obs_set) { /* The procedures Calculate_Obs and Calculate_RADec calculate */ /* the *topocentric* coordinates of the object with ECI position, */ /* {pos}, and velocity, {vel}, from location {geodetic} at {time}. */ /* The {obs_set} returned for Calculate_Obs consists of azimuth, */ /* elevation, range, and range rate (in that order) with units of */ /* radians, radians, kilometers, and kilometers/second, respectively. */ /* The WGS '72 geoid is used and the effect of atmospheric refraction */ /* (under standard temperature and pressure) is incorporated into the */ /* elevation calculation; the effect of atmospheric refraction on */ /* range and range rate has not yet been quantified. */ /* The {obs_set} for Calculate_RADec consists of right ascension and */ /* declination (in that order) in radians. Again, calculations are */ /* based on *topocentric* position using the WGS '72 geoid and */ /* incorporating atmospheric refraction. */ double sin_lat, cos_lat, sin_theta, cos_theta, el, azim, top_s, top_e, top_z; double obs_pos[3]; double obs_vel[3]; double range[3]; double rgvel[3]; Calculate_User_PosVel(time, geodetic, obs_pos, obs_vel); vec3_sub(pos, obs_pos, range); vec3_sub(vel, obs_vel, rgvel); double range_length = vec3_length(range); sin_lat=sin(geodetic->lat); cos_lat=cos(geodetic->lat); sin_theta=sin(geodetic->theta); cos_theta=cos(geodetic->theta); top_s=sin_lat*cos_theta*range[0]+sin_lat*sin_theta*range[1]-cos_lat*range[2]; top_e=-sin_theta*range[0]+cos_theta*range[1]; top_z=cos_lat*cos_theta*range[0]+cos_lat*sin_theta*range[1]+sin_lat*range[2]; azim=atan(-top_e/top_s); /* Azimuth */ if (top_s>0.0) azim=azim+pi; if (azim<0.0) azim = azim + 2*M_PI; el=ArcSin(top_z/range_length); obs_set->x=azim; /* Azimuth (radians) */ obs_set->y=el; /* Elevation (radians) */ obs_set->z=range_length; /* Range (kilometers) */ /* Range Rate (kilometers/second) */ obs_set->w = vec3_dot(range, rgvel)/vec3_length(range); obs_set->y=el; /**** End bypass ****/ if (obs_set->y<0.0) obs_set->y=el; /* Reset to true elevation */ }
VEC3 vec3_normalize(VEC3 v) { return vec3_divide(v, vec3_length(v)); }
vec3 *vec3_norm(vec3 *vec) { return vec3_div_float(vec, vec3_length(vec)); }
Vec3 vec3_normalize(Vec3 a) { return vec3_scale(1/vec3_length(a), a); }
/** * return src / src.length */ inline t_vec3 *vec3_unit_vector(t_vec3 *v, const t_vec3 *src) { return (vec3_assign(v, vec3_div_f(v, src, vec3_length(src)))); }