Rajawali / Rajawali

Android OpenGL ES 2.0/3.0 Engine
https://rajawali.github.io/Rajawali/
Other
2.32k stars 700 forks source link

Create Sphere with phiStart, phiLength, thetaStart, thetaLength #2460

Closed devdivr closed 1 year ago

devdivr commented 1 year ago

Hi, I'm trying to create a sphere with phiStart, phiLength, thetaStart, thetaLength to show parts of Sphere. SphereGeometry.js in three.js is the reference to implement it but it's not shown as expected. If you could check what's wrong, it would be helpful to go further.

class CustomSphere(
    radius: Float,
    widthSegments: Int = 32,
    heightSegments: Int = 16,
    phiStart: Double,
    phiLength: Double,
    thetaStart: Double,
    thetaLength: Double
) : Object3D() {

    init {
        val thetaEnd = min(thetaStart + thetaLength, Math.PI)

        var index = 0
        val grid = arrayListOf<ArrayList<Int>>()

        val vertex = Vector3()
        var normal = Vector3()

        // buffers
        val indices = arrayListOf<Int>()
        val vertices = arrayListOf<Float>()
        val normals = arrayListOf<Float>()
        val uvs = arrayListOf<Float>()

        // generate vertices, normals and uvs
        for (iy in 0..heightSegments) {
            val verticesRow: ArrayList<Int> = arrayListOf()

            val v = iy / heightSegments

            // special case for the poles
            var uOffset = 0.0

            if (iy == 0 && thetaStart == 0.0) {
                uOffset = 0.5 / widthSegments
            } else if (iy == heightSegments && thetaEnd == Math.PI) {
                uOffset = -0.5 / widthSegments
            }

            for (ix in 0..widthSegments) {
                val u = ix / widthSegments

                // vertex
                vertex.x = -radius * cos(phiStart + u * phiLength) * sin(thetaStart + v * thetaLength)
                vertex.y = radius * cos(thetaStart + v * thetaLength)
                vertex.z = radius * sin(phiStart + u * phiLength) * sin(thetaStart + v * thetaLength)

                vertices.add(vertex.x.toFloat())
                vertices.add(vertex.y.toFloat())
                vertices.add(vertex.z.toFloat())

                // normal
                normal = vertex.clone().normalized()
                normals.add(normal.x.toFloat())
                normals.add(normal.y.toFloat())
                normals.add(normal.z.toFloat())

                // uv
                uvs.add((u + uOffset).toFloat())
                uvs.add((1 - v).toFloat())

                verticesRow.add(index++)
            }

            grid.add(verticesRow)

        }

        // indices
        for (iy in 0 until heightSegments) {
            for (ix in 0 until widthSegments) {
                val a = grid[iy][ix + 1]
                val b = grid[iy][ix]
                val c = grid[iy + 1][ix]
                val d = grid[iy + 1][ix + 1]

                if (iy !== 0 || thetaStart > 0) {
                    indices.add(a)
                    indices.add(b)
                    indices.add(d)
                }
                if (iy !== heightSegments - 1 || thetaEnd < Math.PI) {
                    indices.add(b)
                    indices.add(c)
                    indices.add(d)
                }
            }
        }

        // build geometry
        setData(
            vertices.toFloatArray(),
            normals.toFloatArray(),
            uvs.toFloatArray(),
            null,
            indices.toIntArray(),
            true
        )
    }
}
devdivr commented 1 year ago

I resolved this issue. Thanks