<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                譯者前言: 本文譯自[MSDN](http://blogs.msdn.com/b/davrous/archive/2013/06/13/tutorial-series-learning-how-to-write-a-3d-soft-engine-from-scratch-in-c-typescript-or-javascript.aspx),原作者為[David Rousset](https://social.msdn.microsoft.com/profile/david%20rousset/),文章中如果有我的額外說明,我會加上【譯者注:】。 正文開始: 現在我們已經通過前面的教程[編寫相機、網格和設備對象的核心邏輯](http://blog.csdn.net/teajs/article/details/49989681)建立了3D引擎的核心,我們可以對渲染工作做一些增強了。下一步我們再連接點來繪制一些線條來組成一個線框渲染效果。 本章教程是以下系列的一部分: [1 – 編寫相機、網格和設備對象的核心邏輯](http://blog.csdn.net/teajs/article/details/49989681) 2 – 繪制線段和三角形來獲得線框渲染效果(本文) [3 – 加載通過Blender擴展導出JSON格式的網格](http://blog.csdn.net/teajs/article/details/50001659) [4 –填充光柵化的三角形并使用深度緩沖](http://blog.csdn.net/teajs/article/details/50010073) [4b – 額外章節:使用技巧和并行處理來提高性能](http://blog.csdn.net/teajs/article/details/50054509) [5 – 使用平面著色和高氏著色處理光 ?](http://blogs.msdn.com/b/davrous/archive/2013/07/03/tutorial-part-5-learning-how-to-write-a-3d-software-engine-in-c-ts-or-js-flat-amp-gouraud-shading.aspx) [6 – 應用紋理、背面剔除以及一些WebGL相關](http://blogs.msdn.com/b/davrous/archive/2013/07/18/tutorial-part-6-learning-how-to-write-a-3d-software-engine-in-c-ts-or-js-texture-mapping-back-face-culling-amp-webgl.aspx) 在本章教程中,你將學習如何繪制線條、什么是面(Face)以及用Bresenham算法得到一些三角形。 可喜的是,最后你就能知道如何寫出非常酷的東西了。 [點我運行](http://david.blob.core.windows.net/softengine3d/part2sample3/index.html) 大贊!我們的3D旋轉立方體真正展示在了我們的屏幕上! 首先使用基本算法畫出兩個點之間的線 讓我們來先寫一個簡單的算法來繪制2個頂點之間的線,我們將用以下邏輯: - 如果2點之間的距離小于2個像素,什么也不做 - 否則,我們計算兩點之間的中心點 (point0坐標 + (point1坐標 - point0坐標) / 2) - 我們在屏幕上將這個點繪制出來 - 我們使用遞歸的方式在point0&中心點之間以及中心點與point1之間繪制點 下面是示例代碼: 【譯者注:C#代碼】 ~~~ public void DrawLine(Vector2 point0, Vector2 point1) { var dist = (point1 - point0).Length(); // 如果兩點間的距離小于2,什么都不做 if (dist < 2) return; // 查找兩點間的中心點 Vector2 middlePoint = point0 + (point1 - point0)/2; // 繪制這個點到屏幕上 DrawPoint(middlePoint); // 我們使用遞歸的方式在point0&中心點之間以及中心點與point1之間繪制點 DrawLine(point0, middlePoint); DrawLine(middlePoint, point1); } ~~~ 【譯者注:TypeScript代碼】 ~~~ public drawLine(point0: BABYLON.Vector2, point1: BABYLON.Vector2): void { var dist = point1.subtract(point0).length(); // 如果兩點間的距離小于2,什么都不做 if(dist < 2) return; // 查找兩點間的中心點 var middlePoint = point0.add((point1.subtract(point0)).scale(0.5)); // 繪制這個點到屏幕上 this.drawPoint(middlePoint); // 我們使用遞歸的方式在point0&中心點之間以及中心點與point1之間繪制點 this.drawLine(point0, middlePoint); this.drawLine(middlePoint, point1); } ~~~ 【譯者注:JavaScript代碼】 ~~~ Device.prototype.drawLine = function (point0, point1) { var dist = point1.subtract(point0).length(); // 如果兩點間的距離小于2,什么都不做 if (dist < 2) { return; } // 查找兩點間的中心點 var middlePoint = point0.add((point1.subtract(point0)).scale(0.5)); // 繪制這個點到屏幕上 this.drawPoint(middlePoint); // 我們使用遞歸的方式在point0&中心點之間以及中心點與point1之間繪制點 this.drawLine(point0, middlePoint); this.drawLine(middlePoint, point1); }; ~~~ 你需要更新渲染循環處理函數來使用這個新的代碼片段: 【譯者注:C#代碼】 ~~~ for (var i = 0; i < mesh.Vertices.Length - 1; i++) { var point0 = Project(mesh.Vertices[i], transformMatrix); var point1 = Project(mesh.Vertices[i + 1], transformMatrix); DrawLine(point0, point1); } ~~~ 【譯者注:TypeScript代碼】 ~~~ for (var i = 0; i < cMesh.Vertices.length -1; i++){ var point0 = this.project(cMesh.Vertices[i], transformMatrix); var point1 = this.project(cMesh.Vertices[i + 1], transformMatrix); this.drawLine(point0, point1); } ~~~ 【譯者注:JavaScript代碼】 ~~~ for (var i = 0; i < cMesh.Vertices.length -1; i++){ var point0 = this.project(cMesh.Vertices[i], transformMatrix); var point1 = this.project(cMesh.Vertices[i + 1], transformMatrix); this.drawLine(point0, point1); } ~~~ 你現在應該得到這樣的效果: [點擊運行](http://david.blob.core.windows.net/softengine3d/part2sample1/index.html) 我知道這看起來很奇怪,但這是預期的行為。它能幫助你了解如何顯示3D網格。為了有一個更好的渲染效果,需要了解另一個概念。 **顯示三角形的面** 現在,我們知道如何繪制線條,我們需要一個更好的方式來使他們顯示網格。最簡單的2D幾何圖形是三角形。我們使用三維的思想使用這些三角形繪制成我們所需要的網格。那么我們需要將立方體的每一面都分成2個三角形。我們先“手工”做到這一點,以后可以使用3D建模軟件來幫我們自動做到這一步,這就是下一章節的內容了。 要繪制三角形,你需要有3個點(points)/頂點(vertices)。一個簡單的面只包含三個值,這些值是索引下標,通過這些下標可以取得頂點數組中的某一個頂點,然后進行渲染。 要理解這個概念,讓我們再看看Blender中的立方體盒子。 ![頂點與索引](https://box.kancloud.cn/2016-03-22_56f0e988e9db5.jpg "頂點與索引") 我們在此途中使用0,1,2,3來顯示4個頂點。要繪制立方體的上面,我們要畫2個三角形。 第一個,面片0,繪制路徑為 頂點0(-1, 1, 1) 到 頂點1(1,1,1) 到 頂點2(-1, -1, 1) 然后再到 頂點0(-1, 1, 1)。 第二個,面片1,繪制路徑為 頂點1(1, 1, 1) 到 頂點2(-1, -1, 1) 到 頂點3(1, -1 , 1) 然后再到 頂點1(1, 1, 1)。 等效的代碼是這樣的: ~~~ var mesh = new SoftEngine.Mesh("Square", 4, 2); meshes.Add(mesh); mesh.Vertices[0] = new Vector3(-1, 1, 1); mesh.Vertices[1] = new Vector3(1, 1, 1); mesh.Vertices[2] = new Vector3(-1, -1, 1); mesh.Vertices[3] = new Vector3(1, -1, 1); mesh.Faces[0] = new Face { A = 0, B = 1, C = 2 }; mesh.Faces[1] = new Face { A = 1, B = 2, C = 3 }; ~~~ 如果你想繪制完整的立方體,需要找到10個剩下的面片(Face),才能夠組成12個面片(Face)來繪制立方體的6個不同的面(Sides)。 現在讓我們來為面片(Face)對象做定義,這是一個非常簡單的對象,因為內部僅僅只是3個索引下標。也請一并更新新的網格代碼: 【譯者注:C#代碼】 ~~~ namespace SoftEngine { public struct Face { public int A; public int B; public int C; } public class Mesh { public string Name { get; set; } public Vector3[] Vertices { get; private set; } public Face[] Faces { get; set; } public Vector3 Position { get; set; } public Vector3 Rotation { get; set; } public Mesh(string name, int verticesCount, int facesCount) { Vertices = new Vector3[verticesCount]; Faces = new Face[facesCount]; Name = name; } } } ~~~ 【譯者注:TypeScript代碼】 ~~~ ///<reference path="babylon.math.ts"/> module SoftEngine { export interface Face { A: number; B: number; C: number; } export class Mesh { Position: BABYLON.Vector3; Rotation: BABYLON.Vector3; Vertices: BABYLON.Vector3[]; Faces: Face[]; constructor(public name: string, verticesCount: number, facesCount: number) { this.Vertices = new Array(verticesCount); this.Faces = new Array(facesCount); this.Rotation = new BABYLON.Vector3(0, 0, 0); this.Position = new BABYLON.Vector3(0, 0, 0); } } } ~~~ 【譯者注:JavaScript代碼】 ~~~ var SoftEngine; (function (SoftEngine) { var Mesh = (function () { function Mesh(name, verticesCount, facesCount) { this.name = name; this.Vertices = new Array(verticesCount); this.Faces = new Array(facesCount); this.Rotation = new BABYLONTS.Vector3(0, 0, 0); this.Position = new BABYLONTS.Vector3(0, 0, 0); } return Mesh; })(); SoftEngine.Mesh = Mesh; })(SoftEngine || (SoftEngine = {})); ~~~ 現在我們需要更新設備(Device)對象的 渲染(Render() 函數/方法)遍歷所有定義的面片,并繪制相關三角形。 【譯者注:C#代碼】 ~~~ foreach (var face in mesh.Faces) { var vertexA = mesh.Vertices[face.A]; var vertexB = mesh.Vertices[face.B]; var vertexC = mesh.Vertices[face.C]; var pixelA = Project(vertexA, transformMatrix); var pixelB = Project(vertexB, transformMatrix); var pixelC = Project(vertexC, transformMatrix); DrawLine(pixelA, pixelB); DrawLine(pixelB, pixelC); DrawLine(pixelC, pixelA); } ~~~ 【譯者注:TypeScript/JavaScript代碼】 ~~~ for (var indexFaces = 0; indexFaces < cMesh.Faces.length; indexFaces++) { var currentFace = cMesh.Faces[indexFaces]; var vertexA = cMesh.Vertices[currentFace.A]; var vertexB = cMesh.Vertices[currentFace.B]; var vertexC = cMesh.Vertices[currentFace.C]; var pixelA = this.project(vertexA, transformMatrix); var pixelB = this.project(vertexB, transformMatrix); var pixelC = this.project(vertexC, transformMatrix); this.drawLine(pixelA, pixelB); this.drawLine(pixelB, pixelC); this.drawLine(pixelC, pixelA); } ~~~ 最后,我們需要聲明與我們的立方體的12個面片(Face)并進行關聯以保證最新代碼工作達到預期。 這里是新的聲明: 【譯者注:C#代碼】 ~~~ var mesh = new SoftEngine.Mesh("Cube", 8, 12); meshes.Add(mesh); mesh.Vertices[0] = new Vector3(-1, 1, 1); mesh.Vertices[1] = new Vector3(1, 1, 1); mesh.Vertices[2] = new Vector3(-1, -1, 1); mesh.Vertices[3] = new Vector3(1, -1, 1); mesh.Vertices[4] = new Vector3(-1, 1, -1); mesh.Vertices[5] = new Vector3(1, 1, -1); mesh.Vertices[6] = new Vector3(1, -1, -1); mesh.Vertices[7] = new Vector3(-1, -1, -1); mesh.Faces[0] = new Face { A = 0, B = 1, C = 2 }; mesh.Faces[1] = new Face { A = 1, B = 2, C = 3 }; mesh.Faces[2] = new Face { A = 1, B = 3, C = 6 }; mesh.Faces[3] = new Face { A = 1, B = 5, C = 6 }; mesh.Faces[4] = new Face { A = 0, B = 1, C = 4 }; mesh.Faces[5] = new Face { A = 1, B = 4, C = 5 }; mesh.Faces[6] = new Face { A = 2, B = 3, C = 7 }; mesh.Faces[7] = new Face { A = 3, B = 6, C = 7 }; mesh.Faces[8] = new Face { A = 0, B = 2, C = 7 }; mesh.Faces[9] = new Face { A = 0, B = 4, C = 7 }; mesh.Faces[10] = new Face { A = 4, B = 5, C = 6 }; mesh.Faces[11] = new Face { A = 4, B = 6, C = 7 }; ~~~ 【譯者注:TypeScript/JavaScript代碼】 ~~~ var mesh = new SoftEngine.Mesh("Cube", 8, 12); meshes.push(mesh); mesh.Vertices[0] = new BABYLON.Vector3(-1, 1, 1); mesh.Vertices[1] = new BABYLON.Vector3(1, 1, 1); mesh.Vertices[2] = new BABYLON.Vector3(-1, -1, 1); mesh.Vertices[3] = new BABYLON.Vector3(1, -1, 1); mesh.Vertices[4] = new BABYLON.Vector3(-1, 1, -1); mesh.Vertices[5] = new BABYLON.Vector3(1, 1, -1); mesh.Vertices[6] = new BABYLON.Vector3(1, -1, -1); mesh.Vertices[7] = new BABYLON.Vector3(-1, -1, -1); mesh.Faces[0] = { A:0, B:1, C:2 }; mesh.Faces[1] = { A:1, B:2, C:3 }; mesh.Faces[2] = { A:1, B:3, C:6 }; mesh.Faces[3] = { A:1, B:5, C:6 }; mesh.Faces[4] = { A:0, B:1, C:4 }; mesh.Faces[5] = { A:1, B:4, C:5 }; mesh.Faces[6] = { A:2, B:3, C:7 }; mesh.Faces[7] = { A:3, B:6, C:7 }; mesh.Faces[8] = { A:0, B:2, C:7 }; mesh.Faces[9] = { A:0, B:4, C:7 }; mesh.Faces[10] = { A:4, B:5, C:6 }; mesh.Faces[11] = { A:4, B:6, C:7 }; ~~~ 你現在應該得到一個旋轉的美麗立方體: [點擊運行](http://david.blob.core.windows.net/softengine3d/part2sample2/index.html) 恭喜! :) 使用Bresenham算法繪制增強的線條 [Bresenham算法](http://en.wikipedia.org/wiki/Bresenham's_line_algorithm)繪制線條不僅速度快,而且效果比我們的遞歸版本更好。這個算法非常棒,你可以在維基百科上找到它的詞條。 下面是該算法的3種語言實現: 【譯者注:C#代碼】 ~~~ public void DrawBline(Vector2 point0, Vector2 point1) { int x0 = (int)point0.X; int y0 = (int)point0.Y; int x1 = (int)point1.X; int y1 = (int)point1.Y; var dx = Math.Abs(x1 - x0); var dy = Math.Abs(y1 - y0); var sx = (x0 < x1) ? 1 : -1; var sy = (y0 < y1) ? 1 : -1; var err = dx - dy; while (true) { DrawPoint(new Vector2(x0, y0)); if ((x0 == x1) && (y0 == y1)) break; var e2 = 2 * err; if (e2 > -dy) { err -= dy; x0 += sx; } if (e2 < dx) { err += dx; y0 += sy; } } } ~~~ 【譯者注:TypeScript代碼】 ~~~ public drawBline(point0: BABYLON.Vector2, point1: BABYLON.Vector2): void { var x0 = point0.x >> 0; var y0 = point0.y >> 0; var x1 = point1.x >> 0; var y1 = point1.y >> 0; var dx = Math.abs(x1 - x0); var dy = Math.abs(y1 - y0); var sx = (x0 < x1) ? 1 : -1; var sy = (y0 < y1) ? 1 : -1; var err = dx - dy; while (true) { this.drawPoint(new BABYLON.Vector2(x0, y0)); if ((x0 == x1) && (y0 == y1)) break; var e2 = 2 * err; if (e2 > -dy) { err -= dy; x0 += sx; } if (e2 < dx) { err += dx; y0 += sy; } } } ~~~ 【譯者注:JavaScript代碼】 ~~~ Device.prototype.drawBline = function (point0, point1) { var x0 = point0.x >> 0; var y0 = point0.y >> 0; var x1 = point1.x >> 0; var y1 = point1.y >> 0; var dx = Math.abs(x1 - x0); var dy = Math.abs(y1 - y0); var sx = (x0 < x1) ? 1 : -1; var sy = (y0 < y1) ? 1 : -1; var err = dx - dy; while(true) { this.drawPoint(new BABYLON.Vector2(x0, y0)); if((x0 == x1) && (y0 == y1)) break; var e2 = 2 * err; if(e2 > -dy) { err -= dy; x0 += sx; } if(e2 < dx) { err += dx; y0 += sy; } } }; ~~~ 在 Render函數中,使用DrawBline替換掉DrawLine函數調用。 [運行代碼](http://david.blob.core.windows.net/softengine3d/part2sample3/index.html) 如果你注意觀察,應該可以發現Bresenham算法比我們自己實現的波動要小很多。 同樣的,你可以下載源代碼: C#:[SoftEngineCSharpPart2.zip](http://david.blob.core.windows.net/softengine3d/SoftEngineCSharpPart2.zip) TypeScript:[SoftEngineTSPart2.zip](http://david.blob.core.windows.net/softengine3d/SoftEngineTSPart2.zip) JavaScript:[SoftEngineJSPart2.zip](http://david.blob.core.windows.net/softengine3d/SoftEngineJSPart2.zip)?或只需右鍵點擊 -> 查看框架的源代碼 下一章節,你將學習如何從Blender這個免費的建模工具中導出一些Json文件格式的網格,然后加載Json文件并用我們的線框引擎去顯示它。實際上,我們已經擁有一切必備條件可以顯示下面這樣的復雜網格了: ![復雜網格](https://box.kancloud.cn/2016-03-22_56f0e9890dffa.jpg "復雜網格")
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看