//=================================================================================================================================
/// Initializes the internal data structures used by the ray tracer.
/// \param pVertexPositions  The vertices of the mesh
/// \param pIndices          The face indices
/// \param pFaceNormals      The triangle normals
/// \param nVertices         The number of vertices
/// \param nIndices          The number of faces.
/// \param pFaceClusters     An array giving the cluster ID for each face
/// \return True if successful, false if out of memory
//=================================================================================================================================
bool TootleRaytracer::Init(const float* pVertexPositions, const UINT* pIndices, const float* pFaceNormals, UINT nVertices,
                           UINT nFaces, const UINT* pFaceClusters)
{
    m_pFaceClusters = pFaceClusters;

    std::vector<JRTMesh*> meshes;

    try
    {
        meshes.resize(1);
    }
    catch (std::bad_alloc&)
    {
        return false;
    }


    m_pMesh = JRTMesh::CreateMesh((const Vec3f*) pVertexPositions, (const Vec3f*) pFaceNormals, nVertices, nFaces, pIndices);

    if (!m_pMesh)
    {
        return false;
    }

    // fix mesh so its centered on the origin
    // also scale down (doesn't scale up) it so it is inside the radius 1 ball in the origin.
    JRTBoundingBox bb  = m_pMesh->ComputeBoundingBox();
    Vec3f center       = bb.GetCenter();
    Vec3f size         = bb.GetMax() - bb.GetMin();
    float fLongestSide = std::max(size[0], size[1]);
    fLongestSide       = 2.0f * std::max(fLongestSide, size[2]);
    fLongestSide       = std::max(1.0f, fLongestSide);               // make it at least 1

    for (UINT i = 0; i < nVertices; i++)
    {
        float x = m_pMesh->GetVertex(i).x - center.x;
        float y = m_pMesh->GetVertex(i).y - center.y;
        float z = m_pMesh->GetVertex(i).z - center.z;
        m_pMesh->SetVertex(i, Vec3f(x, y, z) / fLongestSide);
    }

    meshes[0] = m_pMesh ;
    m_pCore = JRTCore::Build(meshes);

    if (!m_pCore)
    {
        JRT_SAFE_DELETE(m_pMesh);
        return false;
    }

    return true;
}
Beispiel #2
0
//=================================================================================================================================
/// Cleans up raytracer data structures
//=================================================================================================================================
void TootleRaytracer::Cleanup()
{
    m_pFaceClusters = NULL;
    JRT_SAFE_DELETE(m_pCore);
    JRT_SAFE_DELETE(m_pMesh);
}
Beispiel #3
0
JRTKDTree* JRTKDTreeBuilder::BuildTree(const std::vector<JRTMesh*>& rMeshes)
{
    JRTKDTree* pTree = NULL;
    std::vector<JRTKDNode> nodes;
    std::vector<UINT> indices;
    std::vector<const JRTTriangle*> triArray;
    JRTBoundingBox scene_bounds(Vec3f(FLT_MAX), Vec3f(-FLT_MAX));

    // build an array over all of the triangles
    for (UINT i = 0; i < rMeshes.size();  i++)
    {
        const JRTTriangle* pTri = rMeshes[i]->GetTriangles();

        for (UINT j = 0; j < rMeshes[i]->GetTriangleCount(); j++)
        {
            triArray.push_back(pTri);
            pTri++;
        }
    }

    JRT_ASSERT(triArray.size() > 0);

    // compute scene bounding box
    for (UINT i = 0; i < triArray.size(); i++)
    {
        // this will cause the fourth component of each point
        // passed to Expand() to be junk.  This is ok

        scene_bounds.Expand(triArray[i]->GetV1());
        scene_bounds.Expand(triArray[i]->GetV2());
        scene_bounds.Expand(triArray[i]->GetV3());
    }

    // slight hack:  Expand bounding box a little bit.  This fixes some precision issues with flat polygons on the edge of the model
    scene_bounds.GetMin() += Vec3f(-0.001f, -0.001f, -0.001f);
    scene_bounds.GetMax() += Vec3f(0.001f, 0.001f, 0.001f);

    // construct the tree
    BuildTreeImpl(scene_bounds, triArray, nodes, indices);

    pTree = new JRTKDTree;
    pTree->m_pIndexArray = new UINT[ indices.size() ];
    pTree->m_pMailboxes = new UINT[ triArray.size() ];
    pTree->m_bBackFacing = new bool [ triArray.size() ];

    // initialize the tree structure
    pTree->m_pNodeArray = (JRTKDNode*)_aligned_malloc(sizeof(JRTKDNode) * nodes.size(), 16);
    pTree->m_pTriArray = (JRTCoreTriangle*)_aligned_malloc(sizeof(JRTCoreTriangle) * triArray.size(), 16);

    if (!pTree->m_pNodeArray || !pTree->m_pTriArray)
    {
        JRT_SAFE_DELETE(pTree);
        return NULL;
    }

    pTree->m_nNodeCount = (UINT)nodes.size();
    pTree->m_nTriangleCount = (UINT)triArray.size();
    pTree->m_nIndexCount = (UINT) indices.size();
    pTree->m_treeBounds = scene_bounds;

    // copy node array
    for (UINT i = 0; i < nodes.size(); i++)
    {
        pTree->m_pNodeArray[i] = nodes[i];
    }

    // create index array
    for (UINT i = 0; i < indices.size(); i++)
    {
        pTree->m_pIndexArray[i] = indices[i];
    }

    // create mailbox array
    memset(pTree->m_pMailboxes, 0, sizeof(UINT)*triArray.size());
    pTree->m_nNextRayID = 1;

    // preprocess triangles and copy to array
    for (UINT i = 0; i < triArray.size(); i++)
    {
        PreprocessTri(triArray[i]->GetV1(), triArray[i]->GetV2(), triArray[i]->GetV3(), &pTree->m_pTriArray[i]);
        pTree->m_pTriArray[i].pMesh = triArray[i]->GetMesh();
        pTree->m_pTriArray[i].nTriIndex = triArray[i]->GetIndexInMesh();
    }

    // initialize array of flags telling whether or not a triangle is backfacing (TOOTLE SPECIFIC)
    for (UINT i = 0; i < triArray.size(); i++)
    {
        pTree->m_bBackFacing[i] = false;
    }

    return pTree;
}