void RenderHelper::DrawCircle3D(const Vector3 & center, const Vector3 &emissionVector, float32 radius, bool useFilling) { Polygon3 pts; float32 angle = SEGMENT_LENGTH / radius; int ptsCount = (int)(PI_2 / (DegToRad(angle))) + 1; for (int k = 0; k < ptsCount; ++k) { float32 angleA = ((float)k / (ptsCount - 1)) * PI_2; float sinAngle = 0.0f; float cosAngle = 0.0f; SinCosFast(angleA, sinAngle, cosAngle); Vector3 directionVector(radius * cosAngle, radius * sinAngle, 0.0f); // Rotate the direction vector according to the current emission vector value. Vector3 zNormalVector(0.0f, 0.0f, 1.0f); Vector3 curEmissionVector = emissionVector; curEmissionVector.Normalize(); // This code rotates the (XY) plane with the particles to the direction vector. // Taking into account that a normal vector to the (XY) plane is (0,0,1) this // code is very simplified version of the generic "plane rotation" code. float32 length = curEmissionVector.Length(); if (FLOAT_EQUAL(length, 0.0f) == false) { float32 cosAngleRot = curEmissionVector.z / length; float32 angleRot = acos(cosAngleRot); Vector3 axisRot(curEmissionVector.y, -curEmissionVector.x, 0); Matrix3 planeRotMatrix; planeRotMatrix.CreateRotation(axisRot, angleRot); Vector3 rotatedVector = directionVector * planeRotMatrix; directionVector = rotatedVector; } Vector3 pos = center - directionVector; pts.AddPoint(pos); } if (useFilling) { FillPolygon(pts); } else { DrawPolygon(pts, false); } }
TEST_CASE_F(Triangulate_GivenSelfCrossingTriangle_ReturnsFalse, Fixture) { Polygon3 polygon; polygon.push_back(Vector3Type(0.0, 0.0, 1.0)); polygon.push_back(Vector3Type(3.0, 2.0, 2.0)); polygon.push_back(Vector3Type(3.0, 3.0, 3.0)); polygon.push_back(Vector3Type(1.0, 0.0, 0.0)); TriangulatorType triangulator; TriangulatorType::IndexArray triangles; const bool success = triangulator.triangulate(polygon, triangles); EXPECT_FALSE(success); }
TEST_CASE_F(Triangulate_GivenQuadWithCoincidentVertices_KeepDegenerateTrianglesIsTrue_ReturnsTwoTriangles, Fixture) { Polygon3 polygon; polygon.push_back(Vector3Type(0.0, 0.0, 0.0)); polygon.push_back(Vector3Type(0.0, 1.0, 0.0)); polygon.push_back(Vector3Type(1.0, 1.0, 0.0)); polygon.push_back(Vector3Type(0.0, 0.0, 0.0)); TriangulatorType triangulator(TriangulatorType::KeepDegenerateTriangles); TriangulatorType::IndexArray triangles; const bool success = triangulator.triangulate(polygon, triangles); ASSERT_TRUE(success); EXPECT_EQ(2 * 3, triangles.size()); }
void RenderHelper::DrawCylinder(const Vector3 & center, float32 radius, bool useFilling) { Polygon3 pts; float32 angle = SEGMENT_LENGTH / radius; int32 ptsCount = (int32)(PI_2 / (DegToRad(angle))) + 1; Vector<Vector2> vertexes; for(int32 i = 0; i <= ptsCount; i++) { float32 seta = i * 360.0f / (float32)ptsCount; float32 x = sin(DegToRad(seta)) * radius; float32 y = cos(DegToRad(seta)) * radius; vertexes.push_back(Vector2(x, y)); } for(int32 i = 0; i < ptsCount; ++i) { pts.AddPoint((Vector3(vertexes[i].x, vertexes[i].y, 1) * radius) + center); pts.AddPoint((Vector3(vertexes[i].x, vertexes[i].y, -1) * radius) + center); pts.AddPoint((Vector3(vertexes[i+1].x, vertexes[i+1].y, -1) * radius) + center); pts.AddPoint((Vector3(vertexes[i].x, vertexes[i].y, 1) * radius) + center); pts.AddPoint((Vector3(vertexes[i+1].x, vertexes[i+1].y, 1) * radius) + center); pts.AddPoint((Vector3(vertexes[i+1].x, vertexes[i+1].y, -1) * radius) + center); } if (useFilling) { FillPolygon(pts); } else { DrawPolygon(pts, true); } }
void RenderHelper::DrawCircle(const Vector3 & center, float32 radius) { Polygon3 pts; float32 angle = SEGMENT_LENGTH / radius; int ptsCount = (int)(2 * PI / (DegToRad(angle))) + 1; for (int k = 0; k < ptsCount; ++k) { float32 angle = ((float)k / (ptsCount - 1)) * 2 * PI; float32 sinA = sinf(angle); float32 cosA = cosf(angle); Vector3 pos = center - Vector3(sinA * radius, cosA * radius, 0); pts.AddPoint(pos); } DrawPolygon(pts, false); }
//! Merge all segments triangle's height of which bigger or equal than minTriangleHeight // http://www.math.ru/dic/276 void Polygon3::MergeFlatPolygonSegments(const Polygon3 &srcPolygon, Polygon3 &destPolygon, float32 minTriangleHeight) { float mh2 = minTriangleHeight * minTriangleHeight; destPolygon.Clear(); for (int i0 = 0; i0 < srcPolygon.pointCount - 2; ++i0) { destPolygon.AddPoint(srcPolygon.points[i0]); Vector3 v0 = srcPolygon.points[i0]; for (int i2 = i0 + 2; i2 < srcPolygon.pointCount; ++i2) { Vector3 v2 = srcPolygon.points[i2]; float c = (v2 - v0).Length(); float hc2 = 0.0f; for (int i1 = i0 + 1; i1 < i2; ++i1) { Vector3 v1 = srcPolygon.points[i1]; float a = (v1 - v0).Length(); float b = (v2 - v1).Length(); float p = (a + b + c) / 2.0f; hc2 = 4.0f * p * (p - a) * (p - b) * (p - c) / (c * c); if (hc2 >= mh2) { break; } } if (hc2 >= mh2) { i0 = i2 - 1 - 1; break; } } } destPolygon.AddPoint(srcPolygon.points.back()); }
void RenderHelper::DrawPolygon(const Polygon3 & polygon, bool closed) { int ptCount = polygon.pointCount; if (ptCount >= 2) { vertexStream->Set(TYPE_FLOAT, 3, 0, polygon.GetPoints()); RenderManager::Instance()->SetRenderEffect(RenderManager::FLAT_COLOR); RenderManager::Instance()->SetRenderData(renderDataObject); RenderManager::Instance()->DrawArrays(PRIMITIVETYPE_LINESTRIP, 0, ptCount); if (closed) { Vector3 line[2] = {Vector3(polygon.GetPoints()[0]), Vector3(polygon.GetPoints()[ptCount-1])}; vertexStream->Set(TYPE_FLOAT, 3, 0, line); RenderManager::Instance()->DrawArrays(PRIMITIVETYPE_LINESTRIP, 0, 2); } } }
void RenderHelper::FillPolygon(const Polygon3 & polygon) { int ptCount = polygon.pointCount; if (ptCount >= 3) { vertexStream->Set(TYPE_FLOAT, 3, 0, polygon.GetPoints()); RenderManager::Instance()->SetRenderEffect(RenderManager::FLAT_COLOR); RenderManager::Instance()->SetRenderData(renderDataObject); RenderManager::Instance()->DrawArrays(PRIMITIVETYPE_TRIANGLEFAN, 0, ptCount); } }
TEST_CASE_F(Triangulate_GivenComplexConcavePolygon_ReturnsTrue, Fixture) { Polygon3 polygon; polygon.push_back(Vector3Type(0.137498, -1.09128, 0.0)); polygon.push_back(Vector3Type(0.124257, -1.10419, 0.0)); polygon.push_back(Vector3Type(0.124257, -1.31878, 0.0)); polygon.push_back(Vector3Type(0.240957, -1.30956, 0.0)); polygon.push_back(Vector3Type(0.240957, 1.3116, 0.0)); polygon.push_back(Vector3Type(0.124256, 1.30447, 0.0)); polygon.push_back(Vector3Type(0.124256, 1.08131, 0.0)); polygon.push_back(Vector3Type(0.137498, 1.0684, 0.0)); polygon.push_back(Vector3Type(0.160558, 1.02428, 0.0)); polygon.push_back(Vector3Type(0.168503, 0.975371, 0.0)); polygon.push_back(Vector3Type(0.168503, -0.998254, 0.0)); polygon.push_back(Vector3Type(0.160558, -1.04716, 0.0)); TriangulatorType triangulator; TriangulatorType::IndexArray triangles; const bool success = triangulator.triangulate(polygon, triangles); EXPECT_TRUE(success); }
void RenderHelper::DrawPolygonPoints(const Polygon3 & polygon) { int ptCount = polygon.pointCount; if (ptCount >= 1) { #if defined (__DAVAENGINE_OPENGL__) glPointSize(3.0f); #endif vertexStream->Set(TYPE_FLOAT, 3, 0, polygon.GetPoints()); RenderManager::Instance()->SetRenderEffect(RenderManager::FLAT_COLOR); RenderManager::Instance()->SetRenderData(renderDataObject); RenderManager::Instance()->DrawArrays(PRIMITIVETYPE_POINTLIST, 0, ptCount); #if defined (__DAVAENGINE_OPENGL__) glPointSize(1.0f); #endif } }