آموزش Three.js

saalek110

Well-Known Member
کل بسته را هم لازم نیست از لینک زیر دانلود کنید(با زدن دکمه سبز و زدن download zip)
۳۵۶ مگا.


اون فایلهایی که نیاز دارید را دانلود کنید.
در مورد نیازهای فایل لود کننده obj file در چند پست بالاتر بحث کردیم.

ولی من هنوز با در اختیار گذاشتن همون چند تا فایل در اختیار برنامه، برنامه را امتحان نکردم. ولی احتمالا اجرا میشه.

پنج شش مگا فایلهای اصلی اش است.
اون تا فایل هم هر کدام بیست تا سی کیلو بیشتر نیست.

همچنین از لینک بالا ، تکسچر و عکس های خوبش را دانلود کنید. یا همشو دانلود کنید اگر دوست دارید.

پوشه تکسچرهایش:

 
آخرین ویرایش:

saalek110

Well-Known Member
نرم افزار رایگان در کامپیوتر برای آبجکت سازی ، Blender است.

برای گوشی:

شصت مگا.

فعلا این را سراغ دارم ولی شاید برای این کار نرم افزارهای زیادی باشد و از این بهتر هم باشه.

ولی با این هم کارهای جالبی میشه کرد.
در یوتیوب آموزش کار باهاش است. خودش هم فیلم هایی آموزشی در خودش داره.
 
آخرین ویرایش:

saalek110

Well-Known Member

گیاهان و تکسچر گیاهی ، مثل تنه درخت.

۳ گیگ.
 

saalek110

Well-Known Member
من امروز خیلی از مثالها را مرور کردم. این تکه را همشون دارند:

JavaScript:
<script type="importmap">
            {
                "imports": {
                    "three": "../build/three.module.js",
                    "three/addons/": "./jsm/"
                }
            }
        </script>

        <script type="module">

            import * as THREE from 'three';

            import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
            import { PLYExporter } from 'three/addons/exporters/PLYExporter.js';
            import { GUI } from 'three/addons/libs/lil-gui.module.min.js';

            let scene, camera, renderer, exporter, mesh;

کار این تکه کد اول برنامه اینه که اول فایلهای اصلی را import می کنه ، بعدش بنا به نیاز ، از فایلهای پوشه های واقع در پوشه jsm استفاده می کند. که یک سری فایل با پسوند js هستند که کدهایی گه کارها را انجام میدهد داخل اونهاست و ما با نگاه به اون فایلها از توابع اونها استفاده می کنیم،


البته فایلهای مختلفی را import می کنند ولی همشون این import را دارند.

ولی برنامه ای که ما تا حالا کار می کردیم ، این تکه را نداره. فکر کنم بهتره قالب خود را عوض کنیم و قالب خود را با مثالهای برنامه یکی بکنیم.

ولی مجبور نیستیم داخل اون کدها کار کنیم. من بیرن بسته کار کردم و مسیر را به شکل زیر دادم.
اسم پوشه بسته را هم می بینید عوض کردم و گذاشتم three-js-master




JavaScript:
<script type="importmap">
            {
                "imports": {
                    "three": "./three-js-master/build/three.module.js",
                    "three/addons/": "./three-js-master/examples/jsm/"
                }
            }
        </script>

        <script type="module">

            import * as THREE from 'three';

            import { OBJLoader } from 'three/addons/loaders/OBJLoader.js';
            import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

            let camera, scene, renderer;

            let object;

نمونه برنامه داخل پوشه examples است , یک طبقه بالاتر از پوشه jsm و یک طبقه پایین تر از پوشه buid
برای همین آدرس ها را در نمونه برنامه ها این جوری می دهند.

ولی من بیرون بسته کار می کنم و آدرس ها را از بالا می دهم.
 

saalek110

Well-Known Member
در برنامه اخیر که کار کردیم و کارش load فایل obj است دو تا فایل صدا زده شده ، یعنی import شده ، یکی فایل لودکننده فایل obj است و دیگری فایل کنترل است. احتمالا اینکه میشه صحنه را چرخاند و بزرگ و کوچک کردن شکل را ، توسط کنترل است.
 

saalek110

Well-Known Member

این سورس از این جهت جالبه که یک مکعب است که میشه به این طرف و اون طرف کشیدش.
فکر کنم سورس ساده ای هم باشه.
برای کلیدهای کیبورد هم قابلیتهایی تعیین کرده.

اجرایش را اینجا ببینید:


من فقط کدش را مرور کوم و هنوز باهاش کار نکردم.

اون نکته ای که در پست قبل گفتن که بهتره قالب خود را به قالب جدید تبدیل کنیم،
دنبال برنامه ساده ای با قالب جدید بودم که شاید این برنامه خوب باشه.احتمالا میشه اضافاتش را حذف کرد.


فعلا من از لینک زیر ، سورس ها را مرور می کنم:

 
آخرین ویرایش:

saalek110

Well-Known Member
پوشه jsm کلا ۱۲ مگا است. یعنی همان فایلهای js که import میشه در برنامه.
پوشه controls شامل حدود ۱۰ تا فایل است و ۲۰۰ کیلو حجمشه.
ولی پوشه examples حجمش حدود ۴۵۰ مگاست.

پس کدها نیست که حجم داره، چیزای دیگس.
مثلا پوشه textures که داخل پوشه exampless است ،حجم ۱۰۰ مگا دارد.
و پوشه مدل که داخل examples است حجم ۲۵۰ مگا دارد.
پس تکسچر و مدلها جمعا حدود ۴۰۰ مگا حجم دارد. فقط می مونه ۵۰ مگا برای باقی پوشه ها.
 
آخرین ویرایش:

saalek110

Well-Known Member
JavaScript:
                <!DOCTYPE html>
<html lang="en">
    <head>
        <title>three.js webgl - drag controls</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
        <link type="text/css" rel="stylesheet" href="main.css">
        <style>
            body {
                background-color: #f0f0f0;
                color: #444;
            }
            a {
                color: #08f;
            }
        </style>
    </head>
    <body>

        
        <script type="importmap">
            {
                "imports": {
                    "three": "./three-js-master/build/three.module.js",
                    "three/addons/": "./three-js-master/examples/jsm/"
                }
            }
        </script>

        <script type="module">

            import * as THREE from 'three';

            import { DragControls } from 'three/addons/controls/DragControls.js';

            let container;
            let camera, scene, renderer;
            let controls, group;
            let enableSelection = false;

            const objects = [];

            const mouse = new THREE.Vector2(), raycaster = new THREE.Raycaster();

            init();

            function init() {

                container = document.createElement( 'div' );
                document.body.appendChild( container );

                camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 500 );
                camera.position.z = 25;

                scene = new THREE.Scene();
                scene.background = new THREE.Color( 0xf0f0f0 );

                scene.add( new THREE.AmbientLight( 0xaaaaaa ) );

                const light = new THREE.SpotLight( 0xffffff, 10000 );
                light.position.set( 0, 25, 50 );
                light.angle = Math.PI / 9;

                light.castShadow = true;
                light.shadow.camera.near = 10;
                light.shadow.camera.far = 100;
                light.shadow.mapSize.width = 1024;
                light.shadow.mapSize.height = 1024;

                scene.add( light );

                group = new THREE.Group();
                scene.add( group );

                const geometry = new THREE.BoxGeometry();

                for ( let i = 0; i < 10; i ++ ) {

                    const object = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: Math.random() * 0xffffff } ) );

                    object.position.x = Math.random() * 30 - 15;
                    object.position.y = Math.random() * 15 - 7.5;
                    object.position.z = Math.random() * 20 - 10;

                    object.rotation.x = Math.random() * 2 * Math.PI;
                    object.rotation.y = Math.random() * 2 * Math.PI;
                    object.rotation.z = Math.random() * 2 * Math.PI;

                    object.scale.x = Math.random() * 2 + 1;
                    object.scale.y = Math.random() * 2 + 1;
                    object.scale.z = Math.random() * 2 + 1;

                    object.castShadow = true;
                    object.receiveShadow = true;

                    scene.add( object );

                    objects.push( object );

                }

                renderer = new THREE.WebGLRenderer( { antialias: true } );
                renderer.setPixelRatio( window.devicePixelRatio );
                renderer.setSize( window.innerWidth, window.innerHeight );
                renderer.shadowMap.enabled = true;
                renderer.shadowMap.type = THREE.PCFShadowMap;

                container.appendChild( renderer.domElement );

                controls = new DragControls( [ ... objects ], camera, renderer.domElement );
                controls.rotateSpeed = 2;
                controls.addEventListener( 'drag', render );

                //

                window.addEventListener( 'resize', onWindowResize );

                document.addEventListener( 'click', onClick );
                window.addEventListener( 'keydown', onKeyDown );
                window.addEventListener( 'keyup', onKeyUp );

                render();

            }

            function onWindowResize() {

                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();

                renderer.setSize( window.innerWidth, window.innerHeight );

                render();

            }

            function onKeyDown( event ) {

                enableSelection = ( event.keyCode === 16 ) ? true : false;
            
                if ( event.keyCode === 77 ) {

                    controls.touches.ONE = ( controls.touches.ONE === THREE.TOUCH.PAN ) ? THREE.TOUCH.ROTATE : THREE.TOUCH.PAN;
            
                }

            }

            function onKeyUp() {

                enableSelection = false;

            }

            function onClick( event ) {

                event.preventDefault();

                if ( enableSelection === true ) {

                    const draggableObjects = controls.objects;
                    draggableObjects.length = 0;

                    mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
                    mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;

                    raycaster.setFromCamera( mouse, camera );

                    const intersections = raycaster.intersectObjects( objects, true );

                    if ( intersections.length > 0 ) {

                        const object = intersections[ 0 ].object;

                        if ( group.children.includes( object ) === true ) {

                            object.material.emissive.set( 0x000000 );
                            scene.attach( object );

                        } else {

                            object.material.emissive.set( 0xaaaaaa );
                            group.attach( object );

                        }

                        controls.transformGroup = true;
                        draggableObjects.push( group );

                    }

                    if ( group.children.length === 0 ) {

                        controls.transformGroup = false;
                        draggableObjects.push( ...objects );

                    }

                }

                render();

            }

            function render() {

                renderer.render( scene, camera );

            }

        </script>

    </body>
</html>
 

saalek110

Well-Known Member
من فایل فوق را از پوشه examples خارج کردم و کنار بسته three.js قرار دادم و آدرس ها را تنظیم کردم، این قسمت منظورمه:

JavaScript:
<script type="importmap">
            {
                "imports": {
                    "three": "./three-js-master/build/three.module.js",
                    "three/addons/": "./three-js-master/examples/jsm/"
                }
            }
        </script>

من اسم پوشه three.js را عوض کرده ام و گذاشتم three-js-master
در کد بالا می بینید چطور به جایی که می خواستم در داخل بسته اشاره کرده ام.
داخل کد پست قبل ، مدل و تکسچری موجود نیست.
مکعب های رنگی داریم فقط. پس فقط تنظیم همون آدرس را باید می کردم.

جالبی برنامه اینه که میشه مکعب ها را با لمس تکان داد.

گه احتمالا با اون کنترلی که import کرده این کارو می کند.

یک حلقه for دارد که ۲۰۰ مکعب می ساخت ، من کردم ۱۰ تا. چون صفحه خیلی شلوغ بود.
بعد خط حلقه for می بینید که آبجکت خلق کردن است و بعدش خطوط بعدی چرخاندن راندم اشیای خلق شده است.

مربع ها روی هم سایه می اندازند. به دو خط کد بعد چرخاندن مکعب ها اگر نگاه کنید . کد سایه است ، این خطوط:

JavaScript:
object.castShadow = true;
object.receiveShadow = true;
 
آخرین ویرایش:

saalek110

Well-Known Member
JavaScript:
        <!DOCTYPE html>
<html lang="en">
    <head>
        <title>three.js webgl - animation - groups</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
        <link type="text/css" rel="stylesheet" href="main.css">
    </head>
    <body>

        <div id="info">
            <a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgl - animation - groups
        </div>

        <script type="importmap">
            {
                "imports": {
                    "three": "./three-js-master/build/three.module.js",
                    "three/addons/": "./three-js-master/examples/jsm/"
                }
            }
        </script>

        <script type="module">

            import * as THREE from 'three';

            import Stats from 'three/addons/libs/stats.module.js';

            let stats, clock;
            let scene, camera, renderer, mixer;

            init();

            function init() {

                scene = new THREE.Scene();

                //

                camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 1000 );
                camera.position.set( 50, 50, 100 );
                camera.lookAt( scene.position );

                // all objects of this animation group share a common animation state

                const animationGroup = new THREE.AnimationObjectGroup();

                //

                const geometry = new THREE.BoxGeometry( 5, 5, 5 );
                const material = new THREE.MeshBasicMaterial( { transparent: true } );

                //

                for ( let i = 0; i < 5; i ++ ) {

                    for ( let j = 0; j < 5; j ++ ) {

                        const mesh = new THREE.Mesh( geometry, material );

                        mesh.position.x = 32 - ( 16 * i );
                        mesh.position.y = 0;
                        mesh.position.z = 32 - ( 16 * j );

                        scene.add( mesh );
                        animationGroup.add( mesh );

                    }

                }

                // create some keyframe tracks

                const xAxis = new THREE.Vector3( 1, 0, 0 );
                const qInitial = new THREE.Quaternion().setFromAxisAngle( xAxis, 0 );
                const qFinal = new THREE.Quaternion().setFromAxisAngle( xAxis, Math.PI );
                const quaternionKF = new THREE.QuaternionKeyframeTrack( '.quaternion', [ 0, 1, 2 ], [ qInitial.x, qInitial.y, qInitial.z, qInitial.w, qFinal.x, qFinal.y, qFinal.z, qFinal.w, qInitial.x, qInitial.y, qInitial.z, qInitial.w ] );

                const colorKF = new THREE.ColorKeyframeTrack( '.material.color', [ 0, 1, 2 ], [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ], THREE.InterpolateDiscrete );
                const opacityKF = new THREE.NumberKeyframeTrack( '.material.opacity', [ 0, 1, 2 ], [ 1, 0, 1 ] );

                // create clip

                const clip = new THREE.AnimationClip( 'default', 3, [ quaternionKF, colorKF, opacityKF ] );

                // apply the animation group to the mixer as the root object

                mixer = new THREE.AnimationMixer( animationGroup );

                const clipAction = mixer.clipAction( clip );
                clipAction.play();

                //

                renderer = new THREE.WebGLRenderer( { antialias: true } );
                renderer.setPixelRatio( window.devicePixelRatio );
                renderer.setSize( window.innerWidth, window.innerHeight );
                renderer.setAnimationLoop( animate );
                document.body.appendChild( renderer.domElement );

                //

                stats = new Stats();
                document.body.appendChild( stats.dom );

                //

                clock = new THREE.Clock();

                //

                window.addEventListener( 'resize', onWindowResize );

            }

            function onWindowResize() {

                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();

                renderer.setSize( window.innerWidth, window.innerHeight );

            }

            function animate() {

                const delta = clock.getDelta();

                if ( mixer ) {

                    mixer.update( delta );

                }

                renderer.render( scene, camera );

                stats.update();

            }

        </script>

    </body>
</html>
 

جدیدترین ارسال ها

بالا