Merge pull request #49723 from aaronfranke/fix-csg-sphere

Fix CSGSphere3D mesh creation
This commit is contained in:
Rémi Verschelde 2021-07-28 09:02:07 +02:00 committed by GitHub
commit d426523440
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -923,36 +923,40 @@ CSGBrush *CSGSphere3D::_build_brush() {
Ref<Material> *materialsw = materials.ptrw(); Ref<Material> *materialsw = materials.ptrw();
bool *invertw = invert.ptrw(); bool *invertw = invert.ptrw();
const double lat_step = 1.0 / rings; // We want to follow an order that's convenient for UVs.
const double lon_step = 1.0 / radial_segments; // For latitude step we start at the top and move down like in an image.
const double latitude_step = -Math_PI / rings;
const double longitude_step = Math_TAU / radial_segments;
int face = 0; int face = 0;
for (int i = 1; i <= rings; i++) { for (int i = 0; i < rings; i++) {
double lat0 = Math_PI * (0.5 - (i - 1) * lat_step); double latitude0 = latitude_step * i + Math_TAU / 4;
double c0 = Math::cos(lat0); double cos0 = Math::cos(latitude0);
double s0 = Math::sin(lat0); double sin0 = Math::sin(latitude0);
double v0 = double(i - 1) / rings; double v0 = double(i) / rings;
double lat1 = Math_PI * (0.5 - i * lat_step); double latitude1 = latitude_step * (i + 1) + Math_TAU / 4;
double c1 = Math::cos(lat1); double cos1 = Math::cos(latitude1);
double s1 = Math::sin(lat1); double sin1 = Math::sin(latitude1);
double v1 = double(i) / rings; double v1 = double(i + 1) / rings;
for (int j = 1; j <= radial_segments; j++) { for (int j = 0; j < radial_segments; j++) {
double lng0 = Math_TAU * (0.5 - (j - 1) * lon_step); double longitude0 = longitude_step * j;
double x0 = Math::cos(lng0); // We give sin to X and cos to Z on purpose.
double y0 = Math::sin(lng0); // This allows UVs to be CCW on +X so it maps to images well.
double u0 = double(j - 1) / radial_segments; double x0 = Math::sin(longitude0);
double z0 = Math::cos(longitude0);
double u0 = double(j) / radial_segments;
double lng1 = Math_TAU * (0.5 - j * lon_step); double longitude1 = longitude_step * (j + 1);
double x1 = Math::cos(lng1); double x1 = Math::sin(longitude1);
double y1 = Math::sin(lng1); double z1 = Math::cos(longitude1);
double u1 = double(j) / radial_segments; double u1 = double(j + 1) / radial_segments;
Vector3 v[4] = { Vector3 v[4] = {
Vector3(x0 * c0, s0, y0 * c0) * radius, Vector3(x0 * cos0, sin0, z0 * cos0) * radius,
Vector3(x1 * c0, s0, y1 * c0) * radius, Vector3(x1 * cos0, sin0, z1 * cos0) * radius,
Vector3(x1 * c1, s1, y1 * c1) * radius, Vector3(x1 * cos1, sin1, z1 * cos1) * radius,
Vector3(x0 * c1, s1, y0 * c1) * radius, Vector3(x0 * cos1, sin1, z0 * cos1) * radius,
}; };
Vector2 u[4] = { Vector2 u[4] = {
@ -962,8 +966,8 @@ CSGBrush *CSGSphere3D::_build_brush() {
Vector2(u0, v1), Vector2(u0, v1),
}; };
if (i < rings) { // Draw the first face, but skip this at the north pole (i == 0).
//face 1 if (i > 0) {
facesw[face * 3 + 0] = v[0]; facesw[face * 3 + 0] = v[0];
facesw[face * 3 + 1] = v[1]; facesw[face * 3 + 1] = v[1];
facesw[face * 3 + 2] = v[2]; facesw[face * 3 + 2] = v[2];
@ -979,8 +983,8 @@ CSGBrush *CSGSphere3D::_build_brush() {
face++; face++;
} }
if (i > 1) { // Draw the second face, but skip this at the south pole (i == rings - 1).
//face 2 if (i < rings - 1) {
facesw[face * 3 + 0] = v[2]; facesw[face * 3 + 0] = v[2];
facesw[face * 3 + 1] = v[3]; facesw[face * 3 + 1] = v[3];
facesw[face * 3 + 2] = v[0]; facesw[face * 3 + 2] = v[0];