【问题标题】:positive X-Y coordinate graph using three.js使用three.js的正X-Y坐标图
【发布时间】:2014-03-30 10:05:47
【问题描述】:

我想使用 three.js 创建一个网格格式的正 X-Y 平面。此外,我希望能够单击任何交点并获取坐标值。视图应该像方格纸。

Design.prototype.mouseUp = function (event) {

    var material = new THREE.LineDashedMaterial({
        color:0xffeedd  , dashSize:2 , gapSize:2
    });
    this.container.offsetHeight = 30 , this.container.offsetWidth = 70;
    var a = 0;
    for(var i = 0; i <= this.container.offsetWidth ; i++) {
        var geometry = new THREE.Geometry();
        geometry.vertices.push( new THREE.Vector3( -90 + a,-50, 0 ) );
        geometry.vertices.push( new THREE.Vector3( -90 + a, 50, 0 ) );

        var line = new THREE.Line( geometry, material );
        this.scene.add( line);
        a = a + 1;
    }

    var b = 0;
    for(var j = 0; j <= this.container.offsetHeight; j++) {
        var geometry1 = new THREE.Geometry();
        geometry1.vertices.push( new THREE.Vector3( -90,-50 +b , 0 ) );
        geometry1.vertices.push( new THREE.Vector3(  90,-50 +b , 0 ) );

        var line1 = new THREE.Line( geometry1, material );
        this.scene.add( line1);
        b = b + 1;
    }

};

Design.prototype.onDocumentMouseMove = function( event ) {

    mouseX = event.clientX - (this.container.offsetWidth * 0.5);
    mouseY = event.clientY - (this.container.offsetHeight-window.innerHeight * 0.875);

};

Design.prototype.onDocumentMouseDown = function(event) {

    event.preventDefault();
    alert("X: " + mouseX + " Y: " + mouseY);
    var projector = new THREE.Projector();
    var vector = new THREE.Vector3( ( mouseX / this.container.offsetWidth )*(2-1), - ( mouseY / this.container.offsetHeight )*(2+1), 0.5 );
    projector.unprojectVector( vector, camera );

    var raycaster = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
    var intersects = raycaster.intersectObjects( objects );

    if ( intersects.length > 0 ){

        var sphere = new THREE.Mesh(new THREE.SphereGeometry(size / 4), new THREE.MeshLambertMaterial(intensity));
        sphere.position = intersects[ 0 ].point;
        scene.add(sphere);
    }
};

//three.js code

window.vv = {};
window.vv.messages = {

NO_CONTAINER: "No Container provided."
};
function DesignSpace() {

    this.activeDesign = 0;
this.designes = [];
}

DesignSpace.prototype.getDesignByIndex = function(index) {

    var returnValue = null;
if (index < this.designes.length) {
    returnValue = this.designes[index];
}
return returnValue;
};

DesignSpace.prototype.setActiveDesign = function(index) {

this.activeDesign = index;
};

DesignSpace.prototype.addDesign = function(container) {

var design = new Design(container);
this.designes.push(design);
return design;
};

DesignSpace.prototype.run = function() {

var design = window.vv.designSpace.getDesignByIndex(window.vv.designSpace.activeDesign);
design.getRenderer().render(design.getScene(), design.getCamera());
window.requestAnimationFrame(window.vv.designSpace.run);
};

function Design(container) {

this.renderer = null,
this.scene = null,
this.camera = null,
this.cube = null,
this.animating = null,
this.light = [];
this.grid = null;
this.container = container;
}

Design.prototype.setUp = function() {

if (!this.container) {
    console.log(window.vv.NO_CONTAINER);
    return null;
}
this.container = document.getElementById(this.container);
this.renderer = new THREE.WebGLRenderer({antialias: true});
this.renderer.setSize(this.container.offsetHeight, this.container.offsetHeight);
this.container.appendChild(this.renderer.domElement);


this.scene = new THREE.Scene();

this.camera = new THREE.PerspectiveCamera(90, this.container.offsetWidth / this.container.offsetHeight, 1, 4000);
this.camera.position.set(0, 0, 3);

if (this.light && !this.light.length) {

    this.light.push(new Light({intensity: 1.0, x: 0, y: 1, z:1}));
}
for (var i in this.light) {

    this.scene.add(this.light[i].getLight());
}

this.addMouseHandler();

};
Design.prototype.addMouseHandler = function (event) {

this.renderer.domElement.addEventListener('mouseup', $.proxy(this.mouseUp, this), false);
this.renderer.domElement.addEventListener('mousemove', $.proxy(this.onDocumentMouseMove, this), false);
this.renderer.domElement.addEventListener('mousedown', $.proxy(this.onDocumentMouseDown, this), false);

};

【问题讨论】:

  • X、Y、Z 坐标总是从画布的中心开始。你想从中心开始你的飞机并占据右上象限吗?或者你想让它占据整个画布?
  • SO 不能这样工作。你应该做点什么,然后人们会帮助你。在这里订购将无处可去。
  • @Farzad 我的错。匆忙发布。下次会记住的:)
  • @AmeerTamboli 如您所见,我正在使用一个容器,所以我不想占据整个画布。我希望容器的最左侧底部与画布的原点一致,即(0,0,0)。这样,绘图将仅在正 X-Y 轴上完成。可以吗?
  • 您也可以包含您的three.js 代码吗?一种方法是在three.js 中使用简单的二维平面几何。您的方格纸是静态的,并且在页面演示期间不会移动吗?如果是,您可以简单地通过事件获取鼠标坐标。

