Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411283 Posts in 69325 Topics- by 58380 Members - Latest Member: bob1029

March 29, 2024, 03:27:24 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsCommunityTownhallForum IssuesArchived subforums (read only)TutorialsTutorial: Making Isometric Sprites out of 3d models with Blender
Pages: [1]
Print
Author Topic: Tutorial: Making Isometric Sprites out of 3d models with Blender  (Read 57697 times)
Rock D
Level 0
**


I waited for an hour but this never happened.


View Profile
« on: January 13, 2009, 07:37:17 PM »

If you are making a game in isometric perspective, you might notice that it can require quite a lot of art because characters need to be animated doing their thing facing many directions instead of just 1. A classic way of quickly making a lot of isometric art is prerendering 3d models in isometric perspective. Diablo and Fallout are two well known games that use this technique.
I have made a blender file with a camera setup that helps you render 3d models in isometric perspective from a number of directions. It even supports animations. Here is an example:


Download it here

Version log:
- 101: Changed the perspective angle to actually be 2:1 (with the option to use true isometric)
- 102: Added a static model to use in the second tutorial and fixed the IpoLoop script to loop more properly (without interpolating between loops, but still enabling interpolation within loops).
- 104: Added a script to make a sprite sheet out of the frames (many thanks to Angelo Theodorou for that). Added a guide on how to use scaling as an anti-aliasing filter.

There is a readme included that should be straightforward enough to let novice Blender users use it. If you are completely new to Blender, I do recommend following the Blender user interface tutorial first. Blender's interface is very unintuitive. It even hides vital functionality under hotkeys with no way of discovering it exists through a menu or toolbar. Another useful thing to know is that Blender will never ask you to save on exit regardless whether you've made changes to your file. On the plus side, the interface is very customizable, so once you know about the quirks, you can set it up exactly how you like it.

I have included 2 python scripts to ease customizing the settings. 'CamCircleStops' animates the currently active camera to circle the origin in a set number of steps, optionally stopping for a while at each direction to let a looped animation play out.
'IpoLoop' lets you loop the animation of the currently selected object for the duration of the camera animation.
The 'strip_render' script has instructions on how to render the frames together into one sprite sheet.


Introductory Tutorial: Rendering a static model in 32 directions.

1: This is what you'll see when you open the file.

On the top left there is an overview of the stage area, where you can see the the camera and a light pointed at the origin. On the top right is the view as seen from the camera. You can change the current frame and see the camera and its view animate by clicking and dragging over the timeline, the area in the middle of the screen.
Bottom left contains the scene panel, where you can set where you want to put the resulting files, change the file format and resolution of the render and do the actual rendering by clicking the ANIM button. On the bottom right there is a ReadMe in a text window, which you change to display the two included scripts with the button on the left of the TX:ReadMe label.

2: Let's add a model to the scene. While hovering the mouse over the top left window, press space. From the menu choose Add -> Model -> Monkey. This will place a monkey head model on the origin, where the scene cursor is (the red and white crosshair). You could also import your own model from various formats by opening the File -> Import menu.


3: The model isn't properly rotated and scaled to fit the frame. First rotate the model by pressing 'R', then 'X' to constrain rotation to the X axis, then enter '90' on the numpad and press enter.
Scale the model by pressing 'S' and moving the mouse until the model fits the dashed area in the upper right. Check that the model doesn't get outside of the frame for every frame of the camera animation by clicking and dragging over the timeline in the middle area of the screen.

4: We are almost ready to render the model. Check the output settings on the lower left. By default it will render in 128x128 png format to the directory c:\temp, prefixing each file with 'person'. To start rendering with these settings, press the 'ANIM' button. The render window will show a black background, but the resulting file will have proper alpha transparency to make an 'empty' background. I've made an animated png (that will only work in firefox) out of the first 8 of the 32 rendered frames of the result:


Advanced Tutorial: Animating a model using Blender Bullet physics and using the scripts to render the animation from all directions
There are many ways to animate a model in Blender, from simple transformations to using a bone armature. I'm going to use the built in physics engine to animate a simple figure losing his head. Then I'll make that animation loop every 10 frames with the 'IpoLoop' script and let the camera pause for 10 frames at every direction with the 'CamCircleStops' script.

The default view doesn't have the included model on it. Switch to its layer by hovering your mouse over the top left window and pressing 'Alt 1'. You can rotate around the model with 'Num 4,6,2 and 8' and zoom with 'Num + and -' or the scrollwheel.

Now we're going to make physics objects out of the model. Switch over the button panel view (down left) to 'Logic' by pressing F4 or clicking the purple smiley button in its toolbar. On the left, the purple buttons define the physics properties of the currently selected object. Select the head and then change the physical representation type (purple drop down menu on the top left) to 'Rigid body'

If you press 'P' while on the top left window, you can see the physics simulation play out. You've actually asked Blender to start a 'game' using your scene in that window.  Right now the head just wobbles a bit because the body of the person is set to 'static' and no forces are applied to the head. Press 'Esc' to exit the game mode. We can apply a force by using Blender's game object logic editor on the right of this panel.

