Blender:Starship Windows

From McCwiki
Jump to: navigation, search
Suppose you've got a nice, curved hull surface and you want to put a window (or many windows) into it. How does one approach this problem? Unfortunately, there's no good way to do this; every method requires a certain amount of brute-forcing or manual clean-up. This particular method is pretty fast, though.
Example of a work-in-progress Ambassador class ship from Star Trek that has had this method applied to it.


Prerequisites

  • I assume you have a hull (or other structure) and know your way around Blender.
  • You should also verify that you have the Inset Polygon add-on. It should come stock with Blender these days, but you may need to enable it in your Add-Ons preferences. I have it hotkeyed to i.

Formatting Note

Whenever you see this sort of text, it indicates a hotkey. Hotkeys can be combinations or sequences. Example: Shift S is a combination; these are two keys meant to be pressed in tandem. Shift S, 3 is a sequence, starting with the combination Shift S, then followed by 3. This often happens when the first hotkey brings up a menu or starts an action, and the second hotkey influences the result. This particular example means "Set the Cursor (Shift S) to the center of the active object (3).

Procedure

Window Profile

First, create a profile for your window. If you're modeling an air or spacecraft, these should have rounded corners (or no corners) to reduce structural stress. Unfortunate experiments in early aviation led to the realization that angled windows of the sort found in houses and buildings don't do so well in an air- or spaceframe. You can violate this "rule," of course, but your model's realism will suffer for it (and I'll disown you).

The beginning of our window profile.
For Trek-style windows, the general form is often a line capped on either end by a semi-circle. One easy way to make one is to create a filled circle, rotate it, and pull the bottom verts "down." For this example, I have windows that are 0.5 meters across (radius = 25 cm), and 1 meter tall. Since this is a small feature for a large ship, but I still want it to stand up to pretty close shots, I went with 34 vertices. Also, note the 90° X rotation to orient it vertically.

Why 34 and not the default 32? That trick I mentioned above about pulling verts "down." With 32, you have verts at 0°, 90°, 180°, and 270°. The verts at 90° and 270° mean you'll have some ugly tapering if you try to just pull on the bottom verts. By adding two more verts, you get a pair of edge verts that can be evenly divided between the top and bottom. This isn't a killer issue, of course. You can always split the circle and then separate the two halves to achieve the same result. This is just faster.

Left: 32 verts and the resulting stretching.
Right: 34 verts and no stretching

Extrude the Profile

Next, extrude (e, y for extruding along the Y axis) your window profile by a fair amount, so that one side of the extrusion rests outside of your hull and the other side sits well inside it. In the example here, we're dealing with a large saucer section of a starship, so the extrusion is about 20m.

The extruded window profile, positioned so that it's set into the hull.

Build the Window Array

Presumably, you're not putting in a single window, but a number of them. Blender makes this easy with the Array modifier, coupled with an Offset Object. For this particular example, I have a circular saucer section from a Trek ship, so I want to create an array of windows that goes around the entire saucer perimeter.

First, put the origin of the window object at the radial axis of your saucer. This step doesn't apply to non-radial situations in the same way, but positioning your window object's origin in particular ways can net you all sorts of interesting effects. To do this, assuming your saucer's center is at its axial origin:

  1. Select the saucer in Object Mode
  2. Position the cursor at its center (Shift S, 3 or Shift S, C).
  3. Select the window object in Object Mode
  4. Set the window object's origin to the cursor (Ctrl Alt Shift C, t or Ctrl Alt Shift C, 3).

If your saucer's center isn't at its axial origin:

  1. Reset the saucer's origin (Ctrl Alt Shift C, o or Ctrl Alt Shift C, 2)
  2. Set the cursor to the object's center (Shift S, 3 or Shift S, C)
  3. Select the single vertex at the top of the saucer
  4. Copy its X location to the cursor's X location (in the Properties panel of the 3D View; (n) opens it if it's not already open).
  5. Set the saucer's origin to the cursor (Ctrl Alt Shift C, t or Ctrl Alt Shift C, 3).
  6. Follow the steps above.

Next, with the cursor still at the saucer's center, add an Empty and name it something like Rotator.Window or some other easily recognizable name.

Even if you don't want a window in the dead center of your saucer's midline, leave this initial window object there. You can delete any that you don't want later. For the sake of simplicity, I'm also going to assume that you're left-right mirroring your model, so you only have to work on half of it.

The next thing you need to do is decide at what minimum interval you want your windows. This is a bit tricky to explain, and you can wing it if you want to, but your results will be more reliable if you don't.

Math Time

For my particular example, I had 32 panels per 90° segment of the saucer, which meant I had grid lines every 90° ÷ 32 = 2.8125°. I wanted to have as many as three windows per panel, which meant that each window would be at minimum 0.703125° apart. Why that number? Because 2.8125° represents the angle span between two grid lines, and I wanted three additional bits within those lines. One of the grid lines counts as "0" but the other counts as n+1, where n is the number of bits I want. Net result: 2.8125° ÷ (3 bits + 1) = 0.703125°. If this doesn't make sense, don't worry; just remember to divide your panel arc by the maximum number of windows you want in it plus one.

