Game Development Community

Questions regarding rendering of primitives and textures

by Lethal Concept · in Torque 3D Professional · 09/22/2009 (11:50 am) · 21 replies

Hey folks,

I'm not a programmer in a graphics context at all, so my issue might just be me being dense.
My problem is, that i cant get T3D to draw custom stuff like primitives or textures (for stuff like rotated guibitmaps or "radar" stuff).

I guess the way Rendering is handled did chance a lot since TGEA, since stuff that got drawn in TGEA wont draw in T3D. The drawing code gets executed, but i dont see anything being drawn. E.g. did i add this:

int num = 12;
    for(int i = 0; i < num; i++)
    {
        for(int u = 0; u < num; u++)
        {
            for(int v = 0; v < num; v++)
            {
                GFX->getDrawUtil()->drawLine(Point3F(0,0,0), Point3F(i,u,v), ColorI(255,0,255));
            }
        }
    }

inside the onRender() of the gameTSCtrl. No Effect. I expected this to draw primites into the world, like i've seen it with a TGEA resource. Neither did a version with the PrimBuilder::begin() / ::end() yield any results.
Also, i tried to implement this http://www.garagegames.com/community/forums/viewthread/46855 to rotate a GuiBitmapCtrl derivative ... again, without result, even though the code gets executed without errors. The bitmap is either not drawn or the rotation is simply not happening, depending on where i put
GFX->popWorldMatrix();



I'm rather clueless and couldnt find any documentation, howto or resource that would explain this to someone that isnt familiar with graphics related programming. So i hope someone can supply me with a simple howto or just gimme a pointer to where i can look for a tutorial or any sort of explanation on what i need to do and in which context i need to do it to draw something to the screen/into the world.

Big thanks in advance!
Page «Previous 1 2
#1
09/22/2009 (4:57 pm)
The best way to get familiar with the rendering systems in Torque 3D is to take a look at the examples in Engine\source\T3D\examples.
#2
09/23/2009 (6:03 am)
That does neither really fit the description of what i was looking for, nor does it reall document the necessary steps to "just draw" something.
Thanks anyway.

//edit

In other words, i just need the simplest way to draw something into the world. And I dont mean objects, i mean just lines and primitives, nothing to ghost, collide or interact with by any means.
E.g. visualizing a raycast, drawing a wireframe between a number of world points etc. No material or network features are needed.
Also, this doesnt answer any of the questions that arise with the bitmap rotation.

So, is it possible to do that without attaching it to a simobject?
As i said... it worked in TGEA and i cannot think of a reason to deny this in a more advanced engine.
#3
09/23/2009 (1:50 pm)
While the engine is in beta (and so are the docs), the simplest way to learn what you need is through examples in the source - as Matt suggested.

Here is another example:
Take a look at how you can render debug normals for TSStatic objects.. Look in TSStatic::prepRenderImage. This is where it's checked if your debug rendering will take place. Note the part where a renderDelegate function is bound to the render instance. It's TSStatic::_renderNormals. This is a new way since TGEA 1.7.1, but it worked much the same in 1.8.1. Anyway, you can go deeper, and see how something simple should be rendered in Torque 3D.

As far as bitmap rotations go, I used to have something simple instead of that function.. let me find it...
Oh yes, I wrapped up a glRotate to not have to worry about old resources:
void <GuiObject>::glRotate(F32 angle, Point3F rot) {
   angle = mDegToRad(angle);
   AngAxisF rotAAF( rot, angle );
   MatrixF m;
   rotAAF.setMatrix( &m );
   GFX->multWorld( m );
}

and here is how I'd use it to draw a rotated bitmap:
GFX->pushWorldMatrix();
   // this is where I rotate the world instead of rotating the bitmap
   glRotate(angle, Point3F(0, 0, 1));
   GFX->setTexture(0, texture);
   PrimBuild::color4f(mColor.red/255, mColor.green/255, mColor.blue/255, mAlpha);
   PrimBuild::begin(GFXTriangleFan, 4);
      PrimBuild::texCoord2f(0, 0);
      PrimBuild::vertex2i(-(rect.len_x() / 2), -(rect.len_y() / 2));
      PrimBuild::texCoord2f(1, 0); 
      PrimBuild::vertex2i(rect.len_x() / 2, -(rect.len_y() / 2));
      PrimBuild::texCoord2f(1, 1);
      PrimBuild::vertex2i(rect.len_x() / 2, rect.len_y() / 2);	
      PrimBuild::texCoord2f(0, 1);
      PrimBuild::vertex2i(-(rect.len_x() / 2), rect.len_y() / 2);	
   PrimBuild::end();
GFX->popWorldMatrix();

