Beispiel #1
0
Octree* Octree::Render(Tree* t, const Region& r, uint32_t flags,
                       bool multithread)
{
    auto rp = r.powerOfTwo().view();

    if (multithread && rp.canOctsect())
    {
        std::list<std::future<Octree*>> futures;

        // Start up a set of future rendering every branch of the octree
        for (auto region : rp.octsect())
        {
            auto e = new Evaluator(t);

            futures.push_back(std::async(std::launch::async,
                [e, region, flags](){
                    auto out = new Octree(e, region, flags);
                    delete e;
                    return out;}));
        }

        // Wait for all of the tasks to finish running in the background
        std::array<Octree*, 8> sub;
        int index = 0;
        for (auto& f : futures)
        {
            f.wait();
            sub[index++] = f.get();
        }

        Evaluator e(t);
        return new Octree(&e, sub, rp, flags);
    }

    else
    {
        Evaluator e(t);
        return new Octree(&e, rp, flags);
    }
}
Beispiel #2
0
_STATIC_
void triangulate_voxel(MathTree* tree, const Region r,
                       float** const verts, unsigned* const count,
                       unsigned* const allocated,
                       Region packed, const float* data)
{
    // If we can calculate all of the points in this region with a single
    // eval_r call, then do so.  This large chunk will be used in future
    // recursive calls to make things more efficient.
    const unsigned voxels = (r.ni+1)*(r.nj+1)*(r.nk+1);
    if (!data && voxels < MIN_VOLUME)
    {
        packed = r;

        // Copy the X, Y, Z vectors into a flattened matrix form.
        packed.X = malloc(voxels*sizeof(float));
        packed.Y = malloc(voxels*sizeof(float));
        packed.Z = malloc(voxels*sizeof(float));

        int q = 0;
        for (int k = 0; k <= r.nk; ++k) {
            for (int j = 0; j <= r.nj; ++j) {
                for (int i = 0; i <= r.ni; ++i) {
                    packed.X[q] = r.X[i];
                    packed.Y[q] = r.Y[j];
                    packed.Z[q] = r.Z[k];
                    q++;
                }
            }
        }
        // Update the voxel count
        packed.voxels = voxels;

        data = eval_r(tree, packed);

        // Free the allocated matrices
        free(packed.X);
        free(packed.Y);
        free(packed.Z);
    }

    // If we have greater than one voxel, subdivide and recurse.
    if (r.voxels > 1)
    {
        Region octants[8];
        const uint8_t split = octsect(r, octants);
        for (int i=0; i < 8; ++i)
        {
            if (split & (1 << i))
            {
                triangulate_voxel(tree, octants[i],
                                  verts, count, allocated,
                                  packed, data);
            }
        }
        return;
    }

    // Find corner distance values for this voxel
    float d[8];
    for (int i=0; i < 8; ++i)
    {
        // Figure out where this bit of data lives in the larger eval_r array.
        const unsigned index =
            (r.imin - packed.imin + ((i & 4) ? r.ni : 0)) +
            (r.jmin - packed.jmin + ((i & 2) ? r.nj : 0))
                * (packed.ni+1) +
            (r.kmin - packed.kmin + ((i & 1) ? r.nk : 0))
                * (packed.ni+1) * (packed.nj+1);

        d[i] = data[index];
    }

    // Loop over the six tetrahedra that make up a voxel cell
    for (int t=0; t < 6; ++t)
    {
        // Find vertex positions for this tetrahedron
        uint8_t vertices[] = {0, 7, VERTEX_LOOP[t], VERTEX_LOOP[t+1]};

        // Figure out which of the sixteen possible combinations
        // we're currently experiencing.
        uint8_t lookup = 0;
        for (int v=3; v>=0; --v) {
            lookup = (lookup << 1) + (d[vertices[v]] < 0);
        }

        // Iterate over (up to) two triangles in this tetrahedron
        for (int i=0; i < 2; ++i)
        {
            if (EDGE_MAP[lookup][i][0][0] == -1)    break;

            // Do we need to allocate more space for incoming vertices?
            // If so, double the buffer size.
            if ((*count) + 9 >= (*allocated))
            {
                *allocated *= 2;
                *verts = realloc(*verts, sizeof(float)*(*allocated));
            }

            // ...and insert vertices into the mesh.
            for (int v=0; v < 3; ++v)
            {
                const Vec3f vertex = zero_crossing(d,
                        vertices[EDGE_MAP[lookup][i][v][0]],
                        vertices[EDGE_MAP[lookup][i][v][1]]);
                (*verts)[(*count)++] = vertex.x * (r.X[1] - r.X[0]) + r.X[0];
                (*verts)[(*count)++] = vertex.y * (r.Y[1] - r.Y[0]) + r.Y[0];
                (*verts)[(*count)++] = vertex.z * (r.Z[1] - r.Z[0]) + r.Z[0];
            }
        }
    }

}