Introduction to 3D Modeling. Section 6. Advanced Projects

6 Advanced Projects

Objectives:

  • Practice your scripting skills.
  • Create more complex designs.
  • Learn to decompose complicated designs into smaller steps.

6.1 Carrousel

Let us start with something simple - a carrousel created by translating anf rotating a few thin toruses:

# Define parameters:  
r1 = 0.95  
r2 = 1.0  
r_mid = 0.5 * (r1 + r2)  
h = 0.5 * (r2 - r1)  
 
# Create two master toruses:  
t1 = TORUS(r1, r2)  
t2 = TORUS(r_mid*cos(PI/6) - h, r_mid*cos(PI/6) + h)  
 
# Create two smaller horizontal toruses:  
elevation = r_mid * sin(PI/6)  
MOVE(t2, 0, 0, elevation)  
t3 = COPY(t2)  
MOVE(t3, 0, 0, -2 * elevation)  
 
# Create six vertical toruses:  
t4 = COPY(t1)  
ROTATE(t4, 90, 1)  
t5 = COPY(t4)  
ROTATE(t5, 30, 3)  
t6 = COPY(t5)  
ROTATE(t6, 30, 3)  
t7 = COPY(t6)  
ROTATE(t7, 30, 3)  
t8 = COPY(t7)  
ROTATE(t8, 30, 3)  
t9 = COPY(t8)  
ROTATE(t9, 30, 3)  
 
# Assign colors:  
COLOR(t1, RED)  
COLOR(t2, GREEN)  
COLOR(t3, BLUE)  
COLOR(t4, YELLOW)  
COLOR(t5, YELLOW)  
COLOR(t6, YELLOW)  
COLOR(t7, YELLOW)  
COLOR(t8, YELLOW)  
COLOR(t9, YELLOW)  
 
# Display everything:  
SHOW(t1, t2, t3, t4, t5, t6, t7, t8, t9)

The outpur is shown in Fig. 95.


PIC


Fig. 95: Carrousel.


6.2 Temple

In this subsection we will build the temple that we have seen in Subsection 1.3:


PIC


Fig. 96: 3D model of a temple.


Let us begin with defining variables for the radius and height of the columns:

# Column radius and height:  
r = 1.0  
h = 12.0

Next let’s create one column:

# Create one column:  
basis = BOX(2*r*1.2, 2*r*1.2, h/12.0)  
trunk = CYLINDER(r, (10.0/12.0)*h)  
capital = COPY(basis)  
beam = COPY(capital)  
SCALE(beam, 3, 1, 1)  
column = TOP(TOP(TOP(basis, trunk), capital), beam)  
column = WELD(column)

The column is displayed in Fig. 97.


PIC


Fig. 97: One column.


In the next step we will form a column row by placing n = 4 columns next to each other.

# Number of columns in one row:  
n = 4  
 
# Column row:  
colrow = []  
for i in range(n):  
  newcol = COPY(column)  
  MOVE(newcol, i * 6*r*1.2, 0, 0)  
  colrow.append(newcol)

The column row is displayed in Fig. 98.


PIC


Fig. 98: Column row.


Now we can create the gable and position it on top of the column row:

# Create gable:  
triangle = TRIANGLE([0, 0], [n*3*2*r*1.2, 0], [n*3*r*1.2, h/2])  
prism = PRISM(triangle, r*1.2)  
gable = COPY(prism)  
ROTATE(gable, 90, 1)  
 
# Portal:  
MOVE(gable, -2*r*1.2, 1.5*r*1.2, h/12.0 + (10.0/12.0)*h  
     + 2*h/12.0)  
portal = STRUCT(colrow, gable)

The portal is shown in Fig. 99.


PIC


Fig. 99: The portal.


Append m = 4 inner column rows, and then once more the portal at the end:

# Number of inner column rows:  
m = 4  
 
# Temple base as a list:  
temple_base = [portal]  
for i in range(1, m+1):  
    newcolrow = COPY(colrow)  
    MOVE(newcolrow, 0, 6*i, 0)  
    temple_base.append(newcolrow)  
newportal = COPY(portal)  
MOVE(newportal, 0, 6*(m+1), 0)  
temple_base.append(newportal)

The temple base is displayed in Fig. 100.


PIC


Fig. 100: Temple base.


In the next step we create the foundation plate which is just a box of dimensions 32, 40 and 1 m.

# Create a plate for the temple to stand on:  
ground = BOX(32, 40, 1)  
MOVE(ground, -4.6, -3.8, -0.9)

The last component we need are the secondary roof beams. They are created using the GRID and PRODUCT command that we learned in Subsection 2.25:

# Secondary roof beams:  
x_intervals = GRID(14 * [0.6, -1.2])  
y_intervals = GRID([-0.7] + 5 * [-1, 5])  
z_interval = GRID([-13, 0.6])  
secondary_beams = POWER(POWER(x_intervals, y_intervals), z_interval)

The secondary roof beams are displayed in Fig. 101.


PIC


Fig. 101: Secondary roof beams.


After putting everything together,

# Put all parts together:  
out = UNION(temple_base, secondary_beams, ground)  
COLOR(out, WHITE)

we obtain the model from Fig. 96.

6.3 Sierpinski fractals

Sierpinski fractals are famous fractal sets that saw the light of the world around 1915 before the Mandelbrot’s and Julia’s fractals appeared. The Sierpinski triangle and carpet are shown in Fig. 102.


PIC   PIC


Fig. 102: Sierpinski triangle and carpet.


Both these fractals have their 3D versions, called the Sierpinski tetrahedron and Menger sponge, respectively. They are easy to find in the Internet.

We will only discuss the triangle here since the other shapes work in a similar way. The triangle fractal is constructed by recursively subtracting smaller equilateral triangles from an original equilateral triangle, as shown in Fig. 103.


PIC


Fig. 103: Construction of the Sierpinski triangle fractal.


This process is infinite in mathematical theory, while in reality we only can perform a finite number of steps. Moreover, the procedure that we just described is good from the mathematical point of view, while it is not the best from the point of view of computer implementation. Why is this?

We learned in Subsection 4.5 that it is not a good idea to perform Boolean operations between complex objects with many faces. This leads to a large number of operations and the computation takes a long time. Subtracting a triangle from a fractal that already has many holes is exactly what we should avoid.

Fortunately, there is an elegant way around this which does not use any Boolean operations at all. We start by creating an object st (Sierpinski Triangle) that will be just a single equilateral triangle (0, 0), (1, 0), (12,∘ ----
  3∕4).


PIC


Fig. 104: Initial object st.


Then we add to the object st two identical objects that are obtained via translating st to "east" by the 3D vector (1, 0, 0) and to "north-east" by the 3D vector (12,∘  ----
   3∕4, 0).


PIC


Fig. 105: Object st after adding two identical copies to it.


Of course we do not want our fractal to grow infinitely, so we rescale the new object st (that comprises three triangles now) by 12 in the x and y directions.


PIC


Fig. 106: Object st scaled back to original size.


Now it is sufficient to apply to the new object st the procedure that we described above – adding two identical copies and rescale – as many times as we want. This will create the Sierpinski Triangle fractal. The program looks as follows:

# Number of levels of the Sierpinski triangle:  
# Do not go much higher than 6, number of  
# operations grows exponentially.  
level = 6  
 
# Height of equilateral triangle with unit base:  
from numpy import sqrt  
h = sqrt(0.75)  
 
# Initial object ’st’ is a triangle.  
st = TRIANGLE([0, 0], [1, 0], [0.5, h])  
 
# Add two identical copies of ’st’  
# and rescale back to (0, 1):  
for i in range(level - 1):  
    st1 = COPY(st)  
    MOVE(st1, 0.5, h)  
    st2 = COPY(st)  
    MOVE(st2, 1.0, 0.0)  
    st = UNION(st, st1, st2)  
    SCALE(st, 0.5, 0.5)  
 
# Display in blue color:  
COLOR(st, BLUE)  
SHOW(st)

The resulting geometry for k = 6 levels is shown in Fig. 107. It is easy to calculate that with k levels, the geometry consists of 3k-1 triangles. This means exponential growth – with k = 6 there are 243 triangles, with k = 7 there are 729, with k = 8 there are 2187 etc. Therefore, do not use k much higher than 6.


PIC


Fig. 107: Resulting geometry for k = 6.


6.4 3D gear

In this section we will build the 3D gear that we have seen in Subsection 1.3. In the first step let us define a color along with parameters and measures of one tooth, and create one tooth as a convex hull.

# Number of teeth:  
N = 18  
 
# Width of the tooth:  
x0  = 8  
dx1 = 1  
dx2 = 2.5  
 
# Height of the tooth:  
y0  = 30  
dy1 = 0.5  
dy2 = 4  
 
# Depth of the tooth:  
z1 = 5  
z2 = 8

# Base inner and outer radius, height:  
# (Do not change these)  
base_rin  = 22  
base_rout = 30  
base_h    = 32  
 
# Vertices:  
pts_base = [[0, 0, 0], [x0, 0, 0], [x0, y0, 0], [0, y0, 0]]  
pts_mid  = [[dx1, dy1, z1], [x0 - dx1, dy1, z1], [x0 - dx1, y0 - dy1, z1],  
[dx1, y0 - dy1, z1]]  
pts_top  = [[dx2, dy2, z2], [x0 - dx2, dy2, z2], [x0 - dx2, y0 - dy2, z2],  
[dx2, y0 - dy2, z2]]  
 
# Merging the point lists:  
pts = pts_base + pts_mid + pts_top  
 
# Toothe is a convexhull of the points:  
t = CHULL(pts)

The result is displayed in Fig. 108.


PIC


Fig. 108: One tooth of the gear.


Next we create all teeth by translating and replicating the first one:

# Rotate and translate the tooth:  
ROTATE(t, 90, 1)  
ROTATE(t, 90, 3)  
MOVE(t, base_rout - 0.3, -x0/2., 0)  
 
# Calculate the angle of rotation:  
angle = 360./N  
 
# Create all teeth:  
gear = []  
for i in range(N):  
    ROTATE(t, i * angle, 3)  
    gear.append(t)

The result is displayed in Fig. 109.


PIC


Fig. 109: Teeth are created by replicating the first one.


In the next step we create the base of the gear:

# Base:  
base = TUBE(base_rin, base_rout, base_h, 128)  
dz = (base_h - y0)/2.  
MOVE(base, 0, 0, -dz)

The result is displayed in Fig. 110.


PIC


Fig. 110: Base of the gear.


In order to construct the top ring, we use a regular and a truncated cone.

# Truncated cone:  
tc1 = TCONE(base_rout, base_rout - 1, 1)  
MOVE(tc1, 0, 0, base_h)  
 
# Regular cone:  
cone = CONE(base_rout, base_rout)  
ROTATE(cone, 180, 2)  
MOVE(cone, 0, 0, 40)  
 
# Assign colors:  
COLOR(cone, RED)  
COLOR(tc1, BRASS)  
 
# Display the objects together:  
SHOW(tc1, cone)

The result is displayed in Fig. 111.


PIC


Fig. 111: Getting ready to drill a hole into a truncated cone.


The hole is drilled by subtracting the regular cone from the truncated one.

# Difference of the cones:  
tc = DIFF(tc1, cone)

The result is displayed in Fig. 112.


PIC


Fig. 112: Top ring.


Next the ring and the teeth are attached to the base.

# Put the ring above the base:  
base = TOP(base, tc)  
 
# Attach teeth:  
gear.append(base)

The result is displayed in Fig. 113.


PIC


Fig. 113: Attach the ring and the teeth to the base.


Last we need to build the inner part of the gear. First, create a tube and three boxes:

# Inner layer thickness:  
inner_dr  = 3  
 
# Create inner tube:  
inner = TUBE(base_rin - inner_dr, base_rin, base_h * 0.75)  
MOVE(inner, 0, 0, base_h * 0.25)  
 
# Define three boxes:  
b1 = BOX(50, 10, 35)  
MOVE(b1, -25, -5, 0)  
b2 = COPY(b1)  
ROTATE(b2, 60, 3)  
b3 = COPY(b2)  
ROTATE(b3, 60, 3)  
str = [b1, b2, b3]  
 
# Assign colors:  
COLOR(inner, BRASS)  
COLOR(str, RED)  
 
# Display the objects together:  
SHOW(inner, str)

The result is displayed in Fig. 114.


PIC


Fig. 114: Base for the inner part and boxes to be subtracted.


Next we subtract the three boxes from the tube.

# Subtract all three boxes from the tube:  
inner = DIFF(inner, b1, b2, b3)

The result is displayed in Fig. 115.


PIC


Fig. 115: Result after subtracting the boxes.


Then we subtract the original cone from the inner part.

# Subtract cone from inner part:  
inner = DIFF(inner, cone)  
 
# Translate the inner part:  
MOVE(inner, 0, 0, -dz)  
 
# Assign colors:  
COLOR(inner, BRASS)  
COLOR(cone, RED)  
 
# Display the objects together:  
SHOW(inner, cone)

The result is displayed in Figs. 116 and 117.


PIC


Fig. 116: Cone to be subtracted from the inner part.



PIC


Fig. 117: Result after subtracting the cone.


Finally we attach the inner part to the gear:

# Append inner part to gear:  
gear.append(inner)  
 
# Display the gear:  
COLOR(gear, BRASS)  
SHOW(gear)

The final geometry is shown in Fig. 118.


PIC


Fig. 118: Final geometry.



Table of Contents

Created on August 6, 2018 in 3D Modeling.
Add Comment
0 Comment(s)

Your Comment

By posting your comment, you agree to the privacy policy and terms of service.