Bounding Volume Hierarchy ray traversal issues - c++

I've successfully implemented BVH as described in PBRT. This one although has a slightly huge issue - the traversal looks through ALL nodes that intersect the ray, which is wrong (in terms of performance).
So I ended up optimizing the ray traversal, currently I use the version from Aila & Laine implementation of their "Understanding the efficiency of ray traveral on GPU". First, here is the code:
INLINE bool BVH::Traverse(TriangleWoop* prims, Ray* ray, IntersectResult* result)
{
unsigned int todo[32];
unsigned int todoOffset = 0;
unsigned int nodeNum = 0;
bool hit = false;
IntersectResult tmp = IntersectResult();
*(int*)&tmp.data.w = -1;
float tmin = 2e30f;
float4 origin = ray->origin;
float4 direction = ray->direction;
float4 invdir = rcp(direction);
float tmpx = 0.0f, tmpy = 0.0f;
while(true)
{
while(this->nodes[nodeNum].prim_count == 0)
{
tmpx += 0.01f;
tmpy += 0.001f;
float4 c0v1 = (this->nodes[nodeNum + 1].bounds.minPt - origin) * invdir;
float4 c0v2 = (this->nodes[nodeNum + 1].bounds.maxPt - origin) * invdir;
float4 c1v1 = (this->nodes[this->nodes[nodeNum].above_child].bounds.minPt - origin) * invdir;
float4 c1v2 = (this->nodes[this->nodes[nodeNum].above_child].bounds.maxPt - origin) * invdir;
float4 c0n = f4min(c0v1, c0v2);
float4 c0f = f4max(c0v1, c0v2);
float4 c1n = f4min(c1v1, c1v2);
float4 c1f = f4max(c1v1, c1v2);
float n0 = max(c0n.x, max(c0n.y, c0n.z));
float f0 = min(c0f.x, min(c0f.y, c0f.z));
float n1 = max(c1n.x, max(c1n.y, c1n.z));
float f1 = min(c1f.x, min(c1f.y, c1f.z));
bool child0 = (f0 > 0.0f) && (n0 < f0);
bool child1 = (f1 > 0.0f) && (n1 < f1);
child0 &= (n0 < tmin);
child1 &= (n1 < tmin);
unsigned int nodeAddr = this->nodes[nodeNum].above_child;
nodeNum = nodeNum + 1;
if(child0 != child1)
{
if(child1)
{
nodeNum = nodeAddr;
}
}
else
{
if(!child0)
{
if(todoOffset == 0)
{
goto result;
}
nodeNum = todo[--todoOffset];
}
else
{
if(n1 < n0)
{
swap(nodeNum, nodeAddr);
}
todo[todoOffset++] = nodeAddr;
}
}
}
if(this->nodes[nodeNum].prim_count > 0)
{
for(unsigned int i = this->nodes[nodeNum].prim_offset; i < this->nodes[nodeNum].prim_offset + this->nodes[nodeNum].prim_count; i++)
{
const TriangleWoop* tri = &prims[this->indexes[i]];
if(IntersectRayTriangleWoop(ray, tri, &tmp))
{
if(tmp.data.z > 0.0f && tmp.data.z < result->data.z)
{
tmin = tmp.data.z;
result->data.z = tmp.data.z;
result->data.x = tmp.data.x;
result->data.y = tmp.data.y;
*(int*)&result->data.w = this->indexes[i];
hit = true;
}
}
}
}
if(todoOffset == 0)
{
goto result;
}
nodeNum = todo[--todoOffset];
}
result:
result->data.x = tmpx;
result->data.y = tmpy;
return hit;
}
Technically it's just a standard while-while stack ray-bvh traversal. Now to the main problem, look at next image (viewing sponza from outside), in color you can see how much nodes in BVH has been visited (full red = 100, full yellow = 1100):
Next image shows similar situation inside:
As you can see this is kind of a problem - it just has to traverse much more nodes than it's supposed to. Can someone see something wrong with my code? Any advice is welcomed as I'm stucked with this for few days already and can't think off some solution.

