Jump to content
  • Advertisement
Sign in to follow this  
soarah

(xna) need help spotting a problem (2 small functions)

This topic is 3739 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Ok have been trying for a couple of days to figure this out, using here as a last resort. Aim of these two functions is to load in and display a 3D model. Some simpler 3D models with only 1 texture work fine with these. Has a range of issues depending on the 3Dmodel. Sometimes loads them in with only a couple of textures and the rest white, on more complex meshes gives me an issue with index out of bounds for textures[].
[source lang=csharp]

Model Model1;
Texture2D[] model1Textures;

private Model LoadModel(string assetName, out Texture2D[] textures)
{
  Model newModel = Content.Load<Model>(assetName);

  textures = new Texture2D[newModel.Meshes.Count];
  int i = 0;
  foreach (ModelMesh mesh in newModel.Meshes)
  foreach (BasicEffect currentEffect in mesh.Effects)
      textures[i++] = currentEffect.Texture;
              
   foreach (ModelMesh mesh in newModel.Meshes)
      foreach (ModelMeshPart meshPart in mesh.MeshParts)
            meshPart.Effect = effect.Clone(device);

  return newModel;
}

private void DrawModel1()
{
  Matrix[] Model1Transforms = new Matrix[Model1.Bones.Count];
  Model1.CopyAbsoluteBoneTransformsTo(Model1Transforms);

  int i = 0;
  foreach (ModelMesh mesh in Model1.Meshes)
  {
     foreach (Effect currentEffect in mesh.Effects)
  {
    Matrix worldMatrix = Matrix.CreateScale(0.01f, 0.01f, 0.01f) *       Matrix.CreateRotationY(rotateVal) * Matrix.CreateTranslation(new Vector3(xval, 0.1f, zval));

  currentEffect.CurrentTechnique = currentEffect.Techniques["Textured"];
                        currentEffect.Parameters["xWorld"].SetValue(Model1Transforms[mesh.ParentBone.Index] * worldMatrix);
  currentEffect.Parameters["xView"].SetValue(viewMatrix);
                       currentEffect.Parameters["xProjection"].SetValue(projectionMatrix);                    

currentEffect.Parameters["xTexture"].SetValue(model1Textures[i++]);
  }
  mesh.Draw();
  }
}


[Edited by - soarah on June 30, 2008 11:15:06 PM]

Share this post


Link to post
Share on other sites
Advertisement

Based on the remark over here, I'd guess setting the cloned effects on the meshparts somehow increases the number of effects referenced in the ModelMesh.Effects collection. You could try putting the 'clone loop' before the texture loop to see if that works.

As for the out of bounds exception, meshes may contain multiple meshparts with their own textures, so Texture2D[newModel.Meshes.Count] may well be too small. You could try using a List<Texture2D> instead. It'd be easier to tell where this exception comes from if you could provide a line number where it happens though.

Anyway, you might not need this complicated way of handling the textures. I don't know if you implemented this for a specific reason, but by default the XNA content pipeline already sets up the appropriate effects on the meshes and supplies them with the proper textures. If you're sure currentEffect.Texture is populated properly (since you use it in the load code), the code below might already do for rendering.

[source lang=csharp]
Model Model1;
Texture2D[] model1Textures;

private Model LoadModel(string assetName, out Texture2D[] textures)
{
Model newModel = Content.Load<Model>(assetName);
return newModel;
}

private void DrawModel1()
{
Matrix[] Model1Transforms = new Matrix[Model1.Bones.Count];
Model1.CopyAbsoluteBoneTransformsTo(Model1Transforms);

foreach (ModelMesh mesh in Model1.Meshes)
{
foreach (Effect currentEffect in mesh.Effects)
{
Matrix worldMatrix = Matrix.CreateScale(0.01f, 0.01f, 0.01f) * Matrix.CreateRotationY(rotateVal) * Matrix.CreateTranslation(new Vector3(xval, 0.1f, zval));

currentEffect.CurrentTechnique = currentEffect.Techniques["Textured"];
currentEffect.Parameters["xWorld"].SetValue(Model1Transforms[mesh.ParentBone.Index] * worldMatrix);
currentEffect.Parameters["xView"].SetValue(viewMatrix);
currentEffect.Parameters["xProjection"].SetValue(projectionMatrix);
currentEffect.Parameters["xTexture"].SetValue(currentEffect.Texture);
}

mesh.Draw();
}
}



Share this post


Link to post
Share on other sites
Thanks for the reply. Yeah I am reasonably new to XNA; so still playing around with it.

With the drawModel1() you wrote, it says.

currentEffect.Parameters["xTexture"].SetValue(currentEffect.Texture);


'Microsoft.Xna.Framework.Graphics.Effect' does not contain a definition for 'Texture'

Share this post


Link to post
Share on other sites

Of course, sorry about pointing you down the wrong road [smile]

It depends on what kind of effect you're using for your mesh though. If you are using a BasicEffect (which is the default), then mesh.Draw() will use the appropriate textures for the subparts automatically. Essentially the BasicEffect objects in your model already have a reference to the correct to use. This would mean you can simply omit the 'texture line' from the code I posted. You can find some more information on this over here.

If you're using a custom HLSL effect, then there are a few ways to do this. The 'right way' would be to write a custom content processor to assign your custom effect to the model automatically. This way you shouldn't need any special code either and can use something similar to the above code, give or take a few custom parameters. I have to admit however that my experience with these processors is very limited, so hopefully someone (MJP?) will chip in some more useful information [wink]

Alternatively you could also handle a custom effect in your own code instead of using a content processor, but that's a bit messy messy (esp if you're just starting) and explaining it without knowing if you need it would only complicate matters. If you want to see some basic samples of how custom effects can be handled, here are some samples.

Hope this does help :)

Share this post


Link to post
Share on other sites
Quote:
Original post by remigius
If you're using a custom HLSL effect, then there are a few ways to do this. The 'right way' would be to write a custom content processor to assign your custom effect to the model automatically. This way you shouldn't need any special code either and can use something similar to the above code, give or take a few custom parameters. I have to admit however that my experience with these processors is very limited, so hopefully someone (MJP?) will chip in some more useful information [wink]


AFAIK its the importer that decides what effect gets bound to a model. But while you could write a custom importer for one of the model formats, it sounds about as much fun as...something that's not very much fun at all. I suppose you could override that in a custom content processor, but sounds kinda hacky compared to binding an effect to your model in your 3D modeling app. But I suppose it's an option if you don't want to go through the work of setting up XSI or 3dsmax or whatever to use your custom effects. If you did make a custom processor you could give it a public parameter with an enum or string value that you could set via the Properties windows in Visual Studio.

Probably the easiest option is to just ignore whatever effect is actually bound to the ModelMeshPart and use whatever custom effect you want. I believe this is done in the ShipGame starter kit, which uses a custom NormalMapping effect to render all the geometry.

Share this post


Link to post
Share on other sites
It took me a few days but solved the problem. It was the custom effects file I was using, didnt seem to like complex 3D models with lots of textures.

Also discovered that XNA will almost load/apply textures to your 3D model by itself? which is amazing.

Cheers for all the help

p.s forgot to add instead of a custom effects file; just used BasicEffect which is built in?

Share this post


Link to post
Share on other sites
Quote:
Original post by soarah

Also discovered that XNA will almost load/apply textures to your 3D model by itself? which is amazing.



Yup. If your model specifies textures and shader constants, they will be set in the corresponding effect by the content processor. You can control some aspects of how this is done by going to the properties of any model and expanding the content processor node. For example, you can set whether you want textures loaded to a compressed DXT format or an uncompressed format.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!