中文字幕第五页-中文字幕第页-中文字幕韩国-中文字幕最新-国产尤物二区三区在线观看-国产尤物福利视频一区二区

怎么使用Chrome控制臺(tái)進(jìn)行3D模型編輯的實(shí)現(xiàn)

這篇文章主要介紹怎么使用Chrome控制臺(tái)進(jìn)行3D模型編輯的實(shí)現(xiàn),文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!

創(chuàng)新互聯(lián)主打移動(dòng)網(wǎng)站、成都做網(wǎng)站、成都網(wǎng)站制作、網(wǎng)站改版、網(wǎng)絡(luò)推廣、網(wǎng)站維護(hù)、域名注冊(cè)、等互聯(lián)網(wǎng)信息服務(wù),為各行業(yè)提供服務(wù)。在技術(shù)實(shí)力的保障下,我們?yōu)榭蛻?hù)承諾穩(wěn)定,放心的服務(wù),根據(jù)網(wǎng)站的內(nèi)容與功能再?zèng)Q定采用什么樣的設(shè)計(jì)。最后,要實(shí)現(xiàn)符合網(wǎng)站需求的內(nèi)容、功能與設(shè)計(jì),我們還會(huì)規(guī)劃穩(wěn)定安全的技術(shù)方案做保障。

前言:3D模型編輯的核心是對(duì)頂點(diǎn)位置和紋理顏色的編輯,這個(gè)研究的目的在于尋找一種通過(guò)編程方式直接對(duì)模型進(jìn)行編輯的方法,這種編輯方法和時(shí)下流行的通過(guò)鼠標(biāo)點(diǎn)選、拖拽進(jìn)行編輯的方法之間的關(guān)系,和前端編程中“程序員編寫(xiě)靜態(tài)網(wǎng)頁(yè)”與“美工進(jìn)行網(wǎng)頁(yè)切圖”之間的關(guān)系很相似。

一、工具用法:

1、訪問(wèn) https://ljzc002.github.io/SnowMiku/HTML/MakeRibbon.html打開(kāi)條帶網(wǎng)格生成器頁(yè)面

怎么使用Chrome控制臺(tái)進(jìn)行3D模型編輯的實(shí)現(xiàn)

在場(chǎng)景世界坐標(biāo)系的(0,-10,0),(0,0,0),(0,10,0)處各有一個(gè)綠色小球作為參考點(diǎn),使用上下左右和鼠標(biāo)拖動(dòng)可以進(jìn)行場(chǎng)景漫游。

2、按F12鍵打開(kāi)Chrome控制臺(tái),在控制臺(tái)中輸入:MakeRibbon(MakeRing(5,12),-10,2,11,"mesh_ribbon")回車(chē):

怎么使用Chrome控制臺(tái)進(jìn)行3D模型編輯的實(shí)現(xiàn)

在場(chǎng)景中繪制了一個(gè)半徑為5,曲面細(xì)分度為12,左端位于-10,每?jī)蓚€(gè)圓環(huán)間距2,共由11個(gè)圓環(huán)組成的圓柱面。

拉近查看:

怎么使用Chrome控制臺(tái)進(jìn)行3D模型編輯的實(shí)現(xiàn)

3、輸入ShowNormals(mesh_origin)將用紅色線段顯示每個(gè)頂點(diǎn)的法線方向

怎么使用Chrome控制臺(tái)進(jìn)行3D模型編輯的實(shí)現(xiàn)

輸入DeleteMeshes([lines_normal])可以刪除所有的法線,輸入DeleteMeshes([mesh_origin])則刪除圓柱面網(wǎng)格。

4、鼠標(biāo)移入網(wǎng)格上的三角形,會(huì)顯示三角形的頂點(diǎn)信息:

怎么使用Chrome控制臺(tái)進(jìn)行3D模型編輯的實(shí)現(xiàn)

其中“1:2-5”表示這是三角形的第一個(gè)頂點(diǎn),這個(gè)頂點(diǎn)位于索引是2的圓環(huán)上(第三個(gè)圓環(huán)),這個(gè)頂點(diǎn)在圓環(huán)中的索引是5(也就是第六個(gè)頂點(diǎn))。

5、輸入PickPoints([[2,5],[3,5],[2,6]],mesh_origin)可以選定這些頂點(diǎn)

怎么使用Chrome控制臺(tái)進(jìn)行3D模型編輯的實(shí)現(xiàn)

被選中頂點(diǎn)所影響的所有邊框線標(biāo)示為黃色,這個(gè)“選中”只是改變外觀而已。

6、輸入TransVertex(mesh_origin,arr_ij,BABYLON.Matrix.Translation(0,0,-10))將所選的頂點(diǎn)向z軸負(fù)方向移動(dòng)10,被移動(dòng)的頂點(diǎn)和前面選中的頂點(diǎn)其實(shí)沒(méi)有關(guān)系,其中arr_ij也可以直接用索引數(shù)組[[2,5],[3,5],[2,6]]代替。

怎么使用Chrome控制臺(tái)進(jìn)行3D模型編輯的實(shí)現(xiàn)

另一類(lèi)變形可以通過(guò)輸入:TransVertex(mesh_origin,arr_ij,BABYLON.Matrix.RotationX(Math.PI/2))實(shí)現(xiàn),這可以把被選中的頂點(diǎn)繞X中旋轉(zhuǎn)90度。

輸入DeleteMeshes([lines_inpicked])取消被選中的效果,輸入ChangeMaterial(mesh_origin,mat_blue)將邊框換成藍(lán)色紋理:

怎么使用Chrome控制臺(tái)進(jìn)行3D模型編輯的實(shí)現(xiàn)

可以看到變形后的效果,接下來(lái)還可以繼續(xù)選擇頂點(diǎn)并變形

7、輸入ExportMesh("1",mat_blue),以txt格式導(dǎo)出babylon模型文件,文件名為“1.txt”

怎么使用Chrome控制臺(tái)進(jìn)行3D模型編輯的實(shí)現(xiàn)

8、將導(dǎo)出的txt改名為9.babylon后放入網(wǎng)站目錄中,訪問(wèn)https://ljzc002.github.io/SnowMiku/HTML/LoadBabylon.html模型預(yù)覽頁(yè)面,在控制臺(tái)輸入ImportMesh("","../ASSETS/SCENE/","9.babylon")即可加載剛才導(dǎo)出的模型。

二、編程思路:

1、首先要建立一個(gè)可以進(jìn)行各種測(cè)試的基礎(chǔ)場(chǎng)景,使用的代碼如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>建立一個(gè)條帶網(wǎng)格生成器,能夠輸入?yún)?shù)生成起始條帶,然后通過(guò)命令行選取并修改pathArray,最后導(dǎo)出生成的條帶</title>
    <link href="../CSS/newland.css" rel="stylesheet">
    <link href="../CSS/stat.css" rel="stylesheet">
    <script src="../JS/MYLIB/Events.js"></script>
    <script src="../JS/MYLIB/FileText.js"></script>
    <script src="../JS/MYLIB/View.js"></script>
    <script src="../JS/LIB/babylon.32.all.maxs.js"></script><!--V3.2的穩(wěn)定版本-->
    <script src="../JS/MYLIB/newland.js"></script>
    <script src="../JS/LIB/stat.js"></script>
</head>
<body>
<div id="div_allbase">
    <canvas id="renderCanvas"></canvas>
    <div id="fps" style="z-index: 301;"></div>
</div>
</body>
<script>
    var VERSION=1.0,AUTHOR="[email protected]";
    var machine,canvas,engine,scene,gl,MyGame={};
    canvas = document.getElementById("renderCanvas");
    engine = new BABYLON.Engine(canvas, true);
    gl=engine._gl;//可以結(jié)合使用原生OpenGL和Babylon.js;
    scene = new BABYLON.Scene(engine);
    var divFps = document.getElementById("fps");

    window.onload=beforewebGL;
    function beforewebGL()
    {
        if(engine._webGLVersion==2.0)//輸出ES版本
        {
            console.log("ES3.0");
        }
        else{
            console.log("ES2.0");
        }
        //MyGame=new Game(0,"first_pick","","http://127.0.0.1:8082/");
        /*0-startWebGL
         * */
        webGLStart();
    }
    //從下面開(kāi)始分成簡(jiǎn)單測(cè)試和對(duì)象框架兩種架構(gòu)
    //簡(jiǎn)單測(cè)試
    //全局對(duì)象
    var light0//全局光源
            ,camera0//主相機(jī)
            ;
    //四種常用材質(zhì)
    var mat_frame = new BABYLON.StandardMaterial("mat_frame", scene);
    mat_frame.wireframe = true;
    var mat_red = new BABYLON.StandardMaterial("mat_red", scene);
    mat_red.diffuseColor = new BABYLON.Color3(1, 0, 0);
    mat_red.backFaceCulling=false;
    var mat_green = new BABYLON.StandardMaterial("mat_green", scene);
    mat_green.diffuseColor = new BABYLON.Color3(0, 1, 0);
    mat_green.backFaceCulling=false;
    var mat_blue = new BABYLON.StandardMaterial("mat_blue", scene);
    mat_blue.diffuseColor = new BABYLON.Color3(0, 0, 1);
    mat_blue.backFaceCulling=false;
    var mesh_origin;
    var advancedTexture=BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("ui1");//全屏GUI
    function webGLStart()
    {
        window.addEventListener("resize", function () {//自動(dòng)調(diào)整視口尺寸
            engine.resize();
        });
        camera0 =new BABYLON.FreeCamera("FreeCamera", new BABYLON.Vector3(0, 0, -80), scene);
        camera0.attachControl(canvas, true);
        camera0.speed=0.5;//相機(jī)移動(dòng)速度是默認(rèn)速度的一半
        camera0.minZ=0.01;//相機(jī)位置距前視錐截面的距離,也就是說(shuō)到相機(jī)距離小于0.01的圖元都不會(huì)顯示,這個(gè)值不能過(guò)小,否則Babylon.js內(nèi)置的鼠標(biāo)選取將失效
        camera0.layerMask=2;//相機(jī)的遮罩層次,這個(gè)相機(jī)將只能顯示遮罩層次同為2的網(wǎng)格,如果不設(shè)置這個(gè)屬性,似乎可以顯示所有遮罩層次的網(wǎng)格
        scene.activeCameras.push(camera0);//將相機(jī)加入活躍相機(jī)列表,默認(rèn)情況下Babylon.js只使用一個(gè)活躍相機(jī),但是也可以強(qiáng)行使用多個(gè)
        light0 = new BABYLON.HemisphericLight("Hemi0", new BABYLON.Vector3(0, 1, 0), scene);//半球光源
     //三個(gè)參照物,MeshBuilder是新版Babylon.js中使用的網(wǎng)格構(gòu)建對(duì)象,之前翻譯入門(mén)教程時(shí)還沒(méi)有這個(gè)對(duì)象,它的特點(diǎn)是把一大堆參數(shù)統(tǒng)一整理到一個(gè)option參數(shù)中
        var mesh_base=new BABYLON.MeshBuilder.CreateSphere("mesh_base",{diameter:1},scene);
        mesh_base.material=mat_green;
        mesh_base.position.x=0;
        mesh_base.layerMask=2;
        var mesh_base1=new BABYLON.MeshBuilder.CreateSphere("mesh_base1",{diameter:1},scene);
        mesh_base1.position.y=10;
        mesh_base1.position.x=0;
        mesh_base1.material=mat_green;
        mesh_base1.layerMask=2;
        var mesh_base2=new BABYLON.MeshBuilder.CreateSphere("mesh_base2",{diameter:1},scene);
        mesh_base2.position.y=-10;
        mesh_base2.position.x=0;
        mesh_base2.material=mat_green;
        mesh_base2.layerMask=2;
      。
      。
      。
        MyBeforeRender();
    }
    function MyBeforeRender()
    {
        scene.registerBeforeRender(function() {
            if(scene.isReady())
            {
                。
                。
                。
                。
                。
                。
            }
        });
        engine.runRenderLoop(function () {
            engine.hideLoadingUI();
            if (divFps) {
                // Fps
                divFps.innerHTML = engine.getFps().toFixed() + " fps";
            }
            scene.render();
        });

    } 
</script>
</html>

這個(gè)3D場(chǎng)景包括了簡(jiǎn)單測(cè)試所需要的一些基本元素,這里使用的是包含全部組件的未壓縮版Babylon.js庫(kù),在實(shí)際使用中考慮到節(jié)省帶寬,可以使用Babylon.js官網(wǎng)提供的工具定制精簡(jiǎn)版或壓縮版的Babylon.js庫(kù)

2、建立一個(gè)基礎(chǔ)網(wǎng)格

計(jì)劃通過(guò)對(duì)一個(gè)基礎(chǔ)網(wǎng)格進(jìn)行頂點(diǎn)變換來(lái)產(chǎn)生各種各樣的簡(jiǎn)單模型,在Babylon.js中“條帶”是一種非常適合頂點(diǎn)變換的網(wǎng)格類(lèi)型,Babylon.js官方教程中有關(guān)于條帶構(gòu)造和變形的文檔,可以在這里下載中文翻譯http://down.51cto.com/data/2449757。

用來(lái)建立基礎(chǔ)網(wǎng)格的代碼如下:

//下面這些函數(shù)都通過(guò)控制臺(tái)調(diào)用
    //在ZoY平面里建立一個(gè)圓環(huán)路徑
    //radius:半徑,sumpoint:使用幾個(gè)點(diǎn)
    function MakeRing(radius,sumpoint)
    {
        var arr_point=[];
        var radp=Math.PI*2/sumpoint;
        for(var i=0.0;i<sumpoint;i++)
        {
            var x=0;
            var rad=radp*i;
            //var y=sswr(radius*Math.sin(rad),null,5);//在這里需要降低一些精確度?否則Babylon.js在計(jì)算頂點(diǎn)數(shù)據(jù)時(shí)可能和這里不一致?
            //var z=sswr(radius*Math.cos(rad),null,5);
            var y=radius*Math.sin(rad);
            var z=radius*Math.cos(rad);
            arr_point.push(new BABYLON.Vector3(x,y,z));
        }
        arr_point.push(arr_point[0].clone());//首尾相連,不能這樣相連,否則變形時(shí)會(huì)多出一個(gè)頂點(diǎn)!!,看來(lái)這個(gè)多出的頂點(diǎn)無(wú)法去掉,只能在選取時(shí)額外處理它
        return arr_point;
    }
    var arr_path=[];//核心數(shù)據(jù)
    //arr_point:?jiǎn)蝹€(gè)路徑的點(diǎn)數(shù)組,xstartl:第一個(gè)扁平路徑放在最左側(cè),spacing:路徑的間距,sumpath:一共使用幾條路徑,
    function MakeRibbon(arr_point,xstartl,spacing,sumpath,name)
    {//將一條圓環(huán)路徑擴(kuò)展成相互平行的多個(gè)圓環(huán)路徑,然后使用這些路徑生成條帶
        arr_path=[];
        for(var i=0;i<sumpath;i++)//對(duì)于每一條路徑
        {
            var x=xstartl+spacing*i;
            //var arr=arr_point.concat(null);//為什么拷貝失靈了?
            //var [ ...arr ] = arr_point;//ES6的新擴(kuò)展運(yùn)算符?-》也不好使,因?yàn)閿?shù)組里的元素是指針?!!
            var len=arr_point.length;
            var arr=[];
            for(var j=0;j<len;j++)
            {
                var obj=arr_point[j].clone();
                obj.x=x;
                //
                arr.push(obj);
            }
            arr_path.push(arr);
            arr=null;
        }
        mesh_origin.dispose();
        mesh_origin=BABYLON.MeshBuilder.CreateRibbon(name,{pathArray:arr_path,updatable:true,closePath:false,closeArray:false});
        //mesh_origin=mesh;//用一個(gè)全局變量保存最終會(huì)被導(dǎo)出的mesh
        mesh_origin.sideOrientation=BABYLON.Mesh.DOUBLESIDE;//顯示網(wǎng)格的前后兩面
        mesh_origin.material=mat_frame;
        mesh_origin.layerMask=2;
    }

編程中遇到的幾個(gè)問(wèn)題:

a、路徑中設(shè)置的坐標(biāo)值在實(shí)際顯示時(shí)可能發(fā)生微小的變化,比如5可能變成4.999999999999999999,但是似乎沒(méi)什么影響。

b、雖然圓環(huán)路徑分成12段應(yīng)該由12個(gè)頂點(diǎn)組成,但是如果只有12個(gè)頂點(diǎn),那么在調(diào)用CreateRibbon方法時(shí),如果把closePath參數(shù)設(shè)為true則Babylon.js會(huì)自動(dòng)添加一個(gè)不受控制的頂點(diǎn)來(lái)閉合圓環(huán)路徑,如果設(shè)為false,則路徑無(wú)法閉合。為此在第18行再添加一個(gè)與起始點(diǎn)

重合的頂點(diǎn)使圓環(huán)路徑閉合。

c、原計(jì)劃直接使用數(shù)組的concat方法復(fù)制arr_point數(shù)組產(chǎn)生更多的圓環(huán)路徑,但concat方法似乎只能對(duì)一維數(shù)組使用(棧?),而arr_point的每個(gè)元素都是一個(gè)BABYLON.Vector3對(duì)象,所以只好用for循環(huán)一個(gè)點(diǎn)一個(gè)點(diǎn)的生成路徑

d、MakeRing是一個(gè)生成圓環(huán)路徑的方法,使用者可以根據(jù)需要編寫(xiě)各種其他類(lèi)型的路徑生成方法。

3、調(diào)整網(wǎng)格的屬性:

可以對(duì)網(wǎng)格的屬性進(jìn)行一些調(diào)整,但是這些調(diào)整只在這個(gè)編輯器里生效,并不會(huì)被導(dǎo)出。

比如對(duì)網(wǎng)格材質(zhì)的調(diào)整:

 function ChangeMaterial(mesh,mat)
     {
         mesh.material=mat;
     }

4、顯示網(wǎng)格頂點(diǎn)法線方向

代碼如下:

var lines_normal={};
    /*ShowNormals(mesh_origin)
     DeleteMeshes([lines_normal]);
    * */
    //顯示所有的頂點(diǎn)法線
    function ShowNormals(mesh)
    {
        //DeleteMeshes(arr_line_normal);
        if(lines_normal.dispose)
        {
            lines_normal.dispose();
        }
        //遍歷頂點(diǎn)
        var vb=mesh.geometry._vertexBuffers;
        var data_pos=vb.position._buffer._data;//頂點(diǎn)數(shù)據(jù)
        var data_mormal=vb.normal._buffer._data;//法線數(shù)據(jù)
        var len=data_pos.length;
        var lines=[];
        for(var i=0;i<len;i+=3)
        {//CreateLineSystem使用一個(gè)網(wǎng)格包含很多分立的線段(路徑),CreateLines則是一條首尾相連的路徑
            //
            var vec=new BABYLON.Vector3(data_pos[i],data_pos[i+1],data_pos[i+2]);
            var vec2=vec.clone().add(new BABYLON.Vector3(data_mormal[i],data_mormal[i+1],data_mormal[i+2]).normalize().scale(1));
            lines.push([vec,vec2]);
        }
        lines_normal=new BABYLON.MeshBuilder.CreateLineSystem("lines_normal",{lines:lines,updatable:false},scene);
        lines_normal.color=new BABYLON.Color3(1, 0, 0);
    }

Babylon.js內(nèi)置的CreateLineSystem方法可以方便的建立一個(gè)由很多條線段組成的網(wǎng)格。

5、刪除網(wǎng)格

代碼如下:

function DeleteMeshes(arr)//假設(shè)一個(gè)數(shù)組里的都是mesh,徹底清空它
    {
        var len=arr.length;
        for(var i=0;i<len;i++)
        {
            if(arr[i].dispose)
                arr[i].dispose();
        }
        arr=[];
    }

值得注意的是,直接在控制臺(tái)里執(zhí)行mesh.dispose()并不生效。

這里也體現(xiàn)出CreateLineSystem的方便之處——?jiǎng)h除法線時(shí)只需要dispose一個(gè)對(duì)象。

6、鼠標(biāo)移入時(shí)顯示三角形信息

鼠標(biāo)動(dòng)作監(jiān)聽(tīng)代碼:

mesh_origin=new BABYLON.Mesh("mesh_origin",scene);//建立一個(gè)空的初始網(wǎng)格對(duì)象
        mesh_surface=new BABYLON.Mesh("mesh_surface",scene);
        mesh_surface0=new BABYLON.Mesh("mesh_surface0",scene);
        if(true)
        {//初始化三個(gè)GUI標(biāo)簽
            label_index1=new BABYLON.GUI.TextBlock();
            label_index1.text = "label_index1";
            label_index1.color="white";
            label_index1.isVisible=false;//初始化時(shí)標(biāo)簽不可見(jiàn)
            //label_index1.linkWithMesh(mesh_surface0);//TextBlock并不是頂層元素
            advancedTexture.addControl(label_index1);
            label_index2=new BABYLON.GUI.TextBlock();
            label_index2.text = "label_index2";
            label_index2.color="white";
            label_index2.isVisible=false;
            //label_index2.linkWithMesh(mesh_surface0);
            advancedTexture.addControl(label_index2);
            label_index3=new BABYLON.GUI.TextBlock();
            label_index3.text = "label_index3";
            label_index3.color="white";
            label_index3.isVisible=false;
            //label_index3.linkWithMesh(mesh_surface0);
            advancedTexture.addControl(label_index3);
        }
//監(jiān)聽(tīng)鼠標(biāo)移動(dòng)
canvas.addEventListener("mousemove", function(evt){
var pickInfo = scene.pick(scene.pointerX, scene.pointerY,null,null,camera0);//如果同時(shí)有多個(gè)激活的相機(jī),則要明確的指出使用哪個(gè)相機(jī)
            //cancelPropagation(evt);
            //cancelEvent(evt);
            label_index1.isVisible=false;
            label_index2.isVisible=false;
            label_index3.isVisible=false;
            if(mesh_surface.dispose)
            {
                mesh_surface.dispose();
            }
            if(mesh_surface0.dispose)
            {
                mesh_surface0.dispose();
            }
            if(pickInfo.hit&&(pickInfo.pickedMesh.name=="mesh_origin"||pickInfo.pickedMesh.name=="mesh_ribbon"))//找到鼠標(biāo)所在的三角形并重繪之
            {
          //在鼠標(biāo)所指的地方繪制一個(gè)三角形,表示被選中的三角形
                var faceId=pickInfo.faceId;
                var pickedMesh=pickInfo.pickedMesh;
                var indices=[pickedMesh.geometry._indices[faceId*3]
                    ,pickedMesh.geometry._indices[faceId*3+1],pickedMesh.geometry._indices[faceId*3+2]];
                var vb=pickedMesh.geometry._vertexBuffers;
                var position=vb.position._buffer._data;
                var normal=vb.normal._buffer._data;
                var uv=vb.uv._buffer._data;
                var len=arr_path[0].length;
                var p1={index:indices[0],position:[position[indices[0]*3],position[indices[0]*3+1],position[indices[0]*3+2]]
                    ,normal:[normal[indices[0]*3],normal[indices[0]*3+1],normal[indices[0]*3+2]]
                    ,uv:[uv[indices[0]*2],uv[indices[0]*2+1]],ppi:("1:"+(Math.round(indices[0]/len)+0))+"-"+(indices[0]%len)};//pathpointindex
                var p2={index:indices[1],position:[position[indices[1]*3],position[indices[1]*3+1],position[indices[1]*3+2]]
                    ,normal:[normal[indices[1]*3],normal[indices[1]*3+1],normal[indices[1]*3+2]]
                    ,uv:[uv[indices[1]*2],uv[indices[1]*2+1]],ppi:("2:"+(Math.round(indices[1]/len)+0))+"-"+(indices[1]%len)};
                var p3={index:indices[2],position:[position[indices[2]*3],position[indices[2]*3+1],position[indices[2]*3+2]]
                    ,normal:[normal[indices[2]*3],normal[indices[2]*3+1],normal[indices[2]*3+2]]
                    ,uv:[uv[indices[2]*2],uv[indices[2]*2+1]],ppi:("3:"+(Math.round(indices[2]/len)+0))+"-"+(indices[2]%len)};
                var po=[(p1.position[0]+p2.position[0]+p3.position[0])/3,(p1.position[1]+p2.position[1]+p3.position[1])/3,(p1.position[2]+p2.position[2]+p3.position[2])/3];
                var numm=2;
                mesh_surface0=newland.make_tryangle(p1,p2,p3,"mesh_surface1",scene);//使用三個(gè)點(diǎn)繪制一個(gè)三角形
                mesh_surface0.material=mat_green;
                mesh_surface0.sideOrientation==BABYLON.Mesh.DOUBLESIDE;
                mesh_surface0.layerMask=2;
                label_index1.isVisible=true;
                //label_index1.layerMask=2;//這個(gè)屬性對(duì)于gui被管對(duì)象并不生效?
                label_index1.text=p1.ppi;//ppi表示這個(gè)頂點(diǎn)是三角形的第幾個(gè)頂點(diǎn),以及這個(gè)頂點(diǎn)位于第幾條路徑的第幾個(gè)位置
                var pos1=new BABYLON.Vector3(p1.position[0],p1.position[1],p1.position[2]);
                label_index1.moveToVector3(pos1,scene);
                label_index1.itspos=pos1;
                label_index2.isVisible=true;
                label_index2.text=p2.ppi;
                var pos2=new BABYLON.Vector3(p2.position[0],p2.position[1],p2.position[2]);
                label_index2.moveToVector3(pos2,scene);
                label_index2.itspos=pos2;
                label_index3.isVisible=true;
                label_index3.text=p3.ppi;
                var pos3=new BABYLON.Vector3(p3.position[0],p3.position[1],p3.position[2]);
                label_index3.moveToVector3(pos3,scene);
                label_index3.itspos=pos3;
                //將三個(gè)點(diǎn)移動(dòng)到場(chǎng)景的中心
                pt=[(p1.position[0]-po[0])*numm,(p1.position[1]-po[1])*numm,(p1.position[2]-po[2])*numm];
                p1.position=pt;
                pt=[(p2.position[0]-po[0])*numm,(p2.position[1]-po[1])*numm,(p2.position[2]-po[2])*numm];
                p2.position=pt;
                pt=[(p3.position[0]-po[0])*numm,(p3.position[1]-po[1])*numm,(p3.position[2]-po[2])*numm];
                p3.position=pt;
          //在場(chǎng)景的中心再繪制一個(gè)大一倍的三角形
                mesh_surface=newland.make_tryangle(p1,p2,p3,"mesh_surface",scene);
                mesh_surface.material=mat_green;
                mesh_surface.sideOrientation==BABYLON.Mesh.DOUBLESIDE;
                mesh_surface.layerMask=1;//遮罩層次是1

            }

        },false);

需要注意的有以下幾點(diǎn):

a、鼠標(biāo)指向時(shí)顯示的是這個(gè)點(diǎn)在arr_path中的索引,而不是在“頂點(diǎn)數(shù)據(jù)對(duì)象”中的索引!

b、最初的計(jì)劃是像魔獸爭(zhēng)霸3一樣在窗口的左下角建立一個(gè)遮罩層次為1的小視口,用來(lái)特寫(xiě)被選中的三角形(mesh_surface),但是后來(lái)發(fā)現(xiàn)Babylon.js的GUI不能設(shè)置遮罩層次,也不能像鼠標(biāo)選取一樣設(shè)置相對(duì)于哪一個(gè)相機(jī),所以取消了左下角的小視口。

如果需要添加視口,代碼如下:

var mm = new BABYLON.FreeCamera("minimap", new BABYLON.Vector3(0,0,-20), scene);
        mm.layerMask = 1;
        var xstart = 0.0,
                ystart = 0.1;//意為占屏幕寬高的比例
        var width = 0.2,
                height = 0.2;
        //視口邊界從左下角開(kāi)始
        mm.viewport = new BABYLON.Viewport(
                xstart,
                ystart,
                width,
                height
        );
        scene.activeCameras.push(mm);var mm = new BABYLON.FreeCamera("minimap", new BABYLON.Vector3(0,0,-20), scene);
        mm.layerMask = 1;
        var xstart = 0.0,
                ystart = 0.1;//意為占屏幕寬高的比例
        var width = 0.2,
                height = 0.2;
        //視口邊界從左下角開(kāi)始
        mm.viewport = new BABYLON.Viewport(
                xstart,
                ystart,
                width,
                height
        );
        scene.activeCameras.push(mm);

c、需要注意的是GUI是一次性繪制在視口上的,默認(rèn)情況下即使相關(guān)的網(wǎng)格位置發(fā)生變化,GUI仍然會(huì)保持在視口上最初的位置。linkWithMesh方法可以將GUI和網(wǎng)格綁定起來(lái),但是似乎只能對(duì)部分“底層的”GUI類(lèi)型生效,為了使得標(biāo)簽跟隨頂點(diǎn)移動(dòng),需要手動(dòng)在每一幀渲染之前更新標(biāo)簽的位置:

scene.registerBeforeRender(function() {
            if(scene.isReady())
            {
                if(label_index1.isVisible==true)//不斷刷新gui的位置
                {//在具有多個(gè)激活相機(jī)時(shí)選擇了錯(cuò)誤的參考相機(jī)?-》會(huì)強(qiáng)制選擇最新建立的相機(jī)
                    label_index1.moveToVector3(label_index1.itspos,scene);
                    label_index2.moveToVector3(label_index2.itspos,scene);
                    label_index3.moveToVector3(label_index3.itspos,scene);
                }
            }
        });

7、選取頂點(diǎn):

3DsMax和Blender(Babylon.js庫(kù)在3D模型部分參考了Blender的許多設(shè)計(jì))都使用鼠標(biāo)在網(wǎng)格中選取需要修改的區(qū)域,我不是很習(xí)慣這種方式,所以考慮用JS函數(shù)代替鼠標(biāo)操作:

var lines_inpicked={};//線段系統(tǒng)對(duì)象,表示所有被選中點(diǎn)影響的線段
    var arr_ij=[];//記錄被選中的點(diǎn)在arr_path中的索引的數(shù)組
    /*DeleteMeshes([lines_inpicked]);
    * PickPoints([[0,0],[0,12],[1,1]],mesh_origin)
    * */
    //選定一些頂點(diǎn)
    function PickPoints(arr,mesh)
    {
        if(arr_path.length==0)
        {
            alert("尚未生成路徑數(shù)組!");
            return;
        }
        if(lines_inpicked.dispose)
        {
            lines_inpicked.dispose();
        }
        //arr_ij=[];
        //為了后面考慮,需要先對(duì)arr整體遍歷一遍,把首尾接口處關(guān)聯(lián)起來(lái)
        arr_ij=arr;//把路徑和點(diǎn)的位置記錄下來(lái)
        var vb=mesh.geometry._vertexBuffers;
        var data_pos=vb.position._buffer._data;
        var len_pos=data_pos.length;
        var data_index=mesh.geometry._indices;
        var len_index=data_index.length;
        var len=arr.length;
        var lines=[];
        for(var i=0;i<len;i++)//對(duì)于每一個(gè)需要顯示的被選擇點(diǎn)
        {
            var int0=arr[i][0];
            var int1=arr[i][1];
            var vec=arr_path[int0][int1];//獲取到路徑數(shù)組中的一個(gè)Vector3對(duì)象
            //假設(shè)路徑數(shù)組和頂點(diǎn)數(shù)據(jù)是一一對(duì)應(yīng)的?同時(shí)假設(shè)每一條路徑的長(zhǎng)度都和第一條相同
            var arr_index=[int0*arr_path[0].length+int1];//所有位于所選位置的頂點(diǎn)在頂點(diǎn)數(shù)據(jù)對(duì)象中的索引
            //下面遍歷網(wǎng)格的繪制索引,找出這個(gè)被選中的頂點(diǎn)每一次的使用情況
            for(var j=0;j<len_index;j+=3)//根據(jù)頂點(diǎn)在三角形中的位置分三種情況討論
            {//繪制出和這個(gè)頂點(diǎn)相關(guān)的所有線段,這樣繪制會(huì)有很?chē)?yán)重的線段重合!觀察是否對(duì)性能有很大的影響
                var len2=arr_index.length;
                for(var k=0;k<len2;k++)
                {
                    if(arr_index[k]==data_index[j])//三角形的第一個(gè)頂點(diǎn)
                    {//把這個(gè)頂點(diǎn)和三角形中的另兩個(gè)頂點(diǎn)用黃線連起來(lái)
                        var num2=data_index[j+1]*3;
                        var num3=data_index[j+2]*3;
                        var vec2=new BABYLON.Vector3(data_pos[num2],data_pos[num2+1],data_pos[num2+2]);
                        var vec3=new BABYLON.Vector3(data_pos[num3],data_pos[num3+1],data_pos[num3+2]);
                        lines.push([vec,vec2]);
                        lines.push([vec,vec3]);
                    }
                    else if(arr_index[k]==data_index[j+1])//三角形的第一個(gè)頂點(diǎn)
                    {
                        var num2=data_index[j]*3;
                        var num3=data_index[j+2]*3;
                        var vec2=new BABYLON.Vector3(data_pos[num2],data_pos[num2+1],data_pos[num2+2]);
                        var vec3=new BABYLON.Vector3(data_pos[num3],data_pos[num3+1],data_pos[num3+2]);
                        lines.push([vec,vec2]);
                        lines.push([vec,vec3]);
                    }
                    else if(arr_index[k]==data_index[j+2])//三角形的第一個(gè)頂點(diǎn)
                    {
                        var num2=data_index[j]*3;
                        var num3=data_index[j+1]*3;
                        var vec2=new BABYLON.Vector3(data_pos[num2],data_pos[num2+1],data_pos[num2+2]);
                        var vec3=new BABYLON.Vector3(data_pos[num3],data_pos[num3+1],data_pos[num3+2]);
                        lines.push([vec,vec2]);
                        lines.push([vec,vec3]);
                    }
                }
            }
        }
        lines_inpicked=new BABYLON.MeshBuilder.CreateLineSystem("lines_normal",{lines:lines,updatable:false},scene);
        lines_inpicked.color=new BABYLON.Color3(1, 1, 0);
    }
    //需要一些選擇選定頂點(diǎn)的方法

