static void lookAt(const vec3<Type>& eye, const vec3<Type>& center, const vec3<Type>& up) { const vec3<Type> forward = (center - eye).normalized(); const vec3<Type> side = forward.cross(up).normalized(); const vec3<Type> upVector = side.cross(forward); matrix4<Type> m; m.m_data[0][0] = side.x(); m.m_data[1][0] = side.y(); m.m_data[2][0] = side.z(); m.m_data[3][0] = -side.dot(eye); m.m_data[0][1] = upVector.x(); m.m_data[1][1] = upVector.y(); m.m_data[2][1] = upVector.z(); m.m_data[3][1] = -upVector.dot(eye); m.m_data[0][2] = -forward.x(); m.m_data[1][2] = -forward.y(); m.m_data[2][2] = -forward.z(); m.m_data[3][2] = -forward.dot(eye); m.m_data[0][3] = 0; m.m_data[1][3] = 0; m.m_data[2][3] = 0; m.m_data[3][3] = 1; return m; }
//! Refract this vector through a surface with the given normal \a N and ratio of indices of refraction \a eta. vec3<Type> refract(const vec3<Type>& N, Type eta) const { const vec3<Type>& I(*this); const Type k = 1.0 - eta * eta * (1.0 - N.dot(I) * N.dot(I)); return (k < 0.0) ? 0 : eta * I - (eta * N.dot(I) + std::sqrt(k)) * N; }
vec3 mat3::transformVector(const vec3 &v) const { vec3 temp; temp.x = v.dot(getAxisX()); temp.y = v.dot(getAxisY()); temp.z = v.dot(getAxisZ()); return temp; }
/*! Intersect the ray with the given triangle defined by vert0,vert1,vert2. Return true if there is an intersection. If there is an intersection, a vector a_tuv is returned, where t is the distance to the plane in which the triangle lies and (u,v) represents the coordinates inside the triangle. */ bool intersect(const vec3<Type>& vert0, const vec3<Type>& vert1, const vec3<Type>& vert2, vec3<Type>& a_tuv) const { // Tomas Moller and Ben Trumbore. // Fast, minimum storage ray-triangle intersection. // Journal of graphics tools, 2(1):21-28, 1997 // find vectors for two edges sharing vert0 const vec3<Type> edge1 = vert1 - vert0; const vec3<Type> edge2 = vert2 - vert0; // begin calculating determinant - also used to calculate U parameter const vec3<Type> pvec = m_direction.cross(edge2); // if determinant is near zero, ray lies in plane of triangle const Type det = edge1.dot(pvec); if (det < EPS) return false; // calculate distance from vert0 to ray origin const vec3<Type> tvec = m_origin - vert0; // calculate U parameter and test bounds a_tuv[1] = tvec.dot(pvec); if (a_tuv[1] < 0.0 || a_tuv[1] > det) return false; // prepare to test V parameter const vec3<Type> qvec = tvec.cross(edge1); // calculate V parameter and test bounds a_tuv[2] = m_origin.dot(qvec); if (a_tuv[2] < 0.0 || a_tuv[1] + a_tuv[2] > det) return false; // calculate t, scale parameters, ray intersects triangle a_tuv[0] = edge2.dot(qvec); const Type inv_det = (Type)1.0 / det; a_tuv[0] *= inv_det; a_tuv[1] *= inv_det; a_tuv[2] *= inv_det; return true; }
//! Intersect ray and sphere, returning true if there is an intersection. bool intersect(const ray<Type>& r, Type& tmin, Type& tmax) const { const vec3<Type> r_to_s = r.getOrigin() - m_center; //Compute A, B and C coefficients const Type A = r.getDirection().sqrLength(); const Type B = 2.0f * r_to_s.dot(r.getDirection()); const Type C = r_to_s.sqrLength() - m_radius * m_radius; //Find discriminant Type disc = B * B - 4.0 * A * C; // if discriminant is negative there are no real roots if (disc < 0.0) return false; disc = (Type)std::sqrt((double)disc); tmin = (-B + disc) / (2.0 * A); tmax = (-B - disc) / (2.0 * A); // check if we're inside it if ((tmin < 0.0 && tmax > 0) || (tmin > 0 && tmax < 0)) return false; if (tmin > tmax) std::swap(tmin, tmax); return (tmin > 0); }
inline bool line_sphere_intersect(const vec3 &start, const vec3 &end, const vec3 &sp_center, const float sp_radius) { const vec3 diff = end - start; const float len = nya_math::clamp(diff.dot(sp_center - start) / diff.length_sq(), 0.0f, 1.0f); const vec3 inter_pt = start + len * diff; return (inter_pt - sp_center).length_sq() <= sp_radius * sp_radius; }
void plane:: setNormPt ( const vec3& norm, const vec3& ptOnplane ) { offset = norm.dot ( ptOnplane ); normal = norm; }
quat::quat(const vec3 &from,const vec3 &to) { float len=sqrtf(from.length_sq() * to.length_sq()); if(len<0.0001f) { w=1.0f; return; } w=sqrtf(0.5f*(1.0f + from.dot(to)/len)); v=vec3::cross(from,to)/(len*2.0f*w); }
/*! Calculate the shortest line between two lines in 3D Calculate also the values of mua and mub where Pa = P1 + mua (P2 - P1) Pb = P3 + mub (P4 - P3) Return false if no solution exists. Two lines in 3 dimensions generally don't intersect at a point, they may be parallel (no intersections) or they may be coincident (infinite intersections) but most often only their projection onto a plane intersect.. When they don't exactly intersect at a point they can be connected by a line segment, the shortest line segment is unique and is often considered to be their intersection in 3D. */ bool intersect(const ray<Type>& a_ray, Type& mua, Type& mub) const { // Based on code from Paul Bourke // http://astronomy.swin.edu.au/~pbourke const vec3<Type> p1 = m_origin; const vec3<Type> p2 = m_origin + 1.0f * m_direction; const vec3<Type> p3 = a_ray.m_origin; const vec3<Type> p4 = a_ray.m_origin + 1.0f * a_ray.m_direction; const vec3<Type> p13 = p1 - p3; const vec3<Type> p43 = p4 - p3; if (std::abs(p43[0]) < EPS && std::abs(p43[1]) < EPS && std::abs(p43[2]) < EPS) return false; const vec3<Type> p21 = p2 - p1; if (std::abs(p21[0]) < EPS && std::abs(p21[1]) < EPS && std::abs(p21[2]) < EPS) return false; const Type d1343 = p13.dot(p43); const Type d4321 = p43.dot(p21); const Type d1321 = p13.dot(p21); const Type d4343 = p43.dot(p43); const Type d2121 = p21.dot(p21); const Type denom = d2121 * d4343 - d4321 * d4321; if (std::abs(denom) < EPS) return false; const Type numer = d1343 * d4321 - d1321 * d4343; mua = numer / denom; mub = (d1343 + d4321 * mua) / d4343; return true; }
bool prSphere::Hits(const Ray &r) const { const vec3 vec = r.pos-mCenter; const real b = -vec.dot(r.dir); real det = Square(b) - r.dir.dot(r.dir) * vec.sqr_length() + mSqrRadius; if (det > real(0)) { det = det.Sqrt(); const real i1 = b - det, i2 = b + det; if (i2 > r.minDist) { if (mMaterialFront && i1 < r.dist && i1 > r.minDist) { return true; } else if (mMaterialBack && i2 < r.dist) { return true; } } } return false; }
vec3 traceray(const vec3 &origin, const vec3 &dir, int depth) { if (depth == 0) return vec3(); vec3 fcolor = bgcolor; int obj; float t; if ((obj = intersect(origin, dir, t)) != -1) { fcolor = ambient.mult(myobj_mat[obj].color); int light_size = sizeof(light_pos) / sizeof(vec3); int obj_size = sizeof(mysph_pos) / sizeof(vec3); vec3 pos = origin + (dir * t); for (int i = 0; i < light_size; i++) { vec3 lightray = normalize(light_pos[i] - pos); float temp; if (intersect(pos, lightray, temp) == -1) { if (myobj_mat[obj].kd > 0) { vec3 nor = normalize(pos - mysph_pos[obj]); fcolor = fcolor + ((light_color[i] * (nor.dot(lightray)) * myobj_mat[obj].kd).mult(myobj_mat[obj].color)); } if (myobj_mat[obj].ks > 0) { vec3 refDir = mirrorDir(pos, lightray, obj) * (-1); fcolor = fcolor + ((light_color[i] * (dir.dot(refDir)) * myobj_mat[obj].ks).mult(myobj_mat[obj].color)); } } if(myobj_mat[obj].kr > 0) fcolor = fcolor + ((traceray(pos, mirrorDir(pos, dir, obj), depth - 1) * myobj_mat[obj].kr).mult(myobj_mat[obj].color)); } } // note that, before returning the color, the computed color may be rounded to [0.0, 1.0]. fcolor = clamp(fcolor); return fcolor; }
vec3 GlobalLight::applyShading(vec3 fragColor, vec3 fragPos, vec3 normal) { // ambient double ambientStrength = 0.03; vec3 ambient = color * ambientStrength; // diffuse vec3 lightDir = pos - fragPos; lightDir = lightDir.normalize(); vec3 diffuse = color * std::max(0.0, normal.dot(lightDir)); // specular double specularStrength = 0.3; double shininess = 16.0; vec3 viewDir = vec3() - fragPos; viewDir = viewDir.normalize(); lightDir = lightDir * -1; vec3 reflection = lightDir.reflect(normal); vec3 specular = color * pow(std::max(0.0, reflection.dot(viewDir)), shininess) * specularStrength; return fragColor * (ambient + diffuse + specular); }
void prSphere::Intersect(Ray &r) const { const vec3 vec = r.pos-mCenter; const real b = -vec.dot(r.dir); real det = Square(b) - r.dir.dot(r.dir) * vec.sqr_length() + mSqrRadius; if (det > real(0)) { det = det.Sqrt(); const real i1 = b - det; const real i2 = b + det; if (i2 > r.minDist) { if (mMaterialFront && i1 < r.dist && i1 > r.minDist) { //outside r.gState.object = this; r.dist = i1; } else if (mMaterialBack && i2 < r.dist) { //inside r.gState.object = this; r.dist = i2; } return; } } }
//! Return this vector reflected off the surface with the given normal \a N. N should be normalized. vec3<Type> reflect(const vec3<Type>& N) const { const vec3<Type>& I(*this); return I - 2 * N.dot(I) * N; }
int base::intersectRayPlane(const vec3& p, const vec3& d, const vec3& normal, float offset, float& t) { float dn = normal.dot(d); if(dn==0) return 0; t = (offset - normal.dot(p)) / dn; return t>0? 1: 0; }