First we add a sensor to the head by pressing 'Add' next to the head object listed under the 'Sensors' heading. The default is an 'Always' sensor that will output a high signal (true) every frame on the yellow port to the right of it.
Then we add a controller by pressing 'Add' next to the head object listed under the 'Controller' heading. I won't get into controllers here, the default setting should just pass through the signal on the left yellow input port to the right yellow output port. Link the output port of the sensor to the input port of the controller by clicking and dragging a line between them.
Lastly, press 'Add' next to the head object under the 'Actuators' heading. This should add a simple motion actuator by default, which we can use to apply a force to the head. Fill in -3 in the first value field (X-axis value) next to the 'Force' label. Then link the output of the controller with the input of the actuator. The result should look like this:

If you now press 'P' on the 3D view, you will see the guy losing his head as intended. Because the option 'Render Game physics to IPO' is checked in the Game menu in the upper menu bar, Blender will try to save the path objects take 'in game' due to physics as an animation for those objects. This is a bit flakey, for some reason it doesn't record the animation properly. The way to get it work is by using an undocumented feature (welcome to Blender!) that will bake the physics to an animation directly without starting the game engine by pressing 'Ctrl+Alt+Shift+P'. You can now see the animation play out by click-dragging your mouse over the timeline in the middle of the screen.

Let's take a look at how the animation is actually recorded in Blender. Switch the bottom left window over to the 'IPO curve editor' by clicking the button in its top left corner and selecting that from the menu. Both location and rotation values for all three axes over time are represented as bezier curves, also called IPO curves. A collection of IPO curves of an object is called an IPO. Like with objects in the 3d view you can scale and transform the curves with the 'S' and 'G' keys and constrain those operations to a certain axis with the 'X' and 'Y' keys. Just as with the timeline, you can click and drag over the graph to see how the scene works out in that frame.
Try scaling and transforming the curves (you can select them all at once with 'A') until you have an animation in the first 10 frames that you are satisfied with.

Now we can use the scripts to loop the animation and make the camera wait for them to play out at every direction. Switch the text editor window (bottom right) over to the 'IpoLoop' script by choosing that from the drop down menu that currently has 'TX:Readme' on it. Set the 'aniLen' variable in this script to 10. If you then press 'Alt P', this will run the script and loop the first 10 frames of animation of the currently selected object over and over for the duration of the camera animation. You can see the changes it made in the IPO editor.
For the camera, we change over to the 'CamCircleStops' script. This script will animate the 'currently active camera', so we have to change the active camera to the one in this layer by first selecting it and then, while hovering over the top right window, pressing 'Ctrl+Num0'. Since running the script destroys the animation the camera previously had you have to be careful what camera you run it on (same goes for the object animations when running the IpoLoop script). Make sure the 'aniLen' variable is set to 10 and press 'Alt P'.

Now we have successfully animated a model and the camera to render it to an isometric sprite. Switch the Ipo editor window back over to the button window, and the button window's game logic panel back over to the Scene panel. One last thing to note is that the 'CamCircleStops' script will automatically set the End frame number in the Anim tab to the value that will include the whole animation from all directions. This value isn't tied to the current camera you're using, so be sure to set it to the end frame of the animation of the currently active camera if you are switching between cameras in one file without running the 'CamCircleStops' script on it again. Here are 10 frames (1 direction) from the resulting render:


I am looking forward to your comments, critique, questions and feature requests.
« Last Edit: March 21, 2009, 05:28:26 PM by Rock D » Logged
Javilop
Level 2
**



View Profile
« Reply #1 on: January 14, 2009, 05:09:38 AM »

Thank you!

Could you add a brief guideline and some screenshots? I think this way it would be more useful.
Logged
BorisTheBrave
Level 10
*****


View Profile WWW
« Reply #2 on: January 15, 2009, 05:42:58 AM »

Is this true isometric or 2:1?
Logged
Rock D
Level 0
**


I waited for an hour but this never happened.


View Profile
« Reply #3 on: January 15, 2009, 01:05:00 PM »

Is this true isometric or 2:1?
Good question. It turns out I botched my calculations a bit, so it was neither. Now I've updated the file to use 2:1 by default and optionally true isometric.
Logged
Rock D
Level 0
**


I waited for an hour but this never happened.


View Profile
« Reply #4 on: February 10, 2009, 04:50:41 PM »

I made a little robot dude. I turned off the anti aliasing for this (called OSA in blender) so you can see the characteristic 2:1 pattern at the sharp edges.

I am currently looking into making a script that will paste the whole bunch of rendered images you currently get as output into one spritesheet. Then again, maybe people prefer to use separated files for frames of animations nowadays? I also want to put in support for scaling down large renders to pixel art sizes, because that might give better results than how blender renders small targets.
Logged
Mir@k
Level 1
*


Pffffffft


View Profile WWW
« Reply #5 on: March 19, 2009, 08:04:56 AM »

