I have taken a break from the spherical terrain and virtual world project to work on something a little less complex. I am creating a relatively simple script-only resource for T3D that simply moves objects and players along a path. The resource uses the existing T3D path system, and can be used to create a looping path or a non looping path.
This resource could be used to create currents in rivers, to move cameras or scene decorations around a level, to guide a player towards the next objective, or to create animated effects within a game level.
I am also working on a proximity detection feature which will automatically engage the “force” when the player intersects the path. This is proving to be a lot more complex that I thought, since the path is not solid, and the distance between nodes in the path is not known, and could be large, so I can’t just use a radius search.
Instead, I need to use vector math. I create a vector from the closest node to the player to the two other nodes in both directions. I then normalise these vectors, and scale them by the distance from the player to the closest node. Adding these vectors to the closest node gives me the two points closest to the player on the imaginary lines between the path nodes. If the distance from the player to either of these two points is less than a certain value, the player is captured within the force field.
This concept seems to work, but the implementation is still a little buggy.
I will post the link to the resource once I have uploaded it.
I have succeeded in getting OpenFOAM working. I wasn’t able to install it correctly on windows, despite several attempts, but I did discover an excellent distribution of Linux called CAELinux. This distribution is designed for engineers and programmers, and comes with a whole host of tools, including OpenFOAM. It also has code editors, the Arduino IDE, and visualsation tools for representing data (such as ParaView). It even has Qt installed!
I have been running CAELinux through the Oracle VM Virtual box. I had used the previously for testing a Torque3D project, and it works very well. It seems to run quickly and reliably, with some exceptions. I am beginning to come around to linux as an operating system. I had never really used it before, with the exception of some experience using Ubuntu in college. However I have used both CAELinux and another distribution, the rec
I was able, with some difficulty, to run the OpenFOAM “Motorbike tutorial”. This basically calculates the airflow around a motorbike object. I used Paraview to visualise the solution. I think I achieved relatively good results with it, although the learning curve with both OpenFOAM and paraview is very steep.
The next step is to load my own custom models in place of the stock motorbike, and conduct CFD analysis on them.
I have been creating and testing 3D Models for the purposes of 3D printing for some time now. One of the problems that I have discovered is in testing the model before sending it to the printer. I have had several orders cancelled (and refunded) due to issues. Most of these issues were due to a mesh having holes, multiple shells, or insufficient wall thickness. The problem is that most conventional modelling tools (such as 3DS Max, for example) do not have the tools neccessary to test a model designed for 3D printing.
I am currently using two tools for this purpose, one is “Mini Magics 3.0” and the other is “3D-Tool” Mini Magics is free, and is actually developed by iMaterialise, the 3D printing company that I use for my 3D prints. It is a very easy to use program, that scans for holes and multiple shells, however, it does not check for minimum wall thickness, which is, in my opinion, a vital feature. This is particularly true for people like myself, who model in 3DS Max, as Max does not have an easy way (that I have found at least) to specify or examine dimensions.
3D-Tool has a pro version, but I have been using the free version only, and so far, it seems superior to Mini Magics. This is largely due to the inclusion of a very powerful edge thickness tool. The user can easily specify the minimum thickness that they are working with (which will vary depend on the material) in addition to a number of other features.
The pictures below are from 3D-tool, and show the wall thickness tool in operation. This is a model that was rejected by the printers, and this tool easily shows why. The blue colour on the edge of the star at the center of the model are below the minimum thickness of 3mm. The extrusions at the head of the model are also below 3mm.
I have posted this feature as a resource on GarageGames. It can be viewed HERE.
This is the text of the tutorial from the resource:
This resource is a very useful addition for highlighting objects using a PostFX shader.
When turned on, the screen will change to black and white, except for designated objects which will appear as bright red.
This could be used for night vision, thermal vision, highlighting objectives or special items in a game, highlighting ammunition or health pickups, etc.
The way this system works is by setting the diffuse color of the objects to be highlighted to pure red, by using this line:
%mat.diffuseColor[0] = “255 0 0 255”;
and then searching for that specific color in the shader by using this line:
if(ret.r > 0.98 && ret.g < 0.09){
When it is found, that pixel is set to red, while the rest are set to black and white. This is essentially a “green screen” type concept. As long as no other object in the game has exactly the same colour that the shader is replacing, this should work well.
A limitation of the system is that the selection of objects is done per material, not per object. Which means that multiple instances of the same object, which share the same material, will either be all highlighted or not highlighted at all. To circumvent this, it is possible to just create two version of the same object, with the same texture, but two different materials. Then, highlight one, but not the other.
Another possible limitation is that when using the “selected = 1” dynamic variable to select multiple objects, objects inside a simgroup will not be highlighted unless there is another object sharing the same material outside the simgroup.
To implement this resource, first download the code file from here: (2KB, .rar file).
Place the shaders “objectshighlightP.hlsl” and “objecthighlightV.hlsl” into:
shaders/common/postFx
Place “ObjectHighlightingPostEffect.cs” into:
“scripts/client/postFX/”
Place “ObjectHighlighting.cs” into:
“scripts/server”
and execute is from “scripts/server/scriptExec.cs” by calling:
exec(“./objecthighlighting.cs”);
Using the effect is simple.
To highlight a single object, call:
enableselection(%obj);
and to switch back to regular vision call:
disableselection(%obj);
A more useful way to use this would be to add a dynamic variable called “selected” with a value of “1” to a group of objects in your scene. This can be done using the mission editor, or by calling: “%obj.selected = 1;” Bearing in mind, as mentioned before, that highlighting is done per-material, not per object.
This is a short tutorial detailing the steps needed to create a visibility animation with 3DS Max, by adding a visibility track. This is the easiest way I have found to do this, and is perfect for animating muzzle flashes in particular, as well as any kind of relatively simple animation where a mesh or meshes needs to have it’s visibility changed during an animation. I am writing this tutorial with a focus on 3d gaming, but the same techniques could be applied to an 3d scene or animation.
First, the mesh itself. I am animating a laser fence here, and I want the player to be able to turn this on and off. I am going to add two animations, one to make the lasers change from visible to invisible, and one to make them change from invisible to visible.
The first thing to do is to hightlight only the mesh whose visibility you wish to animate. In this case, I selected just the laser beams of my mesh, and not the vertical support structures.
Then, click on the “Track View” Icon on the command bar, as shown:
Inside the curve editor you will need to make sure that the mesh you wish to animate is selected on the left hand side of the menu.
Then, to add a visibility track, on the command bar, go to Tracks > Visibility Track > Add
You may now animate the visibility of this mesh by using the screen on the right. The numbers a long the bottom are the frames of the animation, and the numbers on the left are the visibility values. By Right clicking on the timeline, and clicking “add keys” you create keys. You can then drag these keys and use them to determine the visibility settings at each frame, like I have done here:
This screen shot shows that at frame 0 (The beginning of the ainmation) the visibility is 20. The visibility then fades to -1 at frame 15, before rising again to 20 at frame 30. This means that the mesh will change from visible to invisible and back again over that 30 frame period. I have not been able to make the ainmation fade seamlessly through the frames, it seems to be 100% visible as long as the visiblity value is above 0, and then instantly becomes invisible when it drops below 0.
In T3D, I can split these 30 frames into two separate ainmations, like so:
This splits the default “ambient” ainmation into two animations of 15 frames each, a “turnoff” ainmation, which stops at frame 15, and a “turnon” animation, which starts at frame 15 and continues to frame 30.
This code is placed in the .cs file that is automatically created when a new art asset is added to the level, and the name of the function must match the name of the art asset, like so:
You should now be able to preview this visibility ainmation in 3dsmax. Notice however that insible meshes do not show as completly invisible in max, they just look transparent, like so:
Rendering the scene will show the mesh as completely invisble.
Now all that is left is to export the mesh to T3D.
Select all of the components of the mesh, and go to Export > Export Selected.
Choose a filename and location, and you will then be presented with the export dialog:
This is quite simple, and the default values are mostly fine, however, you will need to select the checkbox for “Animation” under the “Ainmation” heading. You will also need to select “Bake Ainmation” under “Bake Animation” and make sure tha the Start and End values are set to the actual start and end of your animation (not just the length of the animation bar in max).
This resource adds support for “metablobs” to T3D. This can allow for very realistic fluid simulations, much more so than can be achieved with particle effects.
Included are a realistic Water material, a Lava Material, A Tar material, and a Mud material. I have also included a ported version of the renderMonkey glitter shader.
Tutorial:
First, download the resource from here: (4.2MB’s, .RAR archive)
http://www.phoenixgamedevelopment.com/downloads/FluidDynamics.rar
Copy the “Fluid Dynamics” folder to:
“game/art/shapes/FluidDynamics”
Inside the archive is a folder called “SHADERS”. All files in this folder should be copied to:
game/shaders/common/
Drop the files directly in that folder, do not include the “SHADERS” directory itself.
There should also be a folder called “CODE”. All files in this directory should be added to:
“engine/source/T3D/examples/metaBlobs”
In your compiler, you will then need to add these files to the build.
In order to add MetaBlob based objects to the world using the editor, add the following line to:
“game/tools/worldeditor/scripts/editors/creator.ed.cs
Around line 100, under:
%this.registerMissionObject( “RenderShapeExample” );
add:
%this.registerMissionObject( “metaBlobExample” );
The resource folder also contains a sample mission file showing how to create a metablob object from code.
Finally, execute the file “fluiddynamics.cs” by adding the line:
exec(“art/shapes/FluidDynamics/fluiddynamics.cs”);
to:
“game/scripts/server/scriptExec.cs”
Any questions, comments, etc, can be directed to:
jackstone@phoenixgamedevelopment.com
I have prepared my Genetic Algorithm Example application for upload. I used the QT library to develop the application, but the executable should run on almost any Windows system, whether QT installed or not.
A code listing with comments follows, refer to my earlier post on this topic for more information. To build and execute this code, simple create a new QT gui application, and add the relevant files from the source directory.
gaentity.h:
#ifndef GAENTITY_H
#define GAENTITY_H
class GAEntity
{
public:
GAEntity(int maxnumber);
GAEntity();
int solution; //This is the first, and so far only, “chromasome” of the GA entity
int fitness;
};
#endif // GAENTITY_H
gaentity.cpp:
#include “gaentity.h”
GAEntity::GAEntity(int maxnumber)
{
solution = rand() % maxnumber + 1; //All GA entities are initialised with a random value from 1 to the max number.
fitness = 999; //lower fitness values are better, so initialise entity with an impossibly high value
}
GAEntity::GAEntity()
{
solution = rand() % 1000 + 1; // default constructor, assumes max value is 1000
fitness = 999;
}
Main Logic Function:
void MainWindow::runbtnpushed(){
srand ( time(NULL) ); //init time for random number function
QString s = “”;
//init variables from gui:
int targetnumber = ui->targetIN->value(); //The number that the AI is trying to guess
int maxgenerations = ui->maxgenerationsIN->value(); //The max number of generations that the algorithm will run for.
int populationsize = ui->popsizeIN->value(); //The number of entities to create in each generation, the more there are, the more chance they will solve the problem
int bestfitness = 999;
for(int i = 0; i < populationsize;i++){ GAEntity ent = GAEntity(ui->maxnumberIN->value()); //Create I entities and initialise to random value
ent.fitness = abs(targetnumber – ent.solution); //determine fitness (Simply subtract the solution from the targetnumber, and ignore the sign)
population.push_back(ent); //add to population vector
}
int count = 0;
//pick the best two candidates, mate them, produce new population
GAEntity parent1;
GAEntity parent2;
//choose parents:
for(size_t i = 0; i < population.size();i++){ //lesser fitness is better
GAEntity ent = population[i];
//fitness:
int fitness = abs(targetnumber – abs(ent.solution));
//this code finds the two entities with the highest fitness. This would be an excellent place for improvement!
if(fitness < parent1.fitness){
parent2.fitness = parent1.fitness;
parent2.solution = parent1.solution;
I lost quite a bit of time this week due to major system instabilities I was getting on my main work machine. I was getting frequent Blue Screens, with seemingly random causes. I initially assumed the problem was due to a problem with Flash on my firefox browser, because switching to Chrome actually fixed the problem for several days, but it then returned.
After downloading a very useful tool called “Blue Screen View” from Nirsoft, I could see that most of the BSOD turned out to be of the type “Page fault in Non Paged Area”, which indicates a RAM problem. I used the famous MemTest86+ t0 check every one of my 4 RAM sticks individually, and I found one stick which produced over 86 thousand errors just halfway through the first pass! After removing that stick of RAM the system is back to performing well, albeit with just 6GB of RAM instead of 8.
Unfortunately, it is nearly impossible to buy RAM sticks individually, you almost always have to buy sticks in sets, so I have have to buy more than I need to get back to my preferred 8GB of RAM.
I thought this was worth posting about, since Blue Screens and RAM errors are both relatively common, and the aforementioned programs are invaluable in debugging and fixing them.
Below is a picture of the offending RAM stick. I don’t think Corsair Dominator is a bad brand, not at all, I have been a fan of Corsair memory for a long time. This is the only stick of RAM of theirs that has ever actually failed on me, and it’s about four years old.