I need to write some text on the screen, but my coordinates is a D3DVECTOR datatype. Is it either possible to write text directly in objectspace or do I need to convert objectspace to screen coordinates?
Tried the code similar to this but it just get messed-up coordinates:
I know how to draw the text itself. The problem is that I have coordinates of an object being rendered in the scene, which have xyz coordinates. I need to draw text over that object, thus I need to convert objectspace coordinates to screencoordinates.
That's not how it works. It is the drawing order you have in the rendering loop. DirectX does not sort the polygons for you and you get away with not sorting using the ZBuffer. So what you do in order to render it correctly is draw the text last.
If that's how you are already doing it and you are using Windows XP, for some reason the text may look jerky, especially when you are blitting textured polygons that take up the screen like skyboxes for example. It all depends on the card you are using too when using XP. On some cards it'll look fine and on others it'll look weird. I had this problem working on my game using DirectX8. On my comp which was Windows ME, it was fine. But on the Windows XP on my dads comp it looked jerky. And he has a top of the line video card too.
Over the object, what I mean is... You don't really understand what I want to do. I have an array of objects to render, each one has an id-number. I want to draw a text with the id-number next to the object. Because the camera moves around the x,y coordinates will change.
The objects each has x,y,z coordinates. I cannot draw text with x,y,z coordinates. Of course I cannot use the x and y coordinates from the objects because they are always the same even if the camera moves around. So somehow i have to convert x,y,z coordinates to screencoordinates. There is a function called D3DXVec3Project to do this, but I don't seem to get it working correctly.
Ohhhhhhhh. I think I maybe getting ya now. It's kinda like those massive multiplayer online FPS games to where their screen name (which is OVER the object) follows the object, only in your program, it'll be the object's id number. Am I right?
If I am right. Then what you are looking for is what's called a billboard effect, only in this case, drawing text over an object. I'm not sure if you want the text to zoom in and out or have the text's size stay the same no matter what the camera's Z position is. Which would you like to have done? If you don't know what a billboard effect is, here is what it does. Remember in Doom how no matter what camera position you were in, the creatures and trees always were facing you? Some games even to this day do that for certain polygons.
Here is something on billboard effects just in case you are looking for that.
It shouldn't be to hard to convert the graphical representation to text and eliminate the animation. Also it shouldn't be too hard to eliminate the zooming of the text in case you didn't want it to zoom in and out and just stay the same.
Last edited by Jacob Roman; Nov 20th, 2004 at 05:58 AM.
First you must understand that if you are working in a 3D environment which can be seen from any view there is no theasible way to display an ID above the head of the player using screen coords.
Text being displayed in screen coords will have no depth as in it will always appear to be frontmost.
If you want to display the id above someone's head and have it actually look neat then you must draw a mini-2 faced square above the player, always translate it to above the player and render a texture on it which consists of its ID number.
You could get the ID number by blitting some numbers onto a DDSurface then turning that DDSurface into a texture.
Now if you are working in a top view only 3D world...well that is simple.
In a top view 3D world, your screen can be considered in X,Z.
Because Y on your screen represents Z in the 3D world.
"From what was there, and was meant to be, but not of that was faded away." - - Steve Damm
"The polar opposite of nothingness is existance. When existance calls apon nothingness it shall return to nothingness." - - Steve Damm
"When you do things right, people won't be sure if you did anything at all." - - God from Futurama
Actually, this time it doesn't matter if the text should be visible or not, so I don't have to care about the Z-buffer. D3DXVec3Project seems to be a way to do this but I don't understand how to use it.
Of course, if it's to much work using D3DXVec3Project billboarding would work too, but I think thats more work.
D3DXVec3Project
Projects a vector from object space into screen space.
D3DXVec3Project( _
VOut As D3DVECTOR, _
V As D3DVECTOR, _
Viewport As D3DVIEWPORT8, _
Projection As D3DMATRIX, _
View As D3DMATRIX, _
World As D3DMATRIX)
Just try out the billboarding effect I gave you for your text. It's much easier than working with screen coordinates. And Halsafars right. The text won't always follow the 3D object if you were to base them as screen coordinates in some scenarios. Here's the URL for billboarding:
Trust me on this. It will work with your problem perfectly. Just billboard your text. That's all.
Oh and Halsafar, he wanted it above the object, not on the object. If I were you though, I would allow the Z coodinates to change for the text as well as the object so that way they will always stay together, hence meaning don't worry about screen coordinates and just leave them as polygons that are not TLVERTEX based. Anything else is fine. Billboarding the text will help make sure the text will always face the viewer no matter what the camera angle is.
Last edited by Jacob Roman; Nov 20th, 2004 at 04:32 PM.
Right here, this 3D object is close enough to the camera to change the size of the text shown. Notice the text always faces the viewer no matter what angle the 3D object is:
Last edited by Jacob Roman; Nov 20th, 2004 at 04:29 PM.
If you read the last method mentioned at http://216.5.163.53/DirectX4VB/Tutor...R_Lesson16.asp they convert 3d-points to screen coordinates using D3DXVec3Project. But when I use the same technique in my own app it does not work.
Argh! I've found the error! Let's see if I can explain.
The matrices were transformed and thus giving the D3DVector the coordinates of the point in the TRANSFORMED matirx would be the be the wrong coordinates, instead giving it 0,0,0 would be the real point. Figuring that out i had two alternatives, either i reset the transformations before the call or I set the point to 0,0,0. Because I going to have multiple points projected I thought that reseting the coordinates would be the best way.
It is called ID3DXMatrixStack, and is very user friendly if you are going to move more then one thing after each other. Like if you have a body, and you want to move the uper arm, then the lower arm, and then the hand and so on. If you have the docs (at least in the 9.0c docs, there is a realy nice example with a small algo to help you.
It is done pretty similar to the way you do it in OpenGL, but in DX you must manually push/pop matrices onto/off of the stack and pass them to IDirect3DDevice9::SetTransform() before they become the active matrices. It doesn't pop it automaticaly like it is done in OpenGL.
Originally posted by Halsafar Why put it in a matrix stack then??
Why not just set the matrix before the objects that need it...like normal.
Push/Pop/Transform/Render
or
Transform/Render.
hmmm.
As Halsafar said. Let me give you a better example. It is not as easy to see the body example. Lets see we ahve a boat (2 sec and I will find a good picture).(There I found one. Lets look at this. There is more then one movable part on this ship. But lets only look at the boat it self, and the front turet, and lets devide that one into a turret, and barrel (the pipe on the turret).
Now, suppose you know the position and the orientation of the ship at sea, and you also know the position of the kanons/turretsrelative to the ship, and the position of the barrels (the pipe on the turrots), relative to the turret. Instead of computing multiple matrices for each object and then storing each matrix, you can use a stack and render the ship with the following steps:
1: Create a stack interface with D3DXCreateMatrixStack.
2: Compute the matrix for the ship's position and push that onto the stack.
3:Set the top of the stack as the currentworld transform and render the boat (only the hull thingy).
4: Push the stack and concatenate the relative transform for hte turret.
5:Set the top of the stack as the current worldtransform and render the turret.
6: Push the stack and concatenate the relative transform for the first barrel.
7: Set the top of the stack as the current world transform and render the first barrel.
8: Pop the stack, witch places the turret transform on top.
9: Push the stack and concatenate the relative transform for the second barrel.
10: Set the top of the stack as the current world transform and render the second barrel:
11: Pop the stack, which places the turret transform on top.
12: Pop the stack, which places the ship trnsform on top.
13. Render the other parts of the whip in the same way.
Now this probably looks like a harder way to do it in the start. But when you get used to it, you can save a lot of problems for your self, and of course time when you are going to render big projects. I recomend you read the one in the Docs too. It's intresting reading.
For those of you that don't have the docs, here is what I ment (there is more too, but this is the most intresting reading:
Matrix Stacks
The D3DX utility library provides the ID3DXMatrixStack interface. It supplies a mechanism to enable matrices to be pushed onto and popped off of a matrix stack. Implementing a matrix stack is an efficient way to track matrices while traversing a transform hierarchy.
The D3DX utility library uses a matrix stack to store transformations as matrices. The various methods of the ID3DXMatrixStack interface deal with the current matrix, or the matrix located on top of the stack. You can clear the current matrix with the ID3DXMatrixStack::LoadIdentity method. To explicitly specify a certain matrix to load as the current transformation matrix, use the ID3DXMatrixStack::LoadMatrix method. Then you can call either the ID3DXMatrixStack::MultMatrix method or the ID3DXMatrixStack::MultMatrixLocal method to multiply the current matrix by the specified matrix.
The ID3DXMatrixStack::Pop method enables you to return to the previous transformation matrix and the ID3DXMatrixStack::Push method adds a transformation matrix to the stack.
The individual matrices on the matrix stack are represented as 4×4 homogeneous matrices, defined by the D3DX utility library D3DXMATRIX structure.
The D3DX utility library provides a matrix stack through a Component Object Model (COM) object.
Implementing a Scene Hierarchy
A matrix stack simplifies the construction of hierarchical models, in which complicated objects are constructed from a series of simpler objects.
A scene, or transform, hierarchy is usually represented by a tree data structure. Each node in the tree data structure contains a matrix. A particular matrix represents the change in coordinate systems from the node's parent to the node. For example, if you are modeling a human arm, you might implement the following hierarchy.
In this hierarchy, the Body matrix places the body in the world. The UpperArm matrix contains the rotation of the shoulder, the LowerArm matrix contains the rotation of the elbow, and the Hand matrix contains the rotation of the wrist. To determine where the hand is relative to the world, you multiply all the matrices from Body down through Hand together.
The previous hierarchy is overly simplistic, because each node has only one child. If you begin to model the hand in more detail, you will probably add fingers and a thumb. Each digit can be added to the hierarchy as children of Hand.
If you traverse the complete graph of the arm in depth-first order—traversing as far down one path as possible before moving on to the next path—to draw the scene, you perform a sequence of segmented rendering. For example, to render the hand and fingers, you implement the following pattern.
1. Push the Hand matrix onto the matrix stack.
2. Draw the hand.
3. Push the Thumb matrix onto the matrix stack.
4. Draw the thumb.
5. Pop the Thumb matrix off the stack.
6. Push the Finger 1 matrix onto the matrix stack.
7. Draw the first finger.
8. Pop the Finger 1 matrix off the stack.
9. Push the Finger 2 matrix onto the matrix stack. You continue in 10. this manner until all the fingers and thumb are rendered.
11. After you have completed rendering the fingers, you would pop 12. the Hand matrix off the stack.
You can follow this basic process in code with the following examples. When you encounter a node during the depth-first search of the tree data structure, push the matrix onto the top of the matrix stack.
When you are finished with a node, pop the matrix off the top of the matrix stack.
Code:
MatrixStack->Pop();
In this way, the matrix on the top of the stack always represents the world-transform of the current node. Therefore, before drawing each node, you should set the Microsoft® Direct3D® matrix.
The thing is though is that ID3DXMatrixStack is in DirectX9 and not in DirectX8, at least not in VB's DirectX8. The only VB that DirectX9 supports is VB.NET. How would you manually create Puch and Pop Matrix functions? Some source code would help a lot . I'm not too familiar with pushing and poping matrices but I hear it a lot, especially on OpenGL.
Are you sure it is not in DX8? I don't think they have added one thing for C++ and left it out for VB users. Look it up in the d3dx header file, or check the docs...
Originally posted by eXterminator Searched in the SDK documentation but couldn't find anything useful.
But did you find ID3DXMatrixStack at all? IF you did, then you can use it, and then Google, or a question here would be the next thing if you are stuck....
//===========================================================================
//
// Matrix Stack
//
//===========================================================================
typedef interface ID3DXMatrixStack ID3DXMatrixStack;
typedef interface ID3DXMatrixStack *LPD3DXMATRIXSTACK;
// {E3357330-CC5E-11d2-A434-00A0C90629A8}
DEFINE_GUID( IID_ID3DXMatrixStack,
0xe3357330, 0xcc5e, 0x11d2, 0xa4, 0x34, 0x0, 0xa0, 0xc9, 0x6, 0x29, 0xa8);
#undef INTERFACE
#define INTERFACE ID3DXMatrixStack
DECLARE_INTERFACE_(ID3DXMatrixStack, IUnknown)
{
//
// IUnknown methods
//
STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID * ppvObj) PURE;
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
//
// ID3DXMatrixStack methods
//
// Pops the top of the stack, returns the current top
// *after* popping the top.
STDMETHOD(Pop)(THIS) PURE;
// Pushes the stack by one, duplicating the current matrix.
STDMETHOD(Push)(THIS) PURE;
// Loads identity in the current matrix.
STDMETHOD(LoadIdentity)(THIS) PURE;
// Loads the given matrix into the current matrix
STDMETHOD(LoadMatrix)(THIS_ CONST D3DXMATRIX* pM ) PURE;
// Right-Multiplies the given matrix to the current matrix.
// (transformation is about the current world origin)
STDMETHOD(MultMatrix)(THIS_ CONST D3DXMATRIX* pM ) PURE;
// Left-Multiplies the given matrix to the current matrix
// (transformation is about the local origin of the object)
STDMETHOD(MultMatrixLocal)(THIS_ CONST D3DXMATRIX* pM ) PURE;
// Right multiply the current matrix with the computed rotation
// matrix, counterclockwise about the given axis with the given angle.
// (rotation is about the current world origin)
STDMETHOD(RotateAxis)
(THIS_ CONST D3DXVECTOR3* pV, FLOAT Angle) PURE;
// Left multiply the current matrix with the computed rotation
// matrix, counterclockwise about the given axis with the given angle.
// (rotation is about the local origin of the object)
STDMETHOD(RotateAxisLocal)
(THIS_ CONST D3DXVECTOR3* pV, FLOAT Angle) PURE;
// Right multiply the current matrix with the computed rotation
// matrix. All angles are counterclockwise. (rotation is about the
// current world origin)
// The rotation is composed of a yaw around the Y axis, a pitch around
// the X axis, and a roll around the Z axis.
STDMETHOD(RotateYawPitchRoll)
(THIS_ FLOAT Yaw, FLOAT Pitch, FLOAT Roll) PURE;
// Left multiply the current matrix with the computed rotation
// matrix. All angles are counterclockwise. (rotation is about the
// local origin of the object)
// The rotation is composed of a yaw around the Y axis, a pitch around
// the X axis, and a roll around the Z axis.
STDMETHOD(RotateYawPitchRollLocal)
(THIS_ FLOAT Yaw, FLOAT Pitch, FLOAT Roll) PURE;
// Right multiply the current matrix with the computed scale
// matrix. (transformation is about the current world origin)
STDMETHOD(Scale)(THIS_ FLOAT x, FLOAT y, FLOAT z) PURE;
// Left multiply the current matrix with the computed scale
// matrix. (transformation is about the local origin of the object)
STDMETHOD(ScaleLocal)(THIS_ FLOAT x, FLOAT y, FLOAT z) PURE;
// Right multiply the current matrix with the computed translation
// matrix. (transformation is about the current world origin)
STDMETHOD(Translate)(THIS_ FLOAT x, FLOAT y, FLOAT z ) PURE;
// Left multiply the current matrix with the computed translation
// matrix. (transformation is about the local origin of the object)
STDMETHOD(TranslateLocal)(THIS_ FLOAT x, FLOAT y, FLOAT z) PURE;
// Obtain the current matrix at the top of the stack
STDMETHOD_(D3DXMATRIX*, GetTop)(THIS) PURE;
};
#ifdef __cplusplus
extern "C" {
#endif
HRESULT WINAPI
D3DXCreateMatrixStack(
DWORD Flags,
LPD3DXMATRIXSTACK* ppStack);
Nope it is not there in VB. Even after I enabled "Show hidden members" in the Object Browser. You guys know how to create your own version of ID3DXMatrixStack or the Push/Pop Matrix functions? It would help.