WordPress的北京!

Today, just because it’s Christmas, Beijingers may be able to enjoy WordPress blogging like never before, since all word-press blogs seem to be finally accessible.

Word-press is a cool, slick and easy to use blogging platform, but until now, the only way to get a word-press blog running in Beijing or Shanghai was to host it yourself.

Enjoy!

Seeing Double: reusing Models and Actors in Panda3D

Panda3D makes an essential distinction between nodepaths and nodes.

The easiest (and most useful) way to understand this is to consider that each node in your rendering graph (a PandaNode instance) is encapsulated within a NodePath instance.

Incidentally, this allows sharing nodes. The sample code below will assign an instance of a loaded actor to a new  nodepath. This process (‘instantiation‘ – according to the manual) can be repeated to share your actor.

actor = Actor.Actor(FILE_PATH, ...)
# nodePath is the path to the node you are attaching
# your new instance to,
# e.g. the scene-graph root, render, is actually a NodePath
instancePath = nodePath.attachNewNode(NAME)
actor.instanceTo(instancePath)

Since nodes can be shared, it’s not always possible to get the nodepath knowing the node, so it’s important to keep track of nodepath references.

Note that, if you play an animation on your actor, the same animation will play for every nodepath the actor is attached to. So this would be more useful to duplicate inanimate objects, or sync-ed animated objects.

Don’t touch my IDE

Programmers love their tools. It’s now been a good month that we’ve migrated to Subversion, and even though we know that FDT3 and Subversion aren’t great pals – endless configuration issues apparently, it didn’t prevent our team from ordering a fair batch of licenses at a fair price (not all Eclipse plugins are free).

I didn’t request a license. Instead, I ported my ergonomics to plain text programming. Programmers love their tools, and I’m no exception. Surely I love my tools. I created my tools so I could continue to love (what was to become) my job.

Anyway, today I sent an email to a few colleagues to let them know about my new code editor, ee-ide. Then, feeling ill inspired, I came over at a pal’s desk in the evening and did a quick demonstration.

Oh my… I directed him towards the web page for antegram for web. I chose this one because it downloads sample code, a quick overview of how it works and even runs from inside a zip file (at least, on Windows).

This is how it went.

X: (chmods the jar file) Mhmff. I never run jar files. (double clicks on the jar file, which an archive manager promptly deflates). Mhmff…
Me: OK, do java -jar …
X: Mhmff (UI pops up, and instantly populates with sample files and quick-start info in a corner; then, 3 double clicks later) I don’t know how this works.
Me: It’s OK, just check the quick start info.
X: If I need to read the doc, it’s probably no good anyway.
Me: OK, I’ll show you.
X: Ahh… (Glossing over what looks like a standard project browser) Yea. I got the same thing here. I don’t use it.
Me: Sure. The one in your IDE is too small. It’s not usable.
X: What d’ya mean too small? Yours the same size.
Me: This IDE uses several, not just one. You see the packages, classes and members first, and edit the code in a popup window. That way you always keep in touch with your design and access the code in one click.
X: I use nano when I just need to do a quick change…
Me: Say you want to design 300 classes. Do you use UML?
X: I keep the design in my head. I got the design in my head and the code on the screen. It’s zero clicks. Zero clicks is faster.
Me: Well, I guess that’s my problem. There is nothing in my head.
X: Everybody has a different approach.

Sure. I had smoother presentations. For one thing, ‘keeping in touch with the design’ (and relying less on UML diagrams) was the way somebody described one of the first versions of Antegram, nearly 7 years ago.

As a professional user, I’m forever frustrated with the way companies recycle the same recipes over and over, refuse to innovate and refuse to explore potential improvements in workflow and productivity.

What I never want to admit is:

  • 40% of professional users are disturbed when facing a look and feel different from what they are used to.
  • 90% of professional users are disturbed when facing innovative ergonomics. Innovative ergonomics are perforce different, thus definitionally inferior to what already exists.

Overall, this is also why ee-ide, instead of offering an integrated, well-studied and (considered targetted applications) fairly optimal solution, is a prequel to Antegram – a bridge between established ergonomics and practices and futuristic stuff that (as far as I know) only perfect beginners ever acknowledged.

I’m still working hard to bring onboard features invented elsewhere – even though most of that stuff contributes little to the net sum in terms of ease of use and productivity.

OK. I’d like to stay and expand on this, but I need to disable the java look and feel in ee-ide. It will look horrible on WinXP, but that is what XP developers want.

I’m not giving up.

Bamboozle: Panda3D/Python Crash Tutorials

I have just completed a first aid kit if you’re itching to learn a 3D game engine. I chose Panda3D (www.panda3d.org), which has several advantages (industry grade, open source, comprehensive, approachable, well documented). Also, it uses Python, and Python seems fairly popular in scripting games (and other things).

A mix of quick reference and troubleshooting, the tutorials address intermediate to experienced programmers. The idea is to get a head start and cover essentials.

If you’re ‘new to everything’, the Panda3D website may provide a smoother learning curve.

Now that I’m done with this, I’m planning on starting to code a really simple game. This will get me more into Python, and will reveal shortages in this tutorial.

Panda3D/Python: Setting the Stage

This tutorial is intended as a quick reference to how to setup a simple scene using Panda3D – getting objects loaded, positionning them, and starting your game or virtual world.

If you are new to Panda3D, read and run  the Panda3D hello world in their manual. I also find that the manual’s scene-graph introduction may be important.
Consider downloading the latest of Panda3D, Blender, Python and the Chicken plugin for Blender (The Python release shipping with Panda3D may not be supported by Blender).

Getting up to speed

# load global objects
import direct.directbase.DirectStart
# if you are using animated models
from direct.actor import Actor

Loading models and actors

# all paths must use '/', not '\', even on Windows
loader.loadModel("path")
# an actor is a model associated with several named animations
Actor.Actor(path,{"animName":"animPath"}[,...])

I create my models using Blender and export them using the Chicken plugin (see my article about Chicken export and caveats).

Setting the stage

Methods you can use on models and actors

reparentTo(aNode)  # use reparentTo(render) to add to world root
setScale(x,y,z)    # scale
setPos(x,y,z)      # translate
setHpr(u,v,w)      # rotate (degrees, e.g. 90, 180, ...)

Methods you can use on actors:

play("animName")   # play an animation once
loop("animName")   # loop an animation indefinitely
stop()             # stop all animations

Raising the curtain

Run:

  ppython PATH

where PATH is the path to your python script (including .py extension)

Note: I think ‘ppython’ is only available on Windows; there is an equivalent on Linux – check the Panda3D manual.

Getting Into it: Handle Key Events using Panda3D

At some point I will feel an irresistible  urge to debunk the hairy mouse picking section of the Panda3D manual and, if at all possible, provide a *neat* API for detecting clicks on objects.

In the meantime, I did skim through the keyboard handling section, and it’s not as bad as it looks. Here’s a simple recipe for key handling:

1. Import DirectObject – a key handler must be a subclass of DirectObject.
2. Define a key handler class inheriting from DirectObject
3. Invoke accept(key,function) to bind a key to a callback function. This can be done in your constructor.

Here is how it looks:

#----------------------------------------------------
from direct.showbase.DirectObject import DirectObject
class KeyHandler(DirectObject):
  # constructor
  def __init__(self):
    self.accept('arrow_left', self.lookLeft)
  # handler
  def lookLeft(self):
    # this would rotate the camera to the left
    base.camera.setH(base.camera,2)
#--------------------------------------------------

Useful key names (quote names, like ‘space’):

arrow_left/up/down/right
f1,...,f12
escape,backspace,insert,home,...
page_up/down
enter
[l/r]shift/control/alt (you can ommit l=left or r=right)

You can combine a modifier and a key, like ‘shift-a’, ‘control-shift-a’. Normally, you get the event on key press, if you want the key released event, you append -up, like ‘arrow_up-up’ :D .

If you’re trying to implement keys that perform an action continuously until released, it may be worth mentionning that this isn’t as simple as it looks. If you just try to detect the key-press, you’ll be getting only one key press until the key is released. You can detect repeat key presses by appending -repeat (e.g arrow_up-repeat). But that won’t solve the problem entirely because after pressing a key, there is a very noticeable delay before keyboard auto-repeat kicks in. I’m still looking into this one.