I am currently looking into making a script that will paste the whole bunch of rendered images you currently get as output into one spritesheet. Then again, maybe people prefer to use separated files for frames of animations nowadays? I also want to put in support for scaling down large renders to pixel art sizes, because that might give better results than how blender renders small targets.
All of this sounds great, i hope you do it.
Logged

Rock D
Level 0
**


I waited for an hour but this never happened.


View Profile
« Reply #6 on: March 19, 2009, 06:02:33 PM »

Here is a comparison of my sampling experiments. They're all 32x32 sprites blown up 4 times.

Top is Blender's 8x OSA filter. Middle is OSA off. Bottom is a 320x320 render scaled back down to 32x32. I think it's obvious scaling works best.

I also got making a spritesheet out of the separate frames working. It uses the strip render script from this page (the second one). I'll put a new version up of the sprite stage with a guide how to do the spritesheet rendering and the scaled rendering somewhere this week.
Logged
John Nesky
Level 10
*****


aka shaktool


View Profile WWW
« Reply #7 on: March 19, 2009, 11:51:04 PM »

Rather than rendering at high-res and manually scaling it, try changing your filter from "Gauss" to "CatRom":

Logged
Rock D
Level 0
**


I waited for an hour but this never happened.


View Profile
« Reply #8 on: March 21, 2009, 05:30:08 PM »

The new version of the stage is up. It includes documentation to use scaling as an anti-aliasing filter and a script to render your frames together into one sprite table.

I tried the other filter modes just now at different strengths and while they are a lot better than the Gauss default I couldn't get a result much less blurry than the Mitch 16x filter.
The CatRom filter has some darkening at the edges of contrasting areas. Filters often result in pretty thick anti-aliased bands at the edges. Scaling down seems to preserve details better.
Logged
Zaknafein
Level 4
****



View Profile WWW
« Reply #9 on: March 21, 2009, 06:55:29 PM »

Scaling down 2x2 to 1x1 should be equivalent to a 2x2 Tent or Box filter... have you tried those?
Logged

Rock D
Level 0
**


I waited for an hour but this never happened.


View Profile
« Reply #10 on: March 22, 2009, 06:40:50 AM »

They come close to what you get by scaling but they still lose some detail.


Using the blender filters you can't always make out the box between the treads and the bevel on the top looks more round than it is in the model.
Logged
simAura
TIGBaby
*



View Profile
« Reply #11 on: May 24, 2010, 05:27:51 AM »

This is an excellent tool, but I'm having a few problems with it, mainly with rendering animated models.

First of all, the IpoLoop script gives me an error no matter which model I choose. The error is on line 26, which is for ipocurve in ipo.curves:. The relevant section in the code is:
Code:
...
object = Blender.Object.GetSelected()[0]

ipo = object.getIpo()
newipo =  Blender.Ipo.New('Object','newipo')
for ipocurve in ipo.curves:

length = len(ipocurve.bezierPoints)
if length == 0:
continue
...
And the error output in the console is:
Code:
Traceback (most recent call):
  File "IpoLoop", line 26, in <module>
AttributeError: 'NoneType' object has no attribute 'curves'
I first figured it might be because I had imported an entire additional scene (since I couldn't figure out any other way to import the mesh and the animations from another Blender file), but I got the same error when using the preset guy with the falling head.
I don't know if the problem is that the variables curves has changed or doesn't exist in Blender anymore or if I'm selecting in the wrong way (as NoneType would suggest an invalid object), but any help would be appreciated.

Secondly, I'm finding that the resized sprites that the script outputs are surrounded by a small black border which isn't always really the best. I actually managed to work this around by having the script output full-size images and then resizing them using Photoshop's batch function and it works well so it's not that big of a problem, but is there any way to change this?

Finally, I would like to suggest Sprite Sheet Packer (http://spritesheetpacker.codeplex.com/) for making the sprites into a single sheet while attempting to minimize the amount of pixels used.

Thank you.
« Last Edit: May 24, 2010, 06:29:58 AM by simAura » Logged
Trevor Dunbar
Level 10
*****


Working on unannouned fighting game.


View Profile
« Reply #12 on: June 27, 2010, 06:00:40 PM »

Try just scaling it down and painting over all the pixels manually.
Logged

Toucantastic.
zeff
TIGBaby
*

"one shot, one pic"


View Profile WWW
« Reply #13 on: July 19, 2010, 05:21:24 AM »

thanks for the tutorial
Logged
deWiTTERS
Level 1
*


deWiTTERS


View Profile WWW
« Reply #14 on: July 19, 2010, 05:27:40 AM »

The art for my game Mystic Mine was created using this technique, for both the tiles and objects (including animations). I wrote a python script to take all the rendered images, scale and auto-crop them, and put them into 1 png for sprite rendering. Worked out just fine Smiley.
Logged

Deverez
TIGBaby
*


View Profile
« Reply #15 on: August 31, 2010, 08:07:58 PM »

When I render the model, it only outputs 32x32 PNGs. How can I change this, to make the output larger?
Logged
Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic