PLUGIN: Razorblade 3D - full-blown, modern 3D within AGS!!

Started by DoorKnobHandle, Sun 08/08/2010 16:55:17

Previous topic - Next topic

DoorKnobHandle




This video explains it all:


CLICK BELOW TO WATCH!



Grab Version 1.0 HERE. Note that it does contain a few undocumented functions and there might be bugs - especially in the collision detection area. The important thing for now is that the core functionality is there. Being able to load and display models with custom shaders and so on.

It comes with the demo game that you saw in the trailer (and source code, assets etc. to that) as well as the documentation and - of course - the DLL itself. Using the source code to the demo game and the documentation, it should be a piece of cake to start putting a 3d game together in AGS. Open the demo game up in the editor and run it from there please. If you run it from the Compiled folder it won't find its resources. If you want to publish a game, you have to copy your models and shaders folders into the compiled folder before distribution!

Let me know what you guys are thinking.

One thing I didn't mention: Razorblade 3D also supports casting rays (lines basically) into the level and then you can check if they hit anything and at which distance. This allows you to check whether a bullet hit an enemy for example.

Two notes:

- Sorry for overusing the phrase "you know" in the video. :D
- I misspelled the title of the plugin in the link image above, it's Razorblade, not Razerblade.

Credit goes to Davi "Exsecratus" Arakaki for the art in the demo game!


Here's a guide that straydogsstrut kindly provided! Make sure to read this before trying to develop with Razorblade 3D!

Quote from: straydogstrut on Sat 25/02/2012 23:33:07
** Pre-requisites for using the plugin **


  • AGS 3.2.x

** Installing the plugin **


  • Download the plugin and extract
  • Put the AGS Razorblade Plugin.dll in the main folder where AGS is installed (This is the same folder where the AGS Editor.exe is)

** Running the demo Game **


  • Download the demo game and extract
  • Start the AGS Editor and choose Open an Existing game
  • Find the Razorblade 3D Testgame and select the Game file
  • If the plugin is installed correctly you should see the active plugin listed under the Plugins node in the main tree in AGS (right hand side of the program)

Run the game but be aware that if AGS is installed anywhere other than 'C:\ AGS 3.2.1 SP1' (for example, mine is at C:\Program Files\AGS 3.1.2) it will complain about missing textures. This, it seems, is due to the 3DS Max models supplied with the demo game referencing absolute paths. You can dismiss these errors and the game will still run with a default texture. I no longer have 3DS Max on this machine to test the suggestion of changing the setting in the preferences unfortunately.

The demo game features an environment to move around in. WASD keys to move and arrow keys to move the light source around (IJKL can also be used but are commented out in the code). Left mouse click will cast a ray towards the location of the click and report on what was hit (like a gunshot in any FPS). The base model will return "hit nothing" while the lightbulb will tell you the name of the model hit. Note there is no collision detection in the plugin (this is intentional, it's a graphics engine primarily) so you can move through objects.

** Using the plugin in your own games **


  • Having installed the plugin, launch the AGS Editor and start a new game
  • You should see the plugin listed under the Plugins node in the main tree in AGS - right-click it and choose Use This Plugin
  • Make sure that Default Graphics driver is set to Direct 3D 9 Hardware Acceleration
  • Any models and shaders you want to use can be placed in subfolders in the main game folder called models and shaders respectively like the demo game.
  • Models should be in .dmf format (I haven't seen a link to the exporter previously mentioned)
  • The default texture default.png should be placed in the main game directory - I could not get the game to run without this but again presumably this is a path referenced by the demo models themselves?

Going by the demo game, the 3D scene is created in the GlobalScript file - the main bits to look at are:


  • The variables declared at the top of the GlobalScript.asc file (a boolean to track whether the initial setup has been done and integers for the models, lights and shaders).
  • The init function which sets some defaults (background colour, camera culling and clip distance), adds the the object models, shaders and lights
  • A crosshair GUI (see the example in the demo game under the GUI node) is placed and shown at the end of this function
  • The HandleControls() function calls the PlayerControl and AttachWeapon functions found in the Camera script (look under the script node) to allow camera movement and update the placement of the gun
  • The rest of the handleControls function sets up key presses to move the light source around
  • The GameStart() function sets the max FPS, positions the mouse, camera and shows some debugging info
  • The repeatedly_execute() function checks if the initial setup has already been done and if it has does stuff with the shaders that is beyond me ;) It also calls the HandleControl() function described above.
  • Finally the mouse_click() function contains the hit testing code (notice we added an extra model for the hit test)

The documentation that comes with the plugin is excellent and lists many of the commands available. This includes a description of what they do so you can work it out just by looking up the function call in that file.

** Publishing the game **

It has been mentioned that the models and shaders folders should be added to the Compiled folder when publishing the game. I have not tested this.

For people that just want to check out this plugin's capabilities without downloading anything, here's the current documentation:

Quote from: Documentation
CAMERA
   
function RB_SetCameraPosition ( float x, float y, float z )
float RB_GetCameraPositionX ( )
float RB_GetCameraPositionY ( )
float RB_GetCameraPositionZ ( )

   These functions allow you to set the position of the camera and retrieve it.
   Should be self-explanatory.


function RB_SetCameraTarget ( float x, float y, float z )
float RB_GetCameraTargetX ( )
float RB_GetCameraTargetY ( )
float RB_GetCameraTargetZ ( )

   These functions allow you to set the position of camera target and retrieve it.
   The camera target is a point in 3d space that the camera is looking at.
   Use this point as well as the camera position (see above) to position and orient
   the camera in any way you want.


function RB_SetCameraFOV ( float fov )
float RB_GetCameraFOV ( )

   These functions allow you to set the field-of-view of the camera and retrieve it.
   Play around with this value and see what happens for yourself.
   The FOV defaults to 60.0 - which is a standard value to use - so you don't HAVE to
   set it if you don't want to specifically.


function RB_SetCameraClipDistance ( float clip_distance )
float RB_GetCameraClipDistance ( )

   These functions allow you to set the clip distance of the camera.
   That is the distance at which things will start cutting off.
   Make sure this value is large enough so that your scene is visible.



MODEL

int RB_AddModel ( String filename )

   This function adds a new model into your scene.
   You have to supply a filename relative to the game folder that AGS creates for your
   games and the model has to be in the DWF format. Use an exporter for your 3d model
   program to export your assets in that format.
   The function returns a handle that you have to store (as an integer) if you want to
   change further parameters of the model.


function RB_RemoveModel ( int id )

   This function removes a model from the scene.
   You have to supply a handle to an existing model.


function RB_SetModelShader ( int model_id, int shader_id )

   This function tells the game to use a certain shader for a certain model.
   You have to supply a handle to a model as well as a handle to a shader.
   Models with no shader set will default to a very basic one without lighting.


function RB_SetModelPosition ( int id, float x, float y, float z )
float RB_GetModelPositionX ( int id )
float RB_GetModelPositionY ( int id )
float RB_GetModelPositionZ ( int id )
function RB_SetModelRotation ( int id, float x, float y, float z )
float RB_GetModelRotationX ( int id )
float RB_GetModelRotationY ( int id )
float RB_GetModelRotationZ ( int id )
function RB_SetModelScale ( int id, float x, float y, float z )
float RB_GetModelScaleX ( int id )
float RB_GetModelScaleY ( int id )
float RB_GetModelScaleZ ( int id )

   These functions allow you to position, rotate and scale a model in any way you want as
   well as retrieve their current position, rotation or scale.
   The first parameter has to be a handle to an existing model.
   Rotations are done in degrees.


function RB_SetModelCustomCullMode ( int id, RB_CullMode mode )

   This function sets a custom cull mode for a specific model. If your game doesn't use
   automatic backface culling, this function won't do anything. If it deletes faces that
   are counter-clockwise for example, but you have one specific model that is done the
   other way, you can use this function to set up a different cull mode for this mode only.



HIT MODEL

int RB_AddHitModel ( String filename )
function RB_RemoveHitModel ( int id )
function RB_SetHitModelPosition ( int id, float x, float y, float z )
float RB_GetHitModelPositionX ( int id )
float RB_GetHitModelPositionY ( int id )
float RB_GetHitModelPositionZ ( int id )
function RB_SetHitModelRotation ( int id, float x, float y, float z )
float RB_GetHitModelRotationX ( int id )
float RB_GetHitModelRotationY ( int id )
float RB_GetHitModelRotationZ ( int id )
function RB_SetHitModelScale ( int id, float x, float y, float z )
float RB_GetHitModelScaleX ( int id )
float RB_GetHitModelScaleY ( int id )
float RB_GetHitModelScaleZ ( int id )

   These functions are equivalent to the respective model functions (see above).
   The difference is that these concern not normal models but hit models.
   Hit models are always invisible and are only used to calculate collisions with.
   This way you can have a triangle-heavy visible model and a simplified one
   (a box, a cylinder, a sphere maybe, or a combination of these shapes with very
   few triangles) so that collision calculations are much faster.



LIGHT

int RB_AddLight ( RB_LightType type )

   This function adds a new light to the scene.
   You have to supply a light type. Currently only point lights are supported.
   The function returns a handle (integer as always) to the new light that you have
   to store if you want to change its parameters after the creation.


function RB_RemoveLight ( int id )

   This function removes a light from the scene.
   You have to supply it with a handle to an existing light.


RB_LightType RB_GetLightType ( int id )

   This function returns what particular light type a light in the scene is.
   You have to supply it with a handle to an existing light.
   The function returns the respective light type.


function RB_SetLightPosition ( int id, float x, float y, float z )
float RB_GetLightPositionX ( int id )
float RB_GetLightPositionY ( int id )
float RB_GetLightPositionZ ( int id )

   These functions allow you to set the position of a light as well as retrieve it.
   The first parameter has to be a handle to an existing light.


function RB_SetLightAmbientColor ( int id, floatare, float g, float b )

   This function sets the color of the ambient term of a light.
   The ambient light is added to all of your scene regardless of distance or orientation
   or anything. If you would want your scene to be lit by nothing except a single point
   light, set this to black. If you also want a distant moon lighting all of your scene up
   just a little bit, set it to a dark yellow.
   You have to supply it with a handle to an existing light.


function RB_SetLightDiffuseColor ( int id, floatare, float g, float b )

   This function sets the color of the diffuse term of a light.
   The diffuse light is only added to triangles that face the light to a certain degree and
   that are close enough. If you imagine a candle in a dark environment, the orange light
   coming from the candle and lighting up nearby objects would be the diffuse light.
   You have to supply it with a handle to an existing light.


function RB_SetLightSpecularColor ( int id, floatare, float g, float b )

   This function sets the color of the specular term of a light.
   The specular color is the light that reflects back from a lit up surface to the camera.
   It's particularly strong on objects with a wet or metallic surface.
   You have to supply it with a handle to an existing light.


function RB_SetLightIntensity ( int id, float intensity )
   
   This function sets the overall strength of the light.
   The more intense a light is, the brighter it will appear and the more area will be lit
   up by it.
   You have to supply it with a handle to an existing light.


function RB_SetLightCutoff ( int id, float cutoff )

   This function sets the exponent that is used to calculate the cutoff for the light.
   Setting this to 1.0 would result in a linear cutoff meaning a triangle x units away from
   the light would receive twice the light as a triangle double that distance would.
   Increase the value to get more realistic results where a certain region around the light
   gets lit up a lot and then it fades away very quickly.
   You have to supply it with a handle to an existing light.


function RB_SetLightShininess ( int id, float shininess )
function RB_SetLightSpecularIntensity ( int id, float specular_intensity )

   These functions allow you to control the exact behaviour of the specular part of the light.
   You have to supply them with a handle to an existing light.



SHADER


int RB_AddShader ( String filename )

   This function adds a shader to the scene.
   Store the handle it returns (as an integer) in order to apply it to models.
   You have to supply it with a filename relative to the game folder that AGS creates for your
   game where it can find a shader in the FX format (written in HLSL).


function RB_RemoveShader ( int id )
   
   This function removes a shader from the scene.
   You have to supply it with a handle to an existing shader.


function RB_SendFloatToShader ( int id, String name, float value )
function RB_SendFloat4ToShader ( int id, String name, float value1, float value2, float value3, float value4 )
function RB_SendFloatArrayToShader ( int id, String name, float value[], int element_count );\r\n" );
function RB_SendFloat4ArrayToShader ( int id, String name, float value1[], float value2[], float value3[],
float value4[], int element_count );


   These functions allow you to send varying floating point vales and arrays of values to the shader.
   You have to supply them with a handle to an existing shader, a name to a variable of proper type in
   the shader code as well as the necessary values. For sending arrays you also have to tell the function
   how many elements there are in the array in the last parameter.
   

function RB_SetShaderAutoSendWVP ( int id, String name, bool toggle );\r\n" );
function RB_SetShaderAutoSendW ( int id, String name, bool toggle );\r\n" );

   These functions allow you to make your game send a shader the world-view-projection matrix or simply
   the world matrix automatically each frame.
   You have to supply it with a handle to an existing shader, with a name to a matrix variable in the
   shader code and a boolean value to determine whether you want to turn the automatic sending on (true)
   or off (false).



MISC


function RB_SetClearColor ( floatare, float g, float b )

   This function sets a global clear color.
   That is the color the scene will default to every frame. The color will be visible when you don't have
   a model that surrounds the camera completely.


function RB_SetGlobalCullMode ( RB_CullMode mode )

   This function sets a global cull mode. You can improve performance by letting the game delete faces that
   don't face the camera as these wouldn't be visible anyways.
   Note that the global cull mode can be overwritten for each model.
   You don't have to set this value, it will default to not using culling at all as a wrong cull mode makes
   your models invisible.


int RB_SendRay ( float x1, float y1, float z1, float x2, float y2, float z2, RB_IntersectionType intersect_with )

   This function sends a ray from a position in 3d space to another location.
   You have to supply it with both the origin and the target points.
   You can also choose whether you want the ray to collide with anything or just hit models.
   The function returns a handle to a collision object, use that to check the collision test for results and
   retrieve further details.


int RB_SendScreenRay ( int x, int y, RB_IntersectionType intersect_with )

   This function works in the same way as RB_SendRay except that you can specify 2d coordinates on the screen
   and the game will send a ray through there. This is great for when you want to shoot a bullet through the
   center of the screen and check if it hit an enemy for example.


float RB_GetIntersectionDistance ( int id )

   This function returns the distance at which an intersection occured.
   You have to supply it with a handle to an existing collision object.
   If there was no collision, it will return -1.0.


int RB_GetIntersectionModel ( int id )

   This function returns a handle to the model that collided with the ray first.
   You have to supply it with a handle to an existing collision object.
   If there was no collision, it will return -1.

Edited by Dualnames. Included/replaced with working download link

Kweepa

Pretty freaking cool!
What art packages have you written exporters for? You mention Max. How about Maya?
Still waiting for Purity of the Surf II

Crimson Wizard

That's neat, let's just hope people won't overuse 3d-ness to create silly boring games with fashionable graphics ;)

DoorKnobHandle

Thanks to both of you! :D

Quote from: SteveMcCrea on Sun 08/08/2010 17:07:00
Pretty freaking cool!
What art packages have you written exporters for? You mention Max. How about Maya?

There's only one for Max at the moment, I don't own Maya unfortunately so I'd need to find somebody who has it and has experience with its scripting language (or whatever it uses for plugins). I definitely want to port the Max exporter to Blender as well tho.

If all that fails, I can offer to export your models, until there are Exporters for at least one freeware package.

GarageGothic

#4
Very, very cool!  :o

(Though I have to admit I'm slightly peeved that this, along with the stuff Calin is doing at the moment, make my own budding efforts in plug-in writing begin to feel redundant )

So if I understand correctly, you wrote your own 3D engine from scratch? Just, wow! Here I've been spending a month or so trying to weigh the pros and cons of various open source engines for my plugin - and have yet to find one I'm entirely happy with - never even considered the option of coding one myself (not that I would be able to with my current C++ skills, but even so, I imagined it would take years and years of work).

I look forward to check out the documentation to learn more about the feature set and current limitations. But what I saw in the video looked very promising. This could very well turn out to be the technology I've been looking for all along to use in my next project. Consider me impressed and intrigued :)

Edit: Forgot to say - Razorblade 3D is by far the coolest sounding name of any free 3D engine, I've come across. Not that it would be a deciding factor, of course, even so I'd much rather tell an interviewer that my new game was based on "cutting edge Razorblade 3D tech" than try to pronounce "Irrlicht" without sounding like a Nazi coughing up phlegm.  ;)

DoorKnobHandle

Thanks GG! Yes, it's basically a 3D graphics engine that I wrote from scratch in C++ using D3D9. Was a ton of work! :p

The demo game, the plug-in and the documentation will be available in the next couple of hours!

Dualnames

Quote from: dkh on Sun 08/08/2010 17:35:35
Thanks GG! Yes, it's basically a 3D graphics engine that I wrote from scratch in C++ using D3D9. Was a ton of work! :p

The demo game, the plug-in and the documentation will be available in the next couple of hours!

You tease!!!

Looks uber great!!
Worked on Strangeland, Primordia, Hob's Barrow, The Cat Lady, Mage's Initiation, Until I Have You, Downfall, Hunie Pop, and every game in the Wadjet Eye Games catalogue (porting)

JD

This looks awesome! Looking forward to checking the documentation and trying the plug-in!

DoorKnobHandle

Thanks guys!

THE PLUG-IN IS NOW AVAILABLE!

It comes with the demo game that you saw in the trailer (and source code, assets etc. to that) as well as the documentation and - of course - the DLL itself. Using the source code to the demo game and the documentation, it should be a piece of cake to start putting a 3d game together in AGS. Open the demo game up in the editor and run it from there please. If you run it from the Compiled folder it won't find its resources. If you want to publish a game, you have to copy your models and shaders folders into the compiled folder before distribution!

I will release the exporter for 3D studio Max next so you can start using your own models.

Grab Version 1.0 HERE. Note that it does contain a few undocumented functions and there might be bugs - especially in the collision detection area. The important thing for now is that the core functionality is there. Being able to load and display models with custom shaders and so on.

straydogstrut

That is seriously cool! A tremendous amount of work you've put in there, unbelievable. I also hope everyone doesn't go 3D gaga but I look forward to the interesting uses people find for this. Thank you=)

