• Create Account

Banner advertising on our site currently available from just \$5!

Banderi

Member Since 03 Mar 2013
Offline Last Active Oct 03 2013 10:14 AM

Re: Bill-boarding oriented rectangle

30 September 2013 - 08:59 AM

Continuing from this topic (don't want to be necroposting or anything so I opened a new one just in case), I tried to apply what you guys (thank you very much) told me to be the best way to render a 3D rectangle bill-boarding towards the camera while only rotating on his length axis, defined by two fixed points in the space. This way I'd be able to draw 3D sprites, particles, beams and stuff like that with ease.

From what I understood, I had to:

- take the directional vector (A) of the distance between the two points (I took p2-p1)

- take a directional vector (B) that goes from the camera to the line the points form (I took camera-p1)

- build three vectors: normalized A which I call X, normalized cross product (AxB) which I call Z, normalized cross product (ZxB) which I call Y, then rebuild the second vector with cross product (XxY) that still gets me Z

- the 3x3 matrix that I get out of these three vectors (X, Z, Y) is the orientation matrix that I need to apply to the rectangle in order for it to face the camera

- since DirectX matrices are 4x4, I assume to put in the values manually, so I use the orientation matrix as the first 3x3 values of the 4x4 one, adding the last row as the rectangle world position - just to be sure, I first initialize the 4x4 matrix as an identity

Summed up, I wrote this function:

```D3DXMATRIX OrientationMatrix(D3DXVECTOR3 A, D3DXVECTOR3 B, D3DXVECTOR3 pos)
{
D3DXMATRIX m; D3DXVECTOR3 X, Y, Z;
D3DXMatrixIdentity(&m);

D3DXVec3Normalize(&X, &A); // x
D3DXVec3Cross(&Z,&A,&B);
D3DXVec3Normalize(&Z, &Z); // z
D3DXVec3Cross(&Y,&Z,&B);
D3DXVec3Normalize(&Y, &Y); // y
D3DXVec3Cross(&Z,&X,&Y);
D3DXVec3Normalize(&Z, &Z); // z-2

m._11=X.x;
m._12=X.y;
m._13=X.z;
m._21=Z.x;
m._22=Z.y;
m._23=Z.z;
m._31=Y.x;
m._32=Y.y;
m._33=Y.z;
m._41=pos.x;
m._42=pos.y;
m._43=pos.z;

return m;
}
```

And then I build and render the rectangle this way:

```void BBStrip(D3DXVECTOR3 p1, D3DXVECTOR3 p2, D3DXVECTOR3 camera, float thickness, LPDIRECT3DTEXTURE9 texture, LPDIRECT3DDEVICE9 device)
{
device->SetTexture(0, texture);
device->CreateVertexBuffer(4 * sizeof(TVERTEX), NULL, TVERTEX::FVF, D3DPOOL_DEFAULT, &pVBuffer, NULL);
device->SetStreamSource(0, pVBuffer, 0, sizeof(TVERTEX));
device->SetFVF(TVERTEX::FVF);

D3DXMATRIX w; w = OrientationMatrix(p2-p1, camera-p1, p1);
//D3DXMatrixIdentity(&w);

pVBuffer->Lock(0, 0, (void**)&vert, 0);
vert[0]=TVERTEX::TVERTEX(abs(p2.x-p1.x),thickness*0.5,0,0,0);
vert[1]=TVERTEX::TVERTEX(abs(p2.x-p1.x),-thickness*0.5,0,1,0);
vert[2]=TVERTEX::TVERTEX(0,-thickness*0.5,0,1,1);
vert[3]=TVERTEX::TVERTEX(0,thickness*0.5,0,0,1);
pVBuffer->Unlock();

device->SetRenderState(D3DRS_LIGHTING, false);
device->SetTransform(D3DTS_WORLD,&w);
device->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
device->SetRenderState(D3DRS_LIGHTING, true);
pVBuffer->Release();
}
```

However, strange things happen. (if you already caught some basic math errors or typos, you're probably thinking "duh" at this point)

To try it out, I generated a bunch of random points around the world origin and drew particles between it and them.

At first it seems fine, but the rectangles happen to be stretched when the points are aligned along the world Z axis.

The more they are aligned on the Z axis, the shorter the particles are. Also, they apparently stretch towards the first of the passed points, so switching the points either stretch the particles towards the random points or the origin.

This is what it looks like:

(point 1 is random, point 2 is 0,0,0)

So... What the flying Jupiter am I doing wrong here? XP

EDIT: Oh, if I don't to the rebuilding of Z, it apparently gives me better results.

Bill-boarding oriented rectangle

22 June 2013 - 07:22 PM

Ok, here's a more complicated question.

I have two 3D points which I have to "connect" with a rectangle.. sort of what I'd do drawing a LPD3DXLINE between them, however it needs to be a 3D mesh (i.e. perspective and distance resize it). The thing is, it also needs to bill-board itself towards the camera, and here I really don't know how to do it..

I could build a sin/cosine function that rotates 4 points around 2 vectors given a width, that's easy.. but how do I take care of the bill-boarding too?

EDIT: here's an image as example...

[SOLVED] 3D to screen projection behind camera

22 June 2013 - 04:14 PM

So, I have this function that takes a vector3 representing a 3D point in the scene and returns a vector2 with its projected coordinates on screen space.

```D3DXVECTOR2 WorldToScreen(D3DXVECTOR3 WorldPoint)
{
D3DXVECTOR3 TempWorld;
D3DVIEWPORT9 ViewPort = {0,0,SCREEN_WIDTH,SCREEN_HEIGHT,0,1};
D3DXVec3Project(&TempWorld,&WorldPoint,&ViewPort,&matProjection,&matView,NULL);
D3DXVECTOR2 ScreenPoint = D3DXVECTOR2(TempWorld.x,TempWorld.y);
return ScreenPoint;
}
```

Then I can use the screen coordinates for everything I need, for example drawing text on them.

Everything works impeccably, but when I turn the camera away from the 3D point in the scene, it projects the point on the screen as if the FOV was mirrored.. or something more technically correct than that. I kind of get why, although I don't really know how to prevent it.. any suggestions?

I know this is a very basic thing (space transforms seem to be a very common question) so sorry if this sounds repetitive, but I couldn't find anything specific on this problem.

03 March 2013 - 08:07 AM

Now first, I'm still waaay newbie at HLSL;

I thought such a "simple" code (not many articulated functions, just a big, main one) would be technically correct, but it keeps crashing :/

```//Transformation Matrices
matrix matW;
matrix matVP;

extern float4x4 MatrixPalette[35];
extern int numBoneInfluences = 2;

//Vertex Input
struct VS_INPUT_SKIN
{
float4 position : POSITION0;
float3 normal   : NORMAL;
float2 tex0     : TEXCOORD0;
float4 weights  : BLENDWEIGHT0;
int4   boneIndices : BLENDINDICES0;
};

//Vertex Output / Pixel Shader Input
struct VS_OUTPUT
{
float4 position : POSITION0;
float2 tex0     : TEXCOORD0;
};

VS_OUTPUT vs_Skinning(VS_INPUT_SKIN IN)
{
VS_OUTPUT OUT = (VS_OUTPUT)0;

float4 p = float4(0.0f, 0.0f, 0.0f, 1.0f);
float3 norm = float3(0.0f, 0.0f, 0.0f);
float lastWeight = 0.0f;
int n = numBoneInfluences-1;
IN.normal = normalize(IN.normal);

//Blend vertex position & normal
for(int i = 0; i < n; ++i)
{
lastWeight += IN.weights[i];
p += IN.weights[i] * mul(IN.position, MatrixPalette[IN.boneIndices[i]]);
norm += IN.weights[i] * mul(IN.normal, MatrixPalette[IN.boneIndices[i]]);
}
lastWeight = 1.0f - lastWeight;

p += lastWeight * mul(IN.position, MatrixPalette[IN.boneIndices[n]]);
norm += lastWeight * mul(IN.normal, MatrixPalette[IN.boneIndices[n]]);
p.w = 1.0f;

//Transform vertex to world space
float4 posWorld = mul(p, matW);

//... then to screen space
OUT.position = mul(posWorld, matVP);

//Copy UV coordinate
OUT.tex0 = IN.tex0;

//Calculate Lighting
norm = normalize(norm);
norm = mul(norm, matW);
OUT.shade = max(dot(norm, normalize(lightPos - posWorld)), 0.2f);

return OUT;
}

technique Skinning
{
pass P0
{
Lighting = false;

}
}
```

C++ runs correctly other shader files, but with this one it crashes (0xC0000005 access violation) whenever it gets to the point where it sets the matrices for it (ID3DXEffect->SetMatrix();), no matter what matrix I choose to set first.

Is the error in the HLSL itself or is it C++ related? Do I have to post more code?

PARTNERS