void ConvexPolyhedron3<Real>::Create (const V3Array& rakPoint,
    const IArray& raiConnect)
{
    assert( rakPoint.size() >= 4 && raiConnect.size() >= 4 );

    int iVQuantity = (int)rakPoint.size();
    int iTQuantity = (int)raiConnect.size()/3;
    int iEQuantity = iVQuantity + iTQuantity - 2;
    Reset(iVQuantity,iEQuantity,iTQuantity);
    m_akPoint = rakPoint;

    // Copy polyhedron points into vertex array.  Compute centroid for use in
    // making sure the triangles are counterclockwise oriented when viewed
    // from the outside.
    ComputeCentroid();

    // get polyhedron edge and triangle information
    for (int iT = 0, iIndex = 0; iT < iTQuantity; iT++)
    {
        // get vertex indices for triangle
        int iV0 = raiConnect[iIndex++];
        int iV1 = raiConnect[iIndex++];
        int iV2 = raiConnect[iIndex++];

        // make sure triangle is counterclockwise
        Vector3<Real>& rkV0 = m_akPoint[iV0];
        Vector3<Real>& rkV1 = m_akPoint[iV1];
        Vector3<Real>& rkV2 = m_akPoint[iV2];

        Vector3<Real> kDiff = m_kCentroid - rkV0;
        Vector3<Real> kE1 = rkV1 - rkV0;
        Vector3<Real> kE2 = rkV2 - rkV0;
        Vector3<Real> kNormal = kE1.Cross(kE2);
        Real fLength = kNormal.Length();
        if ( fLength > Math<Real>::EPSILON )
        {
            kNormal /= fLength;
        }
        else
        {
            kNormal = kDiff;
            kNormal.Normalize();
        }

        Real fDistance = kNormal.Dot(kDiff);

        if ( fDistance < (Real)0.0 )
        {
            // triangle is counterclockwise
            Insert(iV0,iV1,iV2);
        }
        else
        {
            // triangle is clockwise
            Insert(iV0,iV2,iV1);
        }
    }

    UpdatePlanes();
}
bool ConvexPolyhedron3<Real>::ComputeSilhouette (V3Array& rkTerminator,
    const Vector3<Real>& rkEye, const Plane3<Real>& rkPlane,
    const Vector3<Real>& rkU, const Vector3<Real>& rkV,
    V2Array& rkSilhouette)
{
    Real fEDist = rkPlane.DistanceTo(rkEye);  // assert:  fEDist > 0

    // closest planar point to E is K = E-dist*N
    Vector3<Real> kClosest = rkEye - fEDist*rkPlane.GetNormal();

    // project polyhedron points onto plane
    for (int i = 0; i < (int)rkTerminator.size(); i++)
    {
        Vector3<Real>& rkPoint = rkTerminator[i];

        Real fVDist = rkPlane.DistanceTo(rkPoint);
        if ( fVDist >= fEDist )
        {
            // cannot project vertex onto plane
            return false;
        }

        // compute projected point Q
        Real fRatio = fEDist/(fEDist-fVDist);
        Vector3<Real> kProjected = rkEye + fRatio*(rkPoint - rkEye);

        // compute (x,y) so that Q = K+x*U+y*V+z*N
        Vector3<Real> kDiff = kProjected - kClosest;
        rkSilhouette.push_back(Vector2<Real>(rkU.Dot(kDiff),rkV.Dot(kDiff)));
    }

    return true;
}
Exemple #3
0
//----------------------------------------------------------------------------
void ExtractTrilinear::MakeUnique (V3Array& rkVA, T3Array& rkTA)
{
    int iVQuantity = (int)rkVA.size(), iTQuantity = (int)rkTA.size();
    if ( iVQuantity == 0 || iTQuantity == 0 )
        return;

    // use a hash table to generate unique storage
    V3Map kVMap;
    V3MapIterator pkVIter;
    for (int iV = 0, iNextVertex = 0; iV < iVQuantity; iV++)
    {
        // keep only unique vertices
        pair<V3MapIterator,bool> kResult = kVMap.insert(
            make_pair(rkVA[iV],iNextVertex));
        if ( kResult.second == true )
            iNextVertex++;
    }

    // use a hash table to generate unique storage
    T3Map kTMap;
    T3MapIterator pkTIter;
    for (int iT = 0, iNextTriangle = 0; iT < iTQuantity; iT++)
    {
        // replace old vertex indices by new ones
        Triangle3& rkTri = rkTA[iT];
        pkVIter = kVMap.find(rkVA[rkTri.i0]);
        assert( pkVIter != kVMap.end() );
        rkTri.i0 = pkVIter->second;
        pkVIter = kVMap.find(rkVA[rkTri.i1]);
        assert( pkVIter != kVMap.end() );
        rkTri.i1 = pkVIter->second;
        pkVIter = kVMap.find(rkVA[rkTri.i2]);
        assert( pkVIter != kVMap.end() );
        rkTri.i2 = pkVIter->second;

        // keep only unique triangles
        pair<T3MapIterator,bool> kResult = kTMap.insert(
            make_pair(rkTri,iNextTriangle));
        if ( kResult.second == true )
            iNextTriangle++;
    }

    // pack the vertices
    rkVA.resize(kVMap.size());
    for (pkVIter = kVMap.begin(); pkVIter != kVMap.end(); pkVIter++)
        rkVA[pkVIter->second] = pkVIter->first;

    // pack the triangles
    rkTA.resize(kTMap.size());
    for (pkTIter = kTMap.begin(); pkTIter != kTMap.end(); pkTIter++)
        rkTA[pkTIter->second] = pkTIter->first;
}
void ConvexPolyhedron3<Real>::Create (const V3Array& rakPoint,
    const IArray& raiConnect, const PArray& rakPlane)
{
    assert( rakPoint.size() >= 4 && raiConnect.size() >= 4 );

    int iVQuantity = (int)rakPoint.size();
    int iTQuantity = (int)raiConnect.size()/3;
    int iEQuantity = iVQuantity + iTQuantity - 2;
    Reset(iVQuantity,iEQuantity,iTQuantity);
    m_akPoint = rakPoint;
    m_akPlane = rakPlane;

    // Copy polyhedron points into vertex array.  Compute centroid for use in
    // making sure the triangles are counterclockwise oriented when viewed
    // from the outside.
    ComputeCentroid();

    // get polyhedron edge and triangle information
    for (int iT = 0, iIndex = 0; iT < iTQuantity; iT++)
    {
        // get vertex indices for triangle
        int iV0 = raiConnect[iIndex++];
        int iV1 = raiConnect[iIndex++];
        int iV2 = raiConnect[iIndex++];

        Real fDistance = m_akPlane[iT].DistanceTo(m_kCentroid);
        if ( fDistance > (Real)0.0 )
        {
            // triangle is counterclockwise
            Insert(iV0,iV1,iV2);
        }
        else
        {
            // triangle is clockwise
            Insert(iV0,iV2,iV1);
        }
    }
}
//----------------------------------------------------------------------------
void VETable::RemoveTriangles (V3Array& rkVA, T3Array& rkTA)
{
    // ear-clip the wireframe to get the triangles
    Triangle3 kTri;
    while ( Remove(kTri) )
    {
        int iV0 = (int)rkVA.size(), iV1 = iV0+1, iV2 = iV1+1;
        rkTA.push_back(Triangle3(iV0,iV1,iV2));

        const Vertex& rkV0 = m_akVertex[kTri.i0];
        const Vertex& rkV1 = m_akVertex[kTri.i1];
        const Vertex& rkV2 = m_akVertex[kTri.i2];

        rkVA.push_back(Vertex3(rkV0.m_fX,rkV0.m_fY,rkV0.m_fZ));
        rkVA.push_back(Vertex3(rkV1.m_fX,rkV1.m_fY,rkV1.m_fZ));
        rkVA.push_back(Vertex3(rkV2.m_fX,rkV2.m_fY,rkV2.m_fZ));
    }
}
Exemple #6
0
//----------------------------------------------------------------------------
void ExtractTrilinear::ComputeNormals (const V3Array& rkVA,
    const T3Array& rkTA, V3Array& rkNA)
{
    // maintain a running sum of triangle normals at each vertex
    int iVQuantity = (int)rkVA.size(), iTQuantity = (int)rkTA.size();
    rkNA.resize(iVQuantity);
    int i, j;
    for (i = 0; i < iVQuantity; i++)
    {
        rkNA[i].x = 0.0f;
        rkNA[i].y = 0.0f;
        rkNA[i].z = 0.0f;
    }

    for (i = 0, j = 0; i < iTQuantity; i++)
    {
        const Triangle3& rkT = rkTA[i];
        Vertex3 kV0 = rkVA[rkT.i0];
        Vertex3 kV1 = rkVA[rkT.i1];
        Vertex3 kV2 = rkVA[rkT.i2];

        // construct triangle normal
        float fEX1 = kV1.x - kV0.x;
        float fEY1 = kV1.y - kV0.y;
        float fEZ1 = kV1.z - kV0.z;
        float fEX2 = kV2.x - kV0.x;
        float fEY2 = kV2.y - kV0.y;
        float fEZ2 = kV2.z - kV0.z;
        float fNX = fEY1*fEZ2 - fEY2*fEZ1;
        float fNY = fEZ1*fEX2 - fEZ2*fEX1;
        float fNZ = fEX1*fEY2 - fEX2*fEY1;

        // maintain the sum of normals at each vertex
        rkNA[rkT.i0].x += fNX;
        rkNA[rkT.i0].y += fNY;
        rkNA[rkT.i0].z += fNZ;
        rkNA[rkT.i1].x += fNX;
        rkNA[rkT.i1].y += fNY;
        rkNA[rkT.i1].z += fNZ;
        rkNA[rkT.i2].x += fNX;
        rkNA[rkT.i2].y += fNY;
        rkNA[rkT.i2].z += fNZ;
    }

    // The normal vector storage was used to accumulate the sum of
    // triangle normals.  Now these vectors must be rescaled to be
    // unit length.
    for (i = 0; i < iVQuantity; i++)
    {
        Vertex3& rkV = rkNA[i];
        float fLength = sqrtf(rkV.x*rkV.x + rkV.y*rkV.y + rkV.z*rkV.z);
        if ( fLength > 1e-08f )
        {
            float fInvLength = 1.0f/fLength;
            rkV.x *= fInvLength;
            rkV.y *= fInvLength;
            rkV.z *= fInvLength;
        }
        else
        {
            rkV.x = 0.0f;
            rkV.y = 0.0f;
            rkV.z = 0.0f;
        }
    }
}