Drawing Static Mesh as Primitives Using CustomEffect for Tex

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
theneonirvana
Posts: 24
Joined: Wed Aug 17, 2011 9:20 pm

Drawing Static Mesh as Primitives Using CustomEffect for Tex

Post by theneonirvana »

hi there...

Basicly what im trying to do is have the Static Mesh or Character Controlled Terrain in the Demo's to be loaded in exactly the way it is, and rendered using a custom effect so i can set a texture to the static mesh.

ive asked on a XNA form cuz i know this quite dost involve BEPU physics however i am using the InstancedModelDrawer class and trying to create a hybrid of a working example before i actually implement it...

This can get a little messy, because ive been trying for a couple days now with no resolve...

Norbo, u know your code better then all, but i know this isnt your codes problem its rendering an effect which i cant get working... as the static mesh still loads and creates its physics, just the object is invisible :) (LOT LIKE my last post,... u were right about that it was the scale)

im going to link to my XNA forum post just to save my self some typing....

Thank you again!.... i was trying to take a break from this today... 4 days was too long :\

XNA Post : http://forums.create.msdn.com/forums/t/97407.aspx
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Drawing Static Mesh as Primitives Using CustomEffect for

Post by Norbo »

The WorldViewProj matrix seems to be set to a WorldMatrix. It should be set to a World * View * Projection matrix. The purpose of the transform sequence is to get the vertices from object space into clip space (object space * world transform -> world space; world space * view transform -> camera space; camera space * projection transform -> clip space). If only the WorldMatrix is provided, then the vertices never get put into clip space and the screen space positions will be wildly incorrect- and generally invisible.

If it still fails after you fix that, it's probably another finicky little issue somewhere. One missing piece here or there could foul up the whole thing in a nondescript way. Typically, shrinking the problem size and debugging individual pieces in sequence helps a lot. Instead of flipping switches across the entire system, look at every piece of data you're getting in the load, check that it gets into the right form, try drawing it with a BasicEffect or something for a baseline, try simplifying or changing shader code and checking the results against your expectations, and so on.

Also, but the ease of development and debugging, I would strongly recommend that you separate your rendering code from the InstancedModelDrawer. The InstancedModelDrawer is not friendly to extension and seems to be entangling your custom attempts in unnecessary complexity. In other words, creating it from scratch will likely be easier than constructing a frankenstein hybrid.
theneonirvana
Posts: 24
Joined: Wed Aug 17, 2011 9:20 pm

Re: Drawing Static Mesh as Primitives Using CustomEffect for

Post by theneonirvana »

Hi Norbo, happy new year! lol, im still driving my self nuts....

ive taken a diffrent approach to not use the model drawer in BEPU and to code from scratch (to a point...)

I was wondering if you could take a look at these couple of Methods, because i am getting the same result, where the static mesh will load and its physics work, however it will not render in the custom effect's texture... tell me to bug off at any point :)

if i cant get this working at this point im going to start a new project and create a model dll drawer and pump it into that, because if i can just draw it with a texture, the physics are there and my job will b complete :\

Its really messy i know, im sorry but any thing commented out has been tried or tried in combination,

i was trying to draw using primitives, then tried another approach by loading the model into a second Model variable and then drawing the model as normal, while BEPU took care for the StaticMesh's physics, thus "overlapping" them

My Vertex buffer and everything seems to work and populate propelry, however ushlly all my texturecorrdinates are 0,0,0 :\

once again to many hours programming, and my eyes are far to buggy :\


Norbo, god knows this aint ur job, but ur always there for a quick response and ur great at it :\

Hope u have a drink on me tonight!, im going out now, cuz i need some R & R :\


Thanks again !

