如果一个3DMAX场景中有多个模型,但是只想控制其中一个模型的颜色,并对其进行模型进行变色(替换贴图)。

补充一下:导入的一个model中,3DMAX建模时的每个小的模型作为这个model的mesh。(囧 大概就这么回事,不好描述啊,多理解理解吧)

WP7-XNA 3D开发 基本贴图控制

这个情况再实际项目中可以用来实现一个播放中的电视机模型(知识设想,回头可以试着实现一个玩一玩),可以将屏幕单独做成一个面,然后只轮换修改其贴图,做出电视播放的效果。

好了 大概就是这么个东西。然后谈谈如何实现。

还是,新建个项目,叫TextureControl吧(由于要对模型的内部结构进行控制,所以显示的时候不能简单的用model.Draw方法,要用之前那个一堆foreach循环那个)

void Draw(GameTime gameTime)
   2: {
   3:     GraphicsDevice.Clear(Color.CornflowerBlue);
   4:  
// TODO: Add your drawing code here
   6:     Matrix world = Matrix.Identity; 
new Vector3(0,100,20), Vector3.Zero, Vector3.Up);
   8:     Matrix projection = Matrix.CreatePerspectiveFieldOfView(
//视角
//屏幕长宽比
//最近拍摄范围
//最远拍摄范围
  13:                                                );
new Matrix[model.Bones.Count];
  15:     model.CopyAbsoluteBoneTransformsTo(transforms);
  16:  
in model.Meshes)
  18:     {
in mesh.Effects)
  20:         {
//光照设置
true;
new Vector3(0.9f, 0.9f, 0.9f);
  24:  
  25:             effect.View = view;
  26:             effect.Projection = projection;
  27:             effect.World = transforms[mesh.ParentBone.Index] * world;
  28:         }
  29:         mesh.Draw();
  30:     }
base.Draw(gameTime);
  32: }

WP7-XNA 3D开发 基本贴图控制

然后构造一个纯色的贴图

新建一个类变量用来保存贴图

   1: Texture2D texture;

然后在LoadContent方法中添加构造贴图的代码(这里构造一个纯红色贴图)

void LoadContent()
   2: {
// Create a new SpriteBatch, which can be used to draw textures.
new SpriteBatch(GraphicsDevice);
   5:  
// TODO: use this.Content to load your game content here
);
   8:  
//创建一个2D图片对象
//改变图像属性(上色)
  11: }

贴上试试

WP7-XNA 3D开发 基本贴图控制

好了 接下来就是重头戏了。。

观察显示模型的foreach循环之前的准备动作那两句

new Matrix[model.Bones.Count];
   2: model.CopyAbsoluteBoneTransformsTo(transforms);

这两句的作用就是将模型中每个Mesh相对于模型基准坐标的平移变量缓存出来

然后观察缓存出来的那个矩阵数据再循环中的应用,也可以证明,这个矩阵数据即使用来分别设置每个Mesh的位置并分别进行显示

//循环模型的每个Mesh
   2: {
//对Mesh的每个Effect进行设置
   4:     {
//光照设置
true;
new Vector3(0.9f, 0.9f, 0.9f);
   8:  
//设置贴图
true;
  11:         effect.Texture = texture;
  12:  
//设置观察矩阵
  14:         effect.View = view;
//设置投影矩阵
  16:         effect.Projection = projection;
//设置位置(相对于基准点)矩阵
  18:         effect.World = transforms[mesh.ParentBone.Index] * world;
  19:     }
//显示Mesh
  21: }

重点观察 设置为是矩阵那一句

   1: effect.World = transforms[mesh.ParentBone.Index] * world;

这里用到了之前缓存回来的矩阵数组。所以数组的游标可以用来控制前正在处理的Mesh。

然后debug观察下mesh.ParentBone.Index值的变化发现这个值再1--9之间变化,结合我之前再Max中给场景创建了9个方块,可知游标从1开始。

所以改变单独一个Mesh的贴图就是在循环中控制只有在需要改变时采取设置贴图,代码如下

void Draw(GameTime gameTime)
   2: {
   3:     GraphicsDevice.Clear(Color.CornflowerBlue);
   4:  
// TODO: Add your drawing code here
   6:     Matrix world = Matrix.Identity; 
new Vector3(0,100,20), Vector3.Zero, Vector3.Up);
   8:     Matrix projection = Matrix.CreatePerspectiveFieldOfView(
//视角
//屏幕长宽比
//最近拍摄范围
//最远拍摄范围
  13:                                                );
new Matrix[model.Bones.Count];
  15:     model.CopyAbsoluteBoneTransformsTo(transforms);
  16:  
in model.Meshes)
  18:     {
in mesh.Effects)
  20:         {
true;
new Vector3(0.9f, 0.9f, 0.9f);
  23:  
//如果当前Mesh游标为1 则修改其贴图
  25:             {
//设置贴图
true;
  28:                 effect.Texture = texture;
  29:             }
else
  31:             {
false;
  33:             }
  34:  
  35:  
  36:             effect.View = view;
  37:             effect.Projection = projection;
//设置位置(相对于基准点)矩阵
  39:             effect.World = transforms[mesh.ParentBone.Index] * world;
  40:         }
//显示Mesh
  42:     }
base.Draw(gameTime);
  44: }

显示效果如下

WP7-XNA 3D开发 基本贴图控制

补充一点,经过测试,对于每个Mash的游标编号和Mash 对应的模型再3DMAX中创建顺序相关,第几个创建的编号就是几。

代码下载:http://vdisk.weibo.com/s/1a7y8

相关文章: