举荐:将 NSDT 场景编辑器 退出你的 3D 开发工具链介绍
网格对象是由三角形和顶点组成的形态
在 CHAI3D 中,多边形网格是定义多面体对象形态的顶点和三角形的汇合。顶点是一个地位以及其余信息,例如色彩、法线矢量和纹理坐标。由直线连贯的两个顶点成为一条边。三个顶点通过三条边相互连接,定义一个三角形,这是欧几里得空间中最简略的多边形。网格对象能够平移、旋转或调整大小,并具备调配给它们的材质和纹理属性。以下代码演示如何创立由 4 个顶点和 2 个三角形组成的带纹理的正方形。
using namespace chai3d;
// create a mesh
object = new cMesh();
// create a texture map
object->m_texture = cTexture2d::create();
// load a texture file
object->m_texture->loadFromFile("myTexture.jpg");
// enable texture mapping
object1->setUseTexture(true);
// set material to white
object1->m_material->setWhite();
// create vertices
int vertex0 = object0->newVertex();
int vertex1 = object0->newVertex();
int vertex2 = object0->newVertex();
int vertex3 = object0->newVertex();
// set position, surface normal, and texture coordinate for vertex 0
object0->m_vertices->setLocalPos(vertex0,-0.1,-0.1, 0.0);
object0->m_vertices->setNormal(vertex0, 0.0, 0.0, 1.0);
object0->m_vertices->setTexCoord(vertex0, 0.0, 0.0);
// set position, surface normal, and texture coordinate for vertex 1
object0->m_vertices->setLocalPos(vertex1, 0.1,-0.1, 0.0);
object0->m_vertices->setNormal(vertex1, 0.0, 0.0, 1.0);
object0->m_vertices->setTexCoord(vertex1, 1.0, 0.0);
// set position, surface normal, and texture coordinate for vertex 2
object0->m_vertices->setLocalPos(vertex2, 0.1, 0.1, 0.0);
object0->m_vertices->setNormal(vertex2, 0.0, 0.0, 1.0);
object0->m_vertices->setTexCoord(vertex2, 1.0, 1.0);
// set position, surface normal, and texture coordinate for vertex 3
object0->m_vertices->setLocalPos(vertex3,-0.1, 0.1, 0.0);
object0->m_vertices->setNormal(vertex3, 0.0, 0.0, 1.0);
object0->m_vertices->setTexCoord(vertex3, 0.0, 1.0);
// create two triangles by assigning their vertex IDs
object0->m_triangles->newTriangle(vertex0, vertex1, vertex2);
object0->m_triangles->newTriangle(vertex0, vertex2, vertex3);
渲染选项
材质
资料属性定义外表如何反射光线。他们通过定义色彩值来实现这一点,其形式与灯光大致相同。材质具备漫射(直射)光、环境(散射)光和镜面反射(反射)光的色彩值,但这些值定义了光的重量如何从材质外表反射。更多信息能够在无关资料的局部找到。材质属性能够启用或禁用,并且须要在世界中至多应用一个光源能力使对象可见。
using namespace chai3d;
// create a mesh
cMesh* mesh = new cMesh();
// add mesh to world
world->addChild(mesh);
// build mesh using a cylinder primitive
cCreatePipe(mesh,
0.15,
0.05,
0.06,
32,
1,
cVector3d(-0.05,-0.20, 0.0),
cMatrix3d(cDegToRad(0), cDegToRad(0), cDegToRad(170), C_EULER_ORDER_XYZ)
);
// enable material property
cylinder->setUseMaterial(true);
// (1) set material by simply assigning a color name
mesh->m_material->setBlueCornflower();
// (2) or set material by assigning a color values for each component
mesh->m_material->m_ambient.set(0.2, 0.1, 0.1);
mesh->m_material->m_diffuse.set(0.6, 0.3, 0.3);
mesh->m_material->m_specular.set(1.0, 1.0, 1.0);
mesh->m_material->setShininess(10);
顶点色彩
能够为网格的每个顶点指定不同的色彩值。如果三角形的三个顶点共享不同的色彩,则三角形上任何点的色彩都是通过三种顶点色彩的插值来计算的。
三角形和顶点色彩
如果启用了资料属性,顶点色彩将与资料色彩组合在一起。通常将材质设置为红色并为不同的顶点调配色彩以产生所需的光晕。如果禁用材质属性,则疏忽所有光源,并应用纯顶点色彩来渲染对象。
using namespace chai3d;
// create a mesh
cMesh* mesh = new cMesh();
// add mesh to world
world->addChild(mesh);
// create three new vertices
int vertex0 = mesh->newVertex();
int vertex1 = mesh->newVertex();
int vertex2 = mesh->newVertex();
// set position of each vertex
mesh->m_vertices->setLocalPos(vertex0, 0.0, 0.0, 0.0);
mesh->m_vertices->setLocalPos(vertex1, 0.0, 1.0, 0.0);
mesh->m_vertices->setLocalPos(vertex2, 1.0, 1.0, 0.0);
// assign color value to each vertex
cColorf color(1.0, 0.2, 0.2);
mesh->m_vertices->setColor(vertex0, color);
mesh->m_vertices->setColor(vertex1, color);
mesh->m_vertices->setColor(vertex2, color);
// create new triangle from vertices
mesh->newTriangle(vertex0, vertex1, vertex2);
// enable vertex colors
mesh->setUseVertexColors(true);
// compute surface normals
mesh->computeAllNormals();
纹理映射
纹理映射
纹理贴图将利用(映射)到形态或多边形的外表。此过程相似于将图案纸利用于纯白框。多边形中的每个顶点都通过显式调配或过程定义调配一个纹理坐标(在 2d 状况下也称为 UV 坐标)。而后,在多边形的外表插值图像采样地位,以生成视觉后果,该后果仿佛比应用无限数量的多边形能够实现的更丰盛。
要理解如何在 CHAI3D 中创立纹理,请参阅本页顶部的第一个示例。
线框图
三角形能够在实心或线模式下渲染。
(左)固体模式。(右)线框模式。
using namespace chai3d;
// enable wireframe rendering mode
mesh->setWireMode(true);
// enable solid rendering mode
mesh->setWireMode(false);
边缘
要同时渲染边和三角形,CHAI3D 提供了显示三角形的选项,并笼罩依据相邻三角形之间所需的最小角度抉择的边子集。
(左)实心和边缘。(右)仅边缘。
using namespace chai3d;
// compute all edges for which adjacent triangles have more than 40 degrees angle
mesh->computeAllEdges(40);
// set line width of edges and color
cColorf color;
color.setBlack();
mesh->setEdgeProperties(1, color);
// (1) enable surfaces and edges
mesh->setShowTriangles(true);
mesh->setShowEdges(true);
// (2) enable edges only
mesh->setShowTriangles(false);
mesh->setShowEdges(true);
面部剔除
反面剔除确定网格对象的三角形是否可见。这是图形管道中的一个步骤,用于测试三角形中的顶点在投影到屏幕上时是否按顺时针程序显示。
using namespace chai3d;
// enable culling
object->setUseCulling(true);
如果启用了面部剔除,但投影在屏幕上的多边形具备逆时针缠绕,则它已旋转为背离相机,不会被绘制。
该过程通过缩小程序绘制的多边形数量,使渲染对象更快、更高效。例如,在城市街道场景中,通常不须要在建筑物背对摄影机的侧面绘制多边形;它们被面向相机的侧面齐全遮挡。
通常,如果反面剔除仅蕴含关闭和不通明的几何体,则能够假设在渲染场景中不会产生可见的伪影。在蕴含通明多边形的场景中,通过 Alpha 合成过程,后向多边形可能会变得可见。
透明度、半透明性和混合
渲染相机的半透明镜头
通明的物理材质显示其前面的对象未被遮挡,并且不会从其外表反射光线。通明玻璃是一种近乎通明的资料。尽管玻璃容许大多数光线不受遮挡地通过,但实际上它也反射了一些光。齐全通明的资料是齐全看不见的。
半透明物理材质显示其前面的对象,但这些对象被半透明材质遮挡。此外,半透明材质会反射照射到它的一些光线,使资料可见。半透明资料的物理示例包含通明布料、薄塑料和烟熏玻璃。通明和半透明通常是同义词。既不通明也不半透明的资料是不通明的。
混合是 OpenGL 的机制,用于将帧缓冲中已有的色彩与传入基元的色彩组合在一起。而后,这种组合的后果将存储回帧缓冲器中。混合常常用于模仿半透明的物理材质。一个例子是渲染汽车的烟熏玻璃挡风玻璃。驾驶员和内饰依然可见,但它们被烟熏玻璃的深色所覆盖。
外表法线
渲染网格的顶点法线
在 CHAI3D 中启用照明时,法线矢量用于确定在指定顶点或外表上接管的光量。如果尚未定义曲面法线,则能够通过取该三角形两条边的向量叉积来计算每个三角形的法线。出于调试目标,能够应用以下调用显示曲面法线:
using namespace chai3d;
// compute all surface normals
mesh->computeAllNormals();
// set normal properties for display
cColorf color;
color.setOrangeTomato();
mesh->setNormalsProperties(0.01, color);
// display surface normals
mesh->setShowNormals(true);
多网格对象
介绍
因为网格对象每个对象仅蕴含一个材质和纹理属性,因而创立应用材质和纹理汇合的网格须要应用称为 cMultiMesh 的不同类,该类将网格列表连贯在一起。通过在独自的网格对象中依据三角形的材质和纹理属性来组织三角形,能够无效地构建和渲染具备丰盛属性集的简单对象。
using namespace chai3d;
// create a multi mesh object
cMultiMesh* multiMesh = new cMultiMesh();
// add multi mesh object to world
world->addChild(multiMesh);
// create a first mesh
cMesh* mesh1 = multiMesh->newMesh();
// create a second mesh
cMesh* mesh2 = multiMesh->newMesh();
文件反对
CHAI3D 反对 3DS、OBJ 和 SLT 文件格式来导入或导出模型。如果您心愿导入不同格局的文件,能够应用 Blender 或 Visual Enterprise Author(以前称为 Deep Exploration)等应用程序来编辑文件并将其转换为所需的格局。
using namespace chai3d;
// load 3DS model file
multiMesh->loadFromFile("myModel.3ds");
// load OBJ model file
multiMesh->loadFromFile("myModel.obj");
// load STL model file
multiMesh->loadFromFile("myModel.stl");
// save model to 3DS file
multiMesh->saveToFile("myModel.3ds");
// save model to OBJ file
multiMesh->saveToFile("myModel.obj");
// save model to STL file
multiMesh->saveToFile("myModel.stl");
碰撞检测
碰撞检测器用于计算射线与组成网格(或多网格)的任何三角形之间的交点。为了使此操作疾速进行,CHAI3D 应用边界体积层次结构或 BVH。BVH 是一组几何对象上的树结构。所有几何对象都包裹在形成树的叶节点的边界体积中。而后将这些节点分组为小汇合,并蕴含在较大的边界体积中。反过来,这些也以递归形式分组并关闭在其余较大的边界体积中,最终导致树结构在树的顶部具备单个边界体积。边界体积层次结构用于无效地反对对几何对象集的多项操作,例如在触觉交互计算、光线追踪或鼠标抉择的碰撞检测中。
轴对齐边界体积层次结构
在 CHAI3D 中,必须在定义三角形后生成边界体积层次结构。如果批改了三角形或挪动了顶点,则必须再次计算层次结构。更新碰撞树时,正确蕴含世界上应用的最大触觉点的半径十分重要。此信息用于创立足够大的包络,以检测与半径小于或等于定义阈值的接触点的任何交互。
using namespace chai3d;
// create axis aligned bounding volume hierarchy
multiMesh->createAABBCollisionDetector(toolRadius);
触觉成果
网格对象的触觉渲染
为了触觉渲染网格对象,CHAI3D 应用由 Ruspini 和 Khatib 开发的虚构“手指代理”算法,相似于 Zilles 和 Salisbury 提出的“上帝对象”。虚构代理是代替虚拟环境中物理手指或探测器的代表性对象。
Ruspini 和 Khatib 的手指代理算法
上图阐明了虚构代理的静止,因为触觉设施的地位产生了变动。代理的静止试图始终朝着指标挪动。当畅通无阻时,代理间接向指标挪动。当代理遇到障碍物时,无奈间接挪动,但代理仍能够通过沿一个或多个束缚曲面挪动来缩短到指标的间隔。抉择静止以部分最小化到指标的间隔。当代理无奈缩小其与指标的间隔时,它将进行在本地最小配置处。力是通过对触觉设施和代理地位之间的虚构弹簧进行建模来计算的。弹簧的刚度在资料属性中定义。
using namespace chai3d;
// create collision detector
mesh->createAABBCollisionDetector(toolRadius);
// set haptic properties
mesh->m_material->setStiffness(1000);
mesh->m_material->setStaticFriction(0.3);
mesh->m_material->setDynamicFriction(0.4);
还能够通过资料属性等级激活和调整其余触觉成果。触觉成果应用势场算法,任何通用形态对象也反对这些算法。请留神,网格对象目前不反对磁性成果。
using namespace chai3d;
// create a haptic stick-slip effect
mesh->createEffectStickSlip();
// set haptic properties
mesh->m_material->setStickSlipForceMax(5.0);
mesh->m_material->setStickSlipStiffness(1000);
3D 建模学习工作室翻译整顿,转载请表明出处!