有以下幾處需要注意:

a、因?yàn)镸akeRing生成的路徑里包括兩個(gè)重合的點(diǎn)(首尾),為了保證變形后的網(wǎng)格仍然連續(xù),在選擇時(shí)這兩個(gè)重合的點(diǎn)必須同時(shí)被選中,經(jīng)過(guò)考慮,規(guī)定這個(gè)確保首尾重合點(diǎn)同時(shí)選中的操作在生成arr數(shù)組參數(shù)時(shí)進(jìn)行。

b、因?yàn)榛A(chǔ)網(wǎng)格mesh_origin的每一個(gè)頂點(diǎn)恰好位置不同,所以一開(kāi)始我以為“與被選中的點(diǎn)的位置相同的點(diǎn)”應(yīng)該具有與被選中點(diǎn)相同的變形效果,但是事實(shí)上經(jīng)過(guò)網(wǎng)格變形后,完全可能出現(xiàn)兩個(gè)不相干的頂點(diǎn)位于同一位置的情況,這時(shí)應(yīng)用相同的變形效果會(huì)出現(xiàn)錯(cuò)誤,比如人可以把手放在腿上,這時(shí)手和腿的接觸點(diǎn)具有相同的位置,但如果因此對(duì)這兩個(gè)點(diǎn)應(yīng)用相同的變形效果,就很詭異了。同時(shí)如前文所說(shuō),有時(shí)arr_path中存儲(chǔ)的位置和頂點(diǎn)數(shù)據(jù)中存儲(chǔ)的位置可能出現(xiàn)微小的偏差。

最后采取的方法是將arr_path中的數(shù)組轉(zhuǎn)化為頂點(diǎn)數(shù)據(jù)對(duì)象中的數(shù)組。

c、這里直接選取了幾個(gè)點(diǎn)進(jìn)行變形,還需要編寫(xiě)一些按照某種規(guī)則批量選取點(diǎn)的方法,也希望大家能幫我想一想怎樣選取頂點(diǎn)比較方便。

8、網(wǎng)格變形:

代碼如下:

/*
    * TransVertex(mesh_origin,arr_ij,BABYLON.Matrix.RotationX(Math.PI/2))
    *TransVertex(mesh_origin,arr_ij,BABYLON.Matrix.Translation(0.5,0,0))
    * */
    //移動(dòng)選定的頂點(diǎn),同時(shí)更新網(wǎng)格、選取線、法線
    function TransVertex(mesh,arr,matrix)
    {
        var len=arr.length;
        for(var i=0;i<len;i++)//移動(dòng)路徑數(shù)組里的每個(gè)頂點(diǎn)
        {
            //var vec=arr_path[arr[i][0]][arr[i][1]];
            arr_path[arr[i][0]][arr[i][1]]=BABYLON.Vector3.TransformCoordinates(arr_path[arr[i][0]][arr[i][1]],matrix);
        }
        //更新網(wǎng)格,發(fā)現(xiàn)設(shè)置了closePath:true之后在頂點(diǎn)數(shù)據(jù)里還是會(huì)自動(dòng)補(bǔ)上一個(gè)接續(xù)點(diǎn),這還不如一開(kāi)始自己添加!起碼自己添加可以保證路徑數(shù)組和頂點(diǎn)數(shù)據(jù)的一致性!!!!
        mesh=BABYLON.MeshBuilder.CreateRibbon(mesh.name,{pathArray:arr_path,updatable:true,instance:mesh,closePath:false,closeArray:false});
        //上面的更新重繪是默認(rèn)重算法線方向的,這與直接修改頂點(diǎn)數(shù)據(jù)不同
        //清空法線
        DeleteMeshes([lines_normal]);
        //更新選取頂點(diǎn)表示
        PickPoints(arr,mesh);
    }
    //需要一些生成變化矩陣的方法

