void WireframeSpheroid::bottomHemisphere(const Float endY, const UnsignedInt rings) { CORRADE_INTERNAL_ASSERT(_positions.empty()); /* Initial vertex */ _positions.push_back(Vector3::yAxis(endY - 1.0f)); /* Connect initial vertex to first ring */ for(UnsignedInt i = 0; i != 4; ++i) _indices.insert(_indices.end(), {0, i+1}); /* Hemisphere vertices and indices */ const Rad ringAngleIncrement(Constants::piHalf()/rings); for(UnsignedInt j = 0; j != rings-1; ++j) { const Rad angle = Float(j+1)*ringAngleIncrement; _positions.emplace_back(0.0f, endY - Math::cos(angle), Math::sin(angle)); _positions.emplace_back(Math::sin(angle), endY - Math::cos(angle), 0.0f); _positions.emplace_back(0.0f, endY - Math::cos(angle), -Math::sin(angle)); _positions.emplace_back(-Math::sin(angle), endY - Math::cos(angle), 0.0f); /* Connect vertices to next ring */ for(UnsignedInt i = 0; i != 4; ++i) _indices.insert(_indices.end(), {UnsignedInt(_positions.size())-4+i, UnsignedInt(_positions.size())+i}); } }
void WireframeSpheroid::topHemisphere(const Float startY, const UnsignedInt rings) { /* Connect previous ring to following vertices */ for(UnsignedInt i = 0; i != 4; ++i) _indices.insert(_indices.end(), {UnsignedInt(_positions.size())-4*_segments+i, UnsignedInt(_positions.size())+i}); /* Hemisphere vertices and indices */ const Rad ringAngleIncrement(Constants::piHalf()/rings); for(UnsignedInt j = 0; j != rings-1; ++j) { const Rad angle = Float(j+1)*ringAngleIncrement; /* Connect previous hemisphere ring to current vertices */ if(j != 0) for(UnsignedInt i = 0; i != 4; ++i) _indices.insert(_indices.end(), {UnsignedInt(_positions.size())-4+i, UnsignedInt(_positions.size())+i}); _positions.emplace_back(0.0f, startY + Math::sin(angle), Math::cos(angle)); _positions.emplace_back(Math::cos(angle), startY + Math::sin(angle), 0.0f); _positions.emplace_back(0.0f, startY + Math::sin(angle), -Math::cos(angle)); _positions.emplace_back(-Math::cos(angle), startY + Math::sin(angle), 0.0f); } /* Final vertex */ _positions.push_back(Vector3::yAxis(startY + 1.0f)); /* Connect last ring to final vertex */ for(UnsignedInt i = 0; i != 4; ++i) _indices.insert(_indices.end(), {UnsignedInt(_positions.size())-5+i, UnsignedInt(_positions.size())-1}); }
Trade::MeshData3D grid3DWireframe(const Vector2i& subdivisions) { const Vector2i vertexCount = subdivisions + Vector2i{2}; const Vector2i faceCount = subdivisions + Vector2i{1}; std::vector<Vector3> positions; positions.reserve(vertexCount.product()); for(Int y = 0; y != vertexCount.y(); ++y) for(Int x = 0; x != vertexCount.x(); ++x) positions.emplace_back((Vector2(x, y)/Vector2(faceCount))*2.0f - Vector2{1.0f}, 0.0f); std::vector<UnsignedInt> indices; indices.reserve(vertexCount.y()*(vertexCount.x() - 1)*2 + vertexCount.x()*(vertexCount.y() - 1)*2); for(Int y = 0; y != vertexCount.y(); ++y) { for(Int x = 0; x != vertexCount.x(); ++x) { /* 3 7 | | ... 2 6 0--1 4--5 ... */ if(x != vertexCount.x() - 1) indices.insert(indices.end(), { UnsignedInt(y*vertexCount.x() + x), UnsignedInt(y*vertexCount.x() + x + 1)}); if(y != vertexCount.y() - 1) indices.insert(indices.end(), { UnsignedInt(y*vertexCount.x() + x), UnsignedInt((y + 1)*vertexCount.x() + x)}); } } return Trade::MeshData3D{MeshPrimitive::Lines, std::move(indices), {std::move(positions)}, {}, {}, {}, nullptr}; }
Trade::MeshData2D Capsule2D::wireframe(UnsignedInt hemisphereRings, UnsignedInt cylinderRings, Float halfLength) { CORRADE_ASSERT(hemisphereRings >= 1 && cylinderRings >= 1, "Capsule must have at least one hemisphere ring, one cylinder ring and three segments", Trade::MeshData2D(MeshPrimitive::Lines, std::vector<UnsignedInt>{}, std::vector<std::vector<Vector2>>{}, std::vector<std::vector<Vector2>>{})); std::vector<Vector2> positions; positions.reserve(hemisphereRings*4+2+(cylinderRings-1)*2); const Rad angleIncrement(Constants::pi()/(2.0f*hemisphereRings)); const Float cylinderIncrement = 2.0f*halfLength/cylinderRings; /* Bottom cap vertex */ positions.emplace_back(0.0f, -halfLength-1.0f); /* Bottom hemisphere */ for(UnsignedInt i = 0; i != hemisphereRings; ++i) { const Rad angle(Float(i+1)*angleIncrement); const Float x = Math::sin(angle); const Float y = -Math::cos(angle)-halfLength; positions.insert(positions.end(), {{-x, y}, {x, y}}); } /* Cylinder (bottom and top vertices are done within caps */ for(UnsignedInt i = 0; i != cylinderRings-1; ++i) { const Float y = (i+1)*cylinderIncrement-halfLength; positions.insert(positions.end(), {{-1.0f, y}, {1.0f, y}}); } /* Top hemisphere */ for(UnsignedInt i = 0; i != hemisphereRings; ++i) { const Rad angle(Float(i)*angleIncrement); const Float x = Math::cos(angle); const Float y = Math::sin(angle)+halfLength; positions.insert(positions.end(), {{-x, y}, {x, y}}); } /* Top cap vertex */ positions.emplace_back(0.0f, halfLength+1.0f); std::vector<UnsignedInt> indices; indices.reserve(hemisphereRings*8+cylinderRings*4); /* Bottom cap indices */ indices.insert(indices.end(), {0, 1, 0, 2}); /* Side indices */ for(UnsignedInt i = 0; i != cylinderRings+hemisphereRings*2-2; ++i) indices.insert(indices.end(), {i*2+1, i*2+3, i*2+2, i*2+4}); /* Top cap indices */ indices.insert(indices.end(), {UnsignedInt(positions.size())-3, UnsignedInt(positions.size())-1, UnsignedInt(positions.size())-2, UnsignedInt(positions.size())-1}); return Trade::MeshData2D(MeshPrimitive::Lines, std::move(indices), {std::move(positions)}, std::vector<std::vector<Vector2>>{}); }
void WireframeSpheroid::ring(const Float y) { /* Ring vertices and indices */ const Rad segmentAngleIncrement(Constants::piHalf()/_segments); for(UnsignedInt j = 0; j != _segments; ++j) { for(UnsignedInt i = 0; i != 4; ++i) { const Rad segmentAngle = Rad(Float(i)*Constants::piHalf()) + Float(j)*segmentAngleIncrement; if(j != 0) _indices.insert(_indices.end(), {UnsignedInt(_positions.size()-4), UnsignedInt(_positions.size())}); _positions.emplace_back(Math::sin(segmentAngle), y, Math::cos(segmentAngle)); } } /* Close the ring */ for(UnsignedInt i = 0; i != 4; ++i) _indices.insert(_indices.end(), {UnsignedInt(_positions.size())-4+i, UnsignedInt(_positions.size())-4*_segments+(i+1)%4}); }
void Timeline::nextFrame() { if(!running) return; auto now = high_resolution_clock::now(); auto duration = UnsignedInt(duration_cast<microseconds>(now-_previousFrameTime).count()); _previousFrameDuration = duration/1e6f; _previousFrameTime = now; }
void Timeline::nextFrame() { if(!running) return; auto now = high_resolution_clock::now(); auto duration = UnsignedInt(duration_cast<microseconds>(now-_previousFrameTime).count()); _previousFrameDuration = duration/1e6f; if(_previousFrameDuration < _minimalFrameTime) { Utility::sleep(std::size_t(_minimalFrameTime*1000) - duration/1000); now = high_resolution_clock::now(); _previousFrameDuration = duration_cast<microseconds>(now-_previousFrameTime).count()/1e6f; } _previousFrameTime = now; }
Trade::MeshData3D grid3DSolid(const Vector2i& subdivisions, const GridFlags flags) { const Vector2i vertexCount = subdivisions + Vector2i{2}; const Vector2i faceCount = subdivisions + Vector2i{1}; std::vector<Vector3> positions; positions.reserve(vertexCount.product()); for(Int y = 0; y != vertexCount.y(); ++y) for(Int x = 0; x != vertexCount.x(); ++x) positions.emplace_back((Vector2(x, y)/Vector2(faceCount))*2.0f - Vector2{1.0f}, 0.0f); std::vector<UnsignedInt> indices; indices.reserve(faceCount.product()*6); for(Int y = 0; y != faceCount.y(); ++y) { for(Int x = 0; x != faceCount.x(); ++x) { /* 2--1 5 | / /| |/ / | 0 3--4 */ indices.insert(indices.end(), { UnsignedInt(y*vertexCount.x() + x), UnsignedInt((y + 1)*vertexCount.x() + x + 1), UnsignedInt((y + 1)*vertexCount.x() + x + 0), UnsignedInt(y*vertexCount.x() + x), UnsignedInt(y*vertexCount.x() + x + 1), UnsignedInt((y + 1)*vertexCount.x() + x + 1)}); } } std::vector<std::vector<Vector3>> normals; if(flags & GridFlag::GenerateNormals) normals.emplace_back(positions.size(), Vector3::zAxis(1.0f)); std::vector<std::vector<Vector2>> textureCoordinates; if(flags & GridFlag::GenerateTextureCoords) { textureCoordinates.emplace_back(); textureCoordinates[0].reserve(positions.size()); for(std::size_t i = 0; i != positions.size(); ++i) textureCoordinates[0].emplace_back(positions[i].xy()*0.5f + Vector2{0.5f}); } return Trade::MeshData3D{MeshPrimitive::Triangles, std::move(indices), {std::move(positions)}, std::move(normals), std::move(textureCoordinates), {}, nullptr}; }
void WireframeSpheroid::cylinder() { /* Connect four vertex pairs of previous and next ring */ for(UnsignedInt i = 0; i != 4; ++i) _indices.insert(_indices.end(), {UnsignedInt(_positions.size())-4*_segments+i, UnsignedInt(_positions.size())+i}); }
// CHECK-LABEL: @explicit_functional_unsigned_int_to_unsigned_int unsigned int explicit_functional_unsigned_int_to_unsigned_int(unsigned int src) { // CHECK-SANITIZE-NOT: call // CHECK: } return UnsignedInt(src); }