2017-12-04 14 views
-1

Ich brauche einen Block von Pixeln aus dem Kommissionieren Puffer zu lesen, um die umgebenden Punkte auf Kollisionen geprüft, wie in der Abbildung unten:gl readPixels Koordinatensystem: lesen und prüfen, mehr als einen Punkt

enter image description here

ich klicken auf meiner canvas bei x, y - so definieren i einen quadratischen Bereich, sagen wir mal, 11x11 Pixel, zentriert bei cX, cY und dann las ich von der Aufnahmepuffer nur in einem Schuss von x1 starten, y1:

var w = 11, h = 11, cX = x, cY = cH - y, rc = ~~(0.5*w), x1 = cX - rc, y1 = cY + rc; 

gl.readPixels(x1, y1, w, h, gl.RGBA, gl.UNSIGNED_BYTE, pickBuf); 

Dann i vom Zentrum meines Puffers am Looping nach außen gehen, im Anschluss an den roten Pfeilen, während für eine positive Reaktion im Innern der Picking Pufferprüfung (Kollision gefunden):

function readAt(i, pickBuf) { 
    return pickBuf[i] << 16 | pickBuf[i+1] << 8 | pickBuf[i+2]; 
} 

var l = rc; 
while(l--) { 
    /* Top-Left sector */ 
    var r = rc+(rc-l), c = l, p = r*w + c, i = 4*p; 
    found = readAt(i, pickBuf) > 0; 
    /* Top-Right sector */ 
    var r = rc+(rc-l), c = rc+(rc-l), p = r*w + c, i = 4*p; 
    found = readAt(i, pickBuf) > 0; 
    /* Bottom-Left sector */ 
    var r = l, c = l, p = r*w + c, i = 4*p; 
    found = readAt(i, pickBuf) > 0; 
    /* Bottom-Right sector */ 
    var r = l, c = rc+(rc-l), p = r*w + c, i = 4*p; 
    found = readAt(i, pickBuf) > 0; 
} 

Das Stück Code funktioniert und ich kann eine Geometrie auswählen, aber jetzt glaube ich, dass ich das ganze Koordinatensystem nicht richtig verstanden habe, weil das Kollisionsergebnis immer über und links von dem Punkt liegt, an dem es sein sollte. Warum passiert das?

Es scheint mir, dass readPixels die Bytes beginnend von der unteren linken Ecke der canvas bis zur oberen rechten Ecke lesen sollte. Ist das wahr, oder fehlt mir etwas?

Ich bin mir bewusst, dass die gl Koordinatensystem Y-invertiert gegen meine canvas, also bin ich die Definition der Mitte des Picking Puffer bei cY = cH - y und die Y Ausgangspunkt für die Kommissionierung Puffer bei y1 = cY + rc, aber trotzdem das gibt mir falsche Ergebnisse während meines Spazierganges von der Mitte nach außen von meiner quadratischen Box. Wohin geht meine Interpretation des Koordinatensystems?

+0

zum downvoter: bitte fair sein und eine Erklärung hinzuzufügen. Ich bin wirklich der Erste, der interessiert ist zu wissen, was ich falsch mache, indem ich diese Frage stelle. – deblocker

Antwort

1

Es scheint mir, dass ReadPixels die Bytes beginnend von der unteren linken Ecke der Leinwand bis zur oberen rechten Ecke lesen sollte. Ist das wahr, oder fehlt mir etwas?

wahr

Das ist sowieso das ist mir zu falschen Ergebnissen bei meinem Spaziergang geben

Mit Ausnahme des mittleren Pixels nicht überprüft wird, ist es für mich funktioniert, vermute ich das Problem an anderer Stelle in deinem Code sein.

// picking 
 
