三个JS空白(黑色)帆布图像到粒子

时间:2017-02-23 17:16:24

标签: javascript three.js

我正在使用three.js在画布上绘制图像,从此图像中收集数据(即像素颜色),并使用从图像中收集的数据(如颜色)将图像重绘为粒子集合

我没有错误消息或警告,只是一个空白的黑色画布。

我正在使用的代码如下:

var xhr = new XMLHttpRequest();
xhr.open("GET", "http://example.com/assets/css/sl.jpg");
xhr.responseType = "blob";
xhr.onload = function() 
{
    blob = xhr.response;
    P.readAsDataURL(blob);
    P.onload = function(){
    image = document.createElement("img");
    image.src = P.result;
        setTimeout(function(){

                // split the image
                addParticles();

            }, 100);
    }
        }
xhr.send();
addLights(); 
update();
setTimeout(function(){
holdAtOrigin = "next";  
},1000)
function addParticles()
    {
        // draw in the image, and make sure it fits the canvas size :)
        var ratio           = 1 / Math.max(image.width/500, image.height/500);
        var scaledWidth     = image.width * ratio;
        var scaledHeight    = image.height * ratio;
        context.drawImage(image,
                            0,0,image.width,image.height,
                            (500 - scaledWidth) * .5, (500 - scaledHeight) *.5, scaledWidth, scaledHeight);

        // now set up the particle material
        var material    = new THREE.MeshPhongMaterial( { } );
        var geometry    = new THREE.Geometry();
        var pixels      = context.getImageData(0,0,WIDTH,HEIGHT);
        var step        = DENSITY * 4;
        var x = 0, y = 0;

        // go through the image pixels
        for(x = 0; x < WIDTH * 4; x+= step)
        {
            for(y = HEIGHT; y >= 0 ; y -= DENSITY)
            {
                var p = ((y * WIDTH * 4) + x);

                // grab the actual data from the
                // pixel, ignoring any transparent ones
                if(pixels.data[p+3] > 0)
                {
                    var pixelCol    = (pixels.data[p] << 16) + (pixels.data[p+1] << 8) + pixels.data[p+2];
                    var color       = new THREE.Color(pixelCol);
                    var vector      = new THREE.Vector3(-300 + x/4, 240 - y, 0);

                    // push on the particle
                    geometry.vertices.push(new THREE.Vector3(vector));
                    geometry.colors.push(color);
                }
            }
        }

        // now create a new system
        particleSystem  = new THREE.Points(geometry, material);
        console.log(particleSystem);
        particleSystem.sortParticles = true;

        // grab a couple of cacheable vals
        particles       = particleSystem.geometry.vertices;
        colors          = particleSystem.geometry.colors;

        // add some additional vars to the
        // particles to ensure we can do physics
        // and so on
        var ps = particles.length;
        while(ps--)
        {
            var particle        = particles[ps];
            particle.velocity   = new THREE.Vector3();
            particle.mass       = 5;
            particle.origPos    = particle.x.clone();
        }

        // gc and add
        pixels = null;
        scene.add(particleSystem);
        //test render
    }

function addLights()
    {
        // point
        pointLight = new THREE.PointLight( 0xFFFFFF );
        pointLight.position.x = 300;
        pointLight.position.y = 300;
        pointLight.position.z = 600;
        scene.add( pointLight );

        // directional
        directionalLight = new THREE.DirectionalLight( 0xFFFFFF );
        directionalLight.position.x = -.5;
        directionalLight.position.y = -1;
        directionalLight.position.z = -.5;
        directionalLight.position.normalize();
        directionalLight.intensity = .6;
        scene.add( directionalLight );
    }   
function update(){
    var ps = particles.length;  
        while(ps--)
        {
            var particle        = particles[ps];

            // if we are holding at the origin
            // values, tween the particles back
            // to where they should be
            if(holdAtOrigin == "start")
            {
                particle.velocity   = new THREE.Vector3();
                //particle.position.x += (particle.origPos.x - particle.position.x) * .2;
                //particle.position.y += (particle.origPos.y - particle.position.y) * .2;
                //particle.position.z += (particle.origPos.z - particle.position.z) * .2;
                 particle.x.x += (particle.origPos.x - .0000000000000000001) * 2;
                 particle.x.y += (particle.origPos.y - .0000000000000000001) * 2;

            }
            else if (holdAtOrigin == "next")
            {
                particle.velocity   = new THREE.Vector3();
                particle.x.x += (particle.origPos.x - particle.x.x) * .2;
                particle.x.y += (particle.origPos.y - particle.x.y) * .2;
                particle.x.z += (particle.origPos.z - particle.x.z) * .2;
            }
            else{
                // get the particles colour and put
                // it into an array
                var col             = colors[ps];
                var colArray        = [col.r, col.g, col.b];

                // go through each component colour
                for(var i = 0; i < colArray.length; i++)
                {
                    // only analyse it if actually
                    // has some of this colour
                    if(colArray[i] > 0)
                    {
                        // get the target based on where it
                        // is in the array
                        var target          = i == 0 ? redCentre :
                                              i == 1 ? greenCentre : 
                                              blueCentre;

                        // get the distance of the particle to the centre in question
                        // and add on the resultant acceleration
                        var dist            = particle.position.distanceToSquared(target.position),
                            force           = ((particle.mass * target.mass) / dist) * colArray[i] * AGGRESSION,
                            acceleration    = (new THREE.Vector3())
                                                .sub(target.position,particle.position)
                                                .normalize()
                                                .multiplyScalar(force);

                        // if we are attracting we add
                        // the velocity
                        if(mode == ATTRACT)
                        {
                            // note we only need to check the 
                            // squared radius for the collision :)
                            if(dist > target.boundRadiusSquared) {
                                particle.velocity.addSelf(acceleration);
                            }
                            else if (bounceParticles) {
                                // bounce, bounce, bounce
                                particle.velocity.negate();
                            }
                            else {
                                // stop dead
                                particle.velocity = new THREE.Vector3();
                            }
                        }
                        else {
                            // push it away
                            particle.velocity.subSelf(acceleration);
                        }

                        particle.position.addSelf(particle.velocity);
                    }
                }
            }
        }
    // set up a request for a render
        requestAnimationFrame(update);
        render();
}

    function render()
    {
        // only render if we have
        // an active image
        if(image) {
            if(holdAtOrigin=="start")
            {
                camera.position.z = 900;
            }
            if(camera.position.z < 200)
            {
            //do nothing    
            }
            else{
            camera.position.z -= 1.7;
            };
            renderer.render( scene, camera );
        }
    }

我以不同的间隔检查了控制台日志,发现像素数据被正确收集,所以我不知道出了什么问题。

是材料吗?当我使用普通(光独立)材料时,代码按预期工作,我可以看到我的粒子。

但是我希望它受到灯光的影响,所以我把它改为var material = new THREE.MeshPhongMaterial( { } );而没有任何参数。

这是我的问题还是在代码的其他地方?

谢谢!

这也可能是恰当的:How to get the absolute position of a vertex in three.js?

因为particle.x.xparticle.x.y看起来不对我,即使我根据记录的对象内容编写了该代码。

编辑:我将Phong行更改为THREE.PointsMaterial并增加了灯光效能,但仍然是一块空白的黑色画布。

编辑2:所以我认为粒子坐标被误解可能是个问题?当我使用console.log(particleSystem);检查时,我得到以下内容:

Vertices Inspector

我以前是否将x,y,z包裹在position属性中,以便删除较新版本的three.js

例如,我找到了例如:

的示例代码
particle.origPos    = particle.position.clone();

但我没有看到position财产?我如何只克隆x,y和z位,还是应该克隆整个顶点?对不起,如果这是令人困惑或无关紧要,只是为了追查为什么我有一个空白的画布。

编辑3:我已经删除了更新功能的位置更改,但即使我正在做的只是克隆,我仍然会得到粒子系统的奇怪的控制台日志粒子使用particle.origPos = particle.clone();

基本上我有和x,y和z属性,但x属性是一个带有后续x,y和z的对象。为什么这样,我该如何解决?

Multiple X, Y and Z

0 个答案:

没有答案