Kweepa

I tried loading the demo game in AGS but the plugin has some missing dependencies (found using Dependency Walker):
D3DX9D_41.DLL (presumably the debug version of the D3D9 dll)
MSVCP90D.DLL
MSVCR90D.DLL (VC debug runtimes - I don't think these are available in VC redist packages, and I don't really want to download them from some random site...)

I think you need to compile with release DLLs.
Still waiting for Purity of the Surf II

DoorKnobHandle

Damn. Let me fix that! :D

Alright, the new link is here. I have also updated all links that were posted before.

Hope it works now!

Calin Leafshade

I have a question.

What possible role could the AGS engine actually play with this plugin?

Surely if you convert the display to a full 3d thing then all the AGS functions are pretty useless?

DoorKnobHandle

The plugin only replaces rooms (objects, masks etc.) and characters. You can still use all that in a game that ALSO uses the 3d plugin but not simultaneously (obviously). But AGS offers a ton of other functionality that you can use together with the 3d graphics. As I say in the video, any user interface you want to have in your 3d game? Just make it exactly like you would for your 2d game. Sound, music and videos? 2d menus? Use AGS just like usual. It's just the game world that is no longer in 2d but 3d. It's still way different and much easier than just using a standard full-size 3d engine in, say, C++.

Calin Leafshade


