Commit 82e82989 authored by gilles's avatar gilles
Browse files

Ajout de la classe LrGeometryFacet

parent 367c6295
Loading
Loading
Loading
Loading

LrGeometryFacet.cpp

0 → 100644
+422 −0
Original line number Diff line number Diff line
#if defined HAVE_CONFIG_H
#include "config.h"
#endif

/*****************************************************************************
 * class LrGeometryFacet (body)                                              *
 *                                                                           *
 * author : Gilles Subrenat                                                  *
 * creation : Thursday, April 24 2008 (4/24/2008)                            *
 * note :                                                                    *
 *---------------------------------------------------------------------------*
 * $Id$
 *---------------------------------------------------------------------------*
 * Log : see end of file                                                     *
 *****************************************************************************/

#include <cassert>

#include "LrGeometryFacet.h"

using namespace std;

/*---------------------------------------------------------------------------*
 * constructors and destructor                                               *
 *---------------------------------------------------------------------------*/
LrGeometryFacet::LrGeometryFacet()
:
    Super(),
    m_points(),
    m_facets(),
    m_normals(),
    m_minMaxOk(false),
    m_min(),
    m_max()
{
}

LrGeometryFacet::LrGeometryFacet(const LrGeometryFacet &source)
:
    Super(source),
    m_points(source.m_points),
    m_facets(source.m_facets),
    m_normals(source.m_normals),
    m_minMaxOk(source.m_minMaxOk),
    m_min(source.m_min),
    m_max(source.m_max)
{
}

LrGeometryFacet *
LrGeometryFacet::clone() const
{
    return new LrGeometryFacet(*this);
}

LrGeometryFacet::LrGeometryFacet(const vector<LrPoint> &points, const vector<Facet> &facets)
:
    Super(),
    m_points(points),
    m_facets(facets),
    m_normals(points.size(), LrVector::ZERO),
    m_minMaxOk(false),
    m_min(),
    m_max()
{
    for (unsigned int i = 0; i < m_facets.size(); i++)
    {
        LrVector AB(m_points[m_facets[i][0]], m_points[m_facets[i][1]]);
        LrVector AC(m_points[m_facets[i][0]], m_points[m_facets[i][2]]);
        LrVector N = AB ^ AC;
        N.normalize();

        for (unsigned int j = 0; j < m_facets[i].size(); j++)
            m_normals[m_facets[i][j]] += N;
    }

    for (unsigned int i = 0; i < m_normals.size(); i++)
        m_normals[i].normalize();
}

LrGeometryFacet::~LrGeometryFacet()
{
}


/*---------------------------------------------------------------------------*
 * assignement operator(s)                                                   *
 *---------------------------------------------------------------------------*/
LrGeometryFacet &
LrGeometryFacet::operator = (const LrGeometryFacet &source)
{
    if (this == &source)
        return *this;

    Super::operator = (source);

    m_points = source.m_points;
    m_facets = source.m_facets;
    m_normals = source.m_normals;
    m_minMaxOk = source.m_minMaxOk;
    m_min = source.m_min;
    m_max = source.m_max;
    
    return *this;
}


/*---------------------------------------------------------------------------*
 * comparison operator(s)                                                    *
 *---------------------------------------------------------------------------*/
bool
operator == (const LrGeometryFacet &lhs, const LrGeometryFacet &rhs)
{
    return    ((LrGeometryFacet::Super &) lhs == (LrGeometryFacet::Super &) rhs)
           && (lhs.m_points == rhs.m_points)
           && (lhs.m_facets == rhs.m_facets);
}

bool
operator != (const LrGeometryFacet &lhs, const LrGeometryFacet &rhs)
{
    return (! (lhs == rhs));
}


/*---------------------------------------------------------------------------*
 * accessors                                                                 *
 *---------------------------------------------------------------------------*/
int
LrGeometryFacet::getNbPoints() const
{
    return m_points.size();
}

LrPoint
LrGeometryFacet::getPoint(int n) const
{
    assert((n >= 0) && ((unsigned int) n < m_points.size()));
    return m_points[n];
}


int
LrGeometryFacet::getNbFacets() const
{
    return m_facets.size();
}

vector<int>
LrGeometryFacet::getFacet(int n) const
{
    assert((n >= 0) && ((unsigned int) n < m_facets.size()));
    return m_facets[n];
}


/*---------------------------------------------------------------------------*
 * fragments                                                                 *
 *---------------------------------------------------------------------------*/
int
LrGeometryFacet::getNbFragments() const
{
    return getNbFacets();
}
    
/*---------------------------------------------------------------------------*
 * intersections                                                             *
 *---------------------------------------------------------------------------*/
