Importing Map Imagery into Unity via Cinema 4D

From NoskeWiki
Jump to: navigation, search

About

NOTE: This page is a daughter page of: Unity and Cinema 4D


I wanted to create a game using some satellite map imagery, and put that into Unity (game engine), via Cinema 4D. This page lists the steps I took.

NOTE: If you prefer Blender or some other 3D package, this page may still be useful, but I find Cinema 4D easiest, so I stuck with that.


Textures in Unity

Unity accepts the following texture resolutions: 32, 64, 128, 256, 512, 1024, 2048, 4096. You are thus limited to Unity's max texture size of 4096x4096, and since your texture is probably bigger, you'll need to break it up into squares of at this size or lower.


Creating Satellite Tiles

In this example I had a square region of 20480x20480 pixels of satellite imagery as a TIF, which I then saved to a JPG "montage.jpg". Here's the steps to take next:

Putting a Huge Texture in Cinema 4D

  • Prepare the folder:
    • Create a folder "SatelliteGame" and subfolder "tex" and put the texture inside the subfolder.
  • Create the material:
    • Open Cinema4D, and save immediately as "SatelliteGame.c4d" in the first folder you created.
    • Go Create > New Material in the Materials panel, and name it "Montage".
    • Make sure only Color is checked, and change the Color > Texture to the JPG image.
    • Before closing the Materials window, click the Editor option and set the "Texture Preview Size" to the maximum ("16384x16384 (1024 MB)") else it will appear very pixelated indeed if binned down to the default preview size.
      • WARNING: this doesn't just increase cache, when you hit save you may noticed your filed size increases dramatically too.
    • Optional: Right click the sphere at the top left and select "Plane Backlit" (this makes no difference to the model, but will remind you it's a flat texture).
  • Create a Plane:
    • created a single Plane of 20480x20480 meters, then in the Attributes panel set the width/height segments to 80x80 (I to be able to change elevation within the 256x256 tiles).
    • Drag the new material onto the plane.
    • By default textures only appear in the Perspective view - to fix this right click the plane "Cinema 4D Tags > Display" then change the Display tag Attributes panel > Tag > Use > Shading Mode > Gourand Shading.
    • If you're worried about moving your Plane accidentally, you can also add the "Cinema 4D Tags > Protection" tag, and this will prevent you from selecting it accidentally as you put other stuff over your Satelite imagery.


Breaking the Plane into Smaller parts

Split the huge plane into 5x5 pieces, each 4096x4096 pixels:

  • Right click the Plane in the Object Manager, and select "Current State to Object" (same effect as making a copy then "Make Editable").
  • Disable/hide the original Plane.
  • Create the tiles:
    • With the editable/polygon version, use the Polygon selection mode (left toolbar) and Rectangle Selection select the top left group of 16x16 pieces, then Mesh > Commands > Disconnect.
    • Separate this first tile by going Mesh > Conversion > Polygon Groups to Objects.
    • Repeat the previous two step 25 times (total) to get 5x5 large tiles.
    • Tip: you may want to create a 5x5 grid over the top to make it easier.
    • Tip: if you had more than 5x5 tiles you might consider writing a Cinema 4D Script or Plugin.
  • Clean up the tiles, and name each appropriately (for example "1,1" for the top left, "1,2" for the one to the right, etc) and put under a single null object called "TILES".


Baking and Exporting to Unity

The best way to get a Cinema 4D model into Unity is by export it as an FBX. But first we need to bake the 4096x4096 tiles.

  • Select your "TILES" and in the Object Manager click: Objects > Bake.
  • In the Bake Object window change the texture width/height to 4096x4096, pixel border to 0 (supersampling should already by 0) and format to TIFF (Unity does it's own texture compression on import, so using pure TIF will be slightly less quality loss) and click Bake.
    • TIP: You will probably also want to select a path to put inside your "tex" subfolder.
  • As you watch you should see it render each of the tiles. Once finished you'll see 25 new materials appear.
  • Delete the original Planes (we don't want these exported.
  • Main menu: File > Export > FBX and call it "Satellite.fbx".


Loading in Unity

  • Make a new Unity project and create a new folder called Models.
  • Move "Satellite.fbx" into the Models folder using a file browse program.
  • Examine the "Satellite.fbx" in Unity (it may take a while to process). Select the materials subfolder and make sure 4096x4096 is selected for each tile.
  • Drag "Satellite.fbx" into the Scene and you should be able to see it full res.
  • To see properly you'll want to add a Light over the square.... position your camera appropriately then click Play.


Alternative Approach To Tiles

In this method above we started with one huge image, and broke it into tiles in Cinema 4D. Go into your texture folder and make a note of the gutter - the black border around the edges of the texture which result from "Bake object". Count the number of pixels gutter: for me it was ~40 pixels (so you lose 80/4096 pixels or ~2% along each axis). These black gutters around images are annoying frankly, because they mean we lose a little resolution. You should also also notice that the outermost boundary of colored pixels is a repeat of the pixels next to them... this is called "edge padding" and without this the very edges of our planes would show a hint of the black gutter. With our wasted 40 black pixels and 2 pixels of edge padding, that's an inset of 42 pixels on each edge.

To eliminate the gutter, an alternative approach is to use a program like Adobe Photoshop to break the main satellite picture into 4096x4096 tiles beforehand. The "split_images_into_png_tiles.jsx" script in Adobe Photoshop - Scripts Related to Montaging will achieve this. Create multiple planes, each 4096x4096 meters, and translate each so they form a 5x5 grid. The good news: you use all of your 4096x4096... the bad news: zoom in close and render [ctrl]+[r] and you'll see a line between all borders... this is because the edges wrap around to the other side. There are settings to fix this Rendering in Cinema 4D (until "tile" in the material tag), but wrapping is always applied in Unity, so you may want to apply 2 pixels of edge padding. There is a "edge_padding.jsx" script in the Adobe Photoshop - Scripts Related to Montaging which will help you do this. After edge padding, apply each texture to its matching plane, change each texture tag's projection to Cubic and use the formula below to set the offset and length values:

  • Stretch: =width/(width-2*inset)
  • % Length U/V: =(width*100/2)*stretch (note: if too big try removing 100)
  • % Offset U/V: =(length/2)+50

If we have width = 4096 pixels and inset = 2 pixels we get:

  • Stretch: =4096/(4096-2*2) = 1.000977517
  • % Length U/V: =(4096*100/2)*1.020937188 = 205000.1955%
  • % Offset U/V: =(length/2)+50 = 102550.0978%

Finally, you'll need to make all the Planes editable (right click > Make Editable), but shouldn't need to bake.


Elevating the Terrain

If you want to create hills and so on, Cinema 4D has a nice "Magnet" tool.

  • Change to Points mode.
  • Select all your tiles
  • In the Perspective window click [ctrl+a] and then right click > Magnet.
    • Before you start deforming points, you will want to make sure you are ONLY tranforming in Y, so in the Attributes panel for the Magnet tool make X and Y affected 0%.
    • A great tip: using the magnet tool you can hold the middle mouse to increase the radius. Hold down the shortcut keys [1], [2] and [3] as you drag the left mouse to change the viewing pan/zoom/angle.

One problem you'll have is that the magnet won't work across tile boundaries. Your likely options are thus:

  • (A) Once happy, manually click ever pair of edge points with the select tool and make sure their Y match.
  • (B) Use the magnet tool when it's all still one mesh.
  • (C) Write a time consuming plugin to automate matching of Y values (maybe if you have actual elevation values you could set them from a file this way).
  • (D) Use the Rectangular Selection tool with "Only select Visible Elements" off to make sure you drag edge points from both tiles along the edge up equally (what I did).

If you find areas like cliffs etc where you want extra points to deform you can use tools like "Knife".


Extruding Buildings

To make the scene more realistic, you probably want to identify buildings and extrude them (give them height).

I tried at one point to use Photoshop to draw and generate paths around buildings, but with limited success. See: Exporting Paths from Photoshop to Cinema 4D.

Instead my approach was to use the Linear Spline tool and occasionally Bezier Spline (for buildings with curves) in the "Top" viewport.

  • Maximize the Top viewport.
  • Draw a spline around your first building in the top viewport (the display tag on the satellite material should make it visible).
  • Create an Extrude object:
    • Go: Create > Generator > Extrude and drag the spline into position as Extrude's only child.
    • With the Extrude selected, change the Attributes Window > Object > Movements settings to 20m in y (0 in z).
    • Check it looks right in the Perspective view.
    • Under "Caps" you may want to remove the start cap if you don't need/want a floor.
    • Create a nice brick/window material and apply it to the Extrude.... notice it applies to the sides - not the roof (cap)... we must do this in the next step.
    • Rename the extrude something suitable ("Petco building") to help you find it later
  • Make editable version:
    • Right click your extrude object and "Current State to Object"
    • Hide the old version (you could delete it, but it's nice to make changes to original spline later).
  • Texture the roof:
    • Expand the new, mesh version of your building and notice "Cap2" (the ceiling) needs a material.
    • Drag your "Montage" material onto Cap2.
    • Select the new texture tag and under Attributes window > Tag, change the Projection to Cubic.
    • You may need to play with the texture offset and length values to get it right, but try the following:
      • Length U & OffsetV = 10240% (half the montage pixel size - you may have to make V negative)
      • OffsetU & OffsetV = 5170% (5120% (half again) + 50%... still not sure why adding 50% is needed - you may have to play with this value and look in the Perspective view to get it perfect)
      • Note: in the Attributes window > "Coordinates" you can set different variables - scale and position in meters, but the end result seems the same.
      • These same settings should work for all buildings, so you might like to copy the texture tag to a new Null object so you can copy it to new buildings as you go.
  • If you want all your surfaces connected (in my case I didn't), select the parent and child mesh, right click > "Connect Objects".
  • Bake the roof:
    • For your final building, you don't want all the Montage texture exported.
    • Select the child mesh and make note of the x and z size in the Coordinates panel, representing the size of your building. For example, x=365.413m, z=337.294 m.
    • Select the Objects panel file menu Objects > Bake Object
    • You could set the height and with to the approximate number of pixels rounded up (366 x 101), but remember that Unity deals with textures in multiples of two, so the more appropriate thing is to round up to the nearest power of 2 and make both height and with the same (512x512). You can reduce to a lower power of 2 in Unity after import, but you can't suddenly decide your texture needs better resolution, so higher is better within reason. Click Bake.
  • Continue this process from the beginning for each building. To save time you might like to make copies of your Extrude part, and you can [ctrl]+drag the roof texture each time you add a new building and need to texture the roof. Read the rest of this document before you trace too many buildings!

Alternative Methods for Extruding Buildings

Just briefly, a couple of alternative approaches / tricks to consider:

  1. To avoid clicking "Current State to Object" on every building, you should consider putting them all under a null object and applying to the root will apply to all children. If you wish to rename "Cap2" to "Roof" I have a Python script that can help.
  2. For your extrude object tick the "Hierarchical" checkbox and you can add all your building splines under this single extrude. This will be easier to manage, and will preserve spline names when you convert it to an editable form, but it means all buildings will be the same height and wall texture.
  3. If you add a Connect object directly under your Extrude, it has a similar effect, but when you do "Current State to Object" all your walls will be one mesh.
  4. Drag your spline under a Loft object if you want just the roof part for something like a shed roof where you don't want walls.
  5. Create a huge cube from your montage image, then drag your extruded building and the cube as the two children of a Boole object, set to "A union B" and in theory it will keep the right textures. I didn't quite get my desired with this approach, but Boole is worth playing with. If you wanted to create a door/holes in your Building then a Boole with "A subtract B" and putting a cube where the door should be would work great.
  6. Instead of using the large Montage texture, you could use the correct tile texture... which would will potentially save space, and saves you from "Baking".

Expanding on the last one: if you wish to avoid baking and instead use the tiles textures, you will need to cut any roof that crosses a tile boundary into pieces... Where the roof crosses a tile boundary, select the roof in the top viewport then right click Knife. Select Knife mode to "Plane" can help, and you still want N-gons. Getting the exact edge is hard - you will need to click the Snap button (left hand toolbar), turn on Edge snapping and then it should snap the the edge of the planes. Once split, it is still one polygon, so duplicate the Roof polygon in place [ctrl+drag] in Object window and rename the copies "RoofN" and "RoofS". Go to the Polygons mode, and with RoofN, select the southern polygon and hit backspace, then do the opposite for RoofN. Now you need to apply the correct texture to each.

Use the offset/length formula from before to work out the cubic projection values form Offset U/V and Length U/V. You're final values will be approximately:

  • Projection: Cubic
  • Offset U/V: 1074 % (half of 2048 + 50 .... and be warning: will be further affected by edge padding... so + inset pixels)
  • Length U/V: 2048 % (half of 4096)

If you have a 42 pixels inset, then the tile to the right of the middle one will have a higher offset V by 42%:

  • Stretch: =4096/(4096-2*42) = 1.020937188
  •  % Length U/V: =(4096/2)*1.020937188 = 2090.879362%
  •  % Offset U/V: =(length/2)+50 = 1095.439681% / 1137.439681%


To help you out, I'd create null object with a texture for each tile and you can then apply appropriate texture in Objects Window to the correct roof by using [ctrl+drag] on the texture tag.


Exporting into Unity

Extruding all building may be very slow, so start by drawing just a couple, bake them, deleted the non baked version and export to Unity by as an FBX as per before. In addition to looking around the model, you may also want to apply collision detection and see your meshes are working well. There are some instructions which can help you animate a character in your 3D scene here: Unity: Importing an Animated Character from Cinema 4D. If that's working, you can commit to drawing the rest! I have some handy tips on drawing and modifying splines in the next section.



Tips on Drawing Splines in Cinema 4D

Drawing so many splines can get tricky! First of all you should know the shortcut keys:

  • Hold down [1] to pan, and [e] lets you move selected points/splines.
  • You will find yourself clicking the dropdown a lot to start a Linear spline. To make this faster you can assign a shortcuts. Go: Window > Customization > Customize Commands. In this task bar search for "Linear", select it and then select the shortcut text box at the bottom and press [`]... and this will assign [`] to that command/button. You can also drag the linear command straight onto the toolbar too if you want the extra button.
  • You'll often want to what to switch between Model mode (where you can easily select any spline) and Points mode (where you can select/move individual points spline) using the left hand toolbar. I decided to assign these to [F1] and [F2] respectively.


Changing Spline Color in Cinema 4D

If you extrude/loft splines as you go, it should be relatively easy to see what you've traced, but it may still appreciate the ability to change default colors and use layers - especially since unselected splines turn black and that may be difficult to see over your satellite image. Here are some tips.

  • To change the default spline color of unselected splines:
    • Draw and select a spline. Under Attributions panel > Basic, click "Use Color" "On" and give bright orange color. Now click Attribute Window > Edit > Save as Default to make sure they all have this color when deselected.
  • To change the default color of selected spline:
    • Go: File > Preferences > Scheme Colors > Editor Colors... "spline start" and "spline end" colors.... I chose white and orange.
  • To use layers:
    • Select all other splines / objects, right click > Add to layer > New layer (same layer)
    • Select all spines, then in the Attributes panel > Basic click "use color" to layer.
    • Open the Window > Layers Manager to rename and change the color of layers. This panel also makes it easy to turn on and off particular layers.

Links

  • none