DoorKnobHandle

Oh, also all the cursor-mode related functionality from AGS is very convenient to still have working when you want to make a 3d adventure specifically, I guess.

Calin Leafshade

can you easily convert a mouse click co-ordinate to the 3d world?

DoorKnobHandle

From the documentation:

Quote
int RB_SendScreenRay ( int x, int y, RB_IntersectionType intersect_with )

   This function works in the same way as RB_SendRay except that you can specify 2d coordinates on the screen
   and the game will send a ray through there. This is great for when you want to shoot a bullet through the
   center of the screen and check if it hit an enemy for example.

Call it with mouse.x and mouse.y and it will return a handle to the model that was clicked. Use one model as a "room" and then seperate models for each object or hotspot IN the room and you're all set. ;D

Khris

I had to copy all AGS and game files to "C:\AGS 3.1.2 SP1\" in order to make it work; looks like there's an absolute path somewhere in the dll?

I does look great though and never drops below 100 FPS on my machine.
Jumping doesn't work yet, pressing space moves the camera up but not back down. I guess this is related to the collision detection not being implemented yet?

DoorKnobHandle

Quote from: Khris on Sun 08/08/2010 22:47:00
I had to copy all AGS and game files to "C:\AGS 3.1.2 SP1\" in order to make it work; looks like there's an absolute path somewhere in the dll?

I does look great though and never drops below 100 FPS on my machine.
Jumping doesn't work yet, pressing space moves the camera up but not back down. I guess this is related to the collision detection not being implemented yet?

Damn, that's because of the textures. Each model makes a reference to a material which then points to a bunch of textures. I couldn't get 3ds Max to use relative paths instead of absolute ones for that reference. I might have to think up some kind of magic to convert them.

Or is there any kind of error when you start a new game with the plug-in as well?

Jumping isn't possible because the collision detection isn't working (it did at some point but then apparently I broke it again). :D But the demo game could easily just move you down again a set amount, since the ground plane doesn't change in height in the level.

SMF spam blocked by CleanTalk