从Threejs模型到用于纹理的Fabricjs画布的Raycast鼠标单击 [英] Raycast mouse clicks from Threejs model to the Fabricjs canvas used for the texture

查看:416
本文介绍了从Threejs模型到用于纹理的Fabricjs画布的Raycast鼠标单击的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建3D产品配置器.

I'm creating a 3D product configurator.

首先,我加载.gltf模型并使用Threejs进行渲染.

First, I load the .gltf model and render it with Threejs.

然后,我将一个svg打印到Fabricjs画布上,并使用该画布制作一个THREE.CanvasTexture并使用该画布更新模型.

Then, I print a svg to a Fabricjs canvas and use that canvas to make a THREE.CanvasTexture and update the model with this canvas.

问题
我允许人们上传文本和图像.这些图像将作为新对象添加到Fabric画布.当主svg锁定在背景上时,可以在画布中拖动这些上载的图像并调整其大小.

The problem
I allow people to upload text and images. Those images are added to the Fabric canvas as new objects. While the main svg is locked at the background, these uploaded images can be dragged and resized in the canvas.

屏幕快照画布对象

Screenshot canvas object

目标
因此,我的目标是能够直接从可见的3D threejs模型(而不是画布)中拖动和调整与Fabricjs图层交互的那些图层.因为画布是display:hidden

Goal
So my goal is to be able to drag and resize those Fabricjs layers interacting directly from the visible 3D threejs model, not the canvas. Because the canvas is display:hidden

模型上的图像

Image on the model

我是3D世界的新手,找不到任何示例或指南,所以我不知道从哪里开始. 我知道我将不得不使用Raycasting,但不知道如何将这些点转换为正确的2d画布点并模拟单击和拖动动作.

I'm new to this 3D world and can't find any example or guidence so i don't know where to start. I know i will have to use Raycasting, but don' know how to convert the points to the correct 2d canvas point and simulate click and drag actions.

推荐答案

您可以尝试以下示例- https://discourse.threejs.org/t/three-js-fabric-js/2111

You can try this example - https://discourse.threejs.org/t/three-js-fabric-js/2111

或者这个- https://codepen.io/ricardcreagia/pen/EdEGod

        /**
         * Fabricjs
         * @type {fabric}
         */

        var canvas = new fabric.Canvas( "canvas" );
        canvas.backgroundColor = "#FFBE9F";

        var rectangle = new fabric.Rect( {
            top: 100,
            left: 100,
            fill: '#FF6E27',
            width: 100,
            height: 100,
            transparentCorners: false,
            centeredScaling: true,
            borderColor: 'black',
            cornerColor: 'black',
            corcerStrokeColor: 'black'
        } );

        canvas.add( rectangle );


        /**
         * Threejs
         */

        var containerHeight = "512";
        var containerWidth = "512";
        var camera, renderer, container, scene, texture, material, geometry,cube;

        var raycaster = new THREE.Raycaster();
        var mouse = new THREE.Vector2();
        var onClickPosition = new THREE.Vector2();

        init();
        animate();


        /**
         * Configurator init function
         */

        function init() {

            /**
             * Camera
             */

            camera = new THREE.PerspectiveCamera( 30, window.innerWidth / window.innerHeight, 0.01, 100 );
            camera.position.set( 0, 0, 3.5 );


            /**
             * Renderer
             */

            container = document.getElementById( "renderer" );
            renderer = new THREE.WebGLRenderer( { antialias: true } );
            renderer.setPixelRatio( window.devicePixelRatio );
            renderer.setSize( containerWidth, containerHeight );
            camera.aspect = container.clientWidth / container.clientHeight;
            camera.updateProjectionMatrix();
            container.appendChild( renderer.domElement );


            /**
             * Scene
             */

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


            /**
             * Texture and material
             */

            texture = new THREE.Texture( document.getElementById( "canvas" ) );
            texture.anisotropy = renderer.capabilities.getMaxAnisotropy();

            material = new THREE.MeshBasicMaterial( { map: texture } );


            /**
             * Model
             */

             geometry = new THREE.BoxGeometry( 1, 1, 1 );
             cube = new THREE.Mesh( geometry, material );
             scene.add( cube );
        }


        /**
         * Configurator frame render function
         */

        function animate() {
            requestAnimationFrame( animate );

            cube.rotation.x += 0.004;
            cube.rotation.y += 0.001;
            texture.needsUpdate = true;

            renderer.render( scene, camera );
        }


        /**
         * Listeners
         */

        container.addEventListener( "mousedown", onMouseClick, false );


        /**
         * Other methods
         */

        function onMouseClick( evt ) {
            evt.preventDefault();

            var array = getMousePosition( container, evt.clientX, evt.clientY );
            onClickPosition.fromArray( array );

            var intersects = getIntersects( onClickPosition, scene.children );

            if ( intersects.length > 0 && intersects[ 0 ].uv ) {
                var uv = intersects[ 0 ].uv;
                intersects[ 0 ].object.material.map.transformUv( uv );

                var circle = new fabric.Circle({
                    radius: 3,
                    left: getRealPosition( "x", uv.x ),
                    top: getRealPosition( "y", uv.y ),
                    fill: 'red'
                });
                canvas.add( circle );
            }
        }

        function getRealPosition( axis, value ) {
            let CORRECTION_VALUE = axis === "x"
                                    ? 4.5
                                    : 5.5;

            return Math.round( value * 512 ) - CORRECTION_VALUE;
        }

        var getMousePosition = function ( dom, x, y ) {
            var rect = dom.getBoundingClientRect();
            return [ ( x - rect.left ) / rect.width, ( y - rect.top ) / rect.height ];
        };

        var getIntersects = function ( point, objects ) {
            mouse.set( ( point.x * 2 ) - 1, - ( point.y * 2 ) + 1 );
            raycaster.setFromCamera( mouse, camera );
            return raycaster.intersectObjects( objects );
        };

我希望这对某人有帮助.

I hope this helps someone.

这篇关于从Threejs模型到用于纹理的Fabricjs画布的Raycast鼠标单击的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