`
wjlgryx
  • 浏览: 307221 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

o3d 怎么用顶点数组创建一个3D 模型

阅读更多

这一章介绍怎么用顶点数组创建一个3D 模型,如何创建一个shape 对象,缓冲(buffers) ,域(fields) 等等。

    由于要定义这个3D 模型的每个顶点,然后存入顶点数组,所以这章不会画出一个比较复杂的3D 模型,我们只是画一个立方体来说明如何创建一个3D 模型,如果对于一个复杂的3D 模型还是一个个顶点画的话,只能说太牛逼了,那时候就要用到3dmax ,maya 等软件来建模了,经过传换成一定格式的文件后再在程序中导入。

    上一章中直接用了一个createSphere ()函数创建了一个球体,这个函数是o3d 自带的,其实也有自带的创建立方体的函数,当然这章是不会用的,否则就没东西可以讲了。我们要做的就是自己写一个。

    function createCube(material, size){
  
    这里的两个参数,前一个是这个立方体要用到的材质,材质这块下一章会讲到。Size 顾名思义就是这个立方体的大小了。

    在o3d 中首先要做的便是创建一个shape 对象,一个图元(primitive )对象和一个streamBank 对象,

var cubeShape = g_pack . createObject ( 'Shape' );
    var cubePrimitive = g_pack . createObject ( 'Primitive' );
    var streamBank = g_pack . createObject ( 'StreamBank' );

cubePrimitive . material = material ;      // 定义这个形状的材质
    cubePrimitive . owner = cubeShape ;            // 定义shape 和图元的关系
    cubePrimitive . streamBank = streamBank ; •• // 定义这个shape 的streamBank

    其中shape 是许多图元的集合,而一个图元则是一个点或者多个点通过一定规律连接在一起组成的图形 ( 不像纸上画画最重要的是把每条线画出来,在O3d 或者说是传统的openGL 和D3D 中画一个模型是把这个模型的每个顶点的坐标定义好,然后系统便会自己把这些点连接起来) 其中点与点之间的连接可以有多种规律,比如说比较常用的每三个点通过连线组成三角形,多个点连成多个连续的三角形,每四个点组成的四边形,多个点连成的多个连续的四边形等等。
  
             下面就要定义一下图元中各个点之间连接的规律了
cubePrimitive . primitiveType = g_o3d . Primitive . TRIANGLELIST ; // 三角形绘制
cubePrimitive . numberPrimitives = 12 ;         // 这个图元中有12 个三角形
    cubePrimitive . numberVertices = 8 ;        // 有8 个顶点

    创建一个绘制元素
cubePrimitive . createDrawElement ( g_pack , null );

  接下来填充这8 个顶点的数据,在js 中这些数据都是存放在一个一维数组中的:
var positionArray = [
    - size/2 , - size/2 ,   size/2 ,   // 顶点0
      size/2 , - size/2 ,   size/2 ,   // 顶点1
    - size/2 ,   size/2 ,   size/2 ,   // 顶点2
      size/2 ,   size/2 ,   size/2 ,   // 顶点3
    - size/2 ,   size/2 , - size/2 ,   // 顶点4
      size/2 ,   size/2 , - size/2 ,   // 顶点5
    - size/2 , - size/2 , - size/2 ,   // 顶点6
      size/2 , - size/2 , - size/2   // 顶点7
  ];

这么大串size/2 (还记得size 是这个函数传进来的参数吧)都是每个顶点的坐标。

现在就有个问题,就是size 要多大才能够在屏幕当中显示一个身材合适的立方体呢,一开始可能会假象这个size 取成10 吧,10 这个数字不大不小蛮好的,可是你会发现屏幕中除了一片灰色就什么都没有了,因为10 对于现在这个情况来说太大了,连摄像机都在那个立方体里面了(当然你不会看到立方体里面那个面,因为一般情况下o3d 是只绘制一个面的)。

在o3d 中到底用的是什么单位导致10 这个在现实世界中这么小的一个数字能够变得这么大。咳咳,其实貌似在这样的3D 世界中是没有单位之说的( 至少我还不知道) ,因为这个物体的大小是相对于镜头的位置的,如果镜头离物体近了,size 就算很小那物体还是庞然大物,因此想要调整物体大小,可以调整size 的大小,也可以把镜头拉远(还记得第一章中设置照相机的位置吧),也可以把物体放远点,这些都是跟真实世界中差不多的。

O3d 中这些顶点的坐标数据都会先放入一个缓冲(buffers) 中,缓冲是一个对象(object) ,用来暂时存储顶点的各种数据的,像位置坐标,色彩,贴图坐标。下面就先创建缓冲对象:
    // 创建顶点缓冲来存放顶点数据
    var positionsBuffer = g_pack.createObject('VertexBuffer');
   
    然后创建域(field) ,域是一小块buffer 。
var positionsField = positionsBuffer . createField ( 'FloatField' , 3 );
positionsBuffer . set ( positionArray );     // 设置该缓冲所用的数组
   
    在一开始有说到要创建一个streamBank 对象,但是没解释为什么,这个真是说来话长啊,因为o3d 使用的是可编程渲染管线(即shader ),而非固定函数渲染管线(fixed function pipeline) ,shader (又可以叫做着色器)可以分为vertex shader (顶点着色器)和pixel shader (像素着色器)。有了pixel shader 之后,你能决定里面的每个像素该怎么填充。因为GPU 浮点运算能力比CPU 比显卡强得多,所以把这些计算交给显卡做再合适不过了。
   
    而这次绘制正方形,每个顶点也是通过vertex shader 来渲染的,是不是有点大材小用了,其实我也这么觉得,不过我们还好暂时还不用去写这个shader ,可以让Js 的接口来做这件事,这就是这个streamBank 做的了,streamBank 把域(field) 中的数据作为vertex shader 的输入。可以是js 中的顶点数据和底层shader 交互的通道。下面这段代码就是把域(field )和vertex shader 联系起来。
streamBank . setVertexStream (
    g_o3d . Stream . POSITION , // semantic: This stream stores vertex positions
    0 ,                     // semantic index: First (and only) position stream
    positionsField ,         // field: the field this stream uses.
    0 );                     // start_index: How many elements to skip in the field.
( 注释的英文我就不翻译了- -)
  
          最后你可以创建一个index buffer ,这个是用来重排上面vertex buffer 里各个点的得排列顺序的。你可以不加这个,不过显示出来的是不是一个立方体就不一定了- - 。
var indicesArray = [
      0 , 1 , 2 ,   // face 1
      2 , 1 , 3 ,
      2 , 3 , 4 ,   // face 2
      4 , 3 , 5 ,
      4 , 5 , 6 ,   // face 3
      6 , 5 , 7 ,
      6 , 7 , 0 ,   // face 4
      0 , 7 , 1 ,
      1 , 7 , 3 ,   // face 5
      3 , 7 , 5 ,
      6 , 0 , 4 ,   // face 6
      4 , 0 , 2
    ];
var indexBuffer = g_pack . createObject ( 'IndexBuffer' );
indexBuffer . set ( indicesArray );
cubePrimitive . indexBuffer = indexBuffer ;
Index buffer 和vertex buffer 的创建方式和存储方式是差不多的. 是两个差不多的Object ,都是用来存储数据的。
  
          函数最后就是把这个已经创建好的shape 返回了。
return cubeShape;
}
       
          函数写好了,得试下先,把前一章用来创建一个球体的语句替换掉,替换成
     var shape = createSphere(material,0.5);
  
         然后就会发现原来那个很丑的圆就变成一个很丑的正方形了。为了体现出这是一个立方体,而不是一个正方形,我们还要做透视投影变换,这个得用shading language 了,
<textarea id="effect">
  // World View Projection matrix that will transform the input vertices
  // to screen space.
  float4x4 worldViewProjection : WorldViewProjection;

  // input parameters for our vertex shader
  struct VertexShaderInput {
    float4 position : POSITION;
  };

  // input parameters for our pixel shader
  struct PixelShaderInput {
    float4 position : POSITION;
  };

  /**
   * The vertex shader simply transforms the input vertices to screen space.
   */
  PixelShaderInput vertexShaderFunction(VertexShaderInput input) {
    PixelShaderInput output;

    // Multiply the vertex positions by the worldViewProjection matrix to
    // transform them to screen space.
    output.position = mul(input.position, worldViewProjection);
    return output;
  }

  /**
   * This pixel shader just returns the color red.
   */
  float4 pixelShaderFunction(PixelShaderInput input): COLOR {
    return float4(1, 0, 0, 1);  // Red.
  }

  // Here we tell our effect file *which* functions are
  // our vertex and pixel shaders.

  // #o3d VertexShaderEntryPoint vertexShaderFunction
  // #o3d PixelShaderEntryPoint pixelShaderFunction
  // #o3d MatrixLoadOrder RowMajor
</textarea>

    这段就是传说中的shading language 了,它放在一个textarea 中方便js 程序获取,可以看到里面有两个函数,vertexShaderFunction 和pixelShaderFunction ,分别为vertex shader 和pixelShader 的入口,这个怎么工作,通俗点讲vertexShaderFunction 就是把每个顶点的数据传进去后经过一定的计算后再返回进行绘制。pixelShaderFunction 也是这样,在这里vertexShaderFunction 就一句代码:output.position = mul(input.position, worldViewProjection); 就是进行了一次投影变换. 而pixelShaderFunction 就只是把这个立方体的颜色变成了红色。最后三句不要看成是注释啊,前两句申明了vertex shader 的入口函数是vertexShaderFunction , pixelShader 的入口函数是pixelShaderFunction 。
  
          接下来就要用这段代码作为这个立方体的shader string, 还记不记得在前面创建过一个effect ,在后面加上下面两句代码
    var shaderString = document.getElementById('effect').value;
  effect.loadFromFXString(shaderString);               // 载入shading language
  
            然后就会发现这个图形已经有立方体的样子了(我们已经能够脑淫出这是个立方体了- - )。
  
            换个视角看会更像,还记得上一章设置摄像机参数吧。
viewInfo.drawContext.view = g_math.matrix4.lookAt([2, 2, 2],  // 将摄像机放置在(2 ,2 ,2 )位置上
                                                      [0, 0, 0],  // 目标仍是立方体
                                                      [0, 1, 0]); // up
  
          关于shading language 和material 这里只是出于需要稍微涉及下,以后会详细地介绍,就像cg 的强大一样,o3d shading language 对于o3d 的渲软能力起到了至关重要的作用。

分享到:
评论

相关推荐

    O3D 物体 编辑器

    综上所述,"O3D 物体编辑器"是一个基于O3D库的3D模型编辑工具,它在Firefox浏览器中实现了3D物体的拖动和旋转操作,为Web上的3D创作和交互提供了强大支持。开发者和设计师可以利用这个工具,轻松地在Web页面上创建和...

    #python+open3d 3D模型的读取与应用.pdf

    使用 Open3D 可视化 3D 模型,可以使用 `o3d.visualization.draw_geometries` 函数,例如: ```python o3d.visualization.draw_geometries([pcd], width=800, height=600) ``` 计算 vertex normals 使用 `compute_...

    O3D学习笔记[一]素材准备*.3ds转成*.o3dtgz

    O3D使用O3DTGZ作为其内部资源包格式,它是一个经过压缩的文件,包含了模型、纹理、脚本和其他资源,可以作为一个整体在程序中加载,减少了内存占用和加载时间。 转换3DS到O3DTGZ的过程通常涉及以下步骤: 1. **...

    谷歌O3D的javascript源码

    场景图是一种层次结构,其中每个节点代表一个3D对象或一组对象。通过操作场景图,开发者可以控制3D空间中的对象布局和交互。 6. **纹理和光照**:为了使3D模型看起来更真实,O3D支持纹理贴图和光照模型。理解如何...

    3D-o3d.zip

    在3D-o3d.zip这个压缩包中,我们看到的是Objective-3D视频游戏引擎的相关资料,这是一个专门用于3D游戏开发的工具。 Objective-3D游戏引擎,以其强大的功能和灵活性,为开发者提供了构建逼真3D游戏环境的可能性。它...

    O3D文档说明(主要关键字的说明及翻译)

    5. **Pack 包**:在O3D中,包是一个管理数据的对象,它存储对其他数据的引用,如纹理、状态、缓冲区、形状和变换。包的主要作用是控制这些数据的生命周期,例如,当一个包被销毁时,与其关联的所有资源也会被释放。 ...

    O3D 实例 研究中

    O3D 是一个开源的 JavaScript 库,它允许开发者在 Web 浏览器中创建高性能的三维图形应用。这个实例可能是为了展示 O3D 的基本用法和功能,帮助用户快速入门。下面我们将深入探讨 O3D 的核心概念、主要特性以及 `...

    google o3d 编程例子1

    google开发的web3d编程APT o3d.提供的各种3d效果例子,因文件太大,分三个包传上

    google o3d例子3

    o3d是Google开发的基于web的3d编程API,因文件太大分三次上传

    o3dv_0.8.3.zip

    Three.js 是一个广泛使用的开源库,专为在WebGL上构建3D应用而设计。它简化了WebGL编程,提供了许多便利的类和功能,如几何体、材质、光源、相机等,以及动画和加载3D模型的支持。 2. **o3dv.min.js**:这是 ...

    readchair_点云_modelnet40_modelnet40可视化_读取点云_

    ModelNet40是一个广泛使用的三维形状数据集,包含了40个常见物体类别的3D模型,如椅子、桌子、瓶子等。每个类别都有多个不同的实例,总计超过12,311个模型,格式通常为Wavefront OBJ或 OFF。这些模型都是从不同角度...

    o3d:从 code.google.compo3d 导入

    **O3D库详解** O3D是一款基于WebGL的开源3D图形库,它允许开发者在网页上创建复杂的3D场景和应用。...对于那些想要在网页上创建引人入胜的3D体验的开发者来说,掌握O3D库将是一个值得投资的技能。

    o3d lib1 graph javascript ajax

    o3d lib1 graph javascript ajax

    WebGL是一种3D绘图标准,可被用于创建具有复杂3D结构的网站页面

    WebGL本质上是OpenGL ES(一种适用于嵌入式系统的3D图形API)的一个JavaScript绑定。这意味着开发者可以直接在网页上利用硬件加速进行3D渲染,从而实现更加流畅、逼真的视觉效果。由于WebGL是内置于现代浏览器中的,...

    o3de实现Texture Distortion

    3. **创建Material**:创建一个Material资源,将你的Shader与纹理绑定,并将其应用到你的3D模型上。 4. **设置动画**:在O3DE中,你可以通过更新Shader的输入参数来驱动纹理扭曲的效果,如时间变量。这可能需要在...

    o3d-webgl-pool:来自废弃 o3d 引擎开发者的 3D 台球游戏演示

    【标题】"o3d-webgl-pool" 是一个基于废弃的 o3d 引擎开发者构建的3D台球游戏演示项目。这个项目利用了WebGL技术来呈现逼真的3D图形,让玩家能够在浏览器中体验台球游戏的乐趣。 【JavaScript】作为主要的编程语言...

    google o3d 编程例子2

    o3d是Google开发的基于web的3d编程API,因文件太大分三次上传

    python三角网格处理程序

    03_trimesh_o3d.py:三棱柱模型可视化,并将open3d的o3d.geometry.TriangleMesh对象转换为trimesh.Trimesh对象。 04_orientation_o3d.py:改变三棱柱表面三角网格的顶点顺序,观察可视化结果。 05_slz.obj:三棱柱...

Global site tag (gtag.js) - Google Analytics