Code: Select all

 internal void InitEffect()
        {


           


            staticmesheffect = Content.Load<Effect>("InstancedEffect3");
            //staticmesheffect.Parameters["LightDirection1"].SetValue(Vector3.Normalize(new Vector3(.8f, -1.5f, -1.2f)));
            //staticmesheffect.Parameters["DiffuseColor1"].SetValue(new Vector3(.66f, .66f, .66f));
            //staticmesheffect.Parameters["LightDirection2"].SetValue(Vector3.Normalize(new Vector3(-.8f, 1.5f, 1.2f)));
            //staticmesheffect.Parameters["DiffuseColor2"].SetValue(new Vector3(.3f, .3f, .5f));
            //staticmesheffect.Parameters["AmbientAmount"].SetValue(.5f);
            staticmesheffect.Parameters["xTexture"].SetValue(Content.Load<Texture2D>("Textures\\tex1"));

            staticmesheffect.CurrentTechnique = staticmesheffect.Techniques[0];
            

/// hmmmm m 
            worldTransformsParameter = staticmesheffect.Parameters["xWorldViewProjection"];
            //textureIndicesParameter = staticmesheffect.Parameters["TextureIndices"];
            //viewParameter = staticmesheffect.Parameters["View"];
            //projectionParameter = staticmesheffect.Parameters["Projection"];

            textureIndicesarray[0] = 1;



            foreach (ModelMesh mesh in this.playgroundModelModel.Meshes)
                foreach (ModelMeshPart meshPart in mesh.MeshParts)
                    meshPart.Effect = this.staticmesheffect.Clone();




            CreateVertexBuffer();

        }
 private void CreateVertexBuffer()
        {




            vertexDeclaration = new VertexDeclaration(new VertexElement[] 
                { 
                    new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0), 
                    new VertexElement(12, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0) 
                }
            );

            vertexBuffer = new VertexBuffer(this.GraphicsDevice, vertexDeclaration, this.verticesarray.Length, BufferUsage.None);

            VertexPositionTexture[] objectVertices = new VertexPositionTexture[this.staticmeshPositionNormalTextures.Count];
            
            for (int x = 0; x < objectVertices.Length; x++)
            {
                //objectVertices[x] = new VertexPositionTexture(this.staticmeshPositionNormalTextures[x].Position, verticesarray[x].TextureCoordinate);
                //objectVertices[x] = new VertexPositionTexture(new Vector3(this.staticMeshVertices[x].X, this.staticMeshVertices[x].Y, this.staticMeshVertices[x].Z), verticesarray[x].TextureCoordinate);
                objectVertices[x] = new VertexPositionTexture(this.staticmeshPositionNormalTextures[x].Position, this.staticmeshPositionNormalTextures[x].TextureCoordinate);
                
            }

            vertexBuffer.SetData<VertexPositionTexture>(objectVertices);
            this.GraphicsDevice.SetVertexBuffer(vertexBuffer);
        } 

 Effect staticmesheffect;
        private readonly Matrix[] worldTransforms = new Matrix[1];
        internal void DrawStaticMesh()
        {





            worldTransforms[0] = Matrix.Identity;

            this.GraphicsDevice.SetVertexBuffers(bindings);
            this.GraphicsDevice.Indices = indexBuffer;


            //worldTransformsParameter.SetValue(worldTransforms);
            //textureIndicesParameter.SetValue(textureIndices);

             RasterizerState rasterizerState1 = new RasterizerState();
            rasterizerState1.CullMode = CullMode.None;
            
            
            this.GraphicsDevice.RasterizerState = rasterizerState1;

            staticmesheffect.Parameters["xWorldViewProjection"].SetValue(WorldMatrix);
            staticmesheffect.Parameters["xTexture"].SetValue(Content.Load<Texture2D>("Textures\\tex1"));
            //staticmesheffect.Parameters["View"].SetValue(this.viewMatrix);
            //staticmesheffect.Parameters["Projection"].SetValue(this.ImaginePlayer.Projection);
            //staticmesheffect.Parameters["TextureIndices"].SetValue(textureIndicesarray);
            //staticmesheffect.Parameters["WorldTransforms"].SetValue(worldTransforms);


            Matrix[] playgroundmodeltransforms = new Matrix[this.playgroundModelModel.Bones.Count];
            this.playgroundModelModel.CopyAbsoluteBoneTransformsTo(playgroundmodeltransforms);



            foreach(EffectPass effectpass in staticmesheffect.CurrentTechnique.Passes)
            {
                effectpass.Apply();
                
            }
            foreach (ModelMesh mesh in this.playgroundModelModel.Meshes)
            {
                foreach (Effect currentEffect in mesh.Effects)
                {
                    Matrix worldMatrix = playgroundmodeltransforms[mesh.ParentBone.Index] * Matrix.Identity;
                    currentEffect.CurrentTechnique = currentEffect.Techniques[0];
                    currentEffect.Parameters["xWorldViewProjection"].SetValue(worldMatrix);
                    currentEffect.Parameters["xTexture"].SetValue(Content.Load<Texture2D>("Textures\\tex1"));

                    

                }
                mesh.Draw();
            }


            //this.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, staticMeshVertices.Length, 0, staticMeshIndices.Length / 3);

            
        }

 private void InitializeTransform()
        {
            //float tilt = (float)System.Math.PI / 8.0f;
            // Use the world matrix to tilt the cube along x and y axes.
            //World = Matrix.CreateRotationX(tilt) *
            //    Matrix.CreateRotationY(tilt);

            //View = Matrix.CreateLookAt(new Vector3(0, 0, 10),
            //    Vector3.Zero, Vector3.Up);

            //Projection = Matrix.CreatePerspectiveFieldOfView(
            //  (float)System.Math.PI / 4.0f,  // 2 PI Radians is 360 degrees, 
            // so this is 45 degrees.

            //(float)this.MAINGAME.GraphicsDevice.Viewport.Width /
            //(float)this.MAINGAME.GraphicsDevice.Viewport.Height,
            //1.0f, 100.0f);

            World = Matrix.Identity * Matrix.CreateTranslation(Vector3.Zero);

            WorldMatrix = World * this.viewMatrix * this.ImaginePlayer.Projection;
        }
        Matrix World;
  internal void LoadStaticMesh()
        {
            //Model temp = Content.Load<Model>("CharacterControllerTestTerrain");
            var t = Content.Load<Model>("CharacterControllerTestTerrain");

            this.playgroundModelModel = t;
            

            //playgroundModel = (BEPUphysics.Collidables.StaticMesh)temp;
            //This load method wraps the TriangleMesh.GetVerticesAndIndicesFromModel method 
            //to output vertices of type StaticTriangleGroupVertex instead of TriangleMeshVertex or simply Vector3.
            BEPUphysics.DataStructures.TriangleMesh.GetVerticesAndIndicesFromModel(t, out staticMeshVertices, out staticMeshIndices);
            playgroundModel = new BEPUphysics.Collidables.StaticMesh(this.staticMeshVertices, this.staticMeshIndices, new AffineTransform(new Vector3(.01f, .01f, .01f), Quaternion.Identity, new Vector3(0, 0, 0)));



            var staticMesh = new BEPUphysics.Collidables.StaticMesh(staticMeshVertices, staticMeshIndices, new AffineTransform(new Vector3(0.1f,0.1f, 0.1f), Quaternion.Identity, new Vector3(0, 0, 0)));
            staticMesh.Sidedness = BEPUphysics.CollisionShapes.ConvexShapes.TriangleSidedness.Counterclockwise;



            GetVertexData(staticmeshPositionNormalTextures, staticMeshUShortIndices, (ushort)staticMeshUShortIndices.Count);



            this.indicesarray = new ushort[staticMeshVertices.Length];
            this.verticesarray = new VertexPositionNormalTexture[staticMeshIndices.Length];



            var newVertices = new VertexPositionNormalTexture[verticesarray.Length + vertexList.Count];
            this.verticesarray.CopyTo(newVertices, 0);
            vertexList.CopyTo(newVertices, this.verticesarray.Length);
            this.verticesarray = newVertices;

            var newIndices = new ushort[this.indicesarray.Length + staticMeshUShortIndices.Count];
            this.staticMeshUShortIndices.CopyTo(newIndices, 0);
            indexList.CopyTo(newIndices, indicesarray.Length);
            indicesarray = newIndices;


            instancingIndices = new float[this.staticMeshVertices.Length];
            var newInstancingIndices = new float[instancingIndices.Length + vertexList.Count];
            instancingIndices.CopyTo(newInstancingIndices, 0);
            for (int i = instancingIndices.Length; i < newInstancingIndices.Length; i++)
                newInstancingIndices[i] = 1; // length of how many objects we have should only b one for testing because of just terrain 
            instancingIndices = newInstancingIndices;


            this.vertexDeclaration = new VertexDeclaration(new VertexElement[]
                {
                    new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0),
                    new VertexElement(12, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0)
                }
            );

            vertexBuffer = new VertexBuffer(this.GraphicsDevice, VertexPositionNormalTexture.VertexDeclaration, verticesarray.Length, BufferUsage.WriteOnly);
            vertexBuffer.SetData(verticesarray);
            instancingBuffer = new VertexBuffer(this.GraphicsDevice, this.vertexDeclaration, instancingIndices.Length, BufferUsage.WriteOnly);
            instancingBuffer.SetData(instancingIndices);
            bindings = new VertexBufferBinding[] { vertexBuffer, instancingBuffer };
            indexBuffer = new IndexBuffer(this.GraphicsDevice, IndexElementSize.SixteenBits, indicesarray.Length, BufferUsage.WriteOnly);
            indexBuffer.SetData(indicesarray);

            vertexList.Clear();
            indexList.Clear();




            this.PhysicsSpace.Add(staticMesh);
            //this.BuildingDrawer.Add(staticMesh);
            InitEffect();
        }

Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Drawing Static Mesh as Primitives Using CustomEffect for

Post by Norbo »

At a glance, it appears the xWorldViewProjection is still only being set to a world matrix. A world matrix pulls an object from 'local' or 'object' or 'configuration' space into the world. Instead, you need a matrix which pulls the object from local space to world space (start with world matrix), then into view space (multiply by camera view matrix), then into clip space (multiply by projection matrix).

To see an example of this in action, create a new Effect file. The default effect template shows an extremely simple vertex shader that uses the transformation sequence explicitly.

Code: Select all

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output;

    float4 worldPosition = mul(input.Position, World);
    float4 viewPosition = mul(worldPosition, View);
    output.Position = mul(viewPosition, Projection);

    // TODO: add your vertex shader code here.

    return output;
}
The output.Position is the clip space result, which gets automatically clipped and perspective-divided after the shader.

When using something like the above where World, View, and Projection are separated, the HLSL compiler will automatically create a preshader to avoid doing redundant calculations. It basically computes a hidden combined WorldViewProjection matrix. You can do the same thing manually by computing the world * view * projection value on the CPU and passing it into your own WorldViewProjection parameter explicitly. Either way works; just pick the more intuitive/convenient one.

Happy new year!
theneonirvana
Posts: 24
Joined: Wed Aug 17, 2011 9:20 pm

Re: Drawing Static Mesh as Primitives Using CustomEffect for

Post by theneonirvana »

Hi there Norbo, Thanks again for all your help! once again you are correct, ive been reading and learning, i seem to have it working, however my only problem is that the model seems to be following my camera as if it was a gun/weapon, instead of drawing it in its fixed position.

this is the method for the world and view and ect, it all filters down from here... and im posative its to do with my "thisworld" variable and what its set to

Code: Select all

  private void InitializeTransform()
        {
            Matrix[] staticworld = new Matrix[this.playgroundModelModel.Bones.Count];
            this.playgroundModelModel.CopyAbsoluteBoneTransformsTo(staticworld);

            Matrix thisWorld = ((Matrix[])staticworld)[this.playgroundModelModel.Meshes[0].ParentBone.Index] *  Matrix.CreateTranslation(new Vector3(5f, 5f, -6f));
            Matrix thisView = Matrix.CreateLookAt(this.ImaginePlayer.Position, this.ImaginePlayer.Target, Vector3.Up);
            Matrix thisProjection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), aspectRatio, drawnearplanedistance, drawfarplanedistance); //this.ImaginePlayer.Projection;// Matrix.CreatePerspectiveFieldOfView((float)System.Math.PI / 4.0f,  // 2 PI Radians is 360 degrees, //so this is 45 degrees.

            WorldMatrix = thisWorld * thisView * thisProjection;
        }
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Drawing Static Mesh as Primitives Using CustomEffect for

Post by Norbo »

Here's some fairly general advice- work through the transforms conceptually, from object space to world space to view space. The final result implies that the mesh is local to the camera, which is a hint. If no individual transform is conceptually wrong and all the values match expectations, start looking for other pieces of logic that might interrupt and confuse the process.

Also, to avoid future confusion, you may want to rename that WorldMatrix property to WorldViewProjection or something since a WorldMatrix is only one part of a WorldViewProjection transform.

As for figuring out exactly what is going wrong, since I don't see a problem immediately, I'll leave it as an exercise :P
Post Reply