本文主要是介绍three.js实现的莫比乌丝圈,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
three.js实现的莫比乌丝圈
<!DOCTYPE html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>three.js 实现的莫比乌丝圈</title>
<style type="text/css">
body{
background:#333333;
}
</style>
<script src="three-r93.min.js"></script>
<script src="TrackballControls.js"></script>
<script src="dat.gui.min.js"></script>
<script src="stats.min.js"></script>
<script src="Detector.js"></script>
</head>
<body>
<SCRIPT LANGUAGE="JScript">
function getrandomcolor()
{
var c1,c2,c3;
c1=Math.round((Math.random()*256));
c2=Math.round((Math.random()*256));
c3=Math.round((Math.random()*256));
// document.write("随机数:"+c1+"."+c2+"."+c3);
return "#"+prefixzero(c1.toString(16),2,1)+prefixzero(c2.toString(16),2,1)+prefixzero(c3.toString(16),2,1);
}
//按要求的宽度输出字串,另上前缀零:
//
//flag: 1 - 如strg的宽度大于wdth,则输出strg (缺省)
// 2 - 如strg的宽度大于wdth,则输出前wdth个字符的strg
// 3 - 如strg的宽度大于wdth,则输出后wdth个字符的strg
function prefixzero(strg,wdth,flag)
{
var zero ="000000000000000000000000000";
var slen=strg.length;
var zlen=zero.length;
var prez;
if (slen>=wdth) {
if (flag == 2) {
return strg.substDonut0(0, wdth)
} else if (flag == 3) {
return strg.substDonut0(slen-wdth, slen)
} else //if (flag == 1)
{
return strg;
}
} else {
prez = zero.substDonut0(0, wdth-slen)
return prez + strg;
}
}
function Deg2Rad(Deg)
{
return (Deg*Math.PI / 180);
}
//点x1,y1 经转af(角度)后的新点坐标x2,y2:
function RotPnt(x1,y1,af)
{
this.x0 = x1;
this.y0 = y1;
// var alfa1 = Deg2Rad(af);
var alfa1 = af;
this.x1 = x1 * Math.cos(alfa1) - y1 * Math.sin(alfa1);
this.y1 = x1 * Math.sin(alfa1) + y1 * Math.cos(alfa1);
this.x2 = originx0+x1 * Math.cos(alfa1) - y1 * Math.sin(alfa1);
this.y2 = originy0+x1 * Math.sin(alfa1) + y1 * Math.cos(alfa1);
}
//https://ithanmang.gitee.io/threejs/home/201806/20180629/01-line.html
var stats = initStats();
var scene, camera, renderer, controls, light, gui;
function initScene() {
scene = new THREE.Scene();
}
function initCamera() {
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);
camera.position.set(0, 200, 300);
camera.lookAt(new THREE.Vector3(0, 0, 0));
}
function initRenderer() {
if (Detector.webgl){
renderer = new THREE.WebGLRenderer({antialias : true,autoClear : true});
}else{
renderer = new THREE.CanvasRenderer();
}
renderer.setSize(window.innerWidth, window.innerHeight);
//渲染
//antialias:true增加抗锯齿效果
renderer.setClearColor(new THREE.Color(0x222222));//设置窗口背景颜色为黑
renderer.setSize(window.innerWidth, window.innerHeight);//设置窗口尺寸
//将renderer关联到container,这个过程类似于获取canvas元素
//container.appendChild(renderer.domElement);
document.body.appendChild( renderer.domElement );
}
function initControls() {
controls = new THREE.TrackballControls(camera, renderer.domElement);
}
function initLight() {
//给场景添加光源
// // 点光源
// light = new THREE.SpotLight( 0xEAEAEA );
// light.position.set(-100, 200, 200);
// scene.add(light);
//自然光
var ambientLight = new THREE.AmbientLight( 0xffffff );
scene.add( ambientLight );
//平行光源
var directionalLight = new THREE.DirectionalLight( 0xffffff );
directionalLight.position.set( 1, 0.75, 0.5 ).normalize();
scene.add( directionalLight );
}
function drawline(p)
{
// 构造线段
var lineGeometry = new THREE.Geometry();
lineGeometry.vertices.push(new THREE.Vector3(p[0][0],p[0][1],p[0][2]));
lineGeometry.vertices.push(new THREE.Vector3(p[1][0],p[1][1],p[1][2]));
var lineMaterial = new THREE.LineDashedMaterial({ color : 0x9B3333 });
var line = new THREE.Line(lineGeometry, lineMaterial);
//line.computeLineDistances(); // 计算线条间的距离
scene.add(line);
}
function drawCircle(scene, meshMaterial, x,y,z,r,s,a1,a2)
{
var circle = new THREE.Mesh(new THREE.CircleGeometry(r, s, a1,a2), meshMaterial);
//circle.translateOnAxis(axis,100)
circle.translateX(x);
circle.translateY(y);
circle.translateZ(z);
circle.rotateX(0);
circle.rotateY(Math.PI/3);
circle.rotateZ(0);
scene.add(circle);
}
function initContent() {
var helperXZ = new THREE.GridHelper(1200, 120, 0x404040, 0x404040 );
helperXZ.position.set( 600,0 ,600);
scene.add(helperXZ);
var helperXY = new THREE.GridHelper(1200, 120, 0x404040, 0x404040 );
helperXY.position.set( 600,600,0 );
helperXY.rotation.x = Math.PI/2;
scene.add(helperXY);
var helperYZ = new THREE.GridHelper(1200, 120, 0x404040, 0x404040 );
helperYZ.position.set( 0,600,600 );
helperYZ.rotation.z = Math.PI/2;
scene.add(helperYZ);
var axesHelper = new THREE.AxesHelper(1200);
scene.add(axesHelper);
}
// radius:圆环半径
// tube:管道半径
// radialSegments:径向的分段数
// tubularSegments:管的分段数,详见下图
// arc:圆环面的弧度,缺省值为Math.PI * 2
//创建一个球
function TorusGeometry(x,y,z,radius, tube, radialSegments, tubularSegments, arc){
var TorusGeo = new THREE.TorusGeometry(radius, tube, radialSegments, tubularSegments, arc);
var sphereMat = new THREE.MeshLambertMaterial({//创建材料
color:0x788085,
wireframe:false
});
var TorusMesh = new THREE.Mesh(TorusGeo, sphereMat);//创建球体网格模型
TorusMesh.position.set(x, y, z);//设置球的坐标
//scene.add(sphereMesh);//将球体添加到场景
return TorusMesh;
}
//创建一个球
function sphere(x,y,z,r){
var sphereGeo = new THREE.SphereGeometry(r, 40, 40);//创建球体 半径、经度、纬度
var sphereMat = new THREE.MeshLambertMaterial({//创建材料
color:0x0000FF,
wireframe:false
});
var sphereMesh = new THREE.Mesh(sphereGeo, sphereMat);//创建球体网格模型
sphereMesh.position.set(x, y, z);//设置球的坐标
//scene.add(sphereMesh);//将球体添加到场景
return sphereMesh;
}
//创建圆柱体
function cylinder(x,y,z,r,l){
//创建圆柱体,括号里的参数分别对应:顶圆半径、底圆半径、圆柱体高度、经度、纬度;
var cylinderGeo = new THREE.CylinderGeometry(r, r ,l ,20 ,20);
// console.log(r,l);
//var texture = THREE.ImageUtils.loadTexture("img/5.jpg",null,function(t){}); //图片地址可使用本地,同根目录下文件夹即可 deprecated
var cylinderMat = new THREE.MeshLambertMaterial({//创建材料
//map:new THREE.TextureLoader().load("img/5.jpg"),
color:0xFF6600,
wireframe:false
});
// var cylinderMat = new THREE.MeshBasicMaterial({//创建材料
// //map:new THREE.TextureLoader().load("img/0.jpg"),
// //side: THREE.DoubleSide,
// color: 0XFF7700,
// wireframe:false
// });
//创建圆柱体网格模型
var cylinderMesh = new THREE.Mesh(cylinderGeo, cylinderMat);
cylinderMesh.position.set(x,y,z);//设置圆柱坐标
cylinderMesh.rotation.x = Math.PI/2;
// cylinderMesh.rotation.y = Math.PI/4;
// cylinderMesh.rotation.z = Math.PI/6;
//scene.add(cylinderMesh);//向场景添加圆柱体
return cylinderMesh;
}
function initStats() {
var stats = new Stats();
stats.setMode(0);
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.body.appendChild(stats.domElement);
return stats;
}
function update() {
stats.update();
controls.update();
controls.handleResize();
}
function init() {
initScene();
initRenderer();
initCamera();
initLight();
initControls();
initContent();
initStats();
var X=300,Y=300,Z=200;
var R=150,x,y,z;
var p =[];
var alfa;
var group=[];
var sph1;
var sph2;
var cyli;
var MOBIUS = 0; //莫比乌丝圈反转个数
var BETA = Math.PI/6.0; //沿中轴的倾斜角
var Torus = TorusGeometry(X,Y,Z,R, 1, 20 , 360, Math.PI * 2);
scene.add(Torus);
for(var i=0;i<360;i=i+2)
{
alfa = i*Math.PI/180.0;
x = X + R * Math.cos(alfa);
y = Y + R * Math.sin(alfa);
z = Z ;
// if(i<180)
// z=Z*i/360
// else
// z=Z*(360-i)/360
// drawline(p[i]);
//console.log(i,x,y,z,alfa);
group = new THREE.Group();
sph1 = sphere (0,0,0+60, 3);
sph2 = sphere (0,0,0-60, 3);
cyli = cylinder (0,0,0, 2,120 );
group.add(sph1 );
group.add(sph2 );
group.add(cyli );
group.rotateOnAxis(new THREE.Vector3(-1*Math.sin(alfa), 1*Math.cos(alfa),0), alfa*MOBIUS/2+BETA);
group.position.set(x,y,z);
scene.add(group);
}
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
update();
}
init();
animate();
</script>
</body>
</html>
这篇关于three.js实现的莫比乌丝圈的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!