c.addEventListener('click',function (e) { 
 
    var 
 
    cX = e.offsetX, // x within canvas 
 
    cY = ctx.drawingBufferHeight - e.offsetY // y within canvas inverted, drawingbufferheight is same as canvas height 
 
    ; 
 

 
    var 
 
    area = 11, 
 
    halfArea = (area/2)|0, 
 
    sX = cX-halfArea, 
 
    sY = cY-halfArea 
 
    ; 
 
    console.log('Picking from ', sX, sY, area,area); 
 
    // read data 
 
    var data = new Uint8Array(area*area*4); 
 
    ctx.readPixels(sX,sY,area,area,ctx.RGBA,ctx.UNSIGNED_BYTE,data); 
 
    // draw cross 
 
    (function (pickBuf,rc,w) { 
 
    function readAt(i, pickBuf) { 
 
     return pickBuf[i]=pickBuf[i+1]=pickBuf[i+2]=0; 
 
    } 
 
    // this is your unmodified loop 
 
    var l = rc; 
 
    while(l--) { 
 
     /* Top-Left sector */ 
 
     var r = rc+(rc-l), c = l, p = r*w + c, i = 4*p; 
 
     found = readAt(i, pickBuf) > 0; 
 
     /* Top-Right sector */ 
 
     var r = rc+(rc-l), c = rc+(rc-l), p = r*w + c, i = 4*p; 
 
     found = readAt(i, pickBuf) > 0; 
 
     /* Bottom-Left sector */ 
 
     var r = l, c = l, p = r*w + c, i = 4*p; 
 
     found = readAt(i, pickBuf) > 0; 
 
     /* Bottom-Right sector */ 
 
     var r = l, c = rc+(rc-l), p = r*w + c, i = 4*p; 
 
     found = readAt(i, pickBuf) > 0; 
 
    } 
 
    })(data,halfArea,area); 
 

 
    // create preview 
 
    var octx = document.createElement('canvas').getContext('2d'); 
 
    octx.canvas.classList.add('preview'); 
 
    octx.canvas.width = octx.canvas.height = area; 
 
    var idata = octx.createImageData(area,area); 
 
    idata.data.set(data); 
 
    octx.putImageData(idata,0,0); 
 
    ctx.canvas.parentElement.insertBefore(octx.canvas,ctx.canvas); 
 
}); 
 

 

 
// context setup 
 
var ctx = c.getContext('webgl',{preserveDrawingBuffer:true}); 
 
ctx.canvas.width = ctx.canvas.height = 256; 
 
ctx.viewport(0,0,256,256); 
 
// shader setup 
 
var vs=ctx.createShader(ctx.VERTEX_SHADER),fs=ctx.createShader(ctx.FRAGMENT_SHADER),prg=ctx.createProgram(); 
 
ctx.shaderSource(vs,` 
 
    attribute vec2 vPos; 
 
    void main(){gl_Position=vec4(vPos,0,1);} 
 
`); 
 
ctx.shaderSource(fs,` 
 
    precision highp float; 
 
    void main(){ 
 
    vec2 p=(gl_FragCoord.xy/256.)*2.-1.; 
 
    gl_FragColor=vec4(sign(p),sign(-p.r),1); 
 
    } 
 
`); 
 
ctx.compileShader(vs); 
 
ctx.compileShader(fs); 
 
ctx.attachShader(prg,vs); 
 
ctx.attachShader(prg,fs); 
 
ctx.linkProgram(prg); 
 
// screenspace setup 
 
var ssq = ctx.createBuffer(); 
 
ctx.bindBuffer(ctx.ARRAY_BUFFER,ssq); 
 
ctx.bufferData(ctx.ARRAY_BUFFER,new Float32Array([-1,-1,1,-1,1,1,-1,1]),ctx.STATIC_DRAW); 
 
ctx.vertexAttribPointer(0,2,ctx.FLOAT,false,0,0); 
 
ctx.enableVertexAttribArray(0); 
 
// draw 
 
ctx.useProgram(prg); 
 
ctx.drawArrays(ctx.TRIANGLE_FAN,0,4);
h2{text-align:center;font-family: Arial,sans-serif;} 
 
#c{display:block;margin:0 auto;outline:1px solid red;cursor:crosshair;} 
 

 
.preview { 
 
width: 64px; 
 
height: 64px; 
 
outline: none; 
 
display:inline; 
 
image-rendering: pixelated; 
 
transform:scaleY(-1); 
 
margin: 10px; 
 
}
<h2>Click 2 Pick</h2> 
 
<canvas id="c"></canvas>

+0

THX für Ihre Zeit, ich habe die erste Überprüfung bei cX, cY der Kürze wegen weggelassen. Das Pick bei cX, cY funktioniert einwandfrei, nichts besonderes da. Ehrlich, ich kann mir das Problem nicht anderswo vorstellen, aber ich werde weiter nachforschen. – deblocker

Verwandte Themen