static void xyz2uvTriangle(const LrPoint &P, const LrPoint &A,
                           const LrPoint &B, const LrPoint &C,
                           Real &u, Real &v)
{
    LrVector AB(A, B);
    LrVector AC(A, C);
    LrVector AP(A, P);
    LrVector N = AB ^ AC;
    LrVector ABvAC = AB ^ AC;
    LrVector APvAC = AP ^ AC;
    LrVector ABvAP = AB ^ AP;

    if ((fabs(N.z) > fabs(N.x)) && (fabs(N.z) > fabs(N.y)))
    {
        u = APvAC.z / ABvAC.z;
        v = ABvAP.z / ABvAC.z;
    }
    else if (fabs(N.y) > fabs(N.x))
    {
        u = APvAC.y / ABvAC.y;
        v = ABvAP.y / ABvAC.y;
    }
    else
    {
        u = APvAC.x / ABvAC.x;
        v = ABvAP.x / ABvAC.x;
    }
}

bool
LrGeometryFacet::getIntersection(const LrRay &ray, LrHit *hit, int fragment,
                                 Real minBound, Real maxBound) const
{
    // on ne gère que les triangles pour l'instant
    assert(m_facets[fragment].size() == 3);

    /*
     * A, B, C : les 3 points du triangle
     * N : normale de la facette
     * P : le point d'impact
     * k : distance entre le départ du rayon et P
     * OA : vector entre le départ du rayon et A
     */
    LrPoint A = m_points[m_facets[fragment][0]];
    LrPoint B = m_points[m_facets[fragment][1]];
    LrPoint C = m_points[m_facets[fragment][2]];
    LrVector AB(A, B);
    LrVector BC(B, C);
    LrVector CA(C, A);
    LrVector N;
    LrPoint P;
    Real k;

    N = - AB^CA;
    N.normalize();

    // si on arrive par l'arrière ou qu'on est parallèle à la facette
    // il n'y a pas d'intersection
    if (N * ray.getDirection() > 0)
        return false;

    // distance avec le point d'impact sur le plan
    LrVector OA(ray.getOrigin(), A);
    k = (OA  * N) / (ray.getDirection() * N);
    if ((k < minBound) || (k > maxBound))
        return false;
    P = ray.getPoint(k);

    // le point est-il dans le triangle
    Real u, v;
    xyz2uvTriangle(P, A, B, C, u, v);
    if (   (u < 0.0) || (u > 1.0) || (v < 0.0) || (v > 1.0) || (u+v > 1.0))
        return false;

    /*
    LrVector AP(A, P);
    LrVector BP(B, P);
    LrVector CP(C, P);
    LrVector ABvAP = AB ^ AP;
    LrVector BCvBP = BC ^ BP;
    LrVector CAvCP = CA ^ CP;
    if ((ABvAP * BCvBP < 0) || (ABvAP * CAvCP < 0))
        return false;
    */

    if (hit != NULL)
    {
        hit->point = P;
        hit->distance = k;
        hit->tangent = AB;
        hit->tangent.normalize();
        hit->normal =   (1.0 - u - v) * m_normals[m_facets[fragment][0]]
                      + u * m_normals[m_facets[fragment][1]]
                      + v * m_normals[m_facets[fragment][2]];
        hit->normal.normalize();
        xyz2uv(P, hit->u, hit->v);
    }
    
    return true;
}

/*---------------------------------------------------------------------------*
 * min et max                                                                *
 *---------------------------------------------------------------------------*/
static void updateMin(LrPoint &min, const LrPoint &P)
{
    if (P.x < min.x)
        min.x = P.x;
    if (P.y < min.y)
        min.y = P.y;
    if (P.z < min.z)
        min.z = P.z;
}

static void updateMax(LrPoint &max, const LrPoint &P)
{
    if (P.x > max.x)
        max.x = P.x;
    if (P.y > max.y)
        max.y = P.y;
    if (P.z > max.z)
        max.z = P.z;
}

void
LrGeometryFacet::getMinMax(LrPoint &min, LrPoint &max, int fragment) const
{
    min = m_points[m_facets[fragment][0]];
    max = min;

    for (unsigned int i = 1; i < m_facets[fragment].size(); i++)
    {
        updateMin(min, m_points[m_facets[fragment][i]]);
        updateMax(max, m_points[m_facets[fragment][i]]);
    }
}

void
LrGeometryFacet::getMinMax(LrPoint &min, LrPoint &max) const
{
    if (! m_minMaxOk)
    {
        Super::getMinMax(m_min, m_max);
        m_minMaxOk = true;
    }

    min = m_min;
    max = m_max;
}


/*---------------------------------------------------------------------------*
 * min et max                                                                *
 *---------------------------------------------------------------------------*/
void
LrGeometryFacet::uv2xyz(Real u, Real v, LrPoint *point,
                        LrVector *normal, LrVector *tangent) const
{
    assert(false);
}


/*---------------------------------------------------------------------------*
 * generation de géométries                                                  *
 *---------------------------------------------------------------------------*/
LrGeometryFacet genereGeoFacet()
{
    vector<LrPoint> points;
    vector<vector<int> > facets;
    vector<int> vertices(3);
    
    points.push_back(LrPoint(0, 0, 0));
    points.push_back(LrPoint(1, 0, 0));
    points.push_back(LrPoint(1, 1, 0));
    points.push_back(LrPoint(0, 1, 0));
    points.push_back(LrPoint(0.5, 0.5, 1));

    vertices[0] = 0;
    vertices[1] = 2;
    vertices[2] = 1;
    facets.push_back(vertices);

    vertices[0] = 0;
    vertices[1] = 3;
    vertices[2] = 2;
    facets.push_back(vertices);

    vertices[0] = 0;
    vertices[1] = 1;
    vertices[2] = 4;
    facets.push_back(vertices);

    vertices[0] = 1;
    vertices[1] = 2;
    vertices[2] = 4;
    facets.push_back(vertices);

    vertices[0] = 2;
    vertices[1] = 3;
    vertices[2] = 4;
    facets.push_back(vertices);

    vertices[0] = 3;
    vertices[1] = 0;
    vertices[2] = 4;
    facets.push_back(vertices);

    return LrGeometryFacet(points, facets);
}

LrGeometryFacet genereGeoFacetFile()
{
    FILE *fd = fopen("atuer.lr", "r");
    int nbPoints, nbFacets;
    vector<LrPoint> points;
    vector<vector<int> > facets;
    vector<int> vertices(3);

    if (fd == NULL)
    {
        fprintf(stderr, "erreur ouverture fic lr\n");
        exit(-1);
    }

    fscanf(fd, "%d %d", &nbPoints, &nbFacets);

    for (int i = 0; i < nbPoints; i++)
    {
        Real x, y, z;
        fscanf(fd, REAL_FORMAT, &x);
        fscanf(fd, REAL_FORMAT, &y);
        fscanf(fd, REAL_FORMAT, &z);
        points.push_back(LrPoint(x, y, z));
    }

    for (int i = 0; i < nbFacets; i++)
    {
        int a, b, c;
        fscanf(fd, "%d", &a);
        fscanf(fd, "%d", &b);
        fscanf(fd, "%d", &c);
        vertices[0] = a;
        vertices[1] = b;
        vertices[2] = c;
        facets.push_back(vertices);
    }

    fclose(fd);
    
    return LrGeometryFacet(points, facets);
}
/*****************************************************************************
 * $Log$
 *****************************************************************************/

LrGeometryFacet.h

0 → 100644
+106 −0
Original line number Diff line number Diff line
/*****************************************************************************
 * class LrGeometryFacet (specification)                                     *
 *                                                                           *
 * author : Gilles Subrenat                                                  *
 * creation : Thursday, April 24 2008 (4/24/2008)                            *
 * note :                                                                    *
 *---------------------------------------------------------------------------*
 * $Id$
 *---------------------------------------------------------------------------*
 * Log : see end of file                                                     *
 *****************************************************************************/

#ifndef LRGEOMETRYFACET_H
#define LRGEOMETRYFACET_H

#include <vector>

#include "LrPoint.h"

#include "LrGeometry.h"

class LrGeometryFacet : public LrGeometry
{
public:

    // constructors and destructor
    // ***************************

    typedef LrGeometry Super;

    LrGeometryFacet();
    LrGeometryFacet(const LrGeometryFacet &source);
    LrGeometryFacet * clone() const;
    LrGeometryFacet(const std::vector<LrPoint> &points,
                    const std::vector<std::vector<int> > &facets);

    virtual ~LrGeometryFacet();

    // assignement operator(s)
    // ***********************

    LrGeometryFacet & operator = (const LrGeometryFacet &source);

    // comparison operator(s)
    // **********************

    friend bool operator == (const LrGeometryFacet &lhs, const LrGeometryFacet &rhs);
    friend bool operator != (const LrGeometryFacet &lhs, const LrGeometryFacet &rhs);

    // accessors
    // *********

    int getNbPoints() const;
    LrPoint getPoint(int n) const;

    int getNbFacets() const;
    std::vector<int> getFacet(int n) const;

    // mère
    // ****
    
    virtual int getNbFragments() const;
    virtual bool getIntersection(const LrRay &ray, LrHit *hit, int fragment,
                                 Real minBound=0, Real maxBound=INFINITY) const;
    virtual void getMinMax(LrPoint &min, LrPoint &max, int fragment) const;
    virtual void getMinMax(LrPoint &min, LrPoint &max) const;
    

protected:

    virtual void uv2xyz(Real u, Real v, LrPoint *point,
                        LrVector *normal, LrVector *tangent) const;

    
private:

    // data
    // ****

    typedef std::vector<int> Facet;

    std::vector<LrPoint> m_points;
    std::vector<Facet> m_facets;
    std::vector<LrVector> m_normals;

    mutable bool m_minMaxOk;
    mutable LrPoint m_min, m_max;
};

LrGeometryFacet genereGeoFacet();
LrGeometryFacet genereGeoFacetFile();

#endif

/*
  #include "LrGeometryFacet.h"
  LrMatrix mat_F = LrMatrix::translate(LrVector(0, 0, 0)) * LrMatrix::scale(10);
  LrGeometryFacet geo_F = genereGeoFacetFile();
  LrEntityElementary* facet_F = new LrEntityElementary(mat_F, &geo_F, opt_A);
  list_entities.push_back(facet_F);
  printf("image en cours ligne %3d/%d\n", l, m_image->getHeight());
*/
  
/*****************************************************************************
 * $Log$
 *****************************************************************************/