Model processing-use custom effects and textures to draw Models

Source: Internet
Author: User
Problem

When you useCodeWhen you load a model to an xNa project, you use a basiceffect instance. In simple cases, basiceffect can draw a model well. When we often want to use a different, custom effect to draw a model.

Solution

By including the model's effect in the basiceffect object, you can obtain all the effect information, such as texture and material. When you copy these attributes to a safe place, you can overwrite the effect with the effect you choose.

Note:You can also use a custom content processor to perform this task more clearly. For more information, see tutorial 4-12.

Working Principle

First, you need to load a model and a custom effect, both of which must be loaded using the content pipeline:

 
Protected override void loadcontent () {Device = graphics. graphicsdevice; basiceffect = new basiceffect (device, null); mymodel = content. load <model> ("tank"); modeltransforms = new matrix [mymodel. bones. count]; customeffect = content. load <Effect> ("bwcolor ");}

In this example, the User-Defined effect uses the grayscale value to draw the model, instead of giving more green weights ).

Because effect is stored in the modelmesh of the model, you can simply overwrite them with a custom effect. However, all original effect information will be lost! This information includes texture and Material color information.

You want to store this information before overwriting the default effect of the model, because custom effect requires certain information, such as the texture used.

You will create a method to process the model and customize the effect. This method will replace all the effect in the model with a copy of the custom effect. Finally, store the initial data and return the arrays of all textures in the initial effect, so that you can pass them to the custom effect. In this example, all effect operations will be rewritten by the user-defined effect, but a small adaptation suffices to override only the effect of a participating modelmeshpart :?) :

 
Private texture2d [] changeeffect (ref model, effect neweffect ){}

Because you want to change the model permanently, you must reference the model parameter (add ref before the first variable ). Otherwise, a local copy will be used, and all changes to this copy will not be known by the calling code.

First, you need to create a copy of the texture used by the original effect:

 
List <texture2d> texturelist = new list <texture2d> (); foreach (modelmesh mesh in model. meshes) foreach (modelmeshpart modmeshpart in mesh. meshparts) {basiceffect oldeffect = (basiceffect) modmeshpart. effect; texturelist. add (oldeffect. texture);} texture2d [] textures = texturelist. toarray (); Return textures;

You have created a set to store textures, and then traverse different modelmeshparts of each modelmesh. Each modelmeshpart contains a link pointing to effect. Pass this effect to a basiceffect object so that you can access its attributes, such as textures. Attaches the texture in the previous texture set to each effect in the model.

After collecting all the textures, you can convert the set into an array and return the array.

Now your operation will overwrite the original effect with a copy of the custom effect, so Add the following code in the second loop:

 
Modmeshpart. effect = neweffect. Clone (device );

Note:You have used the clone method to create a copy of effect. You want to use this copy. Otherwise, all modelmeshparts will share the same effect. Each modelmeshpart can use different textures by applying a copy of each effect to each modelmeshpart.

Call this method after loading the model and custom effect in the loadcontent method:

 
Modeltextures = changeeffect (ref mymodel, customeffect );

When creating a model, you can define each of the following parameters:

Int I = 0; matrix worldmatrix = matrix. createscale (0.01f); mymodel. copyabsolutebonetransformsto (modeltransforms); foreach (modelmesh in mymodel. meshes) {foreach (effect currenteffect in mesh. effects) {currenteffect. parameters ["xworld"]. setvalue (modeltransforms [mesh. parentbone. index] * worldmatrix); currenteffect. parameters ["xview"]. setvalue (fpscam. viewmatrix); currenteffect. parameters ["xprojection"]. setvalue (fpscam. projectionmatrix); currenteffect. parameters ["xtexture"]. setvalue (modeltextures [I ++]);} mesh. draw ();}

Note how you pass the original effect information to the custom effect, such as the texture in this example.

Traverse modelmeshpart instead of Effect

The previous loop traverses all effect, but this will cause problems when you want to set the effect of a specific modelmeshpart, So you traverse the modelmeshpart of modelmesh instead of its effect:

Int I = 0; matrix worldmatrix = matrix. createscale (0.01f); mymodel. copyabsolutebonetransformsto (modeltransforms); foreach (modelmesh in mymodel. meshes) {foreach (modelmeshpart part in mesh. meshparts) {effect currenteffect = part. effect; currenteffect. parameters ["xworld"]. setvalue (modeltransforms [mesh. parentbone. index] * worldmatrix); currenteffect. parameters ["xview"]. setvalue (fpscam. viewmatrix); currenteffect. parameters ["xprojection"]. setvalue (fpscam. projectionmatrix); currenteffect. parameters ["xtexture"]. setvalue (modeltextures [I ++]);} mesh. draw ();}
Store all original information

If you want to store information other than the texture, simply add the original effect to the set to replace the texture:

 
Basiceffect [] originaleffects;

In the changeeffect method, add the original effect to the set:

 
Basiceffect oldeffect = (basiceffect) modmeshpart. effect; effectlist. Add (oldeffect );

When setting a custom effect parameter, you can easily access the initial information:

Currenteffect. Parameters ["xtexture"]. setvalue (originaleffects [I ++]. Texture );
Code

In the loadcontent method, load the model and custom effect:

 
Protected override void loadcontent () {Device = graphics. graphicsdevice; basiceffect = new basiceffect (device, null); ccross = new coordcross (device); mymodel = content. load <model> ("tank"); modeltransforms = new matrix [mymodel. bones. count]; customeffect = content. load <Effect> ("bwcolor"); originaleffects = changeeffect (ref mymodel, customeffect );}

The last line of code replaces the effect in the model with a copy of the custom effect, which is implemented in the following methods:

Private basiceffect [] changeeffect (ref model, effect neweffect) {list <basiceffect> wide tlist = new list <basiceffect> (); foreach (modelmesh mesh in model. meshes) foreach (modelmeshpart modmeshpart in mesh. meshparts) {basiceffect oldeffect = (basiceffect) modmeshpart. effect; effectlist. add (oldeffect); modmeshpart. effect = neweffect. clone (device);} basiceffect [] effects = effectlist. toarray (); Return effects ;}

When creating a model, you can access the stored information as follows:

Int I = 0; matrix worldmatrix = matrix. createscale (0.01f); mymodel. copyabsolutebonetransformsto (modeltransforms); foreach (modelmesh in mymodel. meshes) {foreach (modelmeshpart part in mesh. meshparts) {effect currenteffect = part. effect; currenteffect. parameters ["xworld"]. setvalue (modeltransforms [mesh. parentbone. index] * worldmatrix); currenteffect. parameters ["xview"]. setvalue (fpscam. viewmatrix); currenteffect. parameters ["xprojection"]. setvalue (fpscam. projectionmatrix); currenteffect. parameters ["xtexture"]. setvalue (originaleffects [I ++]. texture);} mesh. draw ();}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.