Please read the docs that came with TGEA 1.8.1 to get a better grip on the basics of GFX2 and more importantly the difference between 1.7.1 and 1.8.1 / Torque 3D rendering. Although even 1.8.1 and Torque 3D differ in this aspect, not so much that you should worry about it just yet, imho.
#4
09/23/2009 (2:49 pm)
@Lethal Concept

drawLine() works the same way in T3D,actually you can see a lot of examples in the source,especially in gui.
DebugDrawer also works well.

About rendering a billboard - take a look at ScatterSky moon rendering.
#5
09/24/2009 (8:12 am)
@Kondrad Kiss

Thanks for your snippets.
The rotation method works, the drawing snippet also draws.. but not what i would expect it to draw. Instead of the image/texture, it draws a filled rectangle. And its drawing it outside of the screen (somewhere left of and above the upper left corner of the screen), only partly visible if you place the GuiCtrl in that corner.
I couldnt seem to find just where i can tell it WHERE to draw it.

@ Picasso

Then what would i have to do to draw lines between objects in the world? I mean, not drawing inside an object(space), but between two objects?
#6
09/24/2009 (11:25 am)
Ok, i figured to place it (almost) were i want it to be and even found my own way to rotate it (will add code later).
Still, ... its not drawing the texture (the class is derived from GuiBitmapCtrl) is not drawn, only the filled rectangle.
Didnt change anything there... so im clueless here.
#7
09/24/2009 (12:41 pm)
well,drawers do work in world space.
You can move to object/world space using some sort of :

GFX->multWorld(mObjToWorld);
GFX->multWorld(mWorldToObj);

..before drawing (no matter what).

Moving in 2D-3D and 3D-2D, i believe you can use an inverse matrix.
But in some of these transform operations(2D-3D) you can lose some data in recovering your transform.
#8
09/24/2009 (1:13 pm)
Would it be to much to ask for a small example (of this special case)?
Atm im a bit confused about in what context i have to call the drawer to draw a (free floating) line between two objects into the world. I mean, lets save i have to Pathmarkers, then want to draw a line between them. How do i pull this off? Especially, from where? Does this need to happen in one of pathmarkers, or do i need some alibi/helper scene object to do the dirty work?
The looped code from the first post is what i put into the render method of the gameTSCtrl to test it (and as far as i see it, nothing shows up)... so this is then trying to draw to the playgui... and i guess theres no way to draw into the world from there?
#9
09/28/2009 (4:57 am)
Well, you have two options, draw it as a 3D line or a 2D line. In either case you have to have the GFX transforms and whatnot setup properly for that type of rendering.

If you want to do 3D rendering you should be able to put it in GameTSCtrl::renderWorld "after" the call to GameRenderWorld.

However, you can't use drawUtil::drawLine for 3D lines, it might have an overload that takes Point3F's but it only draws 2D lines and chops off the z. So you want to use PrimBuild or build your own vb.

Also keep in mind that you need to setup the stateblock which controls blendmode, cullorder, zreadwrite, etc etc, before your rendering or else you are just using whatever someone set it to before you.

#include "gfx/primBuilder.h"

//---------------------------------------------------------------------------
void GameTSCtrl::renderWorld(const RectI &updateRect)
{
   GameRenderWorld();

	GFXStateBlockDesc desc;
	desc.setZReadWrite( true, false );
	desc.setBlend( false );

	GFX->setStateBlockByDesc( desc );

	PrimBuild::begin( GFXLineList, 2 );
	PrimBuild::color3i( 255, 0, 255 );
	PrimBuild::vertex3fv( Point3F::Zero );
	PrimBuild::vertex3fv( Point3F( 0, 0, 75.0f ) );
	PrimBuild::end();
}

You should see a pink line at the scene origin ( 0,0,0 ) sticking up 75 meters.
#10
09/28/2009 (8:57 am)
Hilarious!
Many thanks to you, James.
This will enable a lot of interesting effects for binocular (or similar) optics.

Also, thanks again to Picasso, its working like a charm.
This will in turn enable me to nicely render my navmeshes.

So i guess i have to read up on the GFXSateBlockDesc's.
Does this enable me to draw stuff with 3D coordinats into the GUI?
Like, rotating my menu around the X or Y axis?
Will test that asap.
#11
09/28/2009 (10:30 am)
Could someone explain to me what the different options for the GFXStateBlockDesc do?
If i was to know what each option does, i could maybe deduct whats possible etc.

