Introduction to 3D Modeling. Section 4. Advanced Topics
4 Advanced Topics
Objectives:
- Learn about the XOR operation with solid objects.
- Learn more details about scaling.
- Learn advanced alignment operations.
- Learn to measure dimensions of objects.
- Learn to use Boolean operations more efficiently.
4.1 XOR of objects
XOR ("exclusive or") is after the union, intersection, and difference of objects the last
important Boolean operation of solid modeling.
For illustration let us overlap two differently rotated cubes, show their union and
intersection, and calculate their XOR:
c = CUBE(2)
# Move c so that its center lies at origin (0, 0, 0):
MOVE(c, -1, -1, -1)
# Rotate cube c by 45 degrees about the z-axis:
d = COPY(c)
ROTATE(d, 45, 3)
# Assign colors:
union = UNION(c, d)
COLOR(union, GOLD)
intersection = INTERSECTION(c, d)
COLOR(intersection, RED)
# Display the result:
SHOW(union, intersection)
e = XOR(c, d)
COLOR(e, GOLD)
# Display the result:
SHOW(e)
The two outputs are shown in the left and right parts of Fig. 84.
4.2 More on scaling
When applying the command SCALE(obj, sx, sy, sz), or its abbreviation S(obj,
sx, sy, sz), the x-coordinates of all points in the object obj are multiplied with sx, all
y-coordinates with sy, and all z-coordinates with sz. Hence, if the object obj is not centered
at the origin, it moves in addition to being scaled. This is best illustrated using a simple script
where a cube is moved away from the origin and then scaled down in size several
times:
# move it away from the origin (0, 0, 0):
c = CUBE(8)
MOVE(c, 8, 8, 8)
d = COPY(c)
SCALE(d, 0.5, 0.5, 0.5)
e = COPY(d)
SCALE(e, 0.5, 0.5, 0.5)
f = COPY(e)
SCALE(f, 0.5, 0.5, 0.5)
g = COPY(f)
SCALE(g, 0.5, 0.5, 0.5)
h = COPY(g)
SCALE(h, 0.5, 0.5, 0.5)
# Create compound object:
s = [c, d, e, f, g, h]
# Assign gold color to it and display:
COLOR(s, GOLD)
SHOW(s)
The output is shown in Fig. 85.
4.3 Commands TOP and BOTTOM
The command TOP(obj1, obj2) moves the object obj2 so that it is positioned right above
obj1. For illustration, let us create a cube and a sphere, and move the sphere on top of the
cube:
s = SPHERE(1.0)
TOP(c, s)
The output is shown in Fig. 86.
Analogously, the command BOTTOM(obj1, obj2) moves the object obj2 under the object
obj1. Fig. 87 shows the output of the script
s = SPHERE(1.0)
BOTTOM(c, s)
In both cases, the object obj2 is aligned in such a way that its center is right above / below the center of obj1.
4.4 Measuring dimensions and printing out information
Sometimes we need to measure the dimensions of an object. The command SIZE( obj, 1)
returns the size of the object obj in the first spatial direction (x-axis). Similarly,
commands SIZE(obj, 2) and SIZE(obj, 3) return the size of the object obj in the
direction of the y-axis and in the direction of the z-axis, respectively. The command
print can be used to print out the results. For example, the output of the script
print ~Object dimension in x-direction:~, SIZE(a, 1)
will have the following output:
The values returned by the SIZE command can be stored in variables and more of them can
be printed at the same time. For illustration, the script
b = COPY(a)
SCALE(b, 2.0, 1.0, 0.5)
dim1 = SIZE(b, 1)
dim2 = SIZE(b, 2)
dim3 = SIZE(b, 3)
print ~Object dimensions:~, dim1, dim2, dim3
will print:
4.5 Boolean operations – doing it the wrong way, doing it the right way
Boolean operations can lead to long computations if not done properly. To make them efficient, they should be as much local as possible, meaning that they should occur between as geometrically simple objects as possible.
We will demonstrate this on an example where we first create a vault and then
play a gangster and drill a hole into it. Do not worry about the lenght of the script
below because the vault has many small parts. But the fact that there are many
parts is important here. We will show that while performing a Boolean operation
between the drill and the entire vault is extremely time consuming, drilling into
just the one relevant part of the geometry is done quickly. First, let us create the
vault:
body = BOX(1, 1, 1.2)
interior = BOX(0.86, 0.95, 1.06)
MOVE(interior, 0.07, 0, 0.07)
body = DIFF(body, interior)
# Top part:
top = CHULL([0, 0, 1.2], [1, 0, 1.2], [1, 1, 1.2], \
[0, 1, 1.2], [0.01, 0.01, 1.21], [0.99, 0.01, 1.21], \
[0.99, 0.99, 1.21], [0.01, 0.99, 1.12])
shelf = BOX(1, 0.85, 0.02)
MOVE(shelf, 0, 0.1, 0.4)
shelf2 = COPY(shelf1)
MOVE(shelf2, 0, 0, 0.4)
# Front door:
door = BOX(0.84, 0.05, 1.04)
MOVE(door, 0.08, 0, 0.08)
door_frame = BOX(0.86, 0.03, 1.06)
MOVE(door_frame, 0.07, 0.02, 0.07)
# Truncated cone under the handles:
tcone = TCONE(0.14, 0.13, 0.02)
ROTATE(tcone, 90, 1)
MOVE(tcone, 0.5, 0, 0.6)
cyl = CYL(0.07, 0.1)
ROTATE(cyl, 90, 1)
MOVE(cyl, 0.5, 0, 0.6)
# Small truncated cone at the handles:
stcone = TCONE(0.07, 0.06, 0.01)
ROTATE(stcone, 90, 1)
MOVE(stcone, 0.5, -0.1, 0.6)
# Handles:
h1 = CYL(0.022, 0.3)
ts = TCONE(0.022, 0.017, 0.01)
MOVE(ts, 0, 0, 0.3)
h1 = U(h1, ts)
ROTATE(h1, 180./24, 1)
ROTATE(h1, -7*180./24, 2)
h2 = COPY(h1)
ROTATE(h2, -2*180./3, 2)
h3 = COPY(h2)
ROTATE(h3, -2*180./3, 2)
MOVE(h1, 0.5, -0.06, 0.6)
MOVE(h2, 0.5, -0.06, 0.6)
MOVE(h3, 0.5, -0.06, 0.6)
# Bolts:
b1 = CHULL([0.81, 0, 0.19], [0.83, 0, 0.17], [0.97, 0, 0.17], \
[0.97, 0, 0.26], [0.83, 0, 0.26], [0.81, 0, 0.24], [0.815, -0.01, 0.195], \
[0.835, -0.01, 0.175], [0.965, -0.01, 0.175], [0.965, -0.01, 0.255], \
[0.835, -0.01, 0.255], [0.815, -0.01, 0.235])
b2 = COPY(b1)
MOVE(b2, 0, 0, 0.77)
# Bolt cylinder:
bc = CYL(0.015, 0.1, 16)
bc1 = COPY(bc)
MOVE(bc1, 0.925, -0.009, 0.165)
bc2 = COPY(bc1)
MOVE(bc2, 0, 0, 0.77)
# Small bolt sphere:
sbc = SPHERE(0.01, [8, 8])
ROTATE(sbc, 90, 1)
bsc1 = COPY(sbc)
MOVE(sbc1, 0.845, -0.01, 0.195)
sbc2 = COPY(sbc1)
MOVE(sbc2, 0, 0, 0.035)
sbc3 = COPY(sbc1)
MOVE(sbc3, 0, 0, 0.77)
sbc4 = COPY(sbc3)
MOVE(sbc4, 0, 0, 0.035)
# Vertical handle:
vh = CYL(0.02, 0.5, 16)
MOVE(vh, 0.15, -0.04, 0.35)
# Vertical handle supports:
vh0 = CYL(0.015, 0.06, 16)
ROTATE(vh0, 90, 1)
MOVE(vh0, 0.15, 0.02, 0.4)
vh1 = COPY(vh0)
MOVE(vh1, 0, 0, 0.4)
# Put everything together:
rest = [top, shelf1, shelf2, door, door_frame, tcone, cyl, stcone,
h1, h2, h3, b1, b2, bc1, bc2, sbc1, sbc2, sbc3, sbc4, vh, vh0, vh1]
vault = [body, rest]
SHOW(vault)
The output is shown in Fig. 88.
Now let’s define the drill:
ROTATE(drill, 90, 2)
MOVE(drill, 0.1, 0.5, 0.55)
Next let’s drill into the vault. First we will do it the wrong way – drilling into the vault
object that consists of many parts.
SHOW(drilled_vault)
You can run this script but it will take a very long time.
The correct way to do this is to perform the Boolean operation between the drill
and the body because the body object is much simpler than the complete vault:
SHOW(drilled_body, rest)
Now the computation takes just a few milliseconds! The output is shown in Fig.89.