Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am creating a minecraft like terrain engine thing in XNA and C#, and I am trying to create a item/block selector tool. The thing is I would like to have 3D objects on the tool. So I thought for the 3D objects to not move where the camera rotates/moves I would have to use pretransformed coordinates. Is that true? Also I would like to be able to use the world matrix to transform these objects like I would normally be able to when using world coordinates? Here is what I have got sofar in the effect file:

VertexToPixel PretransformedVS(float4 inPosition : POSITION, float4 inTexCoords : TEXCOORD0, float4 light : TEXCOORD01)  {  
    VertexToPixel Output = (VertexToPixel)0;

    Output.Position = inPosition; // mul(inPosition, World)? 
    Output.TexCoords = inTexCoords;
    Output.Light = light;

    return Output;    
}

technique Pretransformed  {
    pass Pass0  {   
        VertexShader = compile vs_2_0 PretransformedVS();
        PixelShader  = compile ps_2_0 PixelShaderFunction();
    }
}

Then in the pixel shader (I didn't include it in this as it is abit lengthy) all it does is get the color from the texture of that pixel and lights the vertex accordingly.

Any ideas?

EDIT: I just realised a problem with this approch. Each object, has a slightly different rotation when it is further to the left/right of the screen any ideas?

Something like this should work?

view = Matrix.CreateLookAt(Vector3.Zero, new Vector3(0, 0, -10), new Vector3(0, 1, 0));
projection = Matrix.CreateOrthographicOffCenter(0, 800, 600, 0, 0.1f, 100.0f);

The problem is with that is that none of my objects appear for that control on the screen?

EDIT 2:

    public override void Draw(SpriteBatch spriteBatch)
    {
        GetSelector();

        device.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1.0f, 0);     
        world.Draw(spriteBatch);

        DrawSelector(spriteBatch);

    }

    private void GetSelector()
    {
        device.SetRenderTarget(selectorTarget);
        device.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1.0f, 0);

        itemRender.Render(world.player.ItemSelector);

        device.SetRenderTarget(null);
        selectorTexture = (Texture2D)selectorTarget;
    }

    private void DrawSelector(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(selectorTexture, new Vector2(0, 0), null, Color.White, 0, new Vector2(0, 0), 0.4f, SpriteEffects.None, 1);

        selectorTexture = null;
    }

EDIT 3:

Here is my drawing code:

        for (int i = 0; i != 5; ++i)
            DrawModel(sphere, Matrix.CreateScale(2f) * Matrix.CreateTranslation(100 + i * 200, 100, -10), view, projection);

        effect.CurrentTechnique = effect.Techniques["Block"];
        effect.Parameters["World"].SetValue(Matrix.Identity);
        effect.Parameters["View"].SetValue(view);
        effect.Parameters["Projection"].SetValue(projection);
        effect.Parameters["Texture"].SetValue(Variables.TILE_ALAIS.SheetTexture);

        int counter = 0;

        foreach (CubeObject cubeObject in CubeObjects)
        {
            effect.Parameters["World"].SetValue(Matrix.Identity * Matrix.CreateRotationY(MathHelper.ToRadians(65f)) * Matrix.CreateScale(30f) * Matrix.CreateTranslation(100 + counter * 200, 100, -10));

            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Apply();
                device.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, cubeObject.vertices.ToArray(), 0, cubeObject.vertices.Count / 3, cubeObject.indices.ToArray(), 0, cubeObject.indices.Count / 3, VertexPositionTextureLight.VertexDeclaration);
            }

            counter++;
        }

I am drawing the sphere for testing purposes, also note that I have rotated the cube in the world matrix by 65 degress on the y axis but it didn't appear to do anything. Here is what it looks like when I am looking in the air:

enter image description here

And here is what it looks like when I am looking at the terrain, why does it change when I look at the terrain?

enter image description here

enter image description here

The missing faces has nothing to do with culling, I do beleive ambient lighting is not a factor because all faces as a default have full light

EDIT:

Ok, well I fixed the problem and it had to do with me dividing the number of vertices by three... very embarasing. (So is my spelling ;)

Ok, so now I still have a problem... It is explained in the following screen shot:

enter image description here

EDIT 5:

    private void DrawSelector(SpriteBatch spriteBatch)
    {
        device.Clear(ClearOptions.DepthBuffer, Color.White, 1f, 0);

        itemRender.Render(world.player.ItemSelector);
    }