I use primitives to draw the circular sectors of a pie menu, which so far feature no texture, because i didnt yet found out how to use them (the drawing code of Kondrad doesnt draw the texture).
I then took a look at the 3DRadar resource and together with the code of James, i was able to draw stuff into the world from inside the gameTSCtrl. Yet, i dont understand how i can rotate my primitives around the X oder Z axis. Atm im doing the rotation via rotating each point in the primitive and then offsetting it to the screen center. The glRotate() of Konrad rotates the whole screen in around the Z-Axis based on the screen origin (0,0,0). If i just feed it with (1,0,0) instead of (0,0,1) i'd expect it to rotate around the X-Axis... but i cant see anything being drawn then. So since there seem to be a lot of options here and there... im quite overwhelmed and confused as to where to look at to find out why stuff is not working.

So further stuff i'd like to know is, how do i make stuff use the alpha value correctly? Especially in the different cases (with texture, without texture, etc). What preparations are necessary to do this and what are necessary to draw textures (except having the texture object)?
And how do i use the Z-Direction inside the gui, to rotate stuff around the X and Y axis?

I really appreciate your help!
#12
09/28/2009 (11:01 am)
Ah... never mind the Alpha issue, its solved.
Guess i deserved it :
PrimBuild::color4f(mColor.red/255, mColor.green/255, mColor.blue/255, mAlpha);
Well, with mColor being ColorF instead of ColorI it works.

Yet, is there more about the alpha options one gotta know? Or can i mindlessly use
setBlend(true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha);
and live happily ever after?
#13
09/28/2009 (4:38 pm)
Yeah, that's the normal blend mode you want.

The stateblock concept ( and large parts of GFX in general ) are directly modeled after how D3D works, so keep in mind that the DX SDK help docs are extremely good.

In general blend mode works like this...

Hypothetical...

( Source pixel )
Your pixel being rendered
Color( 255, 0, 255, 10 )

( Destination pixel )
Pixel in the render target already at that location
Color( 0, 255, 0, 255 )

NewColorAtPixel = SourceColor * SrcBlendMode + DestinationColor * DstBlendMode;
#14
09/28/2009 (4:41 pm)
If...

SrcBlendMode = BlendSrcAlpha
DtsBlendMode = InvSrcAlpha

OutColor = float3( 1.0, 0, 1.0 ) * 0.1 + float3( 0, 1.0, 0 ) * 0.9;

==

OutColor = float3( 0.1, 0, 0.1 ) + float4( 0, 0.9, 0 );

==

float3( 0.1, 0.9, 0.1 )
#15
09/30/2009 (6:37 am)
Fascinating. Again, thanks to you, James.

Now i still wonder what the zReadWrite() exactly does.

Also, i still hope someone comes around that knows how to use he Z-Axis in the gui, aka drawing 3D objects into the gui?

Or do i have to use "fake" 3D by clinching whatever i want "rotated"?

Since, if i use glRotate() to rotate the world around any other axis than the Z-Axis... nothing is shown onscreen. also, anything thats drawn without the rotation, but a z-value other than 0.0f also doesnt show up.
Does the GUI space HAVE a z-space at all?
#16
09/30/2009 (3:12 pm)
The only gui controls that can render 3D objects ( without more work ) are TSCtrl and those derived from it, and need to do it within the renderWorld method.

I'm not sure where you are seeing glRotate(), that sounds like an old-style gl call from TGB. To change the orientation something is rendered at you should use the world matrix. eg. GFX->setWorldMatrix or GFX->mulWorld().

Currently zRead/Write is not actually working within TSCtrl::renderWorld() because the 3D scene is actually rendered to an offscreen render-target that is not the backbuffer and it is copied onto the backbuffer ( which you now don't have a z buffer for ) before the gui control gets a chance to do additional 3D rendering.

In general, you could take a look at the WorldEditor and Gizmo classes, which are GuiControls ( or sudo-controls ) which render 3D objects.
#17
10/01/2009 (9:16 am)
Hmm... well, i think i can live without it.
Thanks!

btw, the glRotate() was posted earlier in this thread by Konrad Kiss, just scroll up a bit.

Well, then i'll look into some of the methods that use textures for their primitives... mine just dont seem to work :-(

If my results are useable, might just share with the community... no promises though.
#18
10/17/2009 (2:50 pm)
Here we go again.
I got most stuff to work correctly.
Now i just ran into the problem of clipping.
I draw primitives into the world to visualize my navmeshes. But they dont seem to clip and even though i was digging thru a lot of code, i didnt get how clipping is set up. Without it, its kinda hard to tell if some shape is below or above the terrain.
Thanks in advance!
#19
10/19/2009 (4:10 pm)
*hawk*
#20
10/19/2009 (5:28 pm)
You need to enable Z testing in the stateblock (the actual property name escapes me).

However, using a GUI control to render a navmesh (which is to be displayed as a world-space entity) isn't the best way to do it. Creating an object that renders the navmesh and is placed in the scene, using one of the example custom object classes as a base would net much less headaches, since your navmesh renderer would follow the same pipeline as all other 3D objects.
Page «Previous 1 2