前言:3D模型编辑的核心是对顶点位置和纹理颜色的编辑,这个研究的目的在于寻找一种通过编程方式直接对模型进行编辑的方法,这种编辑方法和时下流行的通过鼠标点选、拖拽进行编辑的方法之间的关系,和前端编程中“程序员编写静态网页”与“美工进行网页切图”之间的关系很相似。
一、工具用法:
1、访问 https://ljzc002.github.io/SnowMiku/HTML/MakeRibbon.html打开条带网格生成器页面

在场景世界坐标系的(0,-10,0),(0,0,0),(0,10,0)处各有一个绿色小球作为参考点,使用上下左右和鼠标拖动可以进行场景漫游。
2、按F12键打开Chrome控制台,在控制台中输入:MakeRibbon(MakeRing(5,12),-10,2,11,"mesh_ribbon")回车:

在场景中绘制了一个半径为5,曲面细分度为12,左端位于-10,每两个圆环间距2,共由11个圆环组成的圆柱面。
拉近查看:

3、输入ShowNormals(mesh_origin)将用红色线段显示每个顶点的法线方向

输入DeleteMeshes([lines_normal])可以删除所有的法线,输入DeleteMeshes([mesh_origin])则删除圆柱面网格。
4、鼠标移入网格上的三角形,会显示三角形的顶点信息:

其中“1:2-5”表示这是三角形的第一个顶点,这个顶点位于索引是2的圆环上(第三个圆环),这个顶点在圆环中的索引是5(也就是第六个顶点)。
5、输入PickPoints([[2,5],[3,5],[2,6]],mesh_origin)可以选定这些顶点

被选中顶点所影响的所有边框线标示为黄色,这个“选中”只是改变外观而已。
6、输入TransVertex(mesh_origin,arr_ij,BABYLON.Matrix.Translation(0,0,-10))将所选的顶点向z轴负方向移动10,被移动的顶点和前面选中的顶点其实没有关系,其中arr_ij也可以直接用索引数组[[2,5],[3,5],[2,6]]代替。

另一类变形可以通过输入:TransVertex(mesh_origin,arr_ij,BABYLON.Matrix.RotationX(Math.PI/2))实现,这可以把被选中的顶点绕X中旋转90度。
输入DeleteMeshes([lines_inpicked])取消被选中的效果,输入ChangeMaterial(mesh_origin,mat_blue)将边框换成蓝色纹理:

可以看到变形后的效果,接下来还可以继续选择顶点并变形
7、输入ExportMesh("1",mat_blue),以txt格式导出babylon模型文件,文件名为“1.txt”

8、将导出的txt改名为9.babylon后放入网站目录中,访问https://ljzc002.github.io/SnowMiku/HTML/LoadBabylon.html模型预览页面,在控制台输入ImportMesh("","../ASSETS/SCENE/","9.babylon")即可加载刚才导出的模型。
二、编程思路:
1、首先要建立一个可以进行各种测试的基础场景,使用的代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>建立一个条带网格生成器,能够输入参数生成起始条带,然后通过命令行选取并修改pathArray,最后导出生成的条带</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的稳定版本-->
<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="lz_newland@163.com";
var machine,canvas,engine,scene,gl,MyGame={};
canvas = document.getElementById("renderCanvas");
engine = new BABYLON.Engine(canvas, true);
gl=engine._gl;//可以结合使用原生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();
}
//从下面开始分成简单测试和对象框架两种架构
//简单测试
//全局对象
var light0//全局光源
,camera0//主相机
;
//四种常用材质
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 () {//自动调整视口尺寸
engine.resize();
});
camera0 =new BABYLON.FreeCamera("FreeCamera", new BABYLON.Vector3(0, 0, -80), scene);
camera0.attachControl(canvas, true);
camera0.speed=0.5;//相机移动速度是默认速度的一半
camera0.minZ=0.01;//相机位置距前视锥截面的距离,也就是说到相机距离小于0.01的图元都不会显示,这个值不能过小,否则Babylon.js内置的鼠标选取将失效
camera0.layerMask=2;//相机的遮罩层次,这个相机将只能显示遮罩层次同为2的网格,如果不设置这个属性,似乎可以显示所有遮罩层次的网格
scene.activeCameras.push(camera0);//将相机加入活跃相机列表,默认情况下Babylon.js只使用一个活跃相机,但是也可以强行使用多个
light0 = new BABYLON.HemisphericLight("Hemi0", new BABYLON.Vector3(0, 1, 0), scene);//半球光源
//三个参照物,MeshBuilder是新版Babylon.js中使用的网格构建对象,之前翻译入门教程时还没有这个对象,它的特点是把一大堆参数统一整理到一个option参数中
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())
{
。
。
。
。
。

