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

相关文章

分布式锁在Spring Boot应用中的实现过程

《分布式锁在SpringBoot应用中的实现过程》文章介绍在SpringBoot中通过自定义Lock注解、LockAspect切面和RedisLockUtils工具类实现分布式锁,确保多实例并发操作... 目录Lock注解LockASPect切面RedisLockUtils工具类总结在现代微服务架构中,分布

Java使用Thumbnailator库实现图片处理与压缩功能

《Java使用Thumbnailator库实现图片处理与压缩功能》Thumbnailator是高性能Java图像处理库,支持缩放、旋转、水印添加、裁剪及格式转换,提供易用API和性能优化,适合Web应... 目录1. 图片处理库Thumbnailator介绍2. 基本和指定大小图片缩放功能2.1 图片缩放的

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

Redis客户端连接机制的实现方案

《Redis客户端连接机制的实现方案》本文主要介绍了Redis客户端连接机制的实现方案,包括事件驱动模型、非阻塞I/O处理、连接池应用及配置优化,具有一定的参考价值,感兴趣的可以了解一下... 目录1. Redis连接模型概述2. 连接建立过程详解2.1 连php接初始化流程2.2 关键配置参数3. 最大连

Python实现网格交易策略的过程

《Python实现网格交易策略的过程》本文讲解Python网格交易策略,利用ccxt获取加密货币数据及backtrader回测,通过设定网格节点,低买高卖获利,适合震荡行情,下面跟我一起看看我们的第一... 网格交易是一种经典的量化交易策略,其核心思想是在价格上下预设多个“网格”,当价格触发特定网格时执行买

python设置环境变量路径实现过程

《python设置环境变量路径实现过程》本文介绍设置Python路径的多种方法:临时设置(Windows用`set`,Linux/macOS用`export`)、永久设置(系统属性或shell配置文件... 目录设置python路径的方法临时设置环境变量(适用于当前会话)永久设置环境变量(Windows系统

Python对接支付宝支付之使用AliPay实现的详细操作指南

《Python对接支付宝支付之使用AliPay实现的详细操作指南》支付宝没有提供PythonSDK,但是强大的github就有提供python-alipay-sdk,封装里很多复杂操作,使用这个我们就... 目录一、引言二、准备工作2.1 支付宝开放平台入驻与应用创建2.2 密钥生成与配置2.3 安装ali

Spring Security 单点登录与自动登录机制的实现原理

《SpringSecurity单点登录与自动登录机制的实现原理》本文探讨SpringSecurity实现单点登录(SSO)与自动登录机制,涵盖JWT跨系统认证、RememberMe持久化Token... 目录一、核心概念解析1.1 单点登录(SSO)1.2 自动登录(Remember Me)二、代码分析三、

PyCharm中配置PyQt的实现步骤

《PyCharm中配置PyQt的实现步骤》PyCharm是JetBrains推出的一款强大的PythonIDE,结合PyQt可以进行pythion高效开发桌面GUI应用程序,本文就来介绍一下PyCha... 目录1. 安装China编程PyQt1.PyQt 核心组件2. 基础 PyQt 应用程序结构3. 使用 Q

Python实现批量提取BLF文件时间戳

《Python实现批量提取BLF文件时间戳》BLF(BinaryLoggingFormat)作为Vector公司推出的CAN总线数据记录格式,被广泛用于存储车辆通信数据,本文将使用Python轻松提取... 目录一、为什么需要批量处理 BLF 文件二、核心代码解析:从文件遍历到数据导出1. 环境准备与依赖库