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 | #include <QtCore/QFileInfo> | 19 | #include <QtCore/QFileInfo> |
| 20 | #include <QtNetwork/QNetworkReply> | 20 | #include <QtNetwork/QNetworkReply> |
| 21 | 21 | ||
| 22 | #include <glm/gtx/transform.hpp> | ||
| 22 | #include <shared/Shapes.h> | 23 | #include <shared/Shapes.h> |
| 23 | #include <shared/PlatformHacks.h> | 24 | #include <shared/PlatformHacks.h> |
| 24 | 25 | ||
| @@ -590,8 +591,7 @@ void GeometryCache::buildShapes() { · 565 unmodified lines | |||
| 590 | extrudePolygon<64>(_shapes[Cone], _shapeVertices, _shapeIndices, true); | 591 | extrudePolygon<64>(_shapes[Cone], _shapeVertices, _shapeIndices, true); |
| 591 | // Circle renders as flat Cylinder | 592 | // Circle renders as flat Cylinder |
| 592 | extrudePolygon<64>(_shapes[Circle], _shapeVertices, _shapeIndices); | 593 | extrudePolygon<64>(_shapes[Circle], _shapeVertices, _shapeIndices); |
| 593 | // Not implemented yet: | 594 | //Torus is implemented in renderTorus, not with ShapeData, because the inner radius can change |
| 594 | //Torus, | ||
| 595 | } | 595 | } |
| 596 | 596 | ||
| 597 | const GeometryCache::ShapeData * GeometryCache::getShapeData(const Shape shape) const { | 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 | _lastRegisteredGridBuffer.remove(id); | 697 | _lastRegisteredGridBuffer.remove(id); |
| 698 | _registeredGridBuffers.remove(id); | 698 | _registeredGridBuffers.remove(id); |
| 699 | |||
| 700 | _lastRegisteredTorusBuffer.remove(id); | ||
| 701 | _registeredTorusBuffers.remove(id); | ||
| 699 | } | 702 | } |
| 700 | 703 | ||
| 701 | void GeometryCache::initializeShapePipelines() { | 704 | void GeometryCache::initializeShapePipelines() { |
| @@ -1618,18 +1621,132 @@ void GeometryCache::renderDashedLine(gpu::Batch& batch, const glm::vec3& start, · 916 unmodified lines | |||
| 1618 | batch.draw(gpu::LINES, details.vertices, 0); | 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 | int GeometryCache::BatchItemDetails::population = 0; | 1739 | int GeometryCache::BatchItemDetails::population = 0; |
| 1623 | 1740 | ||
| 1624 | GeometryCache::BatchItemDetails::BatchItemDetails() : | 1741 | GeometryCache::BatchItemDetails::BatchItemDetails() : |
| 1625 | verticesBuffer(NULL), | 1742 | verticesBuffer(NULL), |
| 1626 | normalBuffer(NULL), | 1743 | normalBuffer(NULL), |
| 1627 | colorBuffer(NULL), | 1744 | colorBuffer(NULL), |
| 1628 | streamFormat(NULL), | 1745 | streamFormat(NULL), |
| 1629 | stream(NULL), | 1746 | stream(NULL), |
| 1630 | vertices(0), | 1747 | vertices(0), |
| 1631 | vertexSize(0), | 1748 | vertexSize(0), |
| 1632 | isCreated(false) { | 1749 | isCreated(false) { |
| 1633 | population++; | 1750 | population++; |
| 1634 | #ifdef WANT_DEBUG | 1751 | #ifdef WANT_DEBUG |
| 1635 | qCDebug(renderutils) << "BatchItemDetails()... population:" << population << "**********************************"; | 1752 | qCDebug(renderutils) << "BatchItemDetails()... population:" << population << "**********************************"; |
| @@ -1637,14 +1754,14 @@ isCreated(false) { · 1 unmodified line | |||
| 1637 | } | 1754 | } |
| 1638 | 1755 | ||
| 1639 | GeometryCache::BatchItemDetails::BatchItemDetails(const GeometryCache::BatchItemDetails& other) : | 1756 | GeometryCache::BatchItemDetails::BatchItemDetails(const GeometryCache::BatchItemDetails& other) : |
| 1640 | verticesBuffer(other.verticesBuffer), | 1757 | verticesBuffer(other.verticesBuffer), |
| 1641 | normalBuffer(other.normalBuffer), | 1758 | normalBuffer(other.normalBuffer), |
| 1642 | colorBuffer(other.colorBuffer), | 1759 | colorBuffer(other.colorBuffer), |
| 1643 | streamFormat(other.streamFormat), | 1760 | streamFormat(other.streamFormat), |
| 1644 | stream(other.stream), | 1761 | stream(other.stream), |
| 1645 | vertices(other.vertices), | 1762 | vertices(other.vertices), |
| 1646 | vertexSize(other.vertexSize), | 1763 | vertexSize(other.vertexSize), |
| 1647 | isCreated(other.isCreated) { | 1764 | isCreated(other.isCreated) { |
| 1648 | population++; | 1765 | population++; |
| 1649 | #ifdef WANT_DEBUG | 1766 | #ifdef WANT_DEBUG |
| 1650 | qCDebug(renderutils) << "BatchItemDetails()... population:" << population << "**********************************"; | 1767 | qCDebug(renderutils) << "BatchItemDetails()... population:" << population << "**********************************"; |
| @@ -1728,8 +1845,6 @@ void GeometryCache::useGridPipeline(gpu::Batch& batch, GridBuffer gridBuffer, bo · 77 unmodified lines | |||
| 1728 | batch.setUniformBuffer(0, gridBuffer); | 1845 | batch.setUniformBuffer(0, gridBuffer); |
| 1729 | } | 1846 | } |
| 1730 | 1847 | ||
| 1731 | |||
| 1732 | |||
| 1733 | class SimpleProgramKey { | 1848 | class SimpleProgramKey { |
| 1734 | public: | 1849 | public: |
| 1735 | enum FlagBit { | 1850 | enum FlagBit { |