接着“XNA学习笔记2”中的内容管道说。图片文件、字体文件、.x/.fbx和.fx文件经过内容管道的导入编译等工作,最后通过ContentManager对象的Load方法得到texture、spritefont、model和effect对象。
纹理(或shader)、模型和渲染的关系可以用一个形象的比喻。现在是一个立方体,立方体是模型;渲染就是对立方体的每个部分(这里就想做是每个面,稍后会介绍他的定义)如何添加纹理、颜色、阴影等效果;而纹理就是每个渲染用到的纹理。
第二章讲到了简单2D的纹理是通过SpriteBatch类来处理,这个类仅处理2D的简单纹理,并且没有涉及到模型的概念。
现在讨论一下3D的模型的一些知识。
myModel = Content.Load<Model>("tank");
在大多数情况下,你可以旋转和移动模型的一部分,例如,移动人的手臂。要能实现这个功能,模型应该要被分成几个成员。对每个成员,你需要知道两件事:
几何数据:你想知道顶点,顶点包含了组成模型成员的所有三角形顶点的信息,这些信息包括位置,颜色,法线等。
成员与它们的父成员如何连接:以人的手臂为例,你要指定手臂是连接在肩膀上的。
每个成员的几何数据以ModelMesh对象的形式存储,而ModelMesh对象是在Model的 ModelMeshCollection中,在这个对象你可以找到它的Meshes属性。成员的位置数据以Bone对象的形式存储,而Bone对象在Model的ModelBoneCollection中,在这个对象中你可以找到模型的Bones集合。每个ModelMesh对象包含指向Bone对象的引用,而一个Bone对象包含指向父Bone的引用,它必须连接到这个父Bone。通过这种方式,你可以将所有Bone对象连接到一起。
ModelMeshes和Bones。一个ModelMesh包含模型的一个成员的几何信息,这个成员无法再分成更小的成员。例如,一台笔记本电脑不是一个好的ModelMesh,因为你想翻起/关闭液晶屏,打开/关闭DVD托盘。好的办法是对电脑底座使用一个ModelMesh,液晶屏使用第二个ModelMeshcreen,而DVD托盘使用第三个ModelMesh。因为所有的ModelMesh都需要他连接到一个Bone上,下一步你的三个ModelMeshes还需要三个Bone。你需要将连接到电脑底座的ModelMesh的Bone作为root Bone,因为电脑底座可以看成电脑的初始位置。连接到液晶屏ModelMesh的表示与底座连接的位置。同理连接DVD托盘的ModelMesh的Bone也要指向root Bone,表示托盘相对于底座的位置。
ModelMeshes和ModelMeshParts。你已经为液晶屏定义了一个ModelMesh和对应的Bone,这样很完美,因为液晶屏不包含可动部分。但是,你可能还想使用一个固定纹理的effect绘制液晶屏的塑料外壳,使用另一个effect绘制LCD,例如,这个效果会从另一张纹理采样颜色或你还想添加一点反光效果。这就需要用到ModelMeshParts。每个ModelMesh可以包含多个ModelMeshParts,每个ModelMeshParts可以使用不同的纹理,材质或effect进行绘制。这意味着每个ModelMeshPart 都包含各自的几何数据和对应几何数据的effect。
实现model整体或局部的移动、旋转和缩放的功能
将这部分之前先介绍两个函数:CopyAbsoluteBoneTransformsTo:将模型中的每个bone相对于root的变换信息存储在数组参数中;CopyBoneTransformsTo:将模型中的每个bone相对于其parent bone的变换信息存储在数组参数中。由于在对某个mesh或者part进行变换的时候,同时会对mesh对应的bone的child进行相同的变换。思考:以坦克的火炮为例,火炮的Bone矩阵包含一个诸如(0,0,-2)的偏移量:相对于它的父:炮塔向前移动2个单位。如果你只是简单地将火炮的世界矩阵设置为火炮ModelMesh的矩阵,这会导致火炮ModelMesh被绘制到相对于3D空间的初始位置(0,0,0)偏离(0,0,-2)的地方。但这不是你想要的结果!你实际是想将火炮放置到相对于它的parent:炮塔偏离(0,0,-2)的位置。这个时候会发现CopyAbsoluteBoneTransformsTo方法的重要作用。
你可以简单地使用XNA框架提供的基本方法创建一个变换矩阵:
Matrix.CreateTranslation
Matrix.CreateScale
Matrix.CreateRotationX-Y-Z
第一个方法创建一个平移矩阵,你可以定义将模型沿着X、Y和Z方向移动的距离。第二个方法让你可以缩放模型,第三个方法返回绕X、Y和Z轴旋转的矩阵。
myModel.CopyAbsoluteBoneTransformsTo(modelTransforms);
foreach (ModelMesh mesh in myModel.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.EnableDefaultLighting();
effect.World = modelTransforms[mesh.ParentBone.Index] * worldMatrix;
effect.View = fpsCam.GetViewMatrix();
effect.Projection = fpsCam.GetProjectionMatrix();
}
mesh.Draw();
}
只需要对上面的方法进行组合(*)实现一些复杂的变换。
矩阵乘法的顺序。在矩阵数学中,将矩阵M1乘以矩阵M2的结果通常与将M2乘以M1的结果是不同的。有两个规则(或者说是技巧)你必须记得:在矩阵乘法中,M1*M2就是“M1在M2之后”的意思;使用I.S.R.O.T.作为矩阵组合的顺序通常就是你想要的结果,此处I.S.R.O.T. 分别代表Identity,Scale,Revolve,Orbit,Translate。
碰撞检测
你想检测两个模型是否发生碰撞。如果在场景中有许多模型,你将无法进行一个精确的逐三角形的碰撞检测。你想使用一个快速检测方法并在以后进行一个更好的碰撞检测。当进行碰撞检测时,你会发现常常需要在速度和精确度之间进行衡量。在大多数情况中,你会进行组合检测。在第一轮检测中,使用快速检测遍历所有对象,之后对快速检测中可能发生碰撞的物体进行精确检测。有两个方法处理两个模型间的碰撞检测。快速检测方法是找到模型的全局包围球,并通过调用一个包围球的Intersect 方法检测是否相交。你可以改进这个方法以增加精确度。由几个ModelMeshes组成的模型存储了模型不同部分的几何信息。每个ModelMeshes都能生成各自的包围球,所以你可以检测第一个模型和第二个模型的每个包围球。显然,这样做提高了精度但计算量也随之加大。
快速检测。这个方法使用整个模型的包围球。如果这两个模型的包围球相交,则它们可能发生了碰撞。在某些情况下,这个方法会导致糟糕的结果,例如在滑板游戏中,当你想检测两个玩家的滑板的碰撞时,滑板的包围球相对于滑板本身大得多,滑板的体积不到包围球体积的百分之一,这个方法将会对全局包围球中的所有物体(可能包含其他滑板!)进行检测。但是,这个方法在进行第一次检测时用得还是很多的,因为它的速度足够快。
你可以访问模型中的每个ModelMesh的包围球。使用CreateMerged方法,你可以将这个包围球组合起来,获取包围整个模型的包围球。但是,因为每个ModelMesh的包围球是相对于Bone矩阵定义的,所以你需要进行转换。你将创建一个方法将一个素材加载到一个模型变量中,初始化它的Bone矩阵数组,并将全局包围球保存到模型的Tag属性中。
private Model LoadModelWithBoundingSphere(ref Matrix[] modelTransforms,
string asset, ContentManager content)
{
Model newModel = content.Load<Model>(asset);
modelTransforms = new Matrix[newModel.Bones.Count];
newModel.CopyAbsoluteBoneTransformsTo(modelTransforms);
BoundingSphere completeBoundingSphere = new BoundingSphere();
foreach (ModelMesh mesh in newModel.Meshes)
{
BoundingSphere origMeshSphere = mesh.BoundingSphere;
BoundingSphere transMeshSphere = XNAUtils.TransformBoundingSphere(
origMeshSphere, modelTransforms[mesh.ParentBone.Index]);
completeBoundingSphere = BoundingSphere.CreateMerged(
completeBoundingSphere, transMeshSphere);
}
newModel.Tag = completeBoundingSphere;
return newModel;
}
要检测两个模型间的碰撞,你需要通过世界矩阵变换每个包围球并检查变换过的包围球是否相交。
private bool CoarseCheck(Model model1, Matrix world1, Model model2, Matrix world2)
{
BoundingSphere origSphere1 = (BoundingSphere)model1.Tag;
BoundingSphere sphere1= XNAUtils.TransformBoundingSphere(origSphere1, world1);
BoundingSphere origSphere2= (BoundingSphere)model2.Tag;
BoundingSphere sphere2 = XNAUtils.TransformBoundingSphere(origSphere2,world2);
bool collision = sphere1.Intersects(sphere2);
return collision;
}
精确检测。每个模型是由多个成员组成的,几何数据是存储在模型的Meshes集合中的。每个 ModelMesh都能生成自己的包围球。这些小的包围球的总体积比模型的全局包围球小得多,分别对每个小的包围球进行碰撞检测,通常会返回更好的结果。
你首先将collision变量设置为false,除非检测到碰撞那么这个变量将保持为false。因为你需要将每个小包围球移动到正确的位置,所以需要绝对Bone矩阵。要对第一个模型的每个ModelMesh进行这个检测,你需要将包围球移动到绝对位置。要实现这一步,你需要考虑模型包围球的位置和模型在3D世界中的位置。然后你遍历第二个模型的所有部分并将这些包围球变换到绝对位置。对于第一个模型的每个包围球,你检查是否与第二个模型的任意一个包围球是否发生碰撞,如果是,则将collision变量设置为true。
private bool FinerCheck(Model model1, Matrix world1, Model model2, Matrix world2)
{
//if (CoarseCheck(model1, world1, model2, world2) == false)
// return false;
Matrix[] model1Transforms = new Matrix[model1.Bones.Count];
model1.CopyAbsoluteBoneTransformsTo(model1Transforms);
BoundingSphere[] model1Spheres = new BoundingSphere[model1.Meshes.Count];
for (int i=0; i<model1.Meshes.Count; i++)
{
ModelMesh mesh = model1.Meshes[i];
BoundingSphere origSphere = mesh.BoundingSphere;
Matrix trans = model1Transforms[mesh.ParentBone.Index]* world1;
BoundingSphere transSphere = XNAUtils.TransformBoundingSphere(
origSphere,trans);
model1Spheres[i] = transSphere;
}
Matrix[] model2Transforms = new Matrix[model2.Bones.Count];
model2.CopyAbsoluteBoneTransformsTo(model2Transforms);
BoundingSphere[] model2Spheres= new BoundingSphere[model2.Meshes.Count];
for (int i = 0; i < model1.Meshes.Count;i++)
{
ModelMesh mesh = model2.Meshes[i];
BoundingSphere origSphere = mesh.BoundingSphere;
Matrix trans = model2Transforms[mesh.ParentBone.Index] * world2;
BoundingSphere transSphere = XNAUtils.TransformBoundingSphere(
origSphere, trans);
model2Spheres[i]= transSphere;
}
bool collision = false;
for (int i=0; i<model1Spheres.Length;i++)
for (int j = 0; j < model2Spheres.Length; j++)
if (model1Spheres[i].Intersects(model2Spheres[j]))
return true;
return collision;
}
一般情况下,你首先进行快速检测,如果这次检测返回false,那就没必要进行精确检测。如果快速检测显示可能发生碰撞,那么还要进行更加精确的检测。
对小而快的对象使用Ray-Traced进行碰撞检测。大部分的碰撞检测方法只在两个物体发生物理碰撞时才检测。但是,如果有一个小物体快速地穿过另一个物体,你的程序的更新速度就有可能跟不上而无法检测到碰撞。举一个具体的例子,比如一枚子弹打穿一个瓶子。子弹以5000km/h 的速度射向一个瓶子,而瓶子的宽度只有15cm。XNA程序每秒更新60次,所以每次更新子弹会前进23米的距离。这样的话,在调用Update方法时几乎没有可能检测到子弹和瓶子的碰撞,即使上一帧子弹的确穿过了瓶子。你可以在子弹的上一个位置和当前位置之间创建一个Ray。然后通过调用Ray或包围球的Intersect方法检测Ray是否和包围球发生碰撞。如果发生碰撞,这个方法返回碰撞点与Ray的终点间的距离(你可以使用子弹的前一个位置)。
private bool RayCollision(Model model, Matrix world, Vector3 lastPosition,
Vector3 currentPosition)
{
BoundingSphere modelSpere = (BoundingSphere)model.Tag;
BoundingSphere transSphere = XNAUtils.TransformBoundingSphere(
modelSpere, world);
Vector3 direction = currentPosition - lastPosition;
float distanceCovered = direction.Length();
direction.Normalize();
Ray ray = new Ray(lastPosition, direction);
bool collision = false;
float? intersection = ray.Intersects(transSphere);
if (intersection != null)
if (intersection <= distanceCovered)
collision = true;
return collision;
}
你同样可以通过在模型的不同ModelMesh上的小包围球上进行ray和包围球的碰撞检测提高精度。
下一节,将讨论Effect的相关知识~~
- 大小: 11.4 KB
- 大小: 41 KB
分享到:
相关推荐
功能说明: 本系统主要包括以下功能模块:个人中心,通知公告管理,用户管理,工作人员管理,进门登记管理,出门登记管理,出入统计管理,外来登记管理等模块。 环境说明: 开发语言:Java 框架:ssm,mybatis JDK版本:JDK1.8 数据库:mysql 5.7及以上 数据库工具:Navicat11及以上 开发软件:eclipse/idea Maven包:Maven3.3及以上 服务器:tomcat7及以上
PartSegCore_compiled_backend-0.12.0a0-cp36-cp36m-win_amd64.whl.rar
yolo算法-分神驾驶数据集-8674张图像带标签-没有安全带-唤醒-昏昏欲睡-安全带-电话-打哈欠.zip;yolo算法-分神驾驶数据集-8674张图像带标签-没有安全带-唤醒-昏昏欲睡-安全带-电话-打哈欠.zip;yolo算法-分神驾驶数据集-8674张图像带标签-没有安全带-唤醒-昏昏欲睡-安全带-电话-打哈欠.zip;yolo算法-分神驾驶数据集-8674张图像带标签-没有安全带-唤醒-昏昏欲睡-安全带-电话-打哈欠.zip
python whl离线安装包 pip安装失败可以尝试使用whl离线安装包安装 第一步 下载whl文件,注意需要与python版本配套 python版本号、32位64位、arm或amd64均有区别 第二步 使用pip install XXXXX.whl 命令安装,如果whl路径不在cmd窗口当前目录下,需要带上路径 WHL文件是以Wheel格式保存的Python安装包, Wheel是Python发行版的标准内置包格式。 在本质上是一个压缩包,WHL文件中包含了Python安装的py文件和元数据,以及经过编译的pyd文件, 这样就使得它可以在不具备编译环境的条件下,安装适合自己python版本的库文件。 如果要查看WHL文件的内容,可以把.whl后缀名改成.zip,使用解压软件(如WinRAR、WinZIP)解压打开即可查看。 为什么会用到whl文件来安装python库文件呢? 在python的使用过程中,我们免不了要经常通过pip来安装自己所需要的包, 大部分的包基本都能正常安装,但是总会遇到有那么一些包因为各种各样的问题导致安装不了的。 这时我们就可以通过尝试去Python安装包大全中(whl包下载)下载whl包来安装解决问题。
中国省级与地级市财政转移支付数据-最新.zip
OPENCV 常用XML 内涵17个常用XML,包括人脸检测,微笑检测,人眼检测,用于学习模型训练和使用
python whl离线安装包 pip安装失败可以尝试使用whl离线安装包安装 第一步 下载whl文件,注意需要与python版本配套 python版本号、32位64位、arm或amd64均有区别 第二步 使用pip install XXXXX.whl 命令安装,如果whl路径不在cmd窗口当前目录下,需要带上路径 WHL文件是以Wheel格式保存的Python安装包, Wheel是Python发行版的标准内置包格式。 在本质上是一个压缩包,WHL文件中包含了Python安装的py文件和元数据,以及经过编译的pyd文件, 这样就使得它可以在不具备编译环境的条件下,安装适合自己python版本的库文件。 如果要查看WHL文件的内容,可以把.whl后缀名改成.zip,使用解压软件(如WinRAR、WinZIP)解压打开即可查看。 为什么会用到whl文件来安装python库文件呢? 在python的使用过程中,我们免不了要经常通过pip来安装自己所需要的包, 大部分的包基本都能正常安装,但是总会遇到有那么一些包因为各种各样的问题导致安装不了的。 这时我们就可以通过尝试去Python安装包大全中(whl包下载)下载whl包来安装解决问题。
python whl离线安装包 pip安装失败可以尝试使用whl离线安装包安装 第一步 下载whl文件,注意需要与python版本配套 python版本号、32位64位、arm或amd64均有区别 第二步 使用pip install XXXXX.whl 命令安装,如果whl路径不在cmd窗口当前目录下,需要带上路径 WHL文件是以Wheel格式保存的Python安装包, Wheel是Python发行版的标准内置包格式。 在本质上是一个压缩包,WHL文件中包含了Python安装的py文件和元数据,以及经过编译的pyd文件, 这样就使得它可以在不具备编译环境的条件下,安装适合自己python版本的库文件。 如果要查看WHL文件的内容,可以把.whl后缀名改成.zip,使用解压软件(如WinRAR、WinZIP)解压打开即可查看。 为什么会用到whl文件来安装python库文件呢? 在python的使用过程中,我们免不了要经常通过pip来安装自己所需要的包, 大部分的包基本都能正常安装,但是总会遇到有那么一些包因为各种各样的问题导致安装不了的。 这时我们就可以通过尝试去Python安装包大全中(whl包下载)下载whl包来安装解决问题。
python whl离线安装包 pip安装失败可以尝试使用whl离线安装包安装 第一步 下载whl文件,注意需要与python版本配套 python版本号、32位64位、arm或amd64均有区别 第二步 使用pip install XXXXX.whl 命令安装,如果whl路径不在cmd窗口当前目录下,需要带上路径 WHL文件是以Wheel格式保存的Python安装包, Wheel是Python发行版的标准内置包格式。 在本质上是一个压缩包,WHL文件中包含了Python安装的py文件和元数据,以及经过编译的pyd文件, 这样就使得它可以在不具备编译环境的条件下,安装适合自己python版本的库文件。 如果要查看WHL文件的内容,可以把.whl后缀名改成.zip,使用解压软件(如WinRAR、WinZIP)解压打开即可查看。 为什么会用到whl文件来安装python库文件呢? 在python的使用过程中,我们免不了要经常通过pip来安装自己所需要的包, 大部分的包基本都能正常安装,但是总会遇到有那么一些包因为各种各样的问题导致安装不了的。 这时我们就可以通过尝试去Python安装包大全中(whl包下载)下载whl包来安装解决问题。
开发语言:Java 框架:SSM JDK版本:JDK1.8 服务器:tomcat8.5 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:eclipse/myeclipse/idea 浏览器:谷歌浏览器
yolo系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,包含数据集配置文件data.yaml,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值
中国各省GDP及农业主要指标数据集(1999-2019).zip
功能说明: 系统主要包括系统主页、个人中心、用户管理、图书信息管理、图书分类管理、图书购买管理、图书借阅管理、图书续借管理、图书归还管理、留言板管理、系统管理等功能模块。 环境说明: 开发语言:Java 框架:ssm,mybatis JDK版本:JDK1.8 数据库:mysql 5.7及以上 数据库工具:Navicat11及以上 开发软件:eclipse/idea Maven包:Maven3.3及以上 服务器:tomcat7及以上
2023-04-06-项目笔记-第三百二十阶段-课前小分享_小分享1.坚持提交gitee 小分享2.作业中提交代码 小分享3.写代码注意代码风格 4.3.1变量的使用 4.4变量的作用域与生命周期 4.4.1局部变量的作用域 4.4.2全局变量的作用域 4.4.2.1全局变量的作用域_1 4.4.2.318局变量的作用域_318- 2024-11-17
Saturn_PCB_Toolkit_V7.00_ 是一款功能强大的PCB参数计算工具,本人PCB设计15年一直使用的这款计算器,利用其给出的设计数据(如线距、线宽线厚),布出的PCB实际使用未曾出现过问题 以下是其主要功能特点: 1. **过孔特性计算**:能够计算过孔的寄生电容、寄生电感、过孔阻抗、过孔直流电阻、共振频率、阶跃响应、功耗等参数。 2. **导线载流能力计算**:可以计算不同线宽下的载流能力,根据环境温度和温升条件,提供不同条件下的载流值。 3. **串扰计算**:计算两相互耦合信号线间的串扰,这对于高速PCB设计尤为重要。 4. **波长计算**:提供波长的计算功能,这对于射频和高速数字PCB设计非常关键。 5. **导体阻抗计算**:计算导体的阻抗,这对于阻抗匹配和信号完整性至关重要。 6. **单位换算**:提供单位换算功能,方便不同单位制之间的转换。 7. **差分对计算**:针对差分信号的计算,这对于高速数据传输和降低噪声非常重要。
yolo系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,包含数据集配置文件data.yaml,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值
## 一、数据介绍 数据名称:中国各、省、市、县、乡镇基尼系数数据 数据年份:1992-2023年 样本数量:92064条 数据格式:面板数据 ## 二、指标说明 共计10个指标:年份、省、省代码、市、市代码、县、县代码、乡镇、乡镇代码、夜间灯光基尼系数 ## 三、数据文件 中国各乡镇基尼系数(基于夜间灯光数据)2000-2023年.dta; 中国各区县基尼系数(基于夜间灯光数据)2000-2023年.dta; 中国各城市基尼系数(基于夜间灯光数据)2000-2023年.dta; 中国各省份基尼系数(基于夜间灯光数据)2000-2023年.dta
环境说明: 开发语言:Java 框架:ssm,mybatis JDK版本:JDK1.8 数据库:mysql 5.7及以上 数据库工具:Navicat11及以上 开发软件:eclipse/idea Maven包:Maven3.3及以上 服务器:tomcat7及以上
功能说明: 系统主要包括管理员,商家和用户三大模块 (a) 管理员;管理员进入系统主要功能包括个人中心,用户管理,商家管理,用品分类管理,用品信息管理,系统管理,订单管理等功能并进行操作。 (b) 商家;商家进入系统主要功能包括个人中心,用品信息管理,订单管理等功能并进行操作。 (c) 用户;用户进入系统主要功能包括个人中心,我的收藏管理等功能并进行操作。 环境说明: 开发语言:Java 框架:ssm,mybatis JDK版本:JDK1.8 数据库:mysql 5.7及以上 数据库工具:Navicat11及以上 开发软件:eclipse/idea Maven包:Maven3.3及以上 服务器:tomcat7及以上
最新行政区划、乡镇级矢量地图及2022年道路、水系、建筑轮廓数据(shp格式)-已更至最新.zip