three.js实现的莫比乌丝圈

2024-03-20 20:59
文章标签 实现 js 莫比 three 乌丝

本文主要是介绍three.js实现的莫比乌丝圈,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

three.js实现的莫比乌丝圈

gulaicheng mobius 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实现的莫比乌丝圈的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/830710

相关文章

Python实现AVIF图片与其他图片格式间的批量转换

《Python实现AVIF图片与其他图片格式间的批量转换》这篇文章主要为大家详细介绍了如何使用Pillow库实现AVIF与其他格式的相互转换,即将AVIF转换为常见的格式,比如JPG或PNG,需要的小... 目录环境配置1.将单个 AVIF 图片转换为 JPG 和 PNG2.批量转换目录下所有 AVIF 图

Pydantic中model_validator的实现

《Pydantic中model_validator的实现》本文主要介绍了Pydantic中model_validator的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录引言基础知识创建 Pydantic 模型使用 model_validator 装饰器高级用法mo

AJAX请求上传下载进度监控实现方式

《AJAX请求上传下载进度监控实现方式》在日常Web开发中,AJAX(AsynchronousJavaScriptandXML)被广泛用于异步请求数据,而无需刷新整个页面,:本文主要介绍AJAX请... 目录1. 前言2. 基于XMLHttpRequest的进度监控2.1 基础版文件上传监控2.2 增强版多

Redis分片集群的实现

《Redis分片集群的实现》Redis分片集群是一种将Redis数据库分散到多个节点上的方式,以提供更高的性能和可伸缩性,本文主要介绍了Redis分片集群的实现,具有一定的参考价值,感兴趣的可以了解一... 目录1. Redis Cluster的核心概念哈希槽(Hash Slots)主从复制与故障转移2.

springboot+dubbo实现时间轮算法

《springboot+dubbo实现时间轮算法》时间轮是一种高效利用线程资源进行批量化调度的算法,本文主要介绍了springboot+dubbo实现时间轮算法,文中通过示例代码介绍的非常详细,对大家... 目录前言一、参数说明二、具体实现1、HashedwheelTimer2、createWheel3、n

使用Python实现一键隐藏屏幕并锁定输入

《使用Python实现一键隐藏屏幕并锁定输入》本文主要介绍了使用Python编写一个一键隐藏屏幕并锁定输入的黑科技程序,能够在指定热键触发后立即遮挡屏幕,并禁止一切键盘鼠标输入,这样就再也不用担心自己... 目录1. 概述2. 功能亮点3.代码实现4.使用方法5. 展示效果6. 代码优化与拓展7. 总结1.

Mybatis 传参与排序模糊查询功能实现

《Mybatis传参与排序模糊查询功能实现》:本文主要介绍Mybatis传参与排序模糊查询功能实现,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、#{ }和${ }传参的区别二、排序三、like查询四、数据库连接池五、mysql 开发企业规范一、#{ }和${ }传参的

Docker镜像修改hosts及dockerfile修改hosts文件的实现方式

《Docker镜像修改hosts及dockerfile修改hosts文件的实现方式》:本文主要介绍Docker镜像修改hosts及dockerfile修改hosts文件的实现方式,具有很好的参考价... 目录docker镜像修改hosts及dockerfile修改hosts文件准备 dockerfile 文

基于SpringBoot+Mybatis实现Mysql分表

《基于SpringBoot+Mybatis实现Mysql分表》这篇文章主要为大家详细介绍了基于SpringBoot+Mybatis实现Mysql分表的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可... 目录基本思路定义注解创建ThreadLocal创建拦截器业务处理基本思路1.根据创建时间字段按年进

SpringBoot3实现Gzip压缩优化的技术指南

《SpringBoot3实现Gzip压缩优化的技术指南》随着Web应用的用户量和数据量增加,网络带宽和页面加载速度逐渐成为瓶颈,为了减少数据传输量,提高用户体验,我们可以使用Gzip压缩HTTP响应,... 目录1、简述2、配置2.1 添加依赖2.2 配置 Gzip 压缩3、服务端应用4、前端应用4.1 N