Lightwave
Plugin Tutorials - Lesson Four
| Your first Displacement
Map. If you've been following these tutorials from the start then you should have a "Gravity.p" plugin. This automatically bounces an object, either at a y value of zero or based on 2 nulls. When the object bounces, however, it does not deform. The aim of this tutorial is to introduce displacement maps by creating a plugin to deform our object. To use this download the tutorial files for this project and extract them to a new folder called "Squash". (The tutorial files for this tutorial are different from the previous ones.) Displacement handlers and Displacement access Again you will find a blank displacement map file included ready for you to create a Displacement Map plugin. To follow the tutorial crank up Visual C++ and open the workspace "Squash.dsw". Looking into the file "Squash.c" you will find a commented out copy of how the Lightwave SDK include files define the handler and access structure for a Displacement Map:
Much of this is identical to the Item Motion Plugins we've been looking at. The additional function that we need to define is "newTime". An Item Motion Handler's evaluate function is called for each new frame and contains time information. A Displacement Map is called for each point and does not contain time information. You must save this information in your instance using the "newTime" function. So we add time and frame parameters to our instance structure.
The other elements are
The newTime function No rocket science here, just a few things to set:
Some displacement maps can operate using the limited information available via the Displacement Access pointer that is passed to the process function. But this information contains just the original location of a point, (as it would be in modeller) and the displaced position either in world or local coordinates. This is very little to use. Our sample scene "bounce4.lws" uses the Gravity plugin we created earlier to move the ball. By so doing if we used the Lightwave SDK function for Item Info param, and asked for position information it would report the position at frame zero, all through the scene. We need a way to get at the real information, our thechnique is to do a point scan. Frequently, when writing a Displacement map you will create memory for a set of points for the entire object and deform the object once per frame, possibly via the newTime function. In this plugin we go one step further we create an array of points for every point in the object for every frame. So we can calculate once and then display the result. This is convenient but not very interactive, to use this method for a useful plugin you should add an options box so that your plugin can be informed to recalculate the points array. I'm getting very confused OK, maybe we are rushing ahead here. How do we display an object in 3D? We define a set of points and polygons and let Lightwave do the rest. Displacement maps don't care two figs about polygons, Lightwave already knows about them, they care about points. If we move a point via our Displacement map then that is where it will appear. So we allocate memory for the position of all the points in the object for every frame in the scene.
The reason we use memset to set everything to zero is that our VECTOR includes a set parameter. We want to know where Lightwave will put every point on every frame, if we do nothing. So the first step is to retrieve this information. When our process function is called with mode set to 0 (just created) or 2 (just loaded) it creates the point memory then waits for the user to either create a preview, which is guaranteed to go through every point, or use the play button. Every newTime the points are scanned to see if they have been set yet. When every point has been set we are ready to move them. Here's how the scan function looks
Calculating the squash The squash function is only called when we know where every point in our scene should be. But any deformations want to take place with respect to the centre of our object. We will step through the frames in our scene one by one. We find the current centre of the object in world coordinates and also the top and bottom points. Once we have this information we find the height and the adjusted new height. Then we set our point pointer to the first object point for the current frame:
Now we must iterate through every point if the bottom has gone through y=0.0. (Note as provided the plugin will not work if the gravity plugin uses nulls). If bottom is above y then we need do nothing further as no deformation is required.
If we need to deform then we use a bit of trig to generate a reasonable shape for the deformation. Remember trig functions work with radians, sin(0)=0, sin(PI/2)=1, cos(0)=1, cos(PI/2)=0. Using these functions we can smooth the ramp between not doing something and doing it. The only way to understand stuff like that is to play with the numbers. Try using a spreadsheets and playing with the data and perhaps charting it to get a better visualisation of the trig functions. The process function So the process function is quite simple. We are either scanning or setting. Scanning is terminated when every point has been scanned.
You may have found some of the code in this tutorial a little harder to follow. But, persevere. There is nothing quite so satisfying as the plugin that you have laboured over finally coming good. If you are unfamiliar with pointers then you will almost certainly crash the machine every now and then. Don't worry, we all do this. Try to remember to NULL a new pointer, free any memory you create, and never write beyond the boundaries of your memory allocation. If you remember those golden rules then you will be fine. Summary Now you've come to the end of this short series of tutorials. If they have spurred you on to write a plugin then please send me the results, or any comments you have that might enable me to improve the series. There is far more to learn but hopefully now you have a better idea where to look. Good luck with the plugins!! Lesson
1 - Introduction, compiling your
first plugin. |
|