glm::vec2 ArcPath::getPoint(float f) const { float rad = fabs(radius+offset); if (rad < 400) //TODO: nasty condition here... to protect from 'straight lines' { float r1 = atan2(begin.y - origin.y, begin.x - origin.x); float r2 = atan2(end.y - origin.y, end.x - origin.x); float inc = 0; if (!sign_n) inc = angleDist(r2, r1) * f; else inc = angleDist(r1, r2) * f; if (sign_n) inc = -inc; //todo: fix condition here float angle = r1 + inc; return origin + rad * blib::util::fromAngle(angle); } else { glm::vec2 beginNormal(begindirection.y, -begindirection.x); return begin + (sign_t ? -offset : offset) * glm::normalize(beginNormal) + f * (end - begin); } }
void ArcPath::buildLines() { float rad = fabs(radius+offset); if (rad < 400) //TODO: nasty condition here... to protect from 'straight lines' { float r1 = atan2(begin.y - origin.y, begin.x - origin.x); float r2 = atan2(end.y - origin.y, end.x - origin.x); float inc = blib::math::pif / (5 + glm::min(100.0f, glm::abs(radius+offset))); if (sign_n) inc = -inc; //todo: fix condition here float last = r1; for (float f = r1; fabs(angleDist(f + inc, r2)) > fabs(inc); f += inc) { if (f > blib::math::pif) f -= blib::math::pif * 2; if (f < -blib::math::pif) f += blib::math::pif * 2; lines.push_back(LinePart(origin + rad * blib::util::fromAngle(f), origin + rad * blib::util::fromAngle(f + inc))); last = f + inc; } if (!lines.empty()) { // lines.pop_back(); lines.push_back(LinePart(origin + rad * blib::util::fromAngle(last), origin + rad * blib::util::fromAngle(r2))); } else lines.push_back(LinePart(origin + rad * blib::util::fromAngle(r1), origin + rad * blib::util::fromAngle(r2))); } else { lines.push_back(LinePart(begin, end)); } }
void CitySceneGenerator::generate(Scene* scene) { auto renderer = scene->renderer(); auto material = std::make_shared<PhongMaterial>(renderer); material->setShader(renderer->shaderManager()->getGlslProgram("phong")); PhongMaterialData materialData = { glm::vec4(0.0f, 0.1f, 0.0f, 1.0f), glm::vec4(0.8f, 0.3f, 0.1f, 1.0f), glm::vec4(0.3f, 0.3f, 0.3f, 1.0f), 5.0f }; material->properties()->setData(materialData); material->properties()->flushData(); auto mesh = std::make_shared<Mesh>(); mesh->setPrimitiveType(PrimitiveType::TriangleList); size_t buildingVerticesCount = sizeof(buildingVertices) / sizeof(*buildingVertices); std::vector<char> vertices(reinterpret_cast<const char*>(buildingVertices), reinterpret_cast<const char*>(buildingVertices) + sizeof(buildingVertices)); std::vector<VertexElement> layout = { VertexElement(3, VertexElementType::Float), VertexElement(3, VertexElementType::Float) }; mesh->loadVertices(vertices, buildingVerticesCount, layout); size_t buildingIndicesCount = sizeof(buildingIndices) / sizeof(*buildingIndices); std::vector<uint32_t> indices(reinterpret_cast<const unsigned*>(buildingIndices), reinterpret_cast<const unsigned*>(buildingIndices) + buildingIndicesCount); mesh->loadIndices(indices); size_t numBuildings = 1000; float citySize = 500.0f; float minBuildingSize = 10.0f; float maxBuildingSize = 60.0f; float minHeightToWidthRatio = 8.0f; float maxHeightToWidthRatio = 16.0f; std::uniform_real_distribution<float> angleDist(0.0f, 360.0f); std::uniform_real_distribution<float> positionDist(-citySize, citySize); std::uniform_real_distribution<float> canonicalDist; std::vector<std::shared_ptr<BaseSceneObject>> buildings; for (size_t i = 0; i < numBuildings; i++) { auto building = std::make_shared<Building>(mesh, material); // set random position glm::mat4 model = glm::translate(glm::mat4(1.0f), glm::vec3(positionDist(m_rng), positionDist(m_rng), 0.0f) ); // rotate around z with random angle model = glm::rotate(model, angleDist(m_rng), glm::vec3(0.0f, 0.0f, 1.0f)); glm::vec3 scale; // multiplying uniform distribution will generate beta distribution scale.x = canonicalDist(m_rng) * canonicalDist(m_rng) * canonicalDist(m_rng) * canonicalDist(m_rng) * (maxBuildingSize - minBuildingSize) + minBuildingSize; scale.y = scale.x; scale.z = canonicalDist(m_rng) * canonicalDist(m_rng) * canonicalDist(m_rng) * scale.x * (maxHeightToWidthRatio - minHeightToWidthRatio) + minHeightToWidthRatio; model = glm::scale(model, scale); building->setModelMatrix(model); building->calculateBBox(); buildings.push_back(building); } scene->setStaticGeometry(std::move(buildings)); }