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

95 lines
3.8 KiB
Python

"""
Copyright (c) Contributors to the Open 3D Engine Project.
For complete copyright and license terms please see the LICENSE at the root of this distribution.
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)