Sequences, Parallels & Intervals: Rock your Panda

in Panda3D, a Sequence is a list of ‘actions’ to be executed in order. Each action in the sequence is executed once and waits for the previous action to finish.

s=Sequence(a,b,c,name="NAME") # to create a sequence
s.play() # play once
s.loop() # play over and over
s.stop() # I'm making this up

Typically, a sequence consists in Intervals. The Panda3D manual has a large chapter dedicated to Intervals. Meanwhile, the Actor class provides easy methods to define intervals for position (pos), rotation (hpr) and scale (scale!).
An interval changes a property (location, rotation, scale, color…) at every frame until that property reaches a specified target value. As you can see, an optional start value can be defined for the property we are interpolating.

Actor
  posInterval(seconds,Point3(x,y,z), [start=Point3(x0,y0,z0)])
  hprInterval(seconds,Vec3(x,y,z)) # in degrees, e.g (180,0,0)
  scaleInterval(...)
  posHprInterval(...)
  posScaleInterval(...)
  hprScaleInterval(...)
  posHprScaleInterval(...)

A Parallel uses the same syntax as a sequence. With a parallel, actions are executed in… parallel.

Import statements

# I want to use sequences and parallels
from direct.interval.IntervalGlobal import *
# I have an actor that I want to move around/rotate
from direct.actor import Actor #use actor methods

Wait a second, is that all?

You may have guessed that Sequence and Parallel inherit from Interval. This allows generating complex, hierarchic sequences.

Sometimes we just need to yield a little bit before playing a sound or doing over things. The Wait interval does just that.

w=Wait(seconds) # defines a 'pause' in a sequence

Finally, the Func interval, lets us call any function as part of a sequence:

f=Func(function[,arg1[,arg2[,...]]])

Use and abuse?

Animation is an art, and you’ll find much more in the Panda3D manual, in the meantime, there’s a couple of points worth raising:

  • Where a complex animation is not very interactive, it may not be worth programming at all. What are animation packages for?
  • If your animation is very dynamic, consider updating your objects directly using a task (see previous article). Say you were programming boids. How much should we rely on intervals, and how much on intervals and sequences?

That’s it for now.

Panda3D: Run a Function at Every Frame

Reminder: from direct.task import Task

OK. This and the next tutorial cover useful methods for animating your actors and scenes in Panda3D

If you want a function to be called at every frame, you add a task to the task manager.

taskMgr.add(Function, "FunctionName")

Where a task is a function defined as follows:

def Function(task):
  #do something...
  return Task.cont # use Task.done to stop the task

From the task argument task.time returns the time (in milliseconds I guess)

Panda3D: Illuminations

This import statement allows you to use lightsources:

from pandac.PandaModules import *

1.1 Creating light sources

AmbientLight(name)
DirectionalLight(name)
PointLight(name)
    setAttenuation(Point3(A, B, C))  # try A=0, B=0, C between 0 and 1
Spotlight(name)
    setLens(lens) # e.g PerspectiveLens()

To create colored lights:

myLight.setColor(VBase4(r, g, b, a))

1.2 Attach a light to the scenegraph

node = render.attachNewNode(myLight) # attach to root

We get a node back and get then apply node methods to it (don’t apply node methods to the light objects directly).

1.3 Light node methods

setPos(x,y,z)
lookAt(myObject) # nice with spots
setHpr(x,y,z) # direction vector; useful for directional lights

1.4 Select objects illuminated by a light source

render.setLight(node)  # will apply light everywhere
render.clearLight(node) # disable

See Panda3D lighting basics (from their website) for more details.

Yet  another episode in my Panda3D crash tutorial. If you followed through I’m sure you got the hang of it.

Damn. By the way, I haven’t tested any of this. Sure, there must be some caveats, right?

Chicken Comes First: Exporting Animations from Blender to Panda3D

In my last tutorial, I gave a quick explanation for Blender >> Panda3D conversion using the X plugin. Having said that, this didn’t make me fully confident that I’d be able to use Blender animations with Panda3D.

