Hot New Look, Same Old Stuff


When you logged into my site today to see if there had been any changes since yesterday, you undoubtably panicked when the classic black and green theme didn’t load.  Don’t worry, you don’t need to check to make sure all my posts are the same - this is the same blog - I just got tired of my old theme so I have updated for a more wonderful look that will keep people coming back.  I will probably be switching out the header graphic in the next few days, and am still wading through some CSS nightmares, but hopefully we can all rest easier now that my theme name is no longer “contaminated”.

Also, sign up for Flash on Tap - the early bird special ends September 8th - and this is one conference you don’t want to miss!  Hopefully I will see you there!



Reflections in Papervision3D


reflect3.png

After posting my shadow experiment, Patrick Matte posed a question wondering if I would be able to do real-time reflections in a similar manner. The next day I had it done, along with some nice iterations along the way: orthographic and perspective projection (I can release those later if anyone really wants them). I've been sitting on it every since and finally decided I would take the time to write a little description into how its done and give the code to those who are interested (and I fixed up some code for backface culling in the reflection this morning).

So, the concept of shooting a ray onto a plane still holds true with the reflection stuff, but we handle the rays a little differently than we do shadows. With shadows we simply project the vertices directly onto the plane. This works because we don't care about the perspective distortion we will see on the plane face, since the shadow is black. A reflection is more than a projection. The reflected object is actually cast "inside" the material - so it maintains its own perspective despite the perspective of the plane you are projecting into. So, the problem was, how can i negate the perspective of the plane to make a real reflection?

The answer was pretty cool, and I am very happy with the result. Instead of projecting a vertex directly onto the plane, I multiply the vertex by a reflection matrix. The reflection matrix allows me to flip any object over any plane. Once i get the vertex in "reflected" space, I then cast a ray from my camera to the reflected vertex. Once I have this ray, I can find where it intersects the plane i want to show the reflection on - and then determine where on that material the ray hits. Since the material will be drawn from the camera's perspective, I can draw my reflected space from the camera's perspective as well - directly into the material. It's a little confusing, but it works awesome. Here is a little graphic I made to try and help explain:

reflectui.png

The red square is the object we want to reflect. The blue cube is the object in "reflected" space. The blue cube doesn't actually exist, mind you, all the vertices are flipped there via matrices. The thin red lines shooting from the camera are the rays, and the faint red box is the reflection drawn into the plane. Sorry its not a better graphic - I don't use Illustrator that much...

Anyways - thats about all there is to say about the theory behind it. Here is a brief rundown of the class:

Actionscript:
  1. //CREATE A NEW PlaneReflection
  2. // parameters:
  3. // - id: string
  4. // - blendMode : string
  5. // - alpha : Number (0-1)
  6. // - filters : array
  7. var reflector:PlaneReflection = new PlaneReflection("reflex", "multiply", 1, [new BlurFilter()]);
  8.  
  9. //ADD A MODEL TO THE "REFLECTION LIST"
  10. reflector.addModel(sphere);
  11.  
  12. //RENDER THE REFLECTION
  13. // paramaters:
  14. // - camera  : CameraObject3D - camera you are currently using
  15. // - plane : Plane - a plane to draw into - must have a MovieMaterial applied to it (animated = true);
  16. reflector.render(camera, plane);

That should be enough to get you started! Check out the demo, have fun with it. You will notice I used the planes own material as a displacement map for the reflection - that gives it the nice bumpmap feeling. Planes are still backwards (sorry) - so there is a special case to flip culling if you have a plane object.

View the demo (click and drag to orbit)

and

Get the source



Flash on Tap - Boston - Sign Up!


2008-08-09_1610.png

Imagine the best lineup of speakers you can - put them all in an awesome city - throw in a day of hands on workshops covering cool stuff - and then imagine you were there. This conference, a.k.a. Flash on Tap, will be happening October 7th-9th 2008, in Boston, MA. 3/5 of the Papervision core team will be there, some awesome experimentalists, plenty of red5 and flex developers, and even some designer types. The event is going to be held at the Park Plaza's "Castle" - a very unique location which should be a lot of fun.

If I still haven't sold you - you should at least just come to see my session. I'm going to be doing something very cool on Papervision (that's all I will commit to for now).

Anyways - sign up now! Its going to be a lot of fun and I'd love to meet some cool fellow flashers.

cheers.



Quaternions in Papervision3D



quatsintro.png

I have a feeling that my favorite feature of Papervision3D is actually the most overlooked feature of Papervision3D. Not because it is insignificant or slow - but mostly because it can be a difficult concept to understand, and most Flash programmers don't come from heavy mathematical backgrounds.

If you failed to read the title and still aren't sure what I'm talking about, I'm talking about Quaternions. If you have never heard of them - do a quick google search. I won't bother going over the bare basics of them here - it is a heavily covered topic and I doubt I could do a better job in this post than what you will find on the web. I have put together a quick video, however, in which i explain just the very basics of how I went about getting the motion you see in the demo, and how you can use Quaternions in Papervision.


quatmovie.png

Watch it here

I tried to keep it short - but hopefully it will be helpful. Really the most important thing to know about using quaternions in Papervision is you simply need to multiply their matrix back into your transform matrix.

Actionscript:
  1. object.transform.calculateMultiply3x3(object.transform, quaternion.matrix);

As with all matrix math - order of operation is important - make sure you do transform * quaternion, not quaternion * transform. If you do it the second way, it won't be local to the object (but can still be very useful for some other things). Also make sure you do a 3x3 multiplication - as rotation only deals with 3x3 matrices.

Check out the demo

and

Go get the source (I've included my model for you - yes, I made it myself, and no, I'm not a professional modeler).



Casting Shadows In Papervision3D - Redux



shadowtop.png

As some of you might have noticed - I love coming back to old projects and doing them right (see Dragging in 3D, various Sound/particle projects, and so on). Well, shadows in no different. One of my first posts EVER was Papervision Shadow Casting - it gave developers the ability to shade faces of an object material with "casters" - which obviously cast shadows. It was slow, looked decent if you knew how to hack it, and overall it sucked, at least I think so.

Well, tons of people have written me in response to that - wondering if I would EVER convert it to 2.0. The answer - not yet. But I made something very similar, and what I think is much cooler - and runs much better - and looks much better. The concept with this class is you can cast shadows - PRECISE shadows - onto a plane. Why only a plane? Because if we do anything OTHER than a plane it will be much heavier on the CPU. This technique is very fast - since we know the dimensions of a plane, we can easily determine the UV coordinates of a plane/ray intersection - without having to riddle through faces and checking sides of triangles.

So, lets talk about the class itself. It is a stand-alone class that will let you cast the shadow of any object onto any plane that has a MovieMaterial. You can set your MovieMaterial to animated and it will always be live - or you can call "drawBitmap" after you cast a shadow - which can save on performance if you dont need to update every frame. I require a MovieMaterial because it makes it very easy to do cool stuff with the shadow - Blend/Alpha/Filters - you can apply ALL these things to your shadow. Here's how:

Actionscript:
  1. var shadowCaster:ShadowCaster = new ShadowCaster("shadow1", 0, BlendMode.NORMAL, 0.75, [new BlurFilter(4, 4, 2)]);

Here are the parameters:

  • uid : String - a unique identifier that tells the shadowCaster what layer to draw on. It will create this layer in your MovieMaterial on its first cast.
  • color : uint - Color of the shadow
  • blend : String - BlendMode to use. Defaults to Multiply for nice shading.
  • alpha: alpha of the shadow
  • filters: an array of filters to apply to the shadow. If you pass null a default BlurFilter will be used.

Thats it. The last thing you have to do is cast your shadow!

Actionscript:
  1. shadowCaster.castModel(dae, light, plane, castPerFace, cull);

Here, you can cast an entire model - all of its children included. The parameters should be self-explanatory, but i will go over them quickly. The first is the object you want to cast shadows off of. The second is the LightObject3D you wish to use. The third is the Plane you wish your shadows to be cast onto. The fourth parameter takes a boolean. if you specify true, you will get a precise per-face shadow. It will look like you imagine a shadow should. If you pass false, the shadow will be cast off the bounding sphere of the object. Much faster processor wise, but the shadow will only be a circle, so its not as impressive visually. The last parameter is backface culling. This means it will only render faces that look towards the light. It will cut your projections in half most times - but I have found it to be unreliable. Feel free to take a look at the code and fix it for me.

You can also call castFaces or castBoundingSphere - if you wish to cast per object rather than an entire do3d and its children. They take similar paremeters, so you should be good to go. You can toggle between these two modes in the demo with the "B" key.

Another to note about the ShadowCaster class is that you can change the type of shadow that is drawn. The two types are DIRECTIONAL and SPOTLIGHT. DIRECTIONAL light takes the direction of the light rays from the light source to the object center. All shadows are cast in that direction. This will give you a uniform look - like you would imagine if the sun were lighting something. SPOTLIGHT casts a ray through each vertex - making the light cast long - similar to something you might see in the movies. Play with both. You can set them via the shadowCaster.setType() function - passing in either ShadowCaster.DIRECTIONAL or ShadowCaster.SPOTLIGHT. In the demo you can toggle between these with the "T" key.

The last thing to note about the ShadowCaster class is it stores references to all objects that are cast - this greatly increases render time. You can "flush" the memory so to speak, if you plane or object are moving, by using the invalidate() function. Alternatively, you can simply call invalidateModel, invalidatePlane, or invalidateTarget. These will only invalidate specific parts, saving on re-processing hits. You can take a look in the code to see which each does - but the name will hopefully help you understand.

So thats it! You can cast shadows from anything you want now!

View the Cow Demo

Here is another quick demo I threw together just to show how easy it is - even with animated models:


monsterwalk.png

View the Monster Demo

I simply call shadowCaster.invalidateModels() after every castModel() call. It handles the rest.

Hope you enjoy it. Also give thanks to everyone who helped me debug the Gouraud problem - especially Seb, Benoit, and Tim. The bug has been resolved and you can all now use GouraudMaterial with a smile.

Get the Cow Demo Source and ShadowCaster

Enjoy!