...

    public void Render(ItemSelector itemSelector)
    {
        view = itemSelector.View;
        projection = itemSelector.Projection;

        effect.CurrentTechnique = effect.Techniques["Block"];
        effect.Parameters["World"].SetValue(Matrix.Identity);
        effect.Parameters["View"].SetValue(view);
        effect.Parameters["Projection"].SetValue(projection);
        effect.Parameters["Texture"].SetValue(Variables.TILE_ALAIS.SheetTexture);

        int counter = 0;

        foreach (CubeObject cubeObject in itemSelector.CubeObjects)
        {
            effect.Parameters["World"].SetValue(Matrix.Identity * Matrix.CreateRotationY(MathHelper.ToRadians(45f)) * Matrix.CreateRotationX(-15f) * Matrix.CreateTranslation(100 + counter * 80 + itemSelector.ScrollOffset, 80, -10));

            if (counter == itemSelector.Index)
            {
                effect.Parameters["World"].SetValue(Matrix.Identity * Matrix.CreateRotationY(MathHelper.ToRadians(45f)) * Matrix.CreateRotationX(-15f) * Matrix.CreateScale(1.8f) * Matrix.CreateTranslation(100 + counter * 80 + itemSelector.ScrollOffset, 80, -2));
            }

            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Apply();
                device.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, cubeObject.vertices.ToArray(), 0, cubeObject.vertices.Count, cubeObject.indices.ToArray(), 0, cubeObject.indices.Count / 3, VertexPositionTextureLight.VertexDeclaration);
            }

            counter++;
        }
    }

Any ideas?

Edit 6:

Also when I draw my block selector - it is drawn right before the HUD is - this is what happens:

enter image description here

share|improve this question
    
About your edit, the view matrix looks okay, but the projection matrix is probably a mess. What's with the negative near plane? Set the near plane to something normal like 0.1f instead. And the other values look off too. If your camera is positioned on the origin, what's up with those negative left/right/top/bottom values on the projection matrix? It would be better if you fit your projection matrix to your viewport, so that you can specify the models coordinates as if they were in screenspace. –  David Gouveia Jan 9 '12 at 22:05
    
So something like this?: projection = Matrix.CreateOrthographicOffCenter(0, 800, 600, 0, 0.1f, 100.0f); (I still don't get anything shown, and as my render target thing is null for somereason. I'll post that code above. –  Darestium Jan 10 '12 at 1:42
    
Check my final edit then. –  David Gouveia Jan 10 '12 at 2:15
    
I have no idea why the cubes would only rotate when you rotate the camera, unless you're changing the view matrix, or your shader has some problems. Why are you not using the simple BasicEffect class for this? As for the flat look, it's normal because of the way orthographic projection works and since you're only rotating around the Y axis. Try rotating them a bit in the X axis too so that they look more isometric at least. –  David Gouveia Jan 10 '12 at 4:54
    
The cubes do not rotate when the camera does, the "back side" of it for some reason appears when I look at the terrain... And I can't see the other sides of it only the front faces when I rotate it - but the backside is partially visible when I rotate it. –  Darestium Jan 10 '12 at 5:47
show 9 more comments

1 Answer 1

up vote 4 down vote accepted

If all you want is for those objects to be unaffected by the camera, why don't you just use a separate view matrix for them (one that never changes)? Simple!

And since you probably want them to always appear on front of everything else, don't forget to clear the depth buffer, or use separate render targets.

Edit

I just realised a problem with this approch. Each object, has a slightly different rotation when it is further to the left/right of the screen any ideas?

They don't have a different rotation, that's just the effect of perspective. Use an orthographic projection instead if you don't want it to appear that way.

Edit 2

  1. Download this sample (random 3D sample I downloaded).
  2. Replace the content of HeightmapCollision.cs with this
  3. And it should look just like this video.
  4. Compare with yours, that's all I can say. I did exactly as I described above and it works.

The only relevant differences to the code compared to the original sample are:

fixedViewMatrix = Matrix.CreateLookAt(new Vector3(0, 0, 10), Vector3.Zero, Vector3.Up);
fixedProjectionMatrix = Matrix.CreateOrthographicOffCenter(0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height, 0, 1f, 1000f);

device.Clear(ClearOptions.DepthBuffer, Color.White, 1f, 0);
for (int i = 0; i != 5; ++i)
{
    Matrix worldMatrix = Matrix.CreateScale(2f) * Matrix.CreateRotationY(angle) * Matrix.CreateTranslation(100 + i * 200, 100, -10);
    DrawModel(sphere, worldMatrix, fixedViewMatrix, fixedProjectionMatrix);
}

And it was working even without clearing the depth buffer, so I'm no longer sure if that's even necessary, but added it just in case.

share|improve this answer
    
Id recommended separate render targets, will come in handy when doing things later down the line such as screenshots. –  Twitchy Jan 9 '12 at 13:08
    
Not to mention it would make it easier to apply some post processing effects to your game without affecting your GUI. –  David Gouveia Jan 9 '12 at 13:51
    
So to clear the Z-Buffer I just go: device.Clear(ClearOptions.ZBuffer, Color.Black, 1f, 0);? But that doesn't seem to help and the objects are drawn "in" the terrain, and when the camera is not pointing at the terrain it dissapears... –  Darestium Jan 9 '12 at 21:39
    
I haven't really tested clearing the depth buffer, so just in case render to a separate render target. But yes, that should be the way. –  David Gouveia Jan 9 '12 at 22:01
    
Wow, thanks, the only problems is when I rotate the cubes both sides are oppisite sides are visible and looks flat. –  Darestium Jan 10 '12 at 3:45
show 2 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.