本文原创 如转载请注明出处!!!

本博客地址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模型展示以及体积、表面积计算的更多相关文章

  1. three.js实现3D模型展示

    由于项目需要展示3d模型,所以对three做了点研究,分享出来 希望能帮到大家 先看看效果: three.js整体来说 不是很难 只要你静下心来研究研究 很快就会上手的 首先我们在页面上需要创建一个能 ...

  2. 基于playcanvas的3d模型展示

    1.使用基于playcanvas的离线编辑器制作模型效果 2.使用基于playcanvas的开发包读取编辑好的3d模型进行在线3d展示 效果如下:

  3. ANDROID嵌入式应用Unity3D视图(画廊3D模型)

    转载请注明来自大型玉米的博客文章(http://blog.csdn.net/a396901990),谢谢支持! 效果展示:   watermark/2/text/aHR0cDovL2Jsb2cuY3N ...

  4. 在SAP UI中使用纯JavaScript显示产品主数据的3D模型视图

    在Jerry写这篇文章时,通过Google才知道,SAP其实是有自己的3D模型视图显示解决方案的. 故事要从Right Hemisphere说起,这是一家专业的企业级2D/3D模型浏览及转换的软件供应 ...

  5. 基于 webGL 的元素周期表 3D 交互展示

    前言 之前在网上看到别人写的有关元素周期表的文章,深深的勾起了一波回忆,记忆里初中时期背的“氢氦锂铍硼,碳氮氧氟氖,钠镁铝硅磷,硫氯氩钾钙”.“养(氧)龟(硅)铝铁盖(钙),哪(钠)家(钾)没(镁)青 ...

  6. 扒几个 3D 模型备用

    前言 在上一篇中,我展示了 OpenGL 开发的基本过程,算是向 3D 世界迈出的一小步吧.对于简单的 3D 物体,比如立方体.球体.圆环等等,我们只需要简单的计算就可以得到他们的顶点的坐标.但是仅仅 ...

  7. Mask裁切UI粒子特效或者3D模型

    刚好前几天有人问我这个问题,再加上新项目也可能用,所以这两天就研究了一下.其实如果粒子特效 和3D模型 都用RenderTexture来做的话就不会有裁切的问题,但是粒子特效用RenderTextur ...

  8. 如何让NGUI的对象在3D模型之上

    假设场景中有两台摄像机, 一台是NGUI的摄像机, 另外一台是投影摄像机. 投影摄像机看的是3D模型, Depth比NGUI的摄像机要大, Clear Flags设置的是Depth only. 现在想 ...

  9. 【Android界面实现】可旋转的汽车3D模型效果的实现

    转载请注明出处:http://blog.csdn.net/zhaokaiqiang1992 今天要给大家介绍的是怎样实现可旋转的汽车3D模型. 先看实现效果 这仅仅是静态图,实际上,这个模型是能够依据 ...

随机推荐

  1. Spring data mongodb 聚合,投射,内嵌数组文档分页.

    尽量别直接用 DBObject  ,Spring data mongodb 的api 本来就没什么多大用处,如果还直接用 DBObject 那么还需要自己去解析结果,说动做个对象映射,累不累 Spri ...

  2. Phpstrom操作Git从服务器端克隆代码到本地

    1.第一步点开Git 2.添加项目的路径 第一个框是你所在的项目路径,后缀名是.git,这里我用的是HTTPS的方式(还有一种是SSH) 第二是你要克隆到所在目录,我的是在Apache下面的htdoc ...

  3. 源码编译安装Apache-附一键部署脚本

    1.进入apache官网https://www.apache.org/,点击Download 2.如图选择 3.选择httpd 4.下载两个包,2.2为CentOS6使用,2.4为CentOS7使用 ...

  4. eclipse导入/编译hadoop源代码

    1. 确保安装好JDK和eclipse 详细教程见: http://blog.csdn.net/kangdakangdaa/article/details/11364985 2. 安装 Subclip ...

  5. 决策树学习笔记(Decision Tree)

    什么是决策树? 决策树是一种基本的分类与回归方法.其主要有点事模型具有可得性,分类速度快.学习时,利用训练数据,根据损失函数最小化原则建立决策树模型:预测时,对新数据,利用决策树模型进行分类. 决策树 ...

  6. Windows平台监听服务无法启动报报TNS-12560 TNS-00530案例

      在Windows Server 2012平台使用命令启动监听服务时遇到了TNS-12560 & TNS-00530错误. C:\Users>lsnrctl start GEW_LIS ...

  7. Davinci DM6446开发攻略——DSP开发工程建立

    前段时间一直忙一个项目,同时在生活上时时提防和抵抗中国地沟油.国外核心转基因调和油.大豆油.色拉油.大米玉米.可怕的喂药鱼.药水泡农药喷无虫咬的青菜,所以没时间打理自己的博客,让开发攻略停顿了一段时间 ...

  8. Java并发系列[7]----CountDownLatch源码分析

    CountDownLatch(闭锁)是一个很有用的工具类,利用它我们可以拦截一个或多个线程使其在某个条件成熟后再执行.它的内部提供了一个计数器,在构造闭锁时必须指定计数器的初始值,且计数器的初始值必须 ...

  9. Trouble HDU - 4334

    Hassan is in trouble. His mathematics teacher has given him a very difficult problem called 5-sum. P ...

  10. 常用的freemark语法(三)

    一,符号的意义 1.0,单问号 ?后面要加关键字,例如:<#if object?exists>object对象不为空</#if> <#if str??>${str? ...