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

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

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

image

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

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

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

   1: protected override void Draw(GameTime gameTime)
   2: {
   3:     GraphicsDevice.Clear(Color.CornflowerBlue);
   4:  
   5:     // TODO: Add your drawing code here
   6:     Matrix world = Matrix.Identity; 
   7:     Matrix view = Matrix.CreateLookAt(new Vector3(0,100,20), Vector3.Zero, Vector3.Up);
   8:     Matrix projection = Matrix.CreatePerspectiveFieldOfView(
   9:                                                MathHelper.ToRadians(45),            //视角
  10:                                                GraphicsDevice.Viewport.AspectRatio,  //屏幕长宽比
  11:                                                0.1f, //最近拍摄范围
  12:                                                1000f  //最远拍摄范围
  13:                                                );
  14:     Matrix[] transforms = new Matrix[model.Bones.Count];
  15:     model.CopyAbsoluteBoneTransformsTo(transforms);
  16:  
  17:     foreach (ModelMesh mesh in model.Meshes)
  18:     {
  19:         foreach (BasicEffect effect in mesh.Effects)
  20:         {
  21:             //光照设置
  22:             effect.LightingEnabled = true;
  23:             effect.AmbientLightColor = 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:     }
  31:     base.Draw(gameTime);
  32: }

image

然后构造一个纯色的贴图

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

   1: Texture2D texture;

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

   1: protected override void LoadContent()
   2: {
   3:     // Create a new SpriteBatch, which can be used to draw textures.
   4:     spriteBatch = new SpriteBatch(GraphicsDevice);
   5:  
   6:     // TODO: use this.Content to load your game content here
   7:     model = Content.Load<Model>(@"boxes");
   8:  
   9:     texture = new Texture2D(GraphicsDevice, 1, 1);//创建一个2D图片对象
  10:     texture.SetData(new Color[] { new Color(255, 0, 0, 255) });//改变图像属性(上色)
  11: }

贴上试试

image

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

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

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

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

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

   1: foreach (ModelMesh mesh in model.Meshes)//循环模型的每个Mesh
   2: {
   3:     foreach (BasicEffect effect in mesh.Effects)//对Mesh的每个Effect进行设置
   4:     {
   5:         //光照设置
   6:         effect.LightingEnabled = true;
   7:         effect.AmbientLightColor = new Vector3(0.9f, 0.9f, 0.9f);
   8:  
   9:         //设置贴图
  10:         effect.TextureEnabled = true;
  11:         effect.Texture = texture;
  12:  
  13:         //设置观察矩阵
  14:         effect.View = view;
  15:         //设置投影矩阵
  16:         effect.Projection = projection;
  17:         //设置位置(相对于基准点)矩阵
  18:         effect.World = transforms[mesh.ParentBone.Index] * world;
  19:     }
  20:     mesh.Draw();//显示Mesh
  21: }

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

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

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

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

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

   1: protected override void Draw(GameTime gameTime)
   2: {
   3:     GraphicsDevice.Clear(Color.CornflowerBlue);
   4:  
   5:     // TODO: Add your drawing code here
   6:     Matrix world = Matrix.Identity; 
   7:     Matrix view = Matrix.CreateLookAt(new Vector3(0,100,20), Vector3.Zero, Vector3.Up);
   8:     Matrix projection = Matrix.CreatePerspectiveFieldOfView(
   9:                                                MathHelper.ToRadians(45),            //视角
  10:                                                GraphicsDevice.Viewport.AspectRatio,  //屏幕长宽比
  11:                                                0.1f, //最近拍摄范围
  12:                                                1000f  //最远拍摄范围
  13:                                                );
  14:     Matrix[] transforms = new Matrix[model.Bones.Count];
  15:     model.CopyAbsoluteBoneTransformsTo(transforms);
  16:  
  17:     foreach (ModelMesh mesh in model.Meshes)
  18:     {
  19:         foreach (BasicEffect effect in mesh.Effects)
  20:         {
  21:             effect.LightingEnabled = true;
  22:             effect.AmbientLightColor = new Vector3(0.9f, 0.9f, 0.9f);
  23:  
  24:             if (mesh.ParentBone.Index == 1) //如果当前Mesh游标为1 则修改其贴图
  25:             {
  26:                 //设置贴图
  27:                 effect.TextureEnabled = true;
  28:                 effect.Texture = texture;
  29:             }
  30:             else
  31:             {
  32:                 effect.TextureEnabled = false;
  33:             }
  34:  
  35:  
  36:             effect.View = view;
  37:             effect.Projection = projection;
  38:             //设置位置(相对于基准点)矩阵
  39:             effect.World = transforms[mesh.ParentBone.Index] * world;
  40:         }
  41:         mesh.Draw();//显示Mesh
  42:     }
  43:     base.Draw(gameTime);
  44: }

显示效果如下

image

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

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

posted @ 2011-11-18 00:08  LightingCui  阅读(914)  评论(0编辑  收藏  举报