Alternately, suppose you want to have two or three windows per panel, but you don't want those two-window panels to be confined to being in one of the three-window panel positions, which is a constraint you'd have with the above method. In this case, you sum them. Rather than figuring out the angle for 2 or 3-window panels, you do it for a 5-window panel, and then remove the extra window profiles it generates.

Based on whatever minimum interval you settled on, apply this rotation value to the Empty rotator's Z rotation. At this point, you should also apply any Rotation or Scale that's applied to your window object (Ctrl A, 4 or Ctrl A, o).

Configured Array modifier
Now, add the Array modifier to your window object. You'll have to uncheck Relative Offset, which is checked by default, if you're following the radial explanation. (If you're doing something else, feel free to experiment with the various options to your heart's content.) Instead, check Object Offset and select your Rotator.Window Empty from the field below the Object Offset checkbox.
There! Are! Two! Windows!
If everything went well, you should see two copies of your window, one in the original position and one rotated a small amount around the saucer object's axis! Increase the Count until you have as many window object copies as you need. When working with radial saucers like this, it's often advantageous to just do one "wedge" worth and then copy the result of all of our labor, but sometimes there are differences in each wedge, precluding this. With my example numbers, I needed 257 to get 180° around the saucer.

Once you're happy, Apply the Array modifier to create the copies of the window.

Pare Down the Array

Now that you have an array of too many windows, it's time to go through and delete the ones you don't need. The easiest way to do this is to go into Face mode (Ctrl Tab, f) and use Lasso Select to select the middle faces of the window objects you don't want. Then expand selection (Ctrl Numpad+) until the end caps are selected as well, and hit Delete.

Isolate Target Faces

We're going to cut the windows into the hull, which means a Boolean operation. Boolean operations are slow, cumbersome, and expensive. The less data we feed into the calculation, the better. As such, select only the faces on your hull that are going to be affected by the windows and then Separate (p, 1) them into their own mesh. We'll rejoin them to the main hull later.

Perform a Boolean Operation

With the separated hull faces selected, go to the Modifier panel and add a Boolean modifier at the top of the list. Generally, Intersect is the proper setting; one of the settings will be correct, and it's usually not intuitive (ideally, it would be Subtract, but this is rarely the case in practice). Set the Object to your window object.

If all goes well, you should now see your hull panels will windows cut into them and the remaining window profile either sticking into the hull or jutting out.

Clean Up

The very next thing to do is go into Vertex mode (Ctrl Tab, v), Lasso Select (Ctrl LMB) the inset/outset vertices that are left over from the Boolean operation, and delete them. This will leave you with your be-windowed hull panels. However, there's more to clean up!

You'll have to inspect each window one at a time for errant vertices. Sometimes, the boolean operation will be clean and there won't be any. Other times, many errant vertices will be around. Errant vertices are especially problematic along the top/bottom arches of the window. They can be identified as vertices that sit along an edge, but don't alter the shape of the edge. Select each vert that qualifies and drag-snap (Shift Tab to enable snapping, Ctrl Shift Tab, v for Vertex mode; use g to move verts) to the nearest non-errant vert. Once you're done, Remove Doubles (w, r).

There may also be errant verts along the long edges of the window, but if you've Booleaned across a bend in the hull, be careful about identifying them!

Once all of the errant verts are gone, the next step is to clean up the probably-ugly triangulation left behind. Notice that each window in my sample has a "hull panel" of polygons around it that is unique to it. This may not always be the case, but when it is, it's advantages to use it. Select every other hull panel around each window and perform the following sequence:

  1. Triangulate (Shift t)
  2. Beautify Fill (Alt Shift f)
  3. Quadrangulate (Alt j)

Repeat the above steps for the hull panels we skipped the first time around. The reason to do it in two passes is to prevent Beautify Fill from getting over-zealous about reshaping our hull geometry.

As a final step, make sure there are no non-manifold polygons along the inner edge of the windows. They can sometimes creep in during this optimization pass.

Create the Window Frame

Finally, select one long edge of each window. This can be sped up by doing a Select Similar with Length (Shift g, l), but it's not always reliable. Once they're all selected, select Edge Loop (Ctrl e, l) to select the entire window frame and then create a polygon (f). With your new window polygons still selected, apply a new Material to them called something like Window Frame.

Use Inset Polygon (i) to inset the window frame slightly. I used values of 0.015m and 0.025m for depth and thickness, respectively. This gives a nice beveled edge to the window frame. Make sure you uncheck Select Outer, so that the window panel itself is still selected, rather than the beveled edge.

Next, Extrude with 0 length (e, 0, esc) and then Shrink/Fatten (Alt s) or scale with Z locked (s, Shift z) in Cursor mode, with the Cursor at the center of your object a distance that seems appropriate to you. I tend to use 0.5m or so.

If you're going to create rooms behind your windows, delete the end polygon. Otherwise, apply a new Material called something like "Window Interior". Join the separated object back into your main hull object (select both, hit Ctrl j), switch to Edit Mode and Remove Doubles.

All done!