All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ai.dragonfly.mesh.shape.Drum.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2023 dragonfly.ai
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package ai.dragonfly.mesh.shape

import narr.*
import scala.language.implicitConversions

import slash.Constant.π

import slash.vector.*
import Vec.*

import ai.dragonfly.mesh.*

import scala.scalajs.js.annotation.JSExportTopLevel

object Drum {

  @JSExportTopLevel("Drum")
  def apply(
    angularSegments: Int = 12, sideSegments: Int = 1, baseSegments:Int = 1, capSegments: Int = 1,
    baseRadius: Double = 2.0, capRadius: Double = 1.0, height: Double = 1.0, name:String = "Drum"
  ): Mesh = {

    if (angularSegments < 3) throw new IllegalArgumentException("Drum doesn't support radial segment values less than 3.")
    if (sideSegments < 1 || baseSegments < 1 || capSegments < 1) throw new IllegalArgumentException("Drum doesn't support 0 segment values.")
    if (height < 0.0 || baseRadius < 0.0 || capRadius < 0.0) throw new IllegalArgumentException("Drum doesn't support negative dimension values.")

    val Δθ: Double = (2 * π) / angularSegments
    val cuts: Int = 2 + baseSegments + sideSegments + capSegments - 3

    val points: NArray[Vec[3]] = NArray.ofSize[Vec[3]](2 + (cuts * angularSegments))
    //  println(points.length)

    val pEnd: Int = points.length - 1

    points(0) = Vec[3](0, 0, 0)
    points(pEnd) = Vec[3](0, 0, height)

    var dT = 0.0
    var p = 1
    var pcount = 2;

    var cut:Int = 0; while (cut < cuts) {

      cut += 1

      p = 1
      while (p <= angularSegments) {

        var r:Double = baseRadius
        var h:Double = 0

        if (cut < baseSegments) {
          val w:Double = cut.toDouble / baseSegments.toDouble
          r = baseRadius * w
          //(cut.toDouble / sideSegments.toDouble) * height)
        } else if (cut == baseSegments) {
          r = baseRadius
        } else if (cut < baseSegments + sideSegments) {
          val w:Double = (cut - baseSegments).toDouble / sideSegments.toDouble
          r = w * baseRadius + (1.0 - w) * capRadius
          h = w * height
        } else if (cut == baseSegments + sideSegments) {
//          val w:Double = (cut - baseSegments).toDouble / sideSegments.toDouble
          r = capRadius
          h = height
        } else {
          val w:Double = 1.0 - ((cut - (baseSegments + sideSegments)).toDouble / capSegments.toDouble)
          r = capRadius * w
          h = height
        }

        val x: Double = r * Math.cos(dT)
        val y: Double = r * Math.sin(dT)

        val cutOffset: Int = (cut - 1) * angularSegments
        points(cutOffset + p) = Vec[3](x, y, h)

        dT = p * Δθ
        p = p + 1

      }
      pcount += p - 1

    }

    //    println(pcount)

    val triangles: NArray[Triangle] = new NArray[Triangle](
      2 * angularSegments * ( baseSegments + capSegments + sideSegments - 1 )
    )

    p = 1
    var t = 0

    val coEnd: Int = pEnd - angularSegments - 1 // cuts * radialSegments
    while (p <= angularSegments) {
      val ps: Int = p % angularSegments
      triangles(t) = Triangle(0, ps + 1, p) // bottom
      triangles(t + 1) = Triangle(pEnd, coEnd + p, coEnd + ps + 1) // top
      t += 2
      p += 1
    }

    cut = 0; while (cut < cuts) {

      val cutOffset: Int = cut * angularSegments

      p = 1

      while (p <= angularSegments && t < triangles.length) {
        val ps: Int = p % angularSegments
        val off2 = cutOffset + angularSegments

        t = addQuad(
          off2 + p,
          cutOffset + ps + 1,
          off2 + ps + 1,
          cutOffset + p,
          triangles,
          t
        )

        p += 1
      }
      cut += 1
    }

    println(s"triangles.length = ${triangles.length}, and t = $t")

    new Mesh(points, triangles, name)
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy