add torus rendering
Showing the changes to libraries/render-utils/src/GeometryCache.cpp (1 of 12 files). Show all
Unified · Split
| @@ -19,6 +19,7 @@ · 18 unmodified lines | ||
| 19 | 19 | #include <QtCore/QFileInfo> |
| 20 | 20 | #include <QtNetwork/QNetworkReply> |
| 21 | 21 | |
| 22 | +#include <glm/gtx/transform.hpp> | |
| 22 | 23 | #include <shared/Shapes.h> |
| 23 | 24 | #include <shared/PlatformHacks.h> |
| 24 | 25 | |
| @@ -590,8 +591,7 @@ void GeometryCache::buildShapes() { · 565 unmodified lines | ||
| 590 | 591 | extrudePolygon<64>(_shapes[Cone], _shapeVertices, _shapeIndices, true); |
| 591 | 592 | // Circle renders as flat Cylinder |
| 592 | 593 | extrudePolygon<64>(_shapes[Circle], _shapeVertices, _shapeIndices); |
| 593 | − // Not implemented yet: | |
| 594 | − //Torus, | |
| 594 | + //Torus is implemented in renderTorus, not with ShapeData, because the inner radius can change | |
| 595 | 595 | } |
| 596 | 596 | |
| 597 | 597 | const GeometryCache::ShapeData * GeometryCache::getShapeData(const Shape shape) const { |
| @@ -696,6 +696,9 @@ void GeometryCache::releaseID(int id) { · 98 unmodified lines | ||
| 696 | 696 | |
| 697 | 697 | _lastRegisteredGridBuffer.remove(id); |
| 698 | 698 | _registeredGridBuffers.remove(id); |
| 699 | + | |
| 700 | + _lastRegisteredTorusBuffer.remove(id); | |
| 701 | + _registeredTorusBuffers.remove(id); | |
| 699 | 702 | } |
| 700 | 703 | |
| 701 | 704 | void GeometryCache::initializeShapePipelines() { |
| @@ -1618,18 +1621,132 @@ void GeometryCache::renderDashedLine(gpu::Batch& batch, const glm::vec3& start, · 916 unmodified lines | ||
| 1618 | 1621 | batch.draw(gpu::LINES, details.vertices, 0); |
| 1619 | 1622 | } |
| 1620 | 1623 | |
| 1624 | +void GeometryCache::renderTorus(gpu::Batch& batch, float innerRadius, gpu::BufferPointer& colorBuffer, int id) { | |
| 1625 | + bool registered = (id != UNKNOWN_ID); | |
| 1626 | + BatchItemDetails& details = _registeredTorusBuffers[id]; | |
| 1627 | + | |
| 1628 | + // if this is a registered, and we have buffers, then check to see if the geometry changed and rebuild if needed | |
| 1629 | + if (registered && details.isCreated) { | |
| 1630 | + if (_lastRegisteredTorusBuffer[id] != innerRadius) { | |
| 1631 | + details.clear(); | |
| 1632 | + _lastRegisteredTorusBuffer[id] = innerRadius; | |
| 1633 | +#ifdef WANT_DEBUG | |
| 1634 | + qCDebug(renderutils) << "renderTorus()... RELEASING REGISTERED"; | |
| 1635 | +#endif // def WANT_DEBUG | |
| 1636 | + } | |
| 1637 | + } | |
| 1638 | + | |
| 1639 | + if (!details.isCreated) { | |
| 1640 | + const int NUM_DIVISIONS = 64; | |
| 1641 | + const float ANGLE_STEP = 2.0f * ((float)M_PI) / NUM_DIVISIONS; | |
| 1642 | + const int FLOATS_PER_VERTEX = 3 + 3 + 2 + 3; // vertices + normals + tex coords + tangents | |
| 1643 | + details.isCreated = true; | |
| 1644 | + details.vertices = 6 * (NUM_DIVISIONS + 1) * (NUM_DIVISIONS + 1); | |
| 1645 | + details.vertexSize = FLOATS_PER_VERTEX; | |
| 1646 | + | |
| 1647 | + auto verticesBuffer = std::make_shared<gpu::Buffer>(); | |
| 1648 | + auto indicesBuffer = std::make_shared<gpu::Buffer>(); | |
| 1649 | + auto streamFormat = std::make_shared<gpu::Stream::Format>(); | |
| 1650 | + auto stream = std::make_shared<gpu::BufferStream>(); | |
| 1651 | + | |
| 1652 | + details.verticesBuffer = verticesBuffer; | |
| 1653 | + details.uniformBuffer = indicesBuffer; // we use the uniformBuffer to store the incides | |
| 1654 | + details.streamFormat = streamFormat; | |
| 1655 | + details.stream = stream; | |
| 1656 | + | |
| 1657 | + details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, POSITION_ELEMENT); | |
| 1658 | + details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, NORMAL_ELEMENT, 3 * sizeof(float)); | |
| 1659 | + details.streamFormat->setAttribute(gpu::Stream::TEXCOORD0, 0, TEXCOORD0_ELEMENT, 6 * sizeof(float)); | |
| 1660 | + details.streamFormat->setAttribute(gpu::Stream::TANGENT, 0, TANGENT_ELEMENT, 8 * sizeof(float)); | |
| 1661 | + details.streamFormat->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE); | |
| 1662 | + | |
| 1663 | + details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride); | |
| 1664 | + | |
| 1665 | + // Build our initial circle. Keep track of the center point for normal calculations. | |
| 1666 | + glm::vec3 center = glm::vec3(0.5f - innerRadius, 0.0f, 0.0f); | |
| 1667 | + std::array<glm::vec3, NUM_DIVISIONS + 1> points; | |
| 1668 | + for (int i = 0; i <= NUM_DIVISIONS; i++) { | |
| 1669 | + // Inner radius only affects X. Y still needs to be -0.5 -> 0.5. | |
| 1670 | + points[i] = center + glm::vec3(innerRadius * glm::cos(i * ANGLE_STEP), 0.5f * glm::sin(i * ANGLE_STEP), 0.0f); | |
| 1671 | + } | |
| 1672 | + glm::mat3 normalMatrix = glm::transpose(glm::inverse(glm::scale(glm::vec3(1.0f, 0.5f / innerRadius, 1.0f)))); | |
| 1673 | + | |
| 1674 | + // Build all of our vertex data | |
| 1675 | + float* vertexData = new float[details.vertices * FLOATS_PER_VERTEX]; | |
| 1676 | + float* vertex = vertexData; | |
| 1677 | + for (int y = 0; y <= NUM_DIVISIONS; y++) { | |
| 1678 | + const float ANGLE = y * ANGLE_STEP; | |
| 1679 | + for (int i = 0; i <= NUM_DIVISIONS; i++) { | |
| 1680 | + glm::vec3 currentCenter = fabs(center.x) * glm::vec3(glm::cos(ANGLE), 0.0f, glm::sin(ANGLE)); | |
| 1681 | + // Position | |
| 1682 | + glm::vec3 currentPoint = glm::vec3(0.0f, points[i].y, 0.0f) + fabs(points[i].x) * glm::vec3(glm::cos(ANGLE), 0.0f, glm::sin(ANGLE)); | |
| 1683 | + *(vertex++) = currentPoint.x; | |
| 1684 | + *(vertex++) = currentPoint.y; | |
| 1685 | + *(vertex++) = currentPoint.z; | |
| 1686 | + // Normal | |
| 1687 | + glm::vec3 currentNormal = glm::normalize(normalMatrix * glm::normalize(currentPoint - currentCenter)); | |
| 1688 | + *(vertex++) = currentNormal.x; | |
| 1689 | + *(vertex++) = currentNormal.y; | |
| 1690 | + *(vertex++) = currentNormal.z; | |
| 1691 | + // UV | |
| 1692 | + glm::vec2 currentUV = glm::vec2((float)i / NUM_DIVISIONS, (float)y / NUM_DIVISIONS); | |
| 1693 | + *(vertex++) = currentUV.x; | |
| 1694 | + *(vertex++) = currentUV.y; | |
| 1695 | + // Tangent | |
| 1696 | + int nextIndex = (i + 1) % (NUM_DIVISIONS + 1) + (i / (NUM_DIVISIONS + 1)); | |
| 1697 | + glm::vec3 currentTangent = glm::normalize(glm::cross(currentNormal, points[nextIndex] - points[i])); | |
| 1698 | + *(vertex++) = currentTangent.x; | |
| 1699 | + *(vertex++) = currentTangent.y; | |
| 1700 | + *(vertex++) = currentTangent.z; | |
| 1701 | + } | |
| 1702 | + } | |
| 1703 | + | |
| 1704 | + details.verticesBuffer->append(sizeof(float) * FLOATS_PER_VERTEX * details.vertices, (gpu::Byte*)vertexData); | |
| 1705 | + delete[] vertexData; | |
| 1706 | + | |
| 1707 | + // Build our indices | |
| 1708 | + for (int y = 0; y < NUM_DIVISIONS; y++) { | |
| 1709 | + for (int i = 0; i < NUM_DIVISIONS; i++) { | |
| 1710 | + const int baseIndex = i + (NUM_DIVISIONS + 1) * y; | |
| 1711 | + details.uniformBuffer->append((uint16_t)baseIndex); | |
| 1712 | + details.uniformBuffer->append((uint16_t)(baseIndex + 1)); | |
| 1713 | + details.uniformBuffer->append((uint16_t)(baseIndex + NUM_DIVISIONS + 1)); | |
| 1714 | + details.uniformBuffer->append((uint16_t)(baseIndex + 1)); | |
| 1715 | + details.uniformBuffer->append((uint16_t)(baseIndex + NUM_DIVISIONS + 2)); | |
| 1716 | + details.uniformBuffer->append((uint16_t)(baseIndex + NUM_DIVISIONS + 1)); | |
| 1717 | + } | |
| 1718 | + } | |
| 1719 | + | |
| 1720 | +#ifdef WANT_DEBUG | |
| 1721 | + if (registered) { | |
| 1722 | + qCDebug(renderutils) << "new registered torus buffer made -- _registeredTorusBuffers:" | |
| 1723 | + << _registeredTorusBuffers.size(); | |
| 1724 | + } else { | |
| 1725 | + qCDebug(renderutils) << "new torus buffer made -- _registeredTorusBuffers:" << _registeredTorusBuffers.size(); | |
| 1726 | + } | |
| 1727 | +#endif | |
| 1728 | + } | |
| 1729 | + | |
| 1730 | + // TODO: instanced rendering | |
| 1731 | + gpu::BufferView colorView(colorBuffer, COLOR_ELEMENT); | |
| 1732 | + batch.setInputBuffer(gpu::Stream::COLOR, colorView); | |
| 1733 | + batch.setInputStream(0, *details.stream); | |
| 1734 | + batch.setInputFormat(details.streamFormat); | |
| 1735 | + batch.setIndexBuffer(gpu::Type::UINT16, details.uniformBuffer, 0); // indices are stored in uniformBuffer | |
| 1736 | + batch.drawIndexed(gpu::TRIANGLES, details.vertices, 0); | |
| 1737 | +} | |
| 1621 | 1738 | |
| 1622 | 1739 | int GeometryCache::BatchItemDetails::population = 0; |
| 1623 | 1740 | |
| 1624 | 1741 | GeometryCache::BatchItemDetails::BatchItemDetails() : |
| 1625 | −verticesBuffer(NULL), | |
| 1626 | −normalBuffer(NULL), | |
| 1627 | −colorBuffer(NULL), | |
| 1628 | −streamFormat(NULL), | |
| 1629 | −stream(NULL), | |
| 1630 | −vertices(0), | |
| 1631 | −vertexSize(0), | |
| 1632 | −isCreated(false) { | |
| 1742 | + verticesBuffer(NULL), | |
| 1743 | + normalBuffer(NULL), | |
| 1744 | + colorBuffer(NULL), | |
| 1745 | + streamFormat(NULL), | |
| 1746 | + stream(NULL), | |
| 1747 | + vertices(0), | |
| 1748 | + vertexSize(0), | |
| 1749 | + isCreated(false) { | |
| 1633 | 1750 | population++; |
| 1634 | 1751 | #ifdef WANT_DEBUG |
| 1635 | 1752 | qCDebug(renderutils) << "BatchItemDetails()... population:" << population << "**********************************"; |
| @@ -1637,14 +1754,14 @@ isCreated(false) { · 1 unmodified line | ||
| 1637 | 1754 | } |
| 1638 | 1755 | |
| 1639 | 1756 | GeometryCache::BatchItemDetails::BatchItemDetails(const GeometryCache::BatchItemDetails& other) : |
| 1640 | −verticesBuffer(other.verticesBuffer), | |
| 1641 | −normalBuffer(other.normalBuffer), | |
| 1642 | −colorBuffer(other.colorBuffer), | |
| 1643 | −streamFormat(other.streamFormat), | |
| 1644 | −stream(other.stream), | |
| 1645 | −vertices(other.vertices), | |
| 1646 | −vertexSize(other.vertexSize), | |
| 1647 | −isCreated(other.isCreated) { | |
| 1757 | + verticesBuffer(other.verticesBuffer), | |
| 1758 | + normalBuffer(other.normalBuffer), | |
| 1759 | + colorBuffer(other.colorBuffer), | |
| 1760 | + streamFormat(other.streamFormat), | |
| 1761 | + stream(other.stream), | |
| 1762 | + vertices(other.vertices), | |
| 1763 | + vertexSize(other.vertexSize), | |
| 1764 | + isCreated(other.isCreated) { | |
| 1648 | 1765 | population++; |
| 1649 | 1766 | #ifdef WANT_DEBUG |
| 1650 | 1767 | qCDebug(renderutils) << "BatchItemDetails()... population:" << population << "**********************************"; |
| @@ -1728,8 +1845,6 @@ void GeometryCache::useGridPipeline(gpu::Batch& batch, GridBuffer gridBuffer, bo · 77 unmodified lines | ||
| 1728 | 1845 | batch.setUniformBuffer(0, gridBuffer); |
| 1729 | 1846 | } |
| 1730 | 1847 | |
| 1731 | − | |
| 1732 | − | |
| 1733 | 1848 | class SimpleProgramKey { |
| 1734 | 1849 | public: |
| 1735 | 1850 | enum FlagBit { |