其實(shí)這里移動(dòng)的頂點(diǎn)和前面選擇的點(diǎn)沒(méi)有關(guān)系,不選擇也可以直接變形,只不過(guò)不會(huì)有黃線顯示罷了。這里也同樣需要一些生成更復(fù)雜的變換矩陣的方法。

9、導(dǎo)出:

導(dǎo)出方法的調(diào)用如下:

/*ExportMesh("1",mat_blue)*/
    function ExportMesh(filename,mat)
    {
        try{
            newland.ExportBabylonMesh([mesh_origin],filename,mat);
        }
        catch(e)
        {
            console.error(e)
        }
    }

函數(shù)的第一個(gè)參數(shù)是導(dǎo)出后的文件名(不包括擴(kuò)展名),第二個(gè)參數(shù)是網(wǎng)格使用的材質(zhì)對(duì)象(暫時(shí)只支持簡(jiǎn)單的顏色材質(zhì))。

其中ExportBabylonMesh是我編寫(xiě)的newland庫(kù)中的一個(gè)方法,這個(gè)方法在前面關(guān)與3D模型的文章中也有提到過(guò)(https://www.cnblogs.com/ljzc002/p/6884252.html),這個(gè)方法整體上沒(méi)有太大的改變。但是在舊版的Babylon.js中,頂點(diǎn)數(shù)據(jù)對(duì)象中的data屬性是數(shù)組類(lèi)型(?),而在新版中data屬性則是typedArray類(lèi)型,雖然這兩種數(shù)據(jù)類(lèi)型看起來(lái)很像,但在使用JSON.stringify(arr)轉(zhuǎn)化為JSON字符串時(shí),對(duì)于同樣的數(shù)據(jù)[1,2,3],前者會(huì)轉(zhuǎn)化為"[1,2,3]"后者則是"{"0":1,"1":2,"2":3}"!

在導(dǎo)入模型文件時(shí)后者會(huì)報(bào)錯(cuò):“attempt to access out of range vertices in attribute 0”,這意味著在導(dǎo)入模型時(shí)頂點(diǎn)數(shù)據(jù)數(shù)組沒(méi)有正確的載入,我的解決方案是導(dǎo)出前將data屬性強(qiáng)制轉(zhuǎn)化為數(shù)組類(lèi)型:

//將TypedArray轉(zhuǎn)化為普通array
newland.BuffertoArray2=function(arr)
{
    var arr2=[];
    var len=arr.length;
    for(var i=0;i<len;i++)
    {
        arr2.push(arr[i]);
    }
    return arr2;
}

對(duì)于舊版的Babylon.js應(yīng)該可以不加修改的使用這個(gè)方法,因?yàn)閠ypedArray也具有數(shù)組的大部分功能。

10、導(dǎo)入:

在另一個(gè)頁(yè)面里實(shí)現(xiàn)模型導(dǎo)入功能,這個(gè)頁(yè)面同樣在“基礎(chǔ)場(chǎng)景”的基礎(chǔ)上編寫(xiě),其中導(dǎo)入方法如下:

function ImportMesh(objname,filepath,filename)
    {

        BABYLON.SceneLoader.ImportMesh(objname, filepath, filename, scene
                , function (newMeshes, particleSystems, skeletons)
                {//載入完成的回調(diào)函數(shù)
                    if(mesh_origin&&mesh_origin.dispose)
                    {
                        mesh_origin.dispose();
                    }
                    mesh_origin=newMeshes[0];
                    //mesh_origin.material=mat_frame;
                    //mesh_origin.layerMask=2;
                }
        );
    }

以上是怎么使用Chrome控制臺(tái)進(jìn)行3D模型編輯的實(shí)現(xiàn)的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!

網(wǎng)頁(yè)標(biāo)題:怎么使用Chrome控制臺(tái)進(jìn)行3D模型編輯的實(shí)現(xiàn)
當(dāng)前地址:http://m.2m8n56k.cn/article4/gsejoe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供全網(wǎng)營(yíng)銷(xiāo)推廣網(wǎng)站建設(shè)建站公司動(dòng)態(tài)網(wǎng)站ChatGPT微信公眾號(hào)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:[email protected]。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

微信小程序開(kāi)發(fā)
主站蜘蛛池模板: 免费欧美一级片 | 久久福利资源国产精品999 | 久久国产亚洲 | 国产真实乱子伦精品视 | 2021国产精品系列一区二区 | 波多野结衣一区二区三区高清在线 | 久久精品国产精品青草不卡 | 国产成人高清亚洲一区91 | 毛片视频网站在线观看 | 国产精品一区二区综合 | 点击进入不卡毛片免费观看 | 亚洲欧美一区二区三区综合 | 日本在线观看免费视频 | 亚洲黄色小视频 | 日本一级特黄a大片 | 国产精品久久久精品三级 | 日韩成人毛片高清视频免费看 | 欧美综合亚洲 | 亚洲三级a | 精品一区二区影院在线 | 性欧美高清come | 99re免费99re在线视频手机版 | 国产17部性孕妇孕交在线 | 兔费看全黄三级 | 26uuu欧美日韩国产 | a级片在线观看免费 | 久久精品中文字幕免费 | 国产人成免费视频 | 97精品国产手机 | 精品一区二区三区中文 | 日韩在线第一区 | 日韩精品视频美在线精品视频 | 大片国产片日本观看免费视频 | a级片在线免费看 | 国产成人精品久久综合 | 欧美激情国产一区在线不卡 | 日韩免费在线 | 又黄又湿又爽 | 国产欧美成人一区二区三区 | 高清在线一区二区 | 97免费在线 |