Search code examples
c#matrixrotationxna

XNA CreateBillboard rotates on edge of sphere, not the origin?


I'm trying to create a billboard texture in the 3D world, where the billboard rotates with the center as a rotation point.

The Matrix.CreateBillboard function only rotates the object around a sphere for some reason. So when using this function, the rotation is around the edge of a sphere, but I want the rotation to be around a point in the center of the object.

Here's the code I have set up right now:

effect.World *= Matrix.CreateBillboard(position, position - Camera.Position, Vector3.Up, null);

int topLeftIndex = 0;
int topRightIndex = 1;
int bottomRightIndex = 2;
int bottomLeftIndex = 3;

VertexPositionColorTexture[] vertices = new VertexPositionColorTexture[4];
vertices[topLeftIndex] = new VertexPositionColorTexture(new Vector3(position.X - size.X / 2, position.Y + size.Y / 2, position.Z), Color.White, new Vector2(0, 0));
vertices[topRightIndex] = new VertexPositionColorTexture(new Vector3(position.X + size.X / 2, position.Y + size.Y / 2, position.Z), Color.White, new Vector2(1, 0));
vertices[bottomLeftIndex] = new VertexPositionColorTexture(new Vector3(position.X - size.X / 2, position.Y - size.Y / 2, position.Z), Color.White, new Vector2(0, 1));
vertices[bottomRightIndex] = new VertexPositionColorTexture(new Vector3(position.X + size.X / 2, position.Y - size.Y / 2, position.Z), Color.White, new Vector2(1, 1));

int[] indices = new int[6];
indices[0] = topLeftIndex;
indices[1] = bottomRightIndex;
indices[2] = bottomLeftIndex;
indices[3] = topLeftIndex;
indices[4] = topRightIndex;
indices[5] = bottomRightIndex;

graphicsDeviceManager.GraphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, vertices, 0, 4, indices, 0, 2);

The position variable contains the position of the center of the object, and the Camera.Position is the camera position (obviously).

I'm probably passing in the wrong coordinates to the function, but I've tried everything (including translating the position to object space), but so far nothing has worked.


Solution

  • As for me better solution (for simple case) is:

    1. Create single plane from (0.5,0.5,0) to (-0.5,-0.5,0)

    2. Render this plane with appropriate texture and transform it in shader:

      result = rotation * scale * translation * wvp

    where "rotation" is rotation to the camera, "scale" and "translation" can be presented as Vector4 value, where XYZ is translation and W is billboard scale, or as single scale+translation matrix.

    Soon I'll be able to provide an example.