Related

Triangulation of polygon with holes using ear clipping algorithm

After parsing the contours from a truetype font file, I generated the points that compose the polygon that I want to triangularize.
These points are generated by merging the different holes into one polygon:
Generated Polygon of the letter A:
As you can see i "merged" the holes by picking two points between the inner and outer polygon with the minimum distance.
This polygon breaks my current implementation of the ear clipping algorithm:
static bool
is_point_in_triangle(triangle Triangle, vec2 Point) {
vec2 AB = Triangle.B - Triangle.A;
vec2 BC = Triangle.C - Triangle.B;
vec2 CA = Triangle.A - Triangle.C;
vec2 AP = Point - Triangle.A;
vec2 BP = Point - Triangle.B;
vec2 CP = Point - Triangle.C;
float Cross1 = cross(AB, AP);
float Cross2 = cross(BC, BP);
float Cross3 = cross(CA, CP);
return (Cross1 <= 0.0f) && (Cross2 <= 0.0f) && (Cross3 <= 0.0f);
}
static triangle_list
triangulate_ear_clip(memory_arena* Arena, polygon SimplePolygon) {
triangle_list List = {};
unsigned int TriangleCount = 0;
triangle* Triangles = allocate_array(Arena, triangle, SimplePolygon.Count - 2);
unsigned int* Indices = allocate_array(Arena, unsigned int, SimplePolygon.Count);
int IndexCount = SimplePolygon.Count;
for(int Index = 0; Index < IndexCount; ++Index) {
Indices[Index] = Index;
}
while(IndexCount > 3) {
for(int Index = 0; Index < IndexCount; ++Index) {
int IndexA = Indices[Index];
int IndexB = Indices[Index ? (Index - 1) : (IndexCount - 1)];
int IndexC = Indices[(Index + 1) % IndexCount];
check((IndexA != IndexB) && (IndexA != IndexC) && (IndexC != IndexB));
vec2 A = SimplePolygon.Elements[IndexA];
vec2 B = SimplePolygon.Elements[IndexB];
vec2 C = SimplePolygon.Elements[IndexC];
vec2 AB = B - A;
vec2 AC = C - A;
check((A != B) && (A != C) && (B != C));
if(cross(AB, AC) >= 0.0f) {
bool IsEar = true;
for(int OtherIndex = 0; OtherIndex < (int)SimplePolygon.Count; ++OtherIndex) {
if((OtherIndex != IndexA) && (OtherIndex != IndexB) && (OtherIndex != IndexC)) {
vec2 D = SimplePolygon.Elements[OtherIndex];
if(is_point_in_triangle(triangle_from(B, A, C), D)) {
IsEar = false;
break;
}
}
}
if(IsEar) {
Triangles[TriangleCount++] = triangle_from(B, A, C);
move(Indices + Index, Indices + Index + 1, sizeof(unsigned int) * (IndexCount - Index - 1));
IndexCount--;
break;
}
}
}
}
check(IndexCount == 3);
check(TriangleCount == SimplePolygon.Count - 3);
Triangles[TriangleCount++] = triangle_from(SimplePolygon.Elements[Indices[0]], SimplePolygon.Elements[Indices[1]], SimplePolygon.Elements[Indices[2]]);
List.Count = TriangleCount;
List.Elements = Triangles;
return List;
}
For some reason cross(AB, AC) is always negative and the loop stalls forever.
I can't figure out why this happens since the polygon should be ok to be triangulated.
I also provided a list of the generated points in the second image link.
Even if some types in the provided code are non-standard they should easily be recognizable, feel free to ask otherwise. memory_arena is just a custom allocator i use.
Thanks for your attention.
PS: I dont want to use a library
The problem was that in is_point_in_triangle() the function was considering points on the outline inside the triangle (and then not consider the triangle as an ear).
This breaks because when merging the polygon and the hole, some points overlap.
I fixed this by removing the =: (Cross1 < 0.0f) && (Cross2 < 0.0f) && (Cross3 < 0.0f) and by doing a special check:
vec2 D = SimplePolygon.Elements[OtherIndex];
if((D != A) && (D != B) && (D != C)) {
if(is_point_in_triangle(triangle_from(B, A, C), D)) {
IsEar = false;
break;
}
}

Gravity and collision detection in SFML

This is my first attempt with SFML and game development, and I'm having issues with the collision and gravity.
I'm making a 2D platformer game using a tilemap system.
Collision seems to be working(slightly) but is very choppy and I just can't seem to get gravity to work properly. I've tried a few different tutorials but I cant get anything working and I'm at a bit of a loss right now.
If someone could point out what I'm missing here it'd be greatly appreciated!!
Heres the code I'm using for these elements:
In PlayerSprite class(attempt at gravity)
PlayerSprite::PlayerSprite(const sf::Vector2f& size) : AnimatedSprite(size)
{
playerPos = (sf::Vector2f(300.0f, 400.0f));
dead = false;
jumpHeight = 5.f;
scale = 50.f;
accelGravity = 0.5f;
maxGravity = 5.f;
velocity.x = 2.0f;
velocity.y = 2.0f;
playerTexture.loadFromFile("gfx/spritemansheet.png");
setSize(sf::Vector2f(48, 48));
setPosition(playerPos);
setTexture(&playerTexture);
}
PlayerSprite::~PlayerSprite()
{
}
void PlayerSprite::update(float dt)
{
onGround = false;
if (input->isKeyDown(sf::Keyboard::A)) {
input->setKeyUp(sf::Keyboard::A);
playerPos.x -= (dt * step) * 5;
setPosition(playerPos);
//currentAnimation = &walkBack;
}
if (input->isKeyDown(sf::Keyboard::D)) {
input->setKeyUp(sf::Keyboard::D);
playerPos.x += (dt * step) * 5;
setPosition(playerPos);
//currentAnimation = &walk;
}
if (input->isKeyDown(sf::Keyboard::W) ) {
input->setKeyUp(sf::Keyboard::Space);
playerPos.x += (dt * step) * 5;
setPosition(playerPos);
//currentAnimation = &jump;
velocity.y = -5.f * -1;
}
if (onGround == false) {
velocity.y += accelGravity;
if (velocity.y > maxGravity) {
velocity.y = maxGravity;
}
}
if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
{
input->setMouseLeftUp(sf::Mouse::Left);
currentAnimation = &attack;
}
}
void PlayerSprite::setInput(Input* newInp)
{
input = newInp;
}
void PlayerSprite::collisionResponse(Sprite* sp)
{
if (velocity.x > 0) {
velocity.x = 0.f;
}
if (velocity.x < 0) {
velocity.x = 0.f;
}
if (velocity.y > 0) {
velocity.y = 0.f;
onGround = true;
}
if (velocity.y < 0) {
velocity.y = 0.f;
}
setPosition(getPosition().x, sp->getPosition().y - getSize().y);
}
Collision Detection in Game.cpp
void Game::update(float dt)
{
player.update(dt);
manager.update(dt);
std::vector<Tile>* world = worldMap.getScene();
for (int i = 0; i < (int)world->size(); i++) {
if ((*world)[i].isAlive()) {
if (checkGroundBounding(&player, &(*world)[i])) {
player.collisionResponse(&(*world)[i]);
}
}
}
void Game::render() {
beginDraw();
window->draw(bg);
window->draw(player);
manager.render(window);
worldMap.render(window);
endDraw();
}
bool Game::checkGroundBounding(PlayerSprite* b1, Tile* b2)
{
//get radius of sprites
float r1 = b1->getSize().x / 2;
float r2 = b2->getSize().x / 2;
float xposb1 = b1->getPosition().x + r1;
float xposb2 = b2->getPosition().x + r2;
float yposb1 = b1->getPosition().y + r1;
float yposb2 = b2->getPosition().y + r2;
if (pow(xposb2 - xposb1, 2) + pow(yposb2 - yposb1, 2) < pow(r1 + r2, 2)) {
return true;
}
return false;
}
you're collision is super wonky, simply set a oldPos variable to your player position, then do your movement code but only for the X axis, if collision is detected, set the position to oldPos, then set oldPos to the current position again, and repeat for the Y axis:
Pseudocode example:
//X axis
oldPos = position
if(leftKey):
position.x -= speed
if(rightKey):
position.x += speed
if(collision):
position = oldPos
//Y axis
oldPos = position
if(upKey):
position.y -= speed
if(downKey):
position.y += speed
if(collision):
position = oldPos
also you can replace your tile iteration with:
for(Tile t : *world){
t->doStuff();
}
I also don't recommend declaring your tile vector in your update function unless you hate performance

2D collisions check between 3 and more objects

i've got a problem on my collision Check Algorithm.
The problem is when i try to resolve collisions between 3 objects, 1 of them is still not colliding and not resolving collisions, here's the code:
void check_collisions(engine_t* engine)
{
for (int i = 0; i < engine->actor_count; i++)
{
actor_t* first = (actor_t*)engine->collision_pairs->data[i];
collider_t* a = (collider_t*)get_component_by_name(first, "collider");
for(int j = 0; j < engine->actor_count; j++)
{
actor_t* second = (actor_t*)engine->collision_pairs->data[j];
if(second == first)
continue;
collider_t* b = (collider_t*)get_component_by_name(second, "collider");
hit_state_t hit = aabb(a, b);
resolve_collisions(a, b, hit.normal);
}
}
}
The problem is that when for example: i have A, B, C
A could collide with B and C at the same frame time, it seems that when more object are colliding the first one (first) will not be calculated anymore.. any idea?
void resolve_collisions(collider_t* a, collider_t* b, vec2_t normal)
{
//Stop rigidbody
vec2_t position = a->owner->transform.position;
vec2_t position2 = b->owner->transform.position;
rigid_body_t* rb = (rigid_body_t*)get_component_by_name(a->owner, "rigid_body");
// if(!rb) { SDL_Log("rigid_body not while resolving collisions"); return; }
//hit from dx
if (normal.x > 0.0f && position.x < b->owner->transform.position.x + b->size.x)
{
rb->velocity.x = 0.0f;
// SDL_Log("collided dx");
position.x = (b->owner->transform.position.x + b->size.x) + 0.7f;
}
//hit from sx
if (normal.x < 0.0f && position.x + a->size.x > b->owner->transform.position.x)
{
rb->velocity.x = 0.0f;
float offset = b->size.x - a->size.x;
float offset2 = a->size.x - b->size.x;
// SDL_Log("collided sx");
position.x = (b->owner->transform.position.x - b->size.x) + offset;
position2.x = (a->owner->transform.position.x - a->size.x) + offset2;
}
//hit from top
if (normal.y < 0.0f && position.y + a->size.y > b->owner->transform.position.y)
{
rb->velocity.y = 0.0f;
float offset = b->size.y - a->size.y;
position.y = (b->owner->transform.position.y - b->size.y) + offset;
}
//hit from bottom
if (normal.y > 0.0f && position.y < b->owner->transform.position.y + b->size.y)
{
rb->velocity.y = 0.0f;
// SDL_Log("collided bottom");
position.y = (b->owner->transform.position.y + b->size.y) + 0.7f;
}
//change pos
a->owner->transform.position = position;
}
any help would be much appreciated!
-Thanks

C++ - Pathfinding corner problems

So i'm trying to make characters walk around a tile map, using the following code. tilePath returns a vector of tiles in the path to their target, then their code makes them advance to the next tile in the vector. The problem is that when they get to a corner, they try to move around it too early and end up getting stuck on the wall.
The white squares are walkable tiles, the gray is a wall, and the red is a character. If the character gets to the corner walkable tile, it tries to move around the wall too soon, thus getting blocked by it. They usually end up making it around, but its very noticeable that they've gotten stuck on the wall for a bit.
std::vector<Tile*> TileMap::tilePath(Tile *p_start, Tile *p_end)
{
std::vector<Tile*> path;
std::vector<Tile*> open;
std::map<uint64_t, Tile*> closed;
p_start->previousTile = p_start;
p_start->g = 0;
p_start->h = 0;
p_start->f = 0;
float g, h, f, cost;
Tile* current = p_start;
Tile* previous = nullptr;
while(current != p_end) {
current->m_sprite.setColor(sf::Color(255,255,255,255));
for(auto neighbor : getNeighbors(current))
{
if(neighbor == current) continue;
if(!(neighbor->m_walkable)) continue;
previous = current;
if(tileTrace(current->previousTile, neighbor)) {
cost = manhattan(current->previousTile, neighbor);
g = current->previousTile->g + cost;
h = manhattan(neighbor, p_end);
f = g + h;
previous = current->previousTile;
} else {
cost = ((current->m_coordinates.x != neighbor->m_coordinates.x) && (current->m_coordinates.y != neighbor->m_coordinates.y)) ? 1.4 : 1;
g = current->g + cost;
h = manhattan(neighbor, p_end);
f = g + h;
}
if(std::find(open.begin(), open.end(), neighbor) != open.end() ||
closed.find(neighbor->key()) != closed.end()) {
if(neighbor->f > f) {
neighbor->f = f;
neighbor->g = g;
neighbor->h = h;
neighbor->previousTile = previous;
}
} else {
neighbor->f = f;
neighbor->g = g;
neighbor->h = h;
neighbor->previousTile = previous;
for(auto i = open.begin(); i != open.end(); i++)
{
if(neighbor->f < (*i)->f) {
open.insert(i, neighbor);
break;
}
}
open.push_back(neighbor);
}
}
closed[current->key()] = current;
if(open.size() == 0) {
return std::vector<Tile*>();
}
current = open.front();
open.erase(open.begin());
}
current = p_end;
path.insert(path.begin(), current);
while(current->previousTile != p_start)
{
current->m_sprite.setColor(sf::Color(255,0,0,255));
path.insert(path.begin(), current->previousTile);
current = current->previousTile;
}
return path;
}
bool TileMap::tileTrace(Tile* p_start, Tile* p_end)
{
int sx = p_start->m_coordinates.x;
int sy = p_start->m_coordinates.y;
int ex = p_end->m_coordinates.x;
int ey = p_end->m_coordinates.y;
int dx = fabsf(ex - sx);
int dy = fabsf(ey - sy);
int _x = sx, _y = sy;
int x_inc = (ex > sx) ? 1 : -1;
int y_inc = (ey > sy) ? 1 : -1;
int error = dx - dy;
for(int n = dx + dy; n > 0; n--) {
Tile& t = m_tiles[_y * m_width + _x];
if(!(t.m_walkable)) return false;
if(error < 0) {
_y += y_inc;
error += dx;
} else {
_x += x_inc;
error -= dy;
}
}
return true;
}
What can I do to make this a little smoother? I'd rather the characters not bounce off of the walls either.
Update:
I've added this to see if the character is moving towards or away from the tile it's "on". Granted it's more effective in getting the character around corners, but it sometimes gives a little strange movement.
sf::Vector2f d = start->m_position - p_object->m_position;
float dot = p_object->m_velocity.x * d.x + p_object->m_velocity.y * d.y;
if(dot > 0) {
path.insert(path.begin(), start);
}

ray tracing triangular mesh objects

I'm trying to write a ray tracer for any objects formed of triangular meshes. I'm using an external library to load a cube from .ply format and then trace it down. So far, I've implemented most of the tracer, and now I'm trying to test it with a single cube, but for some reason all I get on the screen is a red line. I've tried several ways to fix it but I simply can't figure it out anymore. For this primary test, I'm only creating primary rays, and if they hit my cube, then I color that pixel to the cube's diffuse color and return. For checking ray-object intersections, I am going through all the triangles that form that object and return the distance to the closest one. It would be great if you could have a look at the code and tell me what could have gone wrong and where. I would greatly appreciate it.
Ray-Triangle intersection:
bool intersectTri(const Vec3D& ray_origin, const Vec3D& ray_direction, const Vec3D& v0, const Vec3D& v1, const Vec3D& v2, double &t, double &u, double &v) const
{
Vec3D edge1 = v1 - v0;
Vec3D edge2 = v2 - v0;
Vec3D pvec = ray_direction.cross(edge2);
double det = edge1.dot(pvec);
if (det > - THRESHOLD && det < THRESHOLD)
return false;
double invDet = 1/det;
Vec3D tvec = ray_origin - v0;
u = tvec.dot(pvec)*invDet;
if (u < 0 || u > 1)
return false;
Vec3D qvec = tvec.cross(edge1);
v = ray_direction.dot(qvec)*invDet;
if (v < 0 || u + v > 1)
return false;
t = edge2.dot(qvec)*invDet;
if (t < 0)
return false;
return true;
}
//Object intersection
bool intersect(const Vec3D& ray_origin, const Vec3D& ray_direction, IntersectionData& idata, bool enforce_max) const
{
double tClosest;
if (enforce_max)
{
tClosest = idata.t;
}
else
{
tClosest = TMAX;
}
for (int i = 0 ; i < indices.size() ; i++)
{
const Vec3D v0 = vertices[indices[i][0]];
const Vec3D v1 = vertices[indices[i][1]];
const Vec3D v2 = vertices[indices[i][2]];
double t, u, v;
if (intersectTri(ray_origin, ray_direction, v0, v1, v2, t, u, v))
{
if (t < tClosest)
{
idata.t = t;
tClosest = t;
idata.u = u;
idata.v = v;
idata.index = i;
}
}
}
return (tClosest < TMAX && tClosest > 0) ? true : false;
}
Vec3D trace(World world, Vec3D &ray_origin, Vec3D &ray_direction)
{
Vec3D objColor = world.background_color;
IntersectionData idata;
double coeff = 1.0;
int depth = 0;
double tClosest = TMAX;
Object *hitObject = NULL;
for (unsigned int i = 0 ; i < world.objs.size() ; i++)
{
IntersectionData idata_curr;
if (world.objs[i].intersect(ray_origin, ray_direction, idata_curr, false))
{
if (idata_curr.t < tClosest && idata_curr.t > 0)
{
idata.t = idata_curr.t;
idata.u = idata_curr.u;
idata.v = idata_curr.v;
idata.index = idata_curr.index;
tClosest = idata_curr.t;
hitObject = &(world.objs[i]);
}
}
}
if (hitObject == NULL)
{
return world.background_color;
}
else
{
return hitObject->getDiffuse();
}
}
int main(int argc, char** argv)
{
parse("cube.ply");
Vec3D diffusion1(1, 0, 0);
Vec3D specular1(1, 1, 1);
Object cube1(coordinates, connected_vertices, diffusion1, specular1, 0, 0);
World wrld;
// Add objects to the world
wrld.objs.push_back(cube1);
Vec3D background(0, 0, 0);
wrld.background_color = background;
// Set light color
Vec3D light_clr(1, 1, 1);
wrld.light_colors.push_back(light_clr);
// Set light position
Vec3D light(0, 64, -10);
wrld.light_positions.push_back(light);
int width = 128;
int height = 128;
Vec3D *image = new Vec3D[width*height];
Vec3D *pixel = image;
// Trace rays
for (int y = -height/2 ; y < height/2 ; ++y)
{
for (int x = -width/2 ; x < width/2 ; ++x, ++pixel)
{
Vec3D ray_dir(x+0.5, y+0.5, -1.0);
ray_dir.normalize();
Vec3D ray_orig(0.5*width, 0.5*height, 0.0);
*pixel = trace(wrld, ray_orig, ray_dir);
}
}
savePPM("./test.ppm", image, width, height);
return 0;
}
I've just ran a test case and I got this:
for a unit cube centered at (0,0, -1.5) and scaled on the X and Y axis by 100. It seems that there is something wrong with the projection, but I can't really tell exactly what from the result. Also, shouldn't, in this case (cube is centered at (0,0)) the final object also appear in the middle of the picture?
FIX: I fixed the centering problem by doing ray_dir = ray_dir - ray_orig before normalizing and calling the trace function. Still, the perspective seems to be plain wrong.
I continued the work and now I started implementing the diffuse reflection according to Phong.
Vec3D trace(World world, Vec3D &ray_origin, Vec3D &ray_direction)
{
Vec3D objColor = Vec3D(0);
IntersectionData idata;
double coeff = 1.0;
int depth = 0;
do
{
double tClosest = TMAX;
Object *hitObject = NULL;
for (unsigned int i = 0 ; i < world.objs.size() ; i++)
{
IntersectionData idata_curr;
if (world.objs[i].intersect(ray_origin, ray_direction, idata_curr, false))
{
if (idata_curr.t < tClosest && idata_curr.t > 0)
{
idata.t = idata_curr.t;
idata.u = idata_curr.u;
idata.v = idata_curr.v;
idata.index = idata_curr.index;
tClosest = idata_curr.t;
hitObject = &(world.objs[i]);
}
}
}
if (hitObject == NULL)
{
return world.background_color;
}
Vec3D newStart = ray_origin + ray_direction*idata.t;
// Compute normal at intersection by interpolating vertex normals (PHONG Idea)
Vec3D v0 = hitObject->getVertices()[hitObject->getIndices()[idata.index][0]];
Vec3D v1 = hitObject->getVertices()[hitObject->getIndices()[idata.index][1]];
Vec3D v2 = hitObject->getVertices()[hitObject->getIndices()[idata.index][2]];
Vec3D n1 = hitObject->getNormals()[hitObject->getIndices()[idata.index][0]];
Vec3D n2 = hitObject->getNormals()[hitObject->getIndices()[idata.index][1]];
Vec3D n3 = hitObject->getNormals()[hitObject->getIndices()[idata.index][2]];
// Vec3D N = n1 + (n2 - n1)*idata.u + (n3 - n1)*idata.v;
Vec3D N = v0.computeFaceNrm(v1, v2);
if (ray_direction.dot(N) > 0)
{
N = N*(-1);
}
N.normalize();
Vec3D lightray_origin = newStart;
for (unsigned int itr = 0 ; itr < world.light_positions.size() ; itr++)
{
Vec3D lightray_dir = world.light_positions[0] - newStart;
lightray_dir.normalize();
double cos_theta = max(N.dot(lightray_dir), 0.0);
objColor.setX(objColor.getX() + hitObject->getDiffuse().getX()*hitObject->getDiffuseReflection()*cos_theta);
objColor.setY(objColor.getY() + hitObject->getDiffuse().getY()*hitObject->getDiffuseReflection()*cos_theta);
objColor.setZ(objColor.getZ() + hitObject->getDiffuse().getZ()*hitObject->getDiffuseReflection()*cos_theta);
return objColor;
}
depth++;
} while(coeff > 0 && depth < MAX_RAY_DEPTH);
return objColor;
}
When I reach an object with the primary ray, I send another ray to the light source positioned at (0,0,0) and return the color according to the Phong illumination model for diffuse reflection, but the result is really not the expected one: http://s15.postimage.org/vc6uyyssr/test.png. The cube is a unit cube centered at (0,0,0) and then translated by (1.5, -1.5, -1.5). From my point of view, the left side of the cube should get more light and it actually does. What do you think of it?