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

相关文章

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略 1. 特权模式限制2. 宿主机资源隔离3. 用户和组管理4. 权限提升控制5. SELinux配置 💖The Begin💖点点关注,收藏不迷路💖 Kubernetes的PodSecurityPolicy(PSP)是一个关键的安全特性,它在Pod创建之前实施安全策略,确保P

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、