2352 lines · 101.2 KB · C++
RawDownload
                                }                                crossing.point = glm::vec3(1.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 0.0f);                            }                            if (alpha2 != alpha3) {                                QRgb hermite = hermiteBase[hermiteStride];                                EdgeCrossing& crossing = crossings[crossingCount++];                                crossing.normal = unpackNormal(hermite);                                if (alpha2 == 0) {                                    crossing.color = colorX[offset3];                                    crossing.material = materialBase ? materialBase[offset3] : 0;                                } else {                                    crossing.color = colorX[size];                                    crossing.material = materialBase ? materialBase[size] : 0;                                }                                crossing.point = glm::vec3(qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 1.0f, 0.0f);                            }                            if (middleZ) {                                if (alpha3 != alpha7) {                                    QRgb hermite = hermiteBase[hermiteStride + VoxelHermiteData::EDGE_COUNT + 2];                                    EdgeCrossing& crossing = crossings[crossingCount++];                                    crossing.normal = unpackNormal(hermite);                                    if (alpha3 == 0) {                                        crossing.color = colorX[offset7];                                        crossing.material = materialBase ? materialBase[offset7] : 0;                                    } else {                                        crossing.color = colorX[offset3];                                        crossing.material = materialBase ? materialBase[offset3] : 0;                                    }                                    crossing.point = glm::vec3(1.0f, 1.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL);                                }                                if (alpha5 != alpha7) {                                    QRgb hermite = hermiteBase[hermiteArea + VoxelHermiteData::EDGE_COUNT + 1];                                    EdgeCrossing& crossing = crossings[crossingCount++];                                    crossing.normal = unpackNormal(hermite);                                    if (alpha5 == 0) {                                        crossing.color = colorX[offset7];                                        crossing.material = materialBase ? materialBase[offset7] : 0;                                    } else {                                        crossing.color = colorX[offset5];                                        crossing.material = materialBase ? materialBase[offset5] : 0;                                    }                                    crossing.point = glm::vec3(1.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 1.0f);                                }                                if (alpha6 != alpha7) {                                    QRgb hermite = hermiteBase[hermiteArea + hermiteStride];                                    EdgeCrossing& crossing = crossings[crossingCount++];                                    crossing.normal = unpackNormal(hermite);                                    if (alpha6 == 0) {                                        crossing.color = colorX[offset7];                                        crossing.material = materialBase ? materialBase[offset7] : 0;                                    } else {                                        crossing.color = colorX[offset6];                                        crossing.material = materialBase ? materialBase[offset6] : 0;                                    }                                    crossing.point = glm::vec3(qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 1.0f, 1.0f);                                }                            }                        }                        if (middleZ) {                            if (alpha1 != alpha5) {                                QRgb hermite = hermiteBase[VoxelHermiteData::EDGE_COUNT + 2];                                EdgeCrossing& crossing = crossings[crossingCount++];                                crossing.normal = unpackNormal(hermite);                                if (alpha1 == 0) {                                    crossing.color = colorX[offset5];                                    crossing.material = materialBase ? materialBase[offset5] : 0;                                } else {                                    crossing.color = colorX[1];                                    crossing.material = materialBase ? materialBase[1] : 0;                                }                                crossing.point = glm::vec3(1.0f, 0.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL);                            }                            if (alpha4 != alpha5) {                                QRgb hermite = hermiteBase[hermiteArea];                                EdgeCrossing& crossing = crossings[crossingCount++];                                crossing.normal = unpackNormal(hermite);                                if (alpha4 == 0) {                                    crossing.color = colorX[offset5];                                    crossing.material = materialBase ? materialBase[offset5] : 0;                                } else {                                    crossing.color = colorX[area];                                    crossing.material = materialBase ? materialBase[area] : 0;                                }                                crossing.point = glm::vec3(qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 0.0f, 1.0f);                            }                        }                    }                    if (middleY) {                        if (alpha0 != alpha2) {                            QRgb hermite = hermiteBase[1];                            EdgeCrossing& crossing = crossings[crossingCount++];                            crossing.normal = unpackNormal(hermite);                            if (alpha0 == 0) {                                crossing.color = colorX[size];                                crossing.material = materialBase ? materialBase[size] : 0;                            } else {                                crossing.color = colorX[0];                                crossing.material = materialBase ? materialBase[0] : 0;                            }                            crossing.point = glm::vec3(0.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 0.0f);                        }                        if (middleZ) {                            if (alpha2 != alpha6) {                                QRgb hermite = hermiteBase[hermiteStride + 2];                                EdgeCrossing& crossing = crossings[crossingCount++];                                crossing.normal = unpackNormal(hermite);                                if (alpha2 == 0) {                                    crossing.color = colorX[offset6];                                    crossing.material = materialBase ? materialBase[offset6] : 0;                                } else {                                    crossing.color = colorX[size];                                    crossing.material = materialBase ? materialBase[size] : 0;                                }                                crossing.point = glm::vec3(0.0f, 1.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL);                            }                            if (alpha4 != alpha6) {                                QRgb hermite = hermiteBase[hermiteArea + 1];                                EdgeCrossing& crossing = crossings[crossingCount++];                                crossing.normal = unpackNormal(hermite);                                if (alpha4 == 0) {                                    crossing.color = colorX[offset6];                                    crossing.material = materialBase ? materialBase[offset6] : 0;                                } else {                                    crossing.color = colorX[area];                                    crossing.material = materialBase ? materialBase[area] : 0;                                }                                crossing.point = glm::vec3(0.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 1.0f);                            }                        }                    }                    if (middleZ && alpha0 != alpha4) {                        QRgb hermite = hermiteBase[2];                        EdgeCrossing& crossing = crossings[crossingCount++];                        crossing.normal = unpackNormal(hermite);                        if (alpha0 == 0) {                            crossing.color = colorX[area];                            crossing.material = materialBase ? materialBase[area] : 0;                        } else {                            crossing.color = colorX[0];                            crossing.material = materialBase ? materialBase[0] : 0;                        }                        crossing.point = glm::vec3(0.0f, 0.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL);                    }                    // at present, we simply average the properties of each crossing as opposed to finding the vertex that                    // minimizes the quadratic error function as described in the reference paper                    glm::vec3 center;                    glm::vec3 normals[MAX_NORMALS_PER_VERTEX];                    int normalCount = 0;                    const float CREASE_COS_NORMAL = glm::cos(glm::radians(45.0f));                    const int MAX_MATERIALS_PER_VERTEX = 4;                    quint8 materials[] = { 0, 0, 0, 0 };                    glm::vec4 materialWeights;                    float totalWeight = 0.0f;                    int red = 0, green = 0, blue = 0;                    for (int i = 0; i < crossingCount; i++) {                        const EdgeCrossing& crossing = crossings[i];                        center += crossing.point;                                                int j = 0;                        for (; j < normalCount; j++) {                            if (glm::dot(normals[j], crossing.normal) > CREASE_COS_NORMAL) {                                normals[j] = safeNormalize(normals[j] + crossing.normal);                                break;                            }                        }                        if (j == normalCount) {                            normals[normalCount++] = crossing.normal;                        }                                                red += qRed(crossing.color);                        green += qGreen(crossing.color);                        blue += qBlue(crossing.color);                                                if (displayHermite) {                            glm::vec3 start = info.minimum + (glm::vec3(clampedX, clampedY, clampedZ) +                                crossing.point) * scale;                            hermiteSegments.append(start);                            hermiteSegments.append(start + crossing.normal * scale);                        }                                                // when assigning a material, search for its presence and, if not found,                        // place it in the first empty slot                        if (crossing.material != 0) {                            for (j = 0; j < MAX_MATERIALS_PER_VERTEX; j++) {                                if (materials[j] == crossing.material) {                                    materialWeights[j] += 1.0f;                                    totalWeight += 1.0f;                                    break;                                                                    } else if (materials[j] == 0) {                                    materials[j] = crossing.material;                                    materialWeights[j] = 1.0f;                                    totalWeight += 1.0f;                                    break;                                }                            }                        }                    }                    center /= crossingCount;                                        // use a sequence of Givens rotations to perform a QR decomposition                    // see http://www.cs.rice.edu/~jwarren/papers/techreport02408.pdf                    glm::mat4 r(0.0f);                    glm::vec4 bottom;                    for (int i = 0; i < crossingCount; i++) {                        const EdgeCrossing& crossing = crossings[i];                        bottom = glm::vec4(crossing.normal, glm::dot(crossing.normal, crossing.point - center));                                                for (int j = 0; j < 4; j++) {                            float angle = glm::atan(-bottom[j], r[j][j]);                            float sina = glm::sin(angle);                            float cosa = glm::cos(angle);                                                        for (int k = 0; k < 4; k++) {                                float tmp = bottom[k];                                bottom[k] = sina * r[k][j] + cosa * tmp;                                r[k][j] = cosa * r[k][j] - sina * tmp;                            }                        }                    }                                        // extract the submatrices, form ata                    glm::mat3 a(r);                    glm::vec3 b(r[3]);                    glm::mat3 atrans = glm::transpose(a);                    glm::mat3 ata = atrans * a;                                        // find the eigenvalues and eigenvectors of ata                    // (see http://en.wikipedia.org/wiki/Jacobi_eigenvalue_algorithm)                    glm::mat3 d = ata;                    glm::quat combinedRotation;                    const int MAX_ITERATIONS = 20;                    for (int i = 0; i < MAX_ITERATIONS; i++) {                        glm::vec3 offDiagonals = glm::abs(glm::vec3(d[1][0], d[2][0], d[2][1]));                        int largestIndex = (offDiagonals[0] > offDiagonals[1]) ? (offDiagonals[0] > offDiagonals[2] ? 0 : 2) :                            (offDiagonals[1] > offDiagonals[2] ? 1 : 2);                        const float DESIRED_PRECISION = 0.00001f;                        if (offDiagonals[largestIndex] < DESIRED_PRECISION) {                            break;                        }                        int largestJ = (largestIndex == 2) ? 1 : 0;                        int largestI = (largestIndex == 0) ? 1 : 2;                         float sjj = d[largestJ][largestJ];                        float sii = d[largestI][largestI];                        float angle = glm::atan(2.0f * d[largestJ][largestI], sjj - sii) / 2.0f;                        glm::quat rotation = glm::angleAxis(angle, largestIndex == 0 ? glm::vec3(0.0f, 0.0f, -1.0f) :                            (largestIndex == 1 ? glm::vec3(0.0f, 1.0f, 0.0f) : glm::vec3(-1.0f, 0.0f, 0.0f)));                        combinedRotation = glm::normalize(rotation * combinedRotation);                        glm::mat3 matrix = glm::mat3_cast(combinedRotation);                        d = matrix * ata * glm::transpose(matrix);                    }                                        // form the singular matrix from the eigenvalues                    const float MIN_SINGULAR_THRESHOLD = 0.1f;                    d[0][0] = (d[0][0] < MIN_SINGULAR_THRESHOLD) ? 0.0f : 1.0f / d[0][0];                    d[1][1] = (d[1][1] < MIN_SINGULAR_THRESHOLD) ? 0.0f : 1.0f / d[1][1];                    d[2][2] = (d[2][2] < MIN_SINGULAR_THRESHOLD) ? 0.0f : 1.0f / d[2][2];                                        // compute the pseudo-inverse, ataplus, and use to find the minimizing solution                    glm::mat3 u = glm::mat3_cast(combinedRotation);                    glm::mat3 ataplus = glm::transpose(u) * d * u;                     glm::vec3 solution = (ataplus * atrans * b) + center;                                        // make sure it doesn't fall beyond the cell boundaries                    center = glm::clamp(solution, 0.0f, 1.0f);                                        if (totalWeight > 0.0f) {                        materialWeights *= (EIGHT_BIT_MAXIMUM / totalWeight);                    }                    VoxelPoint point = { info.minimum + (glm::vec3(clampedX, clampedY, clampedZ) + center) * scale,                        { (quint8)(red / crossingCount), (quint8)(green / crossingCount), (quint8)(blue / crossingCount) },                        { (char)(normals[0].x * 127.0f), (char)(normals[0].y * 127.0f), (char)(normals[0].z * 127.0f) },                        { materials[0], materials[1], materials[2], materials[3] },                        { (quint8)materialWeights[0], (quint8)materialWeights[1], (quint8)materialWeights[2],                            (quint8)materialWeights[3] } };                                        NormalIndex index = { { vertices.size(), vertices.size(), vertices.size(), vertices.size() } };                    vertices.append(point);                    for (int i = 1; i < normalCount; i++) {                        index.indices[i] = vertices.size();                        point.setNormal(normals[i]);                        vertices.append(point);                    }                                        // the first x, y, and z are repeated for the boundary edge; past that, we consider generating                    // quads for each edge that includes a transition, using indices of previously generated vertices                    if (x != 0 && y != 0 && z != 0) {                        if (alpha0 != alpha1) {                            quadIndices.insert(qRgb(x, y, z), indices.size());                            quadIndices.insert(qRgb(x, y - 1, z), indices.size());                            quadIndices.insert(qRgb(x, y - 1, z - 1), indices.size());                            quadIndices.insert(qRgb(x, y, z - 1), indices.size());                                                        const NormalIndex& index1 = lastLineIndices.at(x);                            const NormalIndex& index2 = lastPlaneIndices.at((y - 1) * expanded + x);                            const NormalIndex& index3 = lastPlaneIndices.at(y * expanded + x);                                                        const glm::vec3& first = vertices.at(index.indices[0]).vertex;                            glm::vec3 normal = glm::cross(vertices.at(index1.indices[0]).vertex - first,                                vertices.at(index3.indices[0]).vertex - first);                                                        if (alpha0 == 0) { // quad faces negative x                                indices.append(index3.getClosestIndex(normal = -normal, vertices));                                indices.append(index2.getClosestIndex(normal, vertices));                                indices.append(index1.getClosestIndex(normal, vertices));                            } else { // quad faces positive x                                indices.append(index1.getClosestIndex(normal, vertices));                                indices.append(index2.getClosestIndex(normal, vertices));                                indices.append(index3.getClosestIndex(normal, vertices));                            }                            indices.append(index.getClosestIndex(normal, vertices));                        }                                                if (alpha0 != alpha2) {                            quadIndices.insert(qRgb(x, y, z), indices.size());                            quadIndices.insert(qRgb(x - 1, y, z), indices.size());                            quadIndices.insert(qRgb(x - 1, y, z - 1), indices.size());                            quadIndices.insert(qRgb(x, y, z - 1), indices.size());                                                        const NormalIndex& index1 = lastIndex;                            const NormalIndex& index2 = lastPlaneIndices.at(y * expanded + x - 1);                            const NormalIndex& index3 = lastPlaneIndices.at(y * expanded + x);                                                        const glm::vec3& first = vertices.at(index.indices[0]).vertex;                            glm::vec3 normal = glm::cross(vertices.at(index3.indices[0]).vertex - first,                                vertices.at(index1.indices[0]).vertex - first);                                                        if (alpha0 == 0) { // quad faces negative y                                indices.append(index1.getClosestIndex(normal = -normal, vertices));                                indices.append(index2.getClosestIndex(normal, vertices));                                indices.append(index3.getClosestIndex(normal, vertices));                            } else { // quad faces positive y                                indices.append(index3.getClosestIndex(normal, vertices));                                indices.append(index2.getClosestIndex(normal, vertices));                                indices.append(index1.getClosestIndex(normal, vertices));                            }                            indices.append(index.getClosestIndex(normal, vertices));                        }                                                if (alpha0 != alpha4) {                            quadIndices.insert(qRgb(x, y, z), indices.size());                            quadIndices.insert(qRgb(x - 1, y, z), indices.size());                            quadIndices.insert(qRgb(x - 1, y - 1, z), indices.size());                            quadIndices.insert(qRgb(x, y - 1, z), indices.size());                                                        const NormalIndex& index1 = lastIndex;                            const NormalIndex& index2 = lastLineIndices.at(x - 1);                            const NormalIndex& index3 = lastLineIndices.at(x);                                                        const glm::vec3& first = vertices.at(index.indices[0]).vertex;                            glm::vec3 normal = glm::cross(vertices.at(index1.indices[0]).vertex - first,                                vertices.at(index3.indices[0]).vertex - first);                                                        if (alpha0 == 0) { // quad faces negative z                                indices.append(index3.getClosestIndex(normal = -normal, vertices));                                indices.append(index2.getClosestIndex(normal, vertices));                                indices.append(index1.getClosestIndex(normal, vertices));                            } else { // quad faces positive z                                indices.append(index1.getClosestIndex(normal, vertices));                                indices.append(index2.getClosestIndex(normal, vertices));                                indices.append(index3.getClosestIndex(normal, vertices));                            }                            indices.append(index.getClosestIndex(normal, vertices));                        }                    }                    lastIndex = index;                    lineIndices[x] = index;                    planeIndices[y * expanded + x] = index;                                        if (x != 0) {                        colorX++;                    }                }                lineIndices.swap(lastLineIndices);                                if (y != 0) {                    colorY += size;                }            }            planeIndices.swap(lastPlaneIndices);                        if (z != 0) {                colorZ += area;            }        }        buffer = new VoxelBuffer(vertices, indices, hermiteSegments, quadIndices, size,            material ? material->getMaterials() : QVector<SharedObjectPointer>());    }    BufferDataPointer pointer(buffer);    info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(pointer));    return STOP_RECURSION;} void DefaultMetavoxelRendererImplementation::augment(MetavoxelData& data, const MetavoxelData& previous,        MetavoxelInfo& info, const MetavoxelLOD& lod) {    // copy the previous buffers    MetavoxelData expandedPrevious = previous;    while (expandedPrevious.getSize() < data.getSize()) {        expandedPrevious.expand();    }    const AttributePointer& voxelBufferAttribute =        Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute();    MetavoxelNode* root = expandedPrevious.getRoot(voxelBufferAttribute);    if (root) {        data.setRoot(voxelBufferAttribute, root);        root->incrementReferenceCount();    }    VoxelAugmentVisitor voxelAugmentVisitor(lod);    data.guideToDifferent(expandedPrevious, voxelAugmentVisitor);} class SpannerSimulateVisitor : public SpannerVisitor {public:        SpannerSimulateVisitor(float deltaTime, const MetavoxelLOD& lod);        virtual bool visit(Spanner* spanner); private:        float _deltaTime;}; SpannerSimulateVisitor::SpannerSimulateVisitor(float deltaTime, const MetavoxelLOD& lod) :    SpannerVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getSpannersAttribute(),        QVector<AttributePointer>(), QVector<AttributePointer>(), lod),    _deltaTime(deltaTime) {} bool SpannerSimulateVisitor::visit(Spanner* spanner) {    spanner->getRenderer()->simulate(_deltaTime);    return true;} void DefaultMetavoxelRendererImplementation::simulate(MetavoxelData& data, float deltaTime,        MetavoxelInfo& info, const MetavoxelLOD& lod) {    SpannerSimulateVisitor spannerSimulateVisitor(deltaTime, lod);    data.guide(spannerSimulateVisitor);} class BufferRenderVisitor : public MetavoxelVisitor {public:        BufferRenderVisitor(const AttributePointer& attribute);        virtual int visit(MetavoxelInfo& info); private:        int _order;    int _containmentDepth;}; BufferRenderVisitor::BufferRenderVisitor(const AttributePointer& attribute) :    MetavoxelVisitor(QVector<AttributePointer>() << attribute),    _order(encodeOrder(Application::getInstance()->getDisplayViewFrustum()->getDirection())),    _containmentDepth(INT_MAX) {} int BufferRenderVisitor::visit(MetavoxelInfo& info) {    if (_containmentDepth >= _depth) {        Frustum::IntersectionType intersection = Application::getInstance()->getMetavoxels()->getFrustum().getIntersectionType(            info.getBounds());        if (intersection == Frustum::NO_INTERSECTION) {            return STOP_RECURSION;        }        _containmentDepth = (intersection == Frustum::CONTAINS_INTERSECTION) ? _depth : INT_MAX;    }    if (!info.isLeaf) {        return _order;    }    BufferDataPointer buffer = info.inputValues.at(0).getInlineValue<BufferDataPointer>();    if (buffer) {        buffer->render();    }    return STOP_RECURSION;} void DefaultMetavoxelRendererImplementation::render(MetavoxelData& data, MetavoxelInfo& info, const MetavoxelLOD& lod) {    if (Menu::getInstance()->isOptionChecked(MenuOption::RenderSpanners)) {        SpannerRenderVisitor spannerRenderVisitor(lod);        data.guide(spannerRenderVisitor);    }    if (Menu::getInstance()->isOptionChecked(MenuOption::RenderDualContourSurfaces)) {        BufferRenderVisitor voxelRenderVisitor(Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute());        data.guide(voxelRenderVisitor);    }} SphereRenderer::SphereRenderer() {}  void SphereRenderer::render(const MetavoxelLOD& lod, bool contained, bool cursor) {    Sphere* sphere = static_cast<Sphere*>(_spanner);    const QColor& color = sphere->getColor();    glColor4f(color.redF(), color.greenF(), color.blueF(), color.alphaF());        glPushMatrix();    const glm::vec3& translation = sphere->getTranslation();

Lines 1501–2000 of 2352. Previous lines