在做智慧园区项目时,经常遇到植物模型,为了移动端和模型轻量化,则使用three.js代码生成,本节主要讲解植物模型创建思路。
这是玉兰模型
1、模型分为树干、树叶、花3类,树干通过平面图描点,获得变径管道坐标和直径,树叶通过平面图描点拉伸,获得三角形数组,花由花瓣、花托、花丝组成,花丝为管道体、花瓣、花托为拉伸几何,材质使用透明图片。
2、变径管道坐标和直径通过VolatilePipe转换,获得UV数组、positions数组、normals数组。
3、树叶拉伸后UV生成方式
//创建UV值 strDistance为距离值,sheight为拉伸长度,拉伸之后坐标数量增加1倍
function getLsUvs(strDistance, sheight) {
var jsonDce = JSON.parse("[" + strDistance + "]");
var strUv_x = "";
var strUv_y1 = "";
var strUv_y2 = "";
for (var i = 0; i < jsonDce.length; i++) {
if (i == 0) {
strUv_x = "0";
strUv_y1 = "0";
strUv_y2 = "1";
} else {
strUv_x = strUv_x + "," + keep15Decimal(jsonDce[i] / jsonDce[jsonDce.length - 1]);
strUv_y1 = strUv_y1 + "," + "0";
strUv_y2 = strUv_y2 + "," + "1";
}
}
return strUv_x + "#" + strUv_y1 + "$" + strUv_x + "#" + strUv_y2;
}
//四舍五入保留15位小数(若第二位小数为0,则保留一位小数)
function keep15Decimal(num) {
var result = parseFloat(num);
if (isNaN(result)) {
return "传递参数错误,请检查!";
}
result = Math.round(num * 100000000000000) / 100000000000000;
return result;
}
4、树叶三角形数组生成positions数组、normals数组
//三角形数组转Buffer值
function TrgleToBufferValue(triangleArry) {
// 点数
var triangles = triangleArry.length;
//三角形数组
var trianglePointArry = triangleArry;
var geometry = new THREE.BufferGeometry();
var trgle_positions = [];
// 点的法向量
var trgle_normals = [];
var trgle_colors = [];
var trgle_indexs = [];
var trgle_center = [];
//总的各坐标值
var total_x = 0;
var total_y = 0;
var total_z = 0;
var color = new THREE.Color();
// abc, 三个顶点位置
var pA = new THREE.Vector3();
var pB = new THREE.Vector3();
var pC = new THREE.Vector3();
// c点到b点的方向向量
var cb = new THREE.Vector3();
// a点到b点的方向向量
var ab = new THREE.Vector3();
for (var i = 0; i < triangles; i++) {
//if (i > 0) { break;}
var triangleObj = trianglePointArry[i];//一个三角形对象
var onePoint = triangleObj[0];
var twoPoint = triangleObj[1];
var threePoint = triangleObj[2];
// positions
var ax = onePoint[0];
var ay = onePoint[1];
var az = onePoint[2];
var bx = twoPoint[0];
var by = twoPoint[1];
var bz = twoPoint[2];
var cx = threePoint[0];
var cy = threePoint[1];
var cz = threePoint[2];
// 添加一个三角形的3个顶点, 每个顶点有xyz三个数据
trgle_positions.push(keepNumDecimal(ax), keepNumDecimal(ay), keepNumDecimal(az));
trgle_positions.push(keepNumDecimal(bx), keepNumDecimal(by), keepNumDecimal(bz));
trgle_positions.push(keepNumDecimal(cx), keepNumDecimal(cy), keepNumDecimal(cz));
total_x = total_x + ax + bx + cx;
total_y = total_y + ay + by + cy;
total_z = total_z + az + bz + cz;
// 求法向量, 首先设置三角形的三个顶点
pA.set(ax, ay, az);
pB.set(bx, by, bz);
pC.set(cx, cy, cz);
// 求出两个方向向量
cb.subVectors(pC, pB);
ab.subVectors(pA, pB);
// 叉积, 求法向量
cb.cross(ab);
// 单位化这个法向量
cb.normalize();
var nx = cb.x;
var ny = cb.y;
var nz = cb.z;
// 添加法向量到法向量数组中
//三角形的三个顶点的法向量相同, 因此复制三份
trgle_normals.push(keepNumDecimal(nx), keepNumDecimal(ny), keepNumDecimal(nz));
trgle_normals.push(keepNumDecimal(nx), keepNumDecimal(ny), keepNumDecimal(nz));
trgle_normals.push(keepNumDecimal(nx), keepNumDecimal(ny), keepNumDecimal(nz));
}
//计算中点
var center_x = parseInt(total_x / (triangles * 3));
var center_y = parseInt(total_y / (triangles * 3));
var center_z = parseInt(total_z / (triangles * 3));
trgle_center = [center_x, center_y, center_z];
return { uvs: [], positions: trgle_positions, normals: trgle_normals, center: trgle_center };
}
5、通过BufferGeometry生成模型
//获得BufferMesh
function GetOneBufferGeometry(arryPositions, arryNormals, arryUvs, arryIndexs, meshMaterial, meshName) {
var geometry = new THREE.BufferGeometry();
var positions = arryPositions;
// 点的法向量
var normals = arryNormals;
var uvs = arryUvs;
//var colors = arryColors;
//var indexs = arryIndexs;
// 加入位置信息
geometry.addAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
// 加入法向量信息
geometry.addAttribute('normal', new THREE.Float32BufferAttribute(normals, 3));
//有UV数组时,添加UV映射
if (uvs.length > 0) {
//设置UV UV坐标的数量要大于等于三角形的数量,否则模型空白
geometry.addAttribute('uv', new THREE.Float32BufferAttribute(uvs, 2));
}
geometry.computeBoundingSphere();
var mesh = new THREE.Mesh(geometry, meshMaterial);
mesh.name = meshName;
return mesh;
}
6、在三维场景中,多数模型都可以使用变径管道和线条拉伸结合,重成模型UV、positions、normals,使用BufferGeometry快速渲染。
技术交流:873201677@qq.com