bool EQPhysics::GetRaycastClosestHit(const glm::vec3 & src, const glm::vec3 & dest, glm::vec3 &hit, std::string *name, EQPhysicsFlags flag) const { btVector3 src_bt(src.x, src.y, src.z); btVector3 dest_bt(dest.x, dest.y, dest.z); btCollisionWorld::ClosestRayResultCallback ray_hit(src_bt, dest_bt); ray_hit.m_collisionFilterGroup = (short)flag; ray_hit.m_collisionFilterMask = (short)flag; ray_hit.m_flags |= 1; imp->collision_world->rayTest(src_bt, dest_bt, ray_hit); if (ray_hit.hasHit()) { hit.x = ray_hit.m_hitPointWorld.x(); hit.y = ray_hit.m_hitPointWorld.y(); hit.z = ray_hit.m_hitPointWorld.z(); if (name) { GetEntityHit(ray_hit.m_collisionObject, *name); } return true; } hit.x = 0.0f; hit.y = 0.0f; hit.z = 0.0f; return false; }
/* * Trace a ray, calculating the color of this ray. * This function is called recursively for recursive light. * * @param scene The scene object, which contains all geometries information. * @param recursion The level of recursive light. If the level is larger or * equal to 4, stop recursion. * @param ray_dir Direction vector of ray. * @param ray_pos Start point of ray. * @param tMin Minimum legal time cost for this ray. * @param tMax Maximum legal time cost for this ray. * * @return The color of this ray. */ Color3 Raytracer::trace_ray(Scene const*scene, // geometries const int recursion, // recursion level const Vector3 &ray_dir, const Vector3 &ray_pos, // ray const float tMin, const float tMax // ray range ) { // if this function go beyond the last recursive level, stop and return black color. if (recursion <= 0) return Color3(0, 0, 0); // intersection point information HitVertexInfor hit_vertex; // if not hit any geometry, return background color bool bHit = ray_hit(scene, ray_dir, ray_pos, tMin, tMax, hit_vertex); if (!bHit) return scene->background_color; // if hit, compute color and return it Color3 DI_light (0, 0, 0); Color3 reflected_light(0, 0, 0); Color3 refracted_light(0, 0, 0); // 1. direct illumination if (hit_vertex.refractive_index == 0) DI_light = calculate_DI_light(scene, hit_vertex); // 2. reflection light if (hit_vertex.specular != Color3(0, 0, 0)) // avoid non-necessary reflection calculation { // reflection ray direction Vector3 rfl_ray_dir = normalize( ray_dir - 2 * dot(ray_dir, hit_vertex.normal) * hit_vertex.normal); reflected_light = hit_vertex.specular * hit_vertex.tex_color * trace_ray(scene, recursion-1, rfl_ray_dir, hit_vertex.position, SLOPE_FACTOR, 1000000); } if (hit_vertex.refractive_index == 0) // avoid non-necessary refraction calculation return DI_light + reflected_light; // 3. refraction light Vector3 rfr_ray_dir; // refractive ray direction float R; if (refraction_happened(scene, ray_dir, hit_vertex, rfr_ray_dir, R)) refracted_light = hit_vertex.tex_color * trace_ray(scene, recursion-1, rfr_ray_dir, hit_vertex.position, SLOPE_FACTOR, 1000000); return DI_light + R * reflected_light + (1-R) * refracted_light; }
/* * Calculate direct illumination light. * * @param scene The scene object, which contains all geometries * information. * @param hit_vertex A struct storing all useful intersection point * information. * * @return Direct illumination color. */ Color3 Raytracer::calculate_DI_light(Scene const*scene, const HitVertexInfor &hit_vertex) { // ambient light Color3 ambient_light = hit_vertex.ambient * scene->ambient_light; // accumulate all point light diffuse components Color3 diffuse_light(0, 0, 0); const PointLight* pPointLights = scene->get_lights(); for (size_t i=0; i<scene->num_lights(); i++) { // point light PointLight point_light = pPointLights[i]; // ray from hit point to light Vector3 shadow_ray_pos = hit_vertex.position; Vector3 shadow_ray_dir = point_light.position - shadow_ray_pos; real_t distance = length(shadow_ray_dir); shadow_ray_dir = normalize(shadow_ray_dir); // shadow ray hit test HitVertexInfor tmp_hit_vertex; // temp variable, didn't use it actually bool bExistObstacle = ray_hit(scene, shadow_ray_dir, shadow_ray_pos, distance/1000000, distance, tmp_hit_vertex); // if did not hit other geometry, accumulate diffuse light if (!bExistObstacle) { diffuse_light += point_light.get_attenuation_color(distance) * hit_vertex.diffuse * std::max(dot(hit_vertex.normal, shadow_ray_dir), 0.0f); } } // final direct illumination is multiplication of texture color and diffuse light return hit_vertex.tex_color * (ambient_light + diffuse_light); }