Subversion Repositories gelsvn

Rev

Rev 348 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include "mesh.hpp"
#include "scene.hpp"

#include <Geometry/obj_load.h>

using namespace CGLA;
using namespace Geometry;

extern scene* current;

mesh::mesh(void)
{
        msh_ = new TriMesh;
        tangents_ = new IndexedFaceSet;
        mat_ = 0;
        exitance_ = Vec3f(0.f);
}

mesh::mesh(const std::string& fn)
{
        msh_ = new TriMesh;
        tangents_ = new IndexedFaceSet;
        mat_ = 0;
        exitance_ = Vec3f(0.f);

        TriMesh msh;
        obj_load(fn, msh);
        set_trimesh(msh);
}

mesh::~mesh(void)
{
        delete tangents_;
        delete msh_;
}

const CGLA::Vec3f& mesh::triangle_normal(size_t i) const
{
        return triangle_normals_.at(i);
}

const TriMesh& mesh::get_trimesh(void) const
{
        return *msh_;
}

void mesh::set_trimesh(const TriMesh& tm)
{
        *msh_ = tm;
        
        msh_->compute_normals();
        //
        //int tris = msh_->geometry.no_faces();

        //std::vector<Vec3f> tan1;
        //tan1.resize(tris);
        //triangle_normals_.resize(tris);
        
        //for (int t=0; t<tris; t++)
        //{
        //      const Vec3i& f  = msh_->geometry.face(t);
        //      const Vec3f p0 = msh_->geometry.vertex(f[0]);
        //      const Vec3f a  = msh_->geometry.vertex(f[1]) - p0;
        //      const Vec3f b  = msh_->geometry.vertex(f[2]) - p0;
        //      Vec3f tri_normal = cross(a,b);
        //      float l = sqr_length(tri_normal);
        //      if(l > 0.0f)
        //              tri_normal /= sqrt(l);
        //      triangle_normals_[t] = trs_.mul_3D_vector(tri_normal);

        //}
#if 0
        if (msh_->texcoords.no_faces() == 0)
                return;

        for (long a = 0; a < triangleCount; a++)
        {
                long i1 = triangle->index[0];
                long i2 = triangle->index[1];
                long i3 = triangle->index[2];

                const Point3D& v1 = vertex[i1];
                const Point3D& v2 = vertex[i2];
                const Point3D& v3 = vertex[i3];

                const Point2D& w1 = texcoord[i1];
                const Point2D& w2 = texcoord[i2];
                const Point2D& w3 = texcoord[i3];

                float x1 = v2.x - v1.x;
                float x2 = v3.x - v1.x;
                float y1 = v2.y - v1.y;
                float y2 = v3.y - v1.y;
                float z1 = v2.z - v1.z;
                float z2 = v3.z - v1.z;

                float s1 = w2.x - w1.x;
                float s2 = w3.x - w1.x;
                float t1 = w2.y - w1.y;
                float t2 = w3.y - w1.y;

                float r = 1.0F / (s1 * t2 - s2 * t1);
                Vector3D sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r,
                        (t2 * z1 - t1 * z2) * r);
                Vector3D tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r,
                        (s1 * z2 - s2 * z1) * r);

                tan1[i1] += sdir;
                tan1[i2] += sdir;
                tan1[i3] += sdir;

                tan2[i1] += tdir;
                tan2[i2] += tdir;
                tan2[i3] += tdir;

                triangle++;
        }
#endif

}

const material* mesh::get_material(void) const
{
        return mat_;
}

void mesh::set_material(const material* m)
{
        mat_ = m;
}

bool mesh::sample(const ray& r, 
                                  const hit_info& hi, 
                                  Vec3f& Li, 
                                  Vec3f& w) const
{
        //skip non-emitters
        if (intensity(exitance_) == 0.f)
                return false;

        //pick a random face
        int face = rand() % msh_->geometry.no_faces();
        float pface = 1.f / float(msh_->geometry.no_faces());

        //pick a random position in triangle
        float r1 = std::sqrt(random());
        float r2 = random();
        Vec3f barycentric(1.f - r1, (1.f - r2) * r1, r1 * r2);
        
        //find position
        Vec3i fidx = msh_->geometry.face(face);
        Vec3f vertices[3];
        Vec3f light_pos(0.f);
        for (int i=0; i<3; ++i)
        {
                vertices[i] = msh_->geometry.vertex(fidx[i]);
                light_pos += barycentric[i] * msh_->geometry.vertex(fidx[i]);
        }

        light_pos = trs_.mul_3D_point(light_pos);

        float parea = 2.f / length(cross(vertices[2]-vertices[1], 
                vertices[0]-vertices[1]));

        //find normal
        Vec3i nidx = msh_->normals.face(face);
        Vec3f light_normal(0.f);
        for (int i=0; i<3; ++i)
                light_normal += barycentric[i] * msh_->normals.vertex(nidx[i]);
        light_normal = trs_.mul_3D_vector(light_normal);
        light_normal.normalize();

        //find w
        w = normalize(light_pos - hi.position);
        //float costheta1 = dot(hi.shading_normal, w);
        //if (costheta1 < 0.f)
        //      return false;

        float costheta2 = dot(light_normal, -w);
        if (costheta2 < 0.f)
                return false;

        float d2 = sqr_length(light_pos - hi.position);

        //trace shadow feeler..
        ray s;
        s.origin = hi.position + epsilon * w;
        s.direction = w;
        s.distance = std::sqrt(d2) - 2.f * epsilon;
        s.depth = r.depth + 1;
        if (current->intersect(s))
                return false;

        //compute emitted
        Li = exitance_ / float(M_PI) * costheta2 / (d2 * pface * parea);

        return true;
}

Vec3f mesh::exitance(void) const
{
        return exitance_;
}

void mesh::set_exitance(const CGLA::Vec3f& E)
{
        exitance_ = E;
}

//02566 framework, Anders Wang Kristensen, awk@imm.dtu.dk, 2007

Generated by GNU Enscript 1.6.6.