void Cylinder::getRandomSurfacePoint(Vector3& p, Vector3& N) const { float h = height(); float r = radius(); // Create a random point on a standard cylinder and then rotate to the global frame. // Relative areas (factor of 2PI already taken out) float capRelArea = square(r) / 2.0f; float sideRelArea = r * h; float r1 = uniformRandom(0, capRelArea * 2 + sideRelArea); if (r1 < capRelArea * 2) { // Select a point uniformly at random on a disk // @cite http://mathworld.wolfram.com/DiskPointPicking.html float a = uniformRandom(0, (float)twoPi()); float r2 = sqrt(uniformRandom(0, 1)) * r; p.x = cos(a) * r2; p.z = sin(a) * r2; N.x = 0; N.z = 0; if (r1 < capRelArea) { // Top p.y = h / 2.0f; N.y = 1; } else { // Bottom p.y = -h / 2.0f; N.y = -1; } } else { // Side float a = uniformRandom(0, (float)twoPi()); N.x = cos(a); N.y = 0; N.z = sin(a); p.x = N.x * r; p.z = N.y * r; p.y = uniformRandom(-h / 2.0f, h / 2.0f); } // Transform to world space CoordinateFrame cframe; getReferenceFrame(cframe); p = cframe.pointToWorldSpace(p); N = cframe.normalToWorldSpace(N); }
Vector3 Cylinder::randomInteriorPoint() const { float h = height(); float r = radius(); // Create a random point in a standard cylinder and then rotate to the global frame. // Select a point uniformly at random on a disk // @cite http://mathworld.wolfram.com/DiskPointPicking.html float a = uniformRandom(0, (float)twoPi()); float r2 = sqrt(uniformRandom(0, 1)) * r; Vector3 p( cos(a) * r2, uniformRandom(-h / 2.0f, h / 2.0f), sin(a) * r2); // Transform to world space CoordinateFrame cframe; getReferenceFrame(cframe); return cframe.pointToWorldSpace(p); }
void Capsule::getRandomSurfacePoint(Vector3& p, Vector3& N) const { float h = height(); float r = radius(); // Create a random point on a standard capsule and then rotate to the global frame. // Relative areas float capRelArea = sqrt(r) / 2.0f; float sideRelArea = r * h; float r1 = uniformRandom(0, capRelArea * 2 + sideRelArea); if (r1 < capRelArea * 2) { // Select a point uniformly at random on a sphere N = Sphere(Vector3::zero(), 1).randomSurfacePoint(); p = N * r; p.y += sign(p.y) * h / 2.0f; } else { // Side float a = uniformRandom(0, (float)twoPi()); N.x = cos(a); N.y = 0; N.z = sin(a); p.x = N.x * r; p.z = N.y * r; p.y = uniformRandom(-h / 2.0f, h / 2.0f); } // Transform to world space CoordinateFrame cframe; getReferenceFrame(cframe); p = cframe.pointToWorldSpace(p); N = cframe.normalToWorldSpace(N); }
Vector3 Capsule::randomInteriorPoint() const { float h = height(); float r = radius(); // Create a random point in a standard capsule and then rotate to the global frame. Vector3 p; float hemiVolume = pi() * (r*r*r) * 4 / 6.0; float cylVolume = pi() * square(r) * h; float r1 = uniformRandom(0, 2.0 * hemiVolume + cylVolume); if (r1 < 2.0 * hemiVolume) { p = Sphere(Vector3::zero(), r).randomInteriorPoint(); p.y += sign(p.y) * h / 2.0f; } else { // Select a point uniformly at random on a disk float a = uniformRandom(0, (float)twoPi()); float r2 = sqrt(uniformRandom(0, 1)) * r; p = Vector3(cos(a) * r2, uniformRandom(-h / 2.0f, h / 2.0f), sin(a) * r2); } // Transform to world space CoordinateFrame cframe; getReferenceFrame(cframe); return cframe.pointToWorldSpace(p); }
void MeshAlg::generateGrid( Array<Vector3>& vertex, Array<Vector2>& texCoord, Array<int>& index, int wCells, int hCells, const Vector2& textureScale, bool spaceCentered, bool twoSided, const CoordinateFrame& xform, const Image1::Ref& height) { vertex.fastClear(); texCoord.fastClear(); index.fastClear(); // Generate vertices for (int z = 0; z <= hCells; ++z) { for (int x = 0; x <= wCells; ++x) { Vector3 v(x / (float)wCells, 0, z / (float)hCells); Vector2 t = v.xz() * textureScale; texCoord.append(t); if (height.notNull()) { v.y = height->nearest(v.x * (height->width() - 1), v.z * (height->height() - 1)).value; } if (spaceCentered) { v -= Vector3(0.5f, 0, 0.5f); } v = xform.pointToWorldSpace(v); vertex.append(v); } } // Generate indices for (int z = 0; z < hCells; ++z) { for (int x = 0; x < wCells; ++x) { int A = x + z * (wCells + 1); int B = A + 1; int C = A + (wCells + 1); int D = C + 1; // A B // *-----* // | \ | // | \ | // *-----* // C D index.append(A, D, B); index.append(A, C, D); } } if (twoSided) { // The index array needs to have reversed winding for the bottom // and offset by the original number of vertices Array<int> ti = index; ti.reverse(); for (int i = 0; i < ti.size(); ++i) { ti[i] += vertex.size(); } index.append(ti); // Duplicate the arrays vertex.append(Array<Vector3>(vertex)); texCoord.append(Array<Vector2>(texCoord)); } }