The Chicken plugin is what’s commonly used to export from Blender to Panda3D, so I decided to create a very simple animation and see if I could export it to Panda3D using Chicken.

First, overview of how it works:

  • You create several animations and export them by selecting frame ranges – so for example 0 to 50 could be your first animation, 60 to 90 another animation, and so forth.
  • In Panda3D, it’s recommended to use separate files for models and animations. Chicken let’s you do that.
  • You instantiate the Actor class, loading your models and animations.
  • You invoke your actor to play animations.

Chicken also allows exporting static models (ie, no animation)

This tutorial doesn’t cover using Blender. If you’re not familiar with it, it may save you quite a bit of time to get somebody showing you around. Otherwise, stay posted as I’ve been fumbling around and will publish a few links very soon.

Also, this tutorial assumes that you’re using the ‘walking panda tutorial as a starting point.

Try to follow the steps in this tutorial very carefully. All these steps are a little sensitive and it feels nicer to get something to work first – rather than fiddling for hours, which is practically what happened to me (see caveats below).

Setup

1. Download Chicken
2. Copy archive content  to .blender/scripts/ or  similar (check the Chicken installation info)
3. Ensure you have Python installed. Your version of Python needs to match whatever Blender says on startup. If versions don’t match you can only use built-in plugins with Blender.
4. Ensure you have Panda3D installed. Chicken requires Panda3D

Create and export your animation using Blender/Chicken

1. Create an object
2. Create an armature
3. Parent your object under your armature. create vertex groups using the envelope when prompted.
4. Remove the object from it’s parent (I just do the parenting first to create vertex groups in the only way I figured so far).
5. Add the armature as a modifier to your object.
6. Keyframe your armature. A couple of frames is enough for a test.
7. Select your object (as far as I know, you don’t need to select the armature).
8. Select export using  Chicken. The first time there’s a configuration screen but no need to touch anything as I remember.
9. Add an animation (if not done automatically) using the Chicken GUI
10. Export (deselect ‘single file’). You could enable [pview] to preview your animation (in pview, use the L key to get your materials and textures to show)

There’s more you can do with Chicken, but the hardest part is getting your first animation exporting correctly.

Add your animation to your program

After exporting, you should have two files, one for your model and one for your animation.
The easiest way to test whether everything’s OK is to replace the default animation (just change the paths – you may also need to rescale the model) from the ‘walking panda’.
I tried to get that working by including Actor code into a world definition (e.g, hacking into Solar-System step 2) and it didn’t work (model is displayed, not the animation) – at least not until I moved my actor.loop(ANIM) statement out of the def statement. Why this doesn’t work the other way I have no idea so far.

Caveats

  • Why are my objects all white? For materials and textures to show, you need to add some lighting to your scene. Seems obvious? Maybe, but when exporting to Panda3D via the X plugin for blender, materials show, whether lighting has been added or not.
  • I had to uninstall an old version of Blender to get this to work. When I was asked whether to keep my .scripts folder, I said yes. But then, starting blender, I had no plugins working. I started over again, clearing the .scripts folder (for the record, I also asked the installer to keep my scripts under the blender folder in program files. Not sure if there’s a connection or not).
  • Chicken doesn’t support using an armature’s envelope, only vertex groups. By default, envelope is typically enabled.
  • Chicken doesn’t take into account modifiers other than envelope. Apply your modifiers before exporting.
  • As explained in the last section, I run into a problem when including the loop() call into a def statement. I’ll try to clarify this later.

Here comes your .egg

I’m not really fond of this way of doing things. Never mind the lack of organisation (frame ranges! But at least it appears that we can save export configurations), it’s not very clear how 3D model updates could get into a build process automatically – Chicken exports from Blender, so we’d have to start Blender first, then somehow get Chicken to configure and run as well. However, it doesn’t seem that there is an alternative, and for trying out things on a small scale, it’s ‘kind of OK’.

That’s it for now. If you can’t get this to work, don’t hesitate to ask so I can improve this tutorial – I’ll probably link a couple of sample files and add some screenshots later on, along with references to useful Blender resources.

Next Page »



Follow

Get every new post delivered to your Inbox.