3D模型展示以及体积、表面积计算
本文原创 如转载请注明出处!!!
本博客地址http://www.cnblogs.com/we-jack
本文原创,如果有同样需求的小伙伴请第一时间联系我 或者在留言区留言
上次为大家提供了3D模型的展示之后 发现网上有很多想要计算3D模型表面积和体积的需求 那么经过掉了几百根头发的艰辛历程之后 终于为大家解决了这一需求 按照惯例先上图为证

当然我这样写 有的人认为我在忽悠 你说你的体积 表面积是这就是这啊 没有可验证性么
那好~ 没有对比就没有伤害 下面是某3D打印网站上传同样模型后给出的数据 各位看官们看好了

实打实的讲道理 他给出的体积还是负值 我都给转正了[:斜眼笑]
好了 闲话少絮 直接给大家上代码 (JS代码如果有需要的直接留言找我)
<head>
<meta charset="UTF-8" />
<title>WebGL</title>
<script type="text/javascript" charset="utf-8" src="js/three.js"></script>
<script src="js/STLLoader.js"></script>
<script src="js/TrackballControls.js"></script>
<script src="js/AsciiEffect.js"></script>
<style>body{overflow:hidden;background:#eee}</style>
</head>
先引入我们几个必须的JS (之前有人问OBJ模型怎么上传 这个问题可以直接百度three.js的使用方法)
接下来用JS定义一个画布
var WIDTH,HEIGHT;
var renderer;
定义好了之后 我们初始化一下我们的three
function initThree() {
WIDTH = document.documentElement.clientWidth/2;<!--{foreach from=$recommended_goods item=rgoods}--> <!-- {/foreach} -->
HEIGHT = document.documentElement.clientHeight/2;
/* 渲染器 */
renderer = new THREE.WebGLRenderer();
renderer.setSize(WIDTH , HEIGHT);
renderer.setClearColor(new THREE.Color(0x66666));
renderer.gammaInput = true;
renderer.gammaOutput = true;
document.body.appendChild(renderer.domElement);
}
下来是摄像头定义
/* 摄像头 */
var camera;
function initCamera() {
var VIEW_ANGLE = 45,
ASPECT = WIDTH / HEIGHT,
NEAR = 0.1,
FAR = 10000;
camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
camera.position.set(20, 0, 0);
//设置视野的中心坐标
camera.lookAt(scene.position);
}
场景植入
/* 场景 */
var scene;
function initScene() {
scene = new THREE.Scene();
}
灯光定义
/* 灯光 */
var light,light2,light3;
function initLight() {
//平行光
light = new THREE.DirectionalLight(0xFFFFFF);
light.position.set(0, 99, 0).normalize();
scene.add(light);
//环境光
light2 = new THREE.AmbientLight(0x999999);
scene.add(light2);
//点光源
light3 = new THREE.PointLight(0x00FF00);
light3.position.set(300, 0, 0);
scene.add(light3);
}
动画定义
function animate() {
requestAnimationFrame( animate );
controls.update();
effect.render( scene, camera );
}
调用所有方法开始执行
function threeStart() {
initThree();
initScene();
initCamera();
initLight();
initObject();
initControl();
animate();
}
显示对象
/* 显示对象 */
var cube;
function initObject(){
// ASCII file
var loader = new THREE.STLLoader(); loader.addEventListener( 'load', function ( event ) {
var loading = document.getElementById("Loading");
loading.parentNode.removeChild(loading);
var geometry = event.content;
var Area = 0.0;
var volumes = 0.0; for(var i = 0; i < geometry.faces.length; i++){
var Pi = geometry.faces[i].a;
var Qi = geometry.faces[i].b;
var Ri = geometry.faces[i].c; var P = new THREE.Vector3(geometry.vertices[Pi].x, geometry.vertices[Pi].y, geometry.vertices[Pi].z);
var Q = new THREE.Vector3(geometry.vertices[Qi].x, geometry.vertices[Qi].y, geometry.vertices[Qi].z);
var R = new THREE.Vector3(geometry.vertices[Ri].x, geometry.vertices[Ri].y, geometry.vertices[Ri].z);
// volumes += volumeOfT(P, Q, R); 会产生负数..............
volumes += volumeOfT(R, Q, P);
Area += AreaOfTriangle(R, Q, P);
}
SurfaceArea = (Area / 100).toFixed(2);
console.log('表面积:'+SurfaceArea);
loadedObjectVolume = (volumes / 1000).toFixed(2);
console.log('体积:'+loadedObjectVolume); //砖红色
var material = new THREE.MeshPhongMaterial( { ambient: 0xff5533, color: 0xff5533, specular: 0x111111, shininess: 200 } );
//纯黑色
// var material = new THREE.MeshBasicMaterial( { envMap: THREE.ImageUtils.loadTexture( 'http://localhost:8080/textures/metal.jpg', new THREE.SphericalReflectionMapping() ), overdraw: true } ) ;
//粉色 带阴影
// var material = new THREE.MeshLambertMaterial( { color:0xff5533, side: THREE.DoubleSide } );
//灰色
// var material = new THREE.MeshLambertMaterial({color: 000000}); //材质设定 (颜色) var mesh = new THREE.Mesh( geometry, material );
var center = THREE.GeometryUtils.center(geometry);
var boundbox=geometry.boundingBox;
var vector3 = boundbox.size(null);
var vector3 = boundbox.size(null);
console.log(vector3);
var scale = vector3.length();
camera.position.set(scale, 0, 0);
camera.lookAt(scene.position);
scene.add(camera); //利用一个轴对象以可视化的3轴以简单的方式。X轴是红色的。Y轴是绿色的。Z轴是蓝色的。这有助于理解在空间的所有三个轴的方向。要添加这个帮手,使用下面的代码:
var axisHelper = new THREE.AxisHelper(800);
scene.add(axisHelper); //周围边框
bboxHelper = new THREE.BoxHelper();
bboxHelper.visible = true;
var meshMaterial = material;
mainModel = new THREE.Mesh(geometry, meshMaterial);
bboxHelper.update(mainModel);
bboxHelper.geometry.computeBoundingBox();
scene.add(bboxHelper); //它吸引的特定对象3D对象(它看起来像金字塔)与线几何,这有助于可视化什么指定摄像机包含在它的视锥。
// var cameraParObj = new THREE.Object3D();
// cameraParObj.position.y = 200;
// cameraParObj.position.z = 700;
// scene.add(cameraParObj);
// perspectiveCamera = new THREE.PerspectiveCamera(90, window.innerWidth / window.innerHeight, 0.01, 1500);
// cameraParObj.add(perspectiveCamera);
// var cameraHelper = new THREE.CameraHelper(perspectiveCamera);
// scene.add(cameraHelper); //地板网格
//var gridHelper = new THREE.GridHelper(500, 40); // 500 is grid size, 20 is grid step
//gridHelper.position = new THREE.Vector3(0, 0, 0);
//gridHelper.rotation = new THREE.Euler(0, 0, 0);
//scene.add(gridHelper);
//var gridHelper2 = gridHelper.clone();
//gridHelper2.rotation = new THREE.Euler(Math.PI / 2, 0, 0);
//scene.add(gridHelper2);
//var gridHelper3 = gridHelper.clone();
//gridHelper3.rotation = new THREE.Euler(Math.PI / 2, 0, Math.PI / 2);
//scene.add(gridHelper3); //var grid = new THREE.GridHelper(300, 40, 25, [0, 0, 1], 0x000055, 0.2, true, "#FFFFFF", "left");
//scene.add(grid); mesh.position.set(0,0,0);
// mesh.position.x = scene.position.x;
// mesh.position.y = scene.position.y ;
// mesh.position.z = scene.position.z;
scene.add(mesh); renderer.clear();
renderer.render(scene, camera);
} );
// loader.load( '3dfile/莫比乌斯环.STL' );
loader.load( '3dfile/狼人.STL' );
} //控制
var effect;
var controls;
function initControl(){
effect = new THREE.AsciiEffect( renderer );
effect.setSize( WIDTH, HEIGHT );
controls = new THREE.TrackballControls( camera,renderer.domElement);
}
代码上面的注释都非常清楚了,根据这些我们很清楚的会看到在求体积的时候 我们必须先要得到一个四面体的有符号体积 - 基于你的三角形并在原点处排在最前面。音量的标志来自您的三角形是否指向原点的方向。(三角形的法线本身取决于顶点的顺序,这就是为什么你在下面看不到它的原因。)
这一点大家要是不懂的话 可以去搜索一下一种计算任意非凸多面体积分性质的符号方法 这个方法详细的讲解了 多面体的体积算法
在代码的77行处我们可以看到 我在拿到多面体的每一个面之后进行了遍历从而求出中心点到每个面的距离 再根据THREE提供的方法 得到三个有效点 然后将所有的点进行组合 使用 (-v321 + v231 + v312 - v132 - v213 + v123)/6.0; 求得体积
在计算表面积的时候出现了一点问题 如果模型出现在网格下面那么就会出现负值 但是数字的值是没有问题的 所以我们可以去将组合重新排序从而使负值转正 当然也可以使用绝对值的方法使数值转正
最后声明 如需转载请注明出处!!!
本文原创,如果有同样需求的小伙伴请第一时间联系我 或者在留言区留言
3D模型展示以及体积、表面积计算的更多相关文章
- three.js实现3D模型展示
由于项目需要展示3d模型,所以对three做了点研究,分享出来 希望能帮到大家 先看看效果: three.js整体来说 不是很难 只要你静下心来研究研究 很快就会上手的 首先我们在页面上需要创建一个能 ...
- 基于playcanvas的3d模型展示
1.使用基于playcanvas的离线编辑器制作模型效果 2.使用基于playcanvas的开发包读取编辑好的3d模型进行在线3d展示 效果如下:
- ANDROID嵌入式应用Unity3D视图(画廊3D模型)
转载请注明来自大型玉米的博客文章(http://blog.csdn.net/a396901990),谢谢支持! 效果展示: watermark/2/text/aHR0cDovL2Jsb2cuY3N ...
- 在SAP UI中使用纯JavaScript显示产品主数据的3D模型视图
在Jerry写这篇文章时,通过Google才知道,SAP其实是有自己的3D模型视图显示解决方案的. 故事要从Right Hemisphere说起,这是一家专业的企业级2D/3D模型浏览及转换的软件供应 ...
- 基于 webGL 的元素周期表 3D 交互展示
前言 之前在网上看到别人写的有关元素周期表的文章,深深的勾起了一波回忆,记忆里初中时期背的“氢氦锂铍硼,碳氮氧氟氖,钠镁铝硅磷,硫氯氩钾钙”.“养(氧)龟(硅)铝铁盖(钙),哪(钠)家(钾)没(镁)青 ...
- 扒几个 3D 模型备用
前言 在上一篇中,我展示了 OpenGL 开发的基本过程,算是向 3D 世界迈出的一小步吧.对于简单的 3D 物体,比如立方体.球体.圆环等等,我们只需要简单的计算就可以得到他们的顶点的坐标.但是仅仅 ...
- Mask裁切UI粒子特效或者3D模型
刚好前几天有人问我这个问题,再加上新项目也可能用,所以这两天就研究了一下.其实如果粒子特效 和3D模型 都用RenderTexture来做的话就不会有裁切的问题,但是粒子特效用RenderTextur ...
- 如何让NGUI的对象在3D模型之上
假设场景中有两台摄像机, 一台是NGUI的摄像机, 另外一台是投影摄像机. 投影摄像机看的是3D模型, Depth比NGUI的摄像机要大, Clear Flags设置的是Depth only. 现在想 ...
- 【Android界面实现】可旋转的汽车3D模型效果的实现
转载请注明出处:http://blog.csdn.net/zhaokaiqiang1992 今天要给大家介绍的是怎样实现可旋转的汽车3D模型. 先看实现效果 这仅仅是静态图,实际上,这个模型是能够依据 ...
随机推荐
- Mysql取随机数据效率测试(400W条中读取100条)
测试数据表的创建在文章:http://www.cnblogs.com/wt645631686/p/6868192.html 先看一下我的SQL方案 SELECT * FROM `emp` WHERE ...
- Quartz基本使用
1.Quartz概述:简单的说就是java的一个定时任务的框架,没有那么复杂的解释,跟前端的定时器一样.在了解它之前,首先熟悉几个概念. 2.基本概念 2.1 Job:表示一个工作,要执行的具体内容. ...
- CentOS7网卡命名规则
CentOS6之前基于传统的命名方式如:eth1,eth0.... Centos7提供了不同的命名规则,默认是基于固件.拓扑.位置信息来分配.这样做的优点是命名是全自动的.可预知的,缺点是比eth0. ...
- linux Cacti监控服务器搭建
搭建Cacti监控服务器 部署安装环境(lamp) [root@zhuji1 ~]# yum -y install httpd [root@zhuji1 ~]# yum -y install php ...
- python函数式编程之迭代器
什么是迭代器 顾名思义,就是更新换代的意思 python中的迭代器就是根据上一个结果生成下一个结果,一直循环往复不断重复的过程 迭代器有两个特点: 1.不断重复同一个过程 2.根据上一个结果生成下一个 ...
- 20 个 CSS 高级技巧汇总
原文:https://segmentfault.com/a/1190000003936841 使用技巧会让人变的越来越懒,没错,我就是想让你变懒.下面是我收集的CSS高级技巧,希望你懒出境界. 1. ...
- SPI FLASH与NOR FLASH的区别?
1.SPI Flash (即SPI Nor Flash)是Nor Flash的一种: 2.NOR Flash根据数据传输的位数可以分为并行(Parallel)NOR Flash和串行(SPI)NOR ...
- 利用apache自带的工具 分割访问日志
httpd.conf中CustomLog logs/access.log common 改成 CustomLog "|c:/apache/bin/rotatelogs.exe c:/apac ...
- php学习笔记之一维数组
数组是指可以存放多个数据的数据类型. PHP中数组是一组关键字(key)和值(values)的集合,值可以是任何一种数据类型, 一维数组的创建方式: $arr=array(2,5,6); $arr=a ...
- R语言实现SOM(自组织映射)模型(三个函数包+代码)
每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- SOM自组织映射神经网络模型 的R语言实现 笔 ...