You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Gems/WhiteBox/Editor/Scripts/Sphere.py

94 lines
3.7 KiB
Python

"""
Copyright (c) Contributors to the Open 3D Engine Project
SPDX-License-Identifier: Apache-2.0 OR MIT
"""
import Icosahedron
import WhiteBoxMath as whiteBoxMath
import WhiteBoxInit as init
import argparse
import azlmbr.legacy.general as general
import azlmbr.bus as bus
import azlmbr.whitebox.api as api
# usage: pyRunFile path/to/file/sphere.py <subdivisions>
# get the midpoint of v1 and v2 from created_midpoints if already made, otherwise create new one
def get_midpoint_vertex(whiteBoxMesh, v1, v2, radius, created_midpoints):
# get the index of the vertices to look them up
index1 = v1.Index()
index2 = v2.Index()
# search created_midpoints to see if this midpoint has already been made
# we store edges as tuples but keep in mind the edge (v1, v2) == (v2, v1) so we search both
if (index1, index2) in created_midpoints:
return created_midpoints.get((index1, index2))
if (index2, index1) in created_midpoints:
return created_midpoints.get((index2, index1))
# create the new midpoint vertex and store in created_midpoints
pos1 = whiteBoxMesh.VertexPosition(v1)
pos2 = whiteBoxMesh.VertexPosition(v2)
midpoint = whiteBoxMesh.AddVertex(whiteBoxMath.normalize_midpoint(pos1, pos2, radius))
created_midpoints.update({(index1, index2): midpoint})
return midpoint
# divide each triangular face into four smaller faces
def subdivide_faces(whiteBoxMesh, faces, radius):
new_faces = []
created_midpoints = dict()
for faceVertHandles in faces:
# get each vertex
v0 = faceVertHandles.VertexHandles[0]
v1 = faceVertHandles.VertexHandles[1]
v2 = faceVertHandles.VertexHandles[2]
# get the vertex representing the midpoint of each of the edges
v3 = get_midpoint_vertex(whiteBoxMesh, v0, v1, radius, created_midpoints)
v4 = get_midpoint_vertex(whiteBoxMesh, v1, v2, radius, created_midpoints)
v5 = get_midpoint_vertex(whiteBoxMesh, v0, v2, radius, created_midpoints)
# create four subdivided faces for each original face
new_faces.append(api.util_MakeFaceVertHandles(v0, v3, v5))
new_faces.append(api.util_MakeFaceVertHandles(v3, v1, v4))
new_faces.append(api.util_MakeFaceVertHandles(v4, v2, v5))
new_faces.append(api.util_MakeFaceVertHandles(v3, v4, v5))
return new_faces
# create sphere by subdividing an icosahedron
def create_sphere(whiteBoxMesh, subdivisions=2, radius=0.55):
# create icosahedron faces and subdivide them to create a sphere
icosahedron_faces = Icosahedron.create_icosahedron_faces(whiteBoxMesh, radius)
for division in range (0, subdivisions):
icosahedron_faces = subdivide_faces(whiteBoxMesh, icosahedron_faces, radius)
for face in icosahedron_faces:
whiteBoxMesh.AddPolygon([face])
if __name__ == "__main__":
# cmdline arguments
parser = argparse.ArgumentParser(description='Creates a sphere shaped white box mesh.')
parser.add_argument('subdivisions', nargs='?', default=3, choices=range(0, 5), type=int, help='number of subdivisions to form sphere from icosahedron')
parser.add_argument('radius', nargs='?', default=0.55, type=float, help='radius of the sphere')
args = parser.parse_args()
# initialize whiteBoxMesh
whiteBoxEntity = init.create_white_box_entity("WhiteBox-Sphere")
whiteBoxMeshComponent = init.create_white_box_component(whiteBoxEntity)
whiteBoxMesh = init.create_white_box_handle(whiteBoxMeshComponent)
# clear whiteBoxMesh to make a sphere from scratch
whiteBoxMesh.Clear()
create_sphere(whiteBoxMesh, args.subdivisions, args.radius)
# update whiteBoxMesh
init.update_white_box(whiteBoxMesh, whiteBoxMeshComponent)