标签: javascript three.js coordinates


【解决方案1】:

我根本无法遵循您的代码,所以想出了这样的东西。它还没有完成,还需要继续努力。但在我看来,传达这个想法就足够了。

<!DOCTYPE html>
<html>
<head>
    <title>simple X-Y coordinate example with shader</title>
    <style>canvas { width: 100%; height: 100% ;}</style>
    <style>
        body {
            margin: 0px;
            overflow: hidden;
        }
    </style>
</head>
<body>      
<script src="https://rawgithub.com/mrdoob/three.js/master/build/three.min.js"></script>

<script id="vs" type="x-shader/x-vertex">       
    void main()
    {
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
    }           
</script>

<script id="fs" type="x-shader/x-fragment">

    uniform vec2 resolution;
    #define SCALES 5.0
    #define X_AXIS -5.0
    #define Y_AXIS -5.0
    #define AXIS_THICKNESS 0.08
    #define ORIGIN_INTENSITY 0.40

    void main()
    {
        vec2 point = -1.0 + 2.0 * ( gl_FragCoord.xy/resolution.xy );
        float aspect_ratio = resolution.x/resolution.y;
        float r = length (point);
        vec3 background = (1.0 - 0.15*r) * vec3(0.7-0.07*(point.y+1.0), 0.8, 1.0);
        vec3 col = vec3(1.0);

        point *= SCALES;
        float f = 1.0 - min (
            min( abs( aspect_ratio*point.x - ceil(aspect_ratio*point.x) ), abs( aspect_ratio*point.x - floor(aspect_ratio*point.x) ) ),
            min( abs( point.y - ceil(point.y) ), abs( point.y - floor(point.y) ) ) );
        col *= (1.0 - pow(f, 40.0));

        col = (abs(aspect_ratio*point.x - aspect_ratio*X_AXIS)<AXIS_THICKNESS || abs(point.y - Y_AXIS)<AXIS_THICKNESS) ? vec3(0.0) : col;
        col = (length (vec2(aspect_ratio*point.x, point.y) - vec2(aspect_ratio*X_AXIS, Y_AXIS)) < ORIGIN_INTENSITY )  ? vec3(0.0) : col;

        gl_FragColor = vec4( col*background , 1.0);
    }

</script>

<script type="text/javascript">

    var scene = new THREE.Scene();
    var camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.1, 1000 );
    var renderer = new THREE.WebGLRenderer({ antialias: true});

    window.addEventListener( 'mousedown', onMousePress, false );

    //assignings happen here
    //more info on https://github.com/mrdoob/three.js/wiki/Uniforms-types
    var uniforms = {
        resolution: {
            type: "v2",
            value: new THREE.Vector2( window.innerWidth, window.innerHeight )
        }
    }; 
    var myMaterial = new THREE.ShaderMaterial({
        uniforms: uniforms,
        vertexShader: document.getElementById( 'vs' ).textContent,
        fragmentShader: document.getElementById( 'fs' ).textContent
    });

    camera.position.z = 0.40;
    var itemGeometry = new THREE.PlaneGeometry( window.innerWidth / (window.innerWidth+window.innerHeight), window.innerHeight / (window.innerWidth+window.innerHeight), 0);
    var itemCube = new THREE.Mesh( itemGeometry, myMaterial );
    scene.add( itemCube );

    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );


    function onWindowResize() {

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

        renderer.setSize( window.innerWidth, window.innerHeight );
        uniforms.resolution.value = new THREE.Vector2( window.innerWidth, window.innerHeight );

    }

    function onMousePress(e){
        var scale = 10;
        var aspect = window.innerWidth / window.innerHeight;
        alert(scale*aspect* (e.clientX / window.innerWidth));
        alert(scale* ((window.innerHeight - e.clientY)/ window.innerHeight));
    }

    function render() {

        requestAnimationFrame(render);       
        renderer.render(scene, camera);

    }
    render();
</script>
</body>
</html>

我已经定义了一个带有平面几何图形和自定义着色器的平面网格。在片段着色器中,我在类似于方格纸的平面上进行绘制。您可以使用参数来查看它们如何影响最终结果。在 javascript 代码中,请参阅onWindowResize()。这是我将窗口大小更改应用于相机、渲染器并更新片段着色器参数的地方。在onMousePress(e),我收集用户提供的数据并相应地计算坐标。
同样,代码不完整,但我在这里提供给您一个想法。

【讨论】:

  • 非常感谢!代码真的很有帮助。此代码在整个窗口中展开。我可以在容器中实现相同的代码吗?
  • 为了使原点即 (0,0) 突出,需要 2 条代表 X 轴和 Y 轴的射线。我可以使用以下代码创建 X 轴吗? var origin = new Vector3(0,0,0); var dest = 新向量(20,0,0); dest.normalize(); var ray = new Ray(origin,dest);
  • 渲染发生在画布内部。您可以使用纯 CSS 指定其位置和大小。在上面的代码中,它占据了其父级(在 CSS 层次结构中)的宽度和大小的 100%。当心,如果你这样做,你必须重新考虑并重写编写的鼠标事件函数。
  • 我对上面片段着色器所做的更改将为轴和原点带来厚度。
  • 太棒了!这段代码的问题是,当窗口最小化然后刷新和最大化时,X 轴从场景中消失了。为什么会这样?
猜你喜欢
  • 2014-05-30
  • 2014-12-02
  • 2012-11-26
  • 2021-07-10
  • 1970-01-01
  • 2013-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多