I have a very n00b like question here .. I have this small XNA game in which I tried importing a 3D model already made and provided by Microsoft. The problem is XNA isn't loading the textures associated with this model, even though it makes sure that the associated with the model are present in the project directory (compiler gives an error if it can't find these textures), .. So basically I just see a big clay model :P ..
This picture shows the result I'm getting:
This is what it should be like:
Is there anything which I'm missing here ? Shouldn't XNA automatically apply all textures associated with a specific model ?
When you are rendering your dude.fbx model, make sure that in the loop for drawing the model that you have something like the following:
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.EnableDefaultLighting();
}
}
This is off the top of my head, so the method calls might not be correct.
Xna does not automatically load the textures for the model.
The exception you're getting when the texture is not present is thrown by the Xna's resource compiler and is not related to actually importing anything.
The way you would solve this is by loading the texture manually in LoadContent() or anywhere else where you have a ContentManager using:
modelTexture = Content.Load<Texture2D>("mytexture");
and then add the texture either as a parameter if you have a custom effect or put it in the Texture property on your BasicEffect instance when you draw it:
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect eff in mesh.Effects)
{
eff.TextureEnabled = true;
eff.Texture = modelTexture;
}
mesh.Draw();
}
(drawing should obviously not be done in LoadContent() though)
Notice the eff.TextureEnabled = true; which is required to activate textures when using BasicEffect.
Related
Hey my problem is I have created the perfect model for what I want in 3dsMax I rigged a biped using the skin modifier,
I correctly positioned the envelopes and I animated the biped using frames and then exported as an .fbx and loaded it into XNA using the SkinnedModelPipeline.
Once Loaded into XNA the model deforms and it only seems to be on the models right arm.
As I'm only a new member I can't post images at this moment in time so I am sending a link to the images online.
3dsMax Model:
Model loaded in
Draw function for Models
//an array of the current positions of the model meshes
this.bones = animationPlayer.GetSkinTransforms();
for (int i = 0; i < bones.Length; i++)
{
bones[i] *= Transform.World;
}
//remember we can move this code inside the first foreach loop below
//and use mesh.Name to change the textures applied during the effect
customEffect.CurrentTechnique = customEffect.Techniques[technique];
customEffect.Parameters["DiffuseMapTexture"].SetValue(diffuseMap);
customEffect.Parameters["Bones"].SetValue(bones);
customEffect.Parameters["View"].SetValue(Game.CameraManager.ActiveCamera.ViewProperties.View);
customEffect.Parameters["Projection"].SetValue(Game.CameraManager.ActiveCamera.ProjectionProperties.Projection);
foreach (ModelMesh mesh in model.Meshes)
{
//move code above here to change textures and settings based on mesh.Name
//e.g. if(mesh.Name.Equals("head"))
//then set technique and all params
foreach (ModelMeshPart part in mesh.MeshParts)
{
part.Effect = customEffect;
}
mesh.Draw();
}
I've goggled around for a long time and i cant find anything that would solve this problem.
Any help is appreciated.
When transforming bones you do not move them in 'world' space.
They should inherit their parents transformation, so all bones has to be moved in relation to their parent.
Also issues with the scale\translation matrix in 3dsmax can cause similar looking issues.
This can be checked for by re-importing the FBX back into 3dsmax, if it looks good after doing that then it's the issue is in the code.
I'm trying to create an object that will be responsible of creating and showing different sprites, so I would like to access directly the assets/sprites programmatically instead of drag and drop a sprite in the hierarchy under that object.
There's a way to programmatically create a new sprite and assign what I have in the assets folder?
I also would like to have a sort of data structure with a few images loaded at the start of the game, an array or a dictionary or something like that so I can change based on some situation which images I need to show. But what confuses me since I'm new to Unity is how to create a sprite taking the reference to the sprite programmatically using the assets folder.
edit with progress:
I've created an array of sprites like this:
public Sprite[] mySprites;
in Unity I've added sprites inside the array manually (I just dragged png's inside the variable array) so actually in this Object I have a Component with this array full of sprites
inside the component I also have done this:
public SpriteRenderer renderer;
renderer = transform.GetComponent<SpriteRenderer>();
renderer.sprite = (Sprite)mySprites [0];
I got no error until I run the game, then the sprite is NOT assigned and I got this:
"PPtr cast failed when dereferencing! Castin from Texture2D to Sprite!"
I got this error even without casting (Sprite) and btw I don't know why he is telling my about Texture2D since verything is setted as sprite
To create a sprite programmatically might be a little too difficult to do. You'd probably need to create a Texture in memory, fill in the data, and then write that texture on the disk. After that, you should be able to read that using C#'s File, or Unity's WWW.LoadFromCacheOrDownload.
Here is how you would create a texture dynamically: http://answers.unity3d.com/questions/9919/how-do-i-create-a-texture-dynamically-in-unity.html
To load your sprites programmatically (not the ones created dynamically though), they need to be under a folder with the name Resources (which is a special folder).
I.e. suppose you have a sprite named MySprite.png under a folder named Sprites which is under a folder named Resources. You would then load it like this:
renderer.sprite = Resources.Load<Sprite>("Sprites/MySprite");
(notice how you do not include the Resources folder and the extension of the sprite)
You can find more details in the Loading Resources at Runtime documentation.
PPtr cast failed when dereferencing!
I did some searching and found out from this forum post that usually that happens when you had a list of one type and then changed it into another type. I.e. if mySprites was at some point GameObject[] and you linked a bunch of Sprites, and then changed it to Sprite[]. And since it specifically says Texture2D, I'm assuming that the import settings of your Sprites (or some of them) are set to Texture instead of Sprite:
Also, all MonoBehaviours have already a field named renderer, which is of type Renderer. I would suggest you rename that field to avoid confusion, unless you only used that as an example.
Here is real code.. will help you
void SetSprite(UI2DSprite uiSprite, Sprite[] sprites, string strKey)
{
foreach (Sprite stexture in sprites)
{
if (stexture.name == strKey)
{
uiSprite.sprite2D = stexture;
break;
}
}
}
use it following the way..
UI2DSprite[] uiSprites = tmpObject.GetComponentsInChildren<UI2DSprite>();
Sprite[] sprites = Resources.LoadAll<Sprite>("Textures");
string resName = "icon_favorite_2";
foreach (UI2DSprite uiSprite in uiSprites)
{
if(uiSprite.name = "icon")
SetSprite(uiSprite, sprites , resName);
}
Just to throw my tuppence worth in. I had this problem when I changed a SerializedField from Texture2D to Sprite in the code. The texture was already a sprite in the editor but it needed to be Sprite in the code. The field in the editor initially said type mismatch and then displayed the sprite texture again.
To cure it I set the field in the editor to none and the reset it to the required sprite.
Ok, this is hard to explain without pictures. I made a very limited model of a glock in Blender with an extruded cube making up the base and a scaled cube making up the barrel.
In Blender, It looks fine:
However, after exporting the model to .fbx and loading it into the compiler, it comes out like this:
I don't know exactly what is going on. Everything on the model is properly UV Mapped and the coordinates are correct, It just seems the translation is.. off..
Here is my drawModel code:
private void DrawModel(Model model, Matrix world, Matrix view, Matrix projection)
{
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.EnableDefaultLighting();
effect.World = world;
effect.View = view;
effect.Projection = projection;
}
mesh.Draw();
}
}
Any pointers will be helpful!
EDIT: After Applying rotation, location, and scale, I was able to get them in the right position, but why does it look transparent?
Thank you for all the help!
As Nikola mentioned, in the later versions of Blender, they have proper XNA support.
Here's a screenshot of the settings I chose when exporting a model:
Why this happens:
Your Depth Buffer is not enabled, so when your GPU draws the barrel first, then the stock/handle, the handle is drawn on top of the barrel, even though some parts of it are supposed to be invisible because they would be hidden by the barrel.
How to fix:
Enable Depth Buffer as other answer suggests. And/Or order meshes in your model based on distance from camera, and draw tehm in order from the nearset to the farthest. This may not seem usefull now, but when you start working with transparent objects, you will see why this is a good thing to learn.
Enable depth buffer:
GraphicsDevice.DepthStencilState = DepthStencilStates.Default;
And to Draw a model in Xna you can follow this tutorial, that shows how the bone transforms have to be applied to get the meshes in right position.
I am just getting into XNA programming and have been unable to figure out how can I access the texture from a ".x" model. I am using a custom shader to display my model (just a cube with a texture mapped on it) with the filters set to point. To do this I needed to pass the effect my texture file which needed to be imported separately from my model or else it would complain since it is included in my model as well. This works perfectly how I want it, however this isn't really an agreeable method when I have many different models with their own textures.
My question is:
How am I able to access the texture included in my model directly from it and send that to my shader? Or am I able to access it directly with HLSL?
What I have tried:
I have found posts saying that it can assigned to a texture variable with:
Texture2d texture = ((BasicEffect)model.Meshes[0].Effects[0]).Texture
When I tried this the game runs but the cubes are just black. I can see that the texture variable is holding info and has the right dimensions but I can't tell if it is correctly holding the actual image. When I used just the BasicEffect they rendered just fine with their texture.
Update:
I have managed to get this to work after a little bit of fiddling. My game loads in a few hundred of the same cube and upon creation of each it would try save the texture of the model using the code above and then go through the mesh parts and change the effects to my custom effect. I discovered that the first cube created would save the texture okay but any subsequent cubes created would complain that they can't be cast as a BasicEffect. This resulted in one textured cube and then a lot of black ones. I am guessing that when it reuses the same model over and over like that it will just use the one that was modified to use my custom effect which was done on the first instance of the cube. Is this normal? I have got them all to render as textured by changing the texture variable to static.
Please observe that you are assigning the texture of your model to a temporary Texture2D variable, and not setting the Texture present in the Effect currently tied to your mesh.
If you do the following:
Texture2D textureToSet = Content.Load<Texture2D>("MyTex");
//Keep in mind that this method requires a basic effect type and that only one
//effect is present on each mesh to work properly.
foreach(Mesh mesh in model.Meshes)
{
((BasicEffect)(mesh.Effects[0])).Texture = textureToSet;
}
The quirky stuff going on inside the foreach is simply that you are grabbing the effect, then casting it to a BasicEffect and using its Texture property to give it a new texture to draw when used. Please see the documentation and Shawn's blog for a more detailed introduction.
If anyone else is wondering about this as I was then saving the texture using:
Texture2d texture = ((BasicEffect)model.Meshes[0].Effects[0]).Texture
This does work but there is one thing to watch for which is what was causing me problems. If you change the effect of the model from the default BasicEffect for one instance it will be changed for every instance of the model created thereafter. So you will only be able to use the above code before you change the effect for the first time on a particular model.
I later found this book which describes exactly how to extract the texture and other information from a model: 3D Graphics with XNA Game Studio 4.0 by Sean James - Specifically chapter 2
I have a scene that contains mutiple objects. How can i import it in xna and mentain each objects position? right now i export the scene in .fbx and load it in a model like this :
cube.model = contentManager.Load<Model>("cub");
but the objects don't retain their position and are all gathered in one point.
I need a method to import all the objects as individual objects but to retain the objects position in the scene?
(i.e. i need to import the scene so that i may manipulate the objects and retain their position in the scene so that i shouldn't reposition all the objects by myself)
Each object's scene position is in the fbx. The way to get it and implement it is to create a matrix array to hold every object's transform relative to the scene origin, then utilize the appropriate transforms when setting the effect.World for each object during draw time.
//class variables
Matrix[] objectTransforms;
//LoadContent section
cube.model = contentManager.Load<Model>("cub");
objectTransforms = new Matrix[cube.model.Bones.Count];
cube.model.CopyAbsoluteTransformsTo(objectTransforms);// the magic is done here
//draw method
foreach(ModelMesh mm in cube.model.Meshes)
{
foreach (BasicEffect bfx in mm.Effects)
{
bfx.World = objectTransforms[mm.ParentBone.Index] * whateverLocalTransformYouWant;
//draw here
}
}
Without utilizing 'objectTransforms' all objects will be drawn with their local origins located at the world origin, which sounds like what you are experiencing.
I personally made a level editor for most of the things in my game, but I do have a large scene in blender that links to other models. That way I can arrange all the level pieces in blender. When I export each individual piece, it does retain is global position and import correctly in the game. I would say that the issue resides in your fbx exporter. There should be an option to preserve location.
What modelling program do you use? If you use blender, there is an fbx exporter set made specifically for XNA that you should use.