Ejemplo n.º 1
0
// intersects the scene and return for any intersection
bool intersect_shadow(Scene* scene, ray3f ray) {
    // foreach surface
    for(auto surface : scene->surfaces) {
        // if it is a quad
        if(surface->isquad) {
            // compute ray intersection (and ray parameter), continue if not hit
            auto tray = transform_ray_inverse(surface->frame,ray);
            
            // intersect quad
            if(intersect_quad(tray, surface->radius)) return true;
        } else {
            // compute ray intersection (and ray parameter), continue if not hit
            auto tray = transform_ray_inverse(surface->frame,ray);
            
            // intersect sphere
            if(intersect_sphere(tray, surface->radius)) return true;
        }
    }
    // foreach mesh
    for(auto mesh : scene->meshes) {
        // quads are not supported: check for error
        error_if_not(mesh->quad.empty(), "quad intersection is not supported");
        // tranform the ray
        auto tray = transform_ray_inverse(mesh->frame, ray);
        // if it is accelerated
        if(mesh->bvh) {
            if(intersect_shadow(mesh->bvh, 0, tray,
                                [mesh](int tid, ray3f tray){
                                    // grab triangle
                                    auto triangle = mesh->triangle[tid];
                                          
                                    // grab vertices
                                    auto v0 = mesh->pos[triangle.x];
                                    auto v1 = mesh->pos[triangle.y];
                                    auto v2 = mesh->pos[triangle.z];
                            
                                    // return if intersected
                                    return intersect_triangle(tray, v0, v1, v2);})) return true;
        } else {
            // foreach triangle
            for(auto triangle : mesh->triangle) {
                // grab vertices
                auto v0 = mesh->pos[triangle.x];
                auto v1 = mesh->pos[triangle.y];
                auto v2 = mesh->pos[triangle.z];
                
                // intersect triangle
                if(intersect_triangle(tray, v0, v1, v2)) return true;
            }
        }
    }
    
    // no intersection found
    return false;
}
Ejemplo n.º 2
0
// Performs an intersection test between a ray and the given mesh part
// and stores the result in "point".
bool intersect(const Vector3& rayOrigin, const Vector3& rayDirection, const std::vector<Vertex>& vertices, const std::vector<MeshPart*>& parts, Vector3* point)
{
    const float* orig = &rayOrigin.x;
    const float* dir = &rayDirection.x;

    for (unsigned int i = 0, partCount = parts.size(); i < partCount; ++i)
    {
        MeshPart* part = parts[i];

        for (unsigned int j = 0, indexCount = part->getIndicesCount(); j < indexCount; j += 3)
        {
            const float* v0 = &vertices[part->getIndex( j )].position.x;
            const float* v1 = &vertices[part->getIndex(j+1)].position.x;
            const float* v2 = &vertices[part->getIndex(j+2)].position.x;

            float t, u, v;
            if (intersect_triangle(orig, dir, v0, v1, v2, &t, &u, &v))
            {
                // Found an intersection!
                if (point)
                {
                    Vector3 rd(rayDirection);
                    rd.scale(t);
                    Vector3::add(rayOrigin, rd, point);
                }
                return true;
            }
        }
    }

    return false;
}
Ejemplo n.º 3
0
// Performs an intersection test between a ray and the given mesh part and stores the result in "point".
bool intersect(const Vector3& rayOrigin, const Vector3& rayDirection, const std::vector<Vertex>& vertices, const std::vector<MeshPart*>& parts, Vector3* point)
{
    const float* orig = &rayOrigin.x;
    const float* dir = &rayDirection.x;

    float minT = FLT_MAX;

    for (unsigned int i = 0, partCount = parts.size(); i < partCount; ++i)
    {
        MeshPart* part = parts[i];

        for (unsigned int j = 0, indexCount = part->getIndicesCount(); j < indexCount; j += 3)
        {
            const float* v0 = &vertices[part->getIndex( j )].position.x;
            const float* v1 = &vertices[part->getIndex(j+1)].position.x;
            const float* v2 = &vertices[part->getIndex(j+2)].position.x;

            // Perform a quick check (in 2D) to determine if the point is definitely NOT in the triangle
            float xmin, xmax, zmin, zmax;
            xmin = v0[0] < v1[0] ? v0[0] : v1[0]; xmin = xmin < v2[0] ? xmin : v2[0];
            xmax = v0[0] > v1[0] ? v0[0] : v1[0]; xmax = xmax > v2[0] ? xmax : v2[0];
            zmin = v0[2] < v1[2] ? v0[2] : v1[2]; zmin = zmin < v2[2] ? zmin : v2[2];
            zmax = v0[2] > v1[2] ? v0[2] : v1[2]; zmax = zmax > v2[2] ? zmax : v2[2];
            if (orig[0] < xmin || orig[0] > xmax || orig[2] < zmin || orig[2] > zmax)
                continue;

            // Perform a full ray/traingle intersection test in 3D to get the intersection point
            float t, u, v;
            if (intersect_triangle(orig, dir, v0, v1, v2, &t, &u, &v))
            {
                // Found an intersection!
                if (t < minT)
                {
                    minT = t;

                    if (point)
                    {
                        Vector3 rd(rayDirection);
                        rd.scale(t);
                        Vector3::add(rayOrigin, rd, point);
                    }
                }
                //return true;
            }
        }
    }

    return (minT != FLT_MAX);//false;
}
Ejemplo n.º 4
0
void Surf::IntersectLineSegMesh( vec3d & p0, vec3d & p1, vector< double > & t_vals )
{
    BndBox line_box;
    line_box.Update( p0 );
    line_box.Update( p1 );

    if ( !Compare( line_box, m_BBox ) )
    {
        return;
    }

    double tparm, uparm, vparm;
    list< Tri* >::iterator t;
    list <Tri*> triList = m_Mesh.GetTriList();

    vec3d dir = p1 - p0;

    for ( t = triList.begin() ; t != triList.end(); t++ )
    {
        int iFlag = intersect_triangle( p0.v, dir.v,
                                        ( *t )->n0->pnt.v, ( *t )->n1->pnt.v, ( *t )->n2->pnt.v, &tparm, &uparm, &vparm );

        if ( iFlag && tparm > 0.0 )
        {
            //==== Find If T is Already Included ====//
            int dupFlag = 0;
            for ( int j = 0 ; j < ( int )t_vals.size() ; j++ )
            {
                if ( fabs( tparm - t_vals[j] ) < 0.0000001 )
                {
                    dupFlag = 1;
                    break;
                }
            }

            if ( !dupFlag )
            {
                t_vals.push_back( tparm );
            }
        }
    }
}
Ejemplo n.º 5
0
bool
KDTree::intersectRay(int nodeIndex, const Ray& localRay, float& oDistance)
{
    float boxNear, boxFar;
    if(!mNodes[nodeIndex].mBounds.intersect(localRay, boxNear, boxFar)) return false;

    float distance;
    for(int iTri = mNodes[nodeIndex].mTriStart; iTri < (mNodes[nodeIndex].mTriStart + mNodes[nodeIndex].mTriNum); ++iTri) {
        KDTriangle& triangle = mTriangles[iTri];
        if(intersect_triangle(localRay, triangle, distance)) {
            oDistance = distance;
            return true;
        }
    }

    for(unsigned int iChild = 0; iChild < KDTREE_CHILDREN; ++iChild) {
        if(mNodes[nodeIndex].mChildren[iChild] != 0 && intersectRay(mNodes[nodeIndex].mChildren[iChild], localRay, oDistance))
            return true;
    }

    return false;
}
Ejemplo n.º 6
0
// intersects the scene and return the first intrerseciton
intersection3f intersect(Scene* scene, ray3f ray) {
    // create a default intersection record to be returned
    auto intersection = intersection3f();
    // foreach surface
    for(auto surface : scene->surfaces) {
        // if it is a quad
        if(surface->isquad) {
            // compute ray intersection (and ray parameter), continue if not hit
            auto tray = transform_ray_inverse(surface->frame,ray);
            
            // intersect quad
            auto t = 0.0f; auto p = zero3f;
            auto hit = intersect_quad(tray, surface->radius, t, p);
            
            // skip if not hit
            if(not hit) continue;
            
            // check if this is the closest intersection, continue if not
            if(t > intersection.ray_t and intersection.hit) continue;
            
            // if hit, set intersection record values
            intersection.hit = true;
            intersection.ray_t = t;
            intersection.pos = transform_point(surface->frame,p);
            intersection.norm = transform_normal(surface->frame,z3f);
            intersection.texcoord = {0.5f*p.x/surface->radius+0.5f,0.5f*p.y/surface->radius+0.5f};
            intersection.mat = surface->mat;
        } else {
            // compute ray intersection (and ray parameter), continue if not hit
            auto tray = transform_ray_inverse(surface->frame,ray);
            
            // intersect sphere
            auto t = 0.0f;
            auto hit = intersect_sphere(tray, surface->radius, t);
            
            // skip if not hit
            if(not hit) continue;
            
            // check if this is the closest intersection, continue if not
            if(t > intersection.ray_t and intersection.hit) continue;
            
            // compute local point and normal
            auto p = tray.eval(t);
            auto n = normalize(p);
            
            // if hit, set intersection record values
            intersection.hit = true;
            intersection.ray_t = t;
            intersection.pos = transform_point(surface->frame,p);
            intersection.norm = transform_normal(surface->frame,n);
            intersection.texcoord = {(pif+(float)atan2(n.y, n.x))/(2*pif),(float)acos(n.z)/pif};
            intersection.mat = surface->mat;
        }
    }
    // foreach mesh
    for(auto mesh : scene->meshes) {
        // quads are not supported: check for error
        error_if_not(mesh->quad.empty(), "quad intersection is not supported");
        // tranform the ray
        auto tray = transform_ray_inverse(mesh->frame, ray);
        // save auto mesh intersection
        auto sintersection = intersection3f();
        // if it is accelerated
        if(mesh->bvh) {
            sintersection = intersect(mesh->bvh, 0, tray,
               [mesh](int tid, ray3f tray){
                   // grab triangle
                   auto triangle = mesh->triangle[tid];
                   
                   // grab vertices
                   auto v0 = mesh->pos[triangle.x];
                   auto v1 = mesh->pos[triangle.y];
                   auto v2 = mesh->pos[triangle.z];
                   
                   // intersect triangle
                   auto t = 0.0f, u = 0.0f, v = 0.0f;
                   auto hit = intersect_triangle(tray, v0, v1, v2, t, u, v);
                   
                   // skip if not hit
                   if(not hit) return intersection3f();
                   
                   // if hit, set up intersection, trasforming hit data to world space
                   auto sintersection = intersection3f();
                   sintersection.hit = true;
                   sintersection.ray_t = t;
                   sintersection.pos = tray.eval(t);
                   sintersection.norm = normalize(mesh->norm[triangle.x]*u+
                                                  mesh->norm[triangle.y]*v+
                                                  mesh->norm[triangle.z]*(1-u-v));
                   if(mesh->texcoord.empty()) sintersection.texcoord = zero2f;
                   else {
                       sintersection.texcoord = mesh->texcoord[triangle.x]*u+
                                                mesh->texcoord[triangle.y]*v+
                                                mesh->texcoord[triangle.z]*(1-u-v);
                   }
                   sintersection.mat = mesh->mat;
                   return sintersection;
               });
        } else {
            // clear intersection
            sintersection = intersection3f();
            // foreach triangle
            for(auto triangle : mesh->triangle) {
                // grab vertices
                auto v0 = mesh->pos[triangle.x];
                auto v1 = mesh->pos[triangle.y];
                auto v2 = mesh->pos[triangle.z];
                
                // intersect triangle
                auto t = 0.0f, u = 0.0f, v = 0.0f;
                auto hit = intersect_triangle(tray, v0, v1, v2, t, u, v);
                
                // skip if not hit
                if(not hit) continue;
                
                // check if closer then the found hit
                if(t > sintersection.ray_t and sintersection.hit) continue;
                
                // if hit, set up intersection, trasforming hit data to world space
                sintersection.hit = true;
                sintersection.ray_t = t;
                sintersection.pos = tray.eval(t);
                sintersection.norm = normalize(mesh->norm[triangle.x]*u+
                                               mesh->norm[triangle.y]*v+
                                               mesh->norm[triangle.z]*(1-u-v));
                if(mesh->texcoord.empty()) sintersection.texcoord = zero2f;
                else {
                    sintersection.texcoord = mesh->texcoord[triangle.x]*u+
                                             mesh->texcoord[triangle.y]*v+
                                             mesh->texcoord[triangle.z]*(1-u-v);
                }
                sintersection.mat = mesh->mat;
            }
        }
        // if did not hit the mesh, skip
        if(not sintersection.hit) continue;
        // check not first intersection, skip
        if(sintersection.ray_t > intersection.ray_t and intersection.hit) continue;
        // set interserction
        intersection = sintersection;
        // transform by mesh frame
        intersection.pos = transform_point(mesh->frame,sintersection.pos);
        intersection.norm = transform_normal(mesh->frame,sintersection.norm);
        // set material
        intersection.mat = sintersection.mat;
    }
    
    // record closest intersection
    return intersection;
}
Ejemplo n.º 7
0
// intersect triangle without returning bounds
inline bool intersect_triangle(const ray3f& ray, const vec3f& v0, const vec3f& v1, const vec3f& v2) {
    float t, u, v; return intersect_triangle(ray, v0, v1, v2, t, u, v);
}
Ejemplo n.º 8
0
bool ModelGetIsVertexHitLineDirection(Model* model, Vector3D origin, Vector3D direction, Vector3D* hitVector, Vector3D* hitVectorGlobal) {
	Matrix3D modelMatrix;
	//현재 매트릭스 가져오기
	glGetFloatv(GL_MODELVIEW_MATRIX, (float*)&modelMatrix);
	
	Vector3D triangleVector[3];
	Vector3D collosion[3];
	Vector3D* vertex = model->hitVertex;
	for(int i = 0; i < model->hitTrianglePolygonLength; i++) {
		if(i == 0) {
			triangleVector[0] = vertex[0];
			triangleVector[1] = vertex[1];
			triangleVector[2] = vertex[2];
			vertex += 3;
		} else {
			if(model->isTriangleFanMode) {
				triangleVector[0] = model->hitVertex[0];
				triangleVector[1] = triangleVector[2];
				triangleVector[2] = vertex[0];
			} else {
				triangleVector[0] = triangleVector[1];
				triangleVector[1] = triangleVector[2];
				triangleVector[2] = vertex[0];
			}
			vertex += 1;
		}
		collosion[0] = Matrix3DMultiplyVector3D(modelMatrix, triangleVector[0]);
		collosion[1] = Matrix3DMultiplyVector3D(modelMatrix, triangleVector[1]);
		collosion[2] = Matrix3DMultiplyVector3D(modelMatrix, triangleVector[2]);
		double ta, tb, tc;
		double ori[3], dir[3], va[3], vb[3], vc[3];
		ori[0] = (double)origin.x;
		dir[0] = (double)direction.x;
		va[0] = (double)collosion[0].x;
		vb[0] = (double)collosion[1].x;
		vc[0] = (double)collosion[2].x;
		
		ori[1] = (double)origin.y;
		dir[1] = (double)direction.y;
		va[1] = (double)collosion[0].y;
		vb[1] = (double)collosion[1].y;
		vc[1] = (double)collosion[2].y;
		
		ori[2] = (double)origin.z;
		dir[2] = (double)direction.z;
		va[2] = (double)collosion[0].z;
		vb[2] = (double)collosion[1].z;
		vc[2] = (double)collosion[2].z;
		
		bool hit = intersect_triangle(ori, dir, va, vb, vc, &ta, &tb, &tc);
		if(hitVector || hitVectorGlobal) {
			Vector3D collisionVector = Vector3DInit(origin.x + (direction.x * ta), 
													origin.y + (direction.y * ta), 
													origin.z + (direction.z * ta));
			if(hitVectorGlobal) {
				*hitVectorGlobal = Vector3DInit(collisionVector.x, collisionVector.y, collisionVector.z);
			}
			if(hitVector) {
				Vector3D collisionVectorOfModel = Matrix3DMultiplyVector3D(Matrix3DInverte(modelMatrix), collisionVector);
				*hitVector = Vector3DInit(collisionVectorOfModel.x, collisionVectorOfModel.y, collisionVectorOfModel.z);
			}
		}
		if(hit)
			return hit;
	}
	return false;
}
Ejemplo n.º 9
0
/******************************************
* Performs ambient occlusion on vertices  *
******************************************/
void objAmbientOcclusion(object *obj)
{
    int i;
    int j;
    int k = 0;
    int r;
    
    float ray_num;
    float ray_hit;
    
    double vert1[3];
    double vert2[3];
    double vert3[3];
    
    double orig[3];
    double dir[3];
    
    double norm[3];
    
    float light[] = {4,3,-2};
    float mag;
    
    int current_mesh = 0;
    int current_mat = 0;
    int current_vertex = 0;
    int current_normal = 0;
    int current_face = 0;
    
    int test_mesh;  
    int test_face;
    
    mesh        *meshp;
    mesh        *tmeshp;

    face        *facep;
    face        *tfacep;
    vertex      *vertp;
    point3      *normp;
    
    double b[3];
    
    double ot;
    double ou;
    double ov;
    
    
    // boobs (also, normalize the light vector)
    mag = sqrt(light[0]*light[0]+ light[1]*light[1]+ light[2]*light[2]);
    light[0] /= mag;
    light[1] /= mag;
    light[2] /= mag;
    
    
    printf("Ambient occlusion");
    // perform AO
    for(current_mesh = 0; current_mesh < obj->numMeshes; current_mesh++)
    {
        meshp = &obj->meshes[current_mesh];
        
        
        if(strstr(meshp->name, "_noao") == NULL){
            
        //for(current_face = 0; current_face < meshp->numFaces; current_face++)
        //{
            
            for(current_vertex = 0; current_vertex < meshp->numVertices; current_vertex++)
            {
                if((current_vertex & 2) == 2) printf("\rMesh %d/%d\t\t%d percent completed          ", current_mesh+1, obj->numMeshes, lroundf(((float)(current_vertex)/(float)(meshp->numVertices)) * 100.0f));
                
            //facep = &meshp->faces[current_face];
            //vertp = &meshp->vertices[current_vertex];
            
            //vertp = &meshp->vertices[facep->v[current_vertex]-1];
            //normp = &meshp->normals[facep->vn[current_vertex]-1];
            
            vertp = &meshp->vertices[current_vertex];
            
            // now cast a shitload of rays out randomly from the point, towards the normal(ish)
            ray_num = 0;
            ray_hit = 0;
                
            for(r = 0; r < 300; r++)
            {
                ray_num++;
                
                // make this ray start at the current vertex
                // bias in the direction of the normal
                orig[0] = vertp->x + vertp->nx * 0.0001;   
                orig[1] = vertp->y + vertp->ny * 0.0001;  
                orig[2] = vertp->z + vertp->nz * 0.0001;  
                
                norm[0] = vertp->nx;
                norm[1] = vertp->ny;
                norm[2] = vertp->nz;
                
                // generate a random vector inside the unit sphere
                while(1){
                    dir[0] = (   (double)rand() / ((double)(RAND_MAX)+(double)(1)) )*2.0f-1.0f;
                    dir[1] = (   (double)rand() / ((double)(RAND_MAX)+(double)(1)) )*2.0f-1.0f;
                    dir[2] = (   (double)rand() / ((double)(RAND_MAX)+(double)(1)) )*2.0f-1.0f;
                    
                    if(sqrt(dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2]) <= 1.0f)
                        break;
                }
                    
                if(DOT(norm, dir) < 0.0f){
                    dir[0] *= -1;
                    dir[1] *= -1;
                    dir[2] *= -1;
                }

                // test this ray against every other single goddamn triangle
                for(test_mesh = 0; test_mesh < obj->numMeshes; test_mesh++)
                {
                    tmeshp = &obj->meshes[test_mesh];
                    
                    // go through each triangle
                    for(test_face = 0; test_face < tmeshp->numFaces; test_face++)
                    {
                        tfacep = &tmeshp->faces[test_face];
                        
                        vert1[0] = tmeshp->vertices[tfacep->v[0]-1].x;
                        vert1[1] = tmeshp->vertices[tfacep->v[0]-1].y;
                        vert1[2] = tmeshp->vertices[tfacep->v[0]-1].z;
                        
                        vert2[0] = tmeshp->vertices[tfacep->v[1]-1].x;
                        vert2[1] = tmeshp->vertices[tfacep->v[1]-1].y;
                        vert2[2] = tmeshp->vertices[tfacep->v[1]-1].z;
                        
                        vert3[0] = tmeshp->vertices[tfacep->v[2]-1].x;
                        vert3[1] = tmeshp->vertices[tfacep->v[2]-1].y;
                        vert3[2] = tmeshp->vertices[tfacep->v[2]-1].z;
                        if(intersect_triangle(orig, dir, vert1, vert2, vert3, &ot, &ou, &ov) == 1)
                        {
                            // hit!
                            if(ot > -0.0001) 
                            {
                                ray_hit++;
                                goto next_ray;
                            }
                        }
                        
                    }
                    
                }
                
next_ray: ov = 0;
            }
            
            // done testing all rays
            vertp->b = 255 - (ray_hit / ray_num) * 255 ;
            
            i = DOT(norm, light)*64+128;
            if(i> 255) i = 255;
            if(i <0) i = 0;
            
//            vertp->b = i>vertp->b ? vertp->b : i;
            
        }
        printf("\rMesh %d/%d\t\t100 percent completed          ", current_mesh+1, obj->numMeshes);
        }
    }
    
    printf("\n\n");
}