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

相关文章

Java实现检查多个时间段是否有重合

《Java实现检查多个时间段是否有重合》这篇文章主要为大家详细介绍了如何使用Java实现检查多个时间段是否有重合,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录流程概述步骤详解China编程步骤1:定义时间段类步骤2:添加时间段步骤3:检查时间段是否有重合步骤4:输出结果示例代码结语作

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

Java覆盖第三方jar包中的某一个类的实现方法

《Java覆盖第三方jar包中的某一个类的实现方法》在我们日常的开发中,经常需要使用第三方的jar包,有时候我们会发现第三方的jar包中的某一个类有问题,或者我们需要定制化修改其中的逻辑,那么应该如何... 目录一、需求描述二、示例描述三、操作步骤四、验证结果五、实现原理一、需求描述需求描述如下:需要在

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

如何通过Python实现一个消息队列

《如何通过Python实现一个消息队列》这篇文章主要为大家详细介绍了如何通过Python实现一个简单的消息队列,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录如何通过 python 实现消息队列如何把 http 请求放在队列中执行1. 使用 queue.Queue 和 reque

Python如何实现PDF隐私信息检测

《Python如何实现PDF隐私信息检测》随着越来越多的个人信息以电子形式存储和传输,确保这些信息的安全至关重要,本文将介绍如何使用Python检测PDF文件中的隐私信息,需要的可以参考下... 目录项目背景技术栈代码解析功能说明运行结php果在当今,数据隐私保护变得尤为重要。随着越来越多的个人信息以电子形

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

使用Python快速实现链接转word文档

《使用Python快速实现链接转word文档》这篇文章主要为大家详细介绍了如何使用Python快速实现链接转word文档功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 演示代码展示from newspaper import Articlefrom docx import

前端原生js实现拖拽排课效果实例

《前端原生js实现拖拽排课效果实例》:本文主要介绍如何实现一个简单的课程表拖拽功能,通过HTML、CSS和JavaScript的配合,我们实现了课程项的拖拽、放置和显示功能,文中通过实例代码介绍的... 目录1. 效果展示2. 效果分析2.1 关键点2.2 实现方法3. 代码实现3.1 html部分3.2