2013-07-21 4 views
13

Я пытаюсь добавить asm.js аннотации к Перлин симплекс функции шума:пишущие asm.js вручную

"use strict"; 

// Ported from Stefan Gustavson's java implementation 
// http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf 
// Read Stefan's excellent paper for details on how this code works. 
// 
// Sean McCullough [email protected] 

function SimplexNoise(stdlib,foreign,heap) { 
    "use asm"; 
    // heap should be at least 1024*4+12*3*4 bytes long 
    var floor = stdlib.Math.floor, 
     sqrt = stdlib.Math.sqrt, 
     random = new stdlib.Float32Array(heap), 
     buf = new stdlib.Int32Array(heap), 
     F2 = 0.0, F3 = 0.0, 
     G2 = 0.0, G3 = 0.0; 
    F2 = (sqrt(3.0)-1.0)*0.5; F3 = 1.0/3.0; 
    G2 = (3.0-sqrt(3.0))/6.0; G3 = 1.0/6.0; 
    function init() { 
     // before calling this function, set the first 256 floats in the heap to be random numbers between 0..1 
     // the heap gets rewritten, but if you record the IV separately, the noise is reproducable 
     for(var i=0; i<256; i++) { 
      buf[i] = buf[i+256] = floor(random[i]*256.0) & 0xff; 
      buf[i+512] = buf[i+512+256] = (buf[i] % 12) * 3 + 1024; 
     } 
     i = 1024; 
     buf[i++] = 1; buf[i++] = 1; buf[i++] = 0; 
     buf[i++] = -1; buf[i++] = 1; buf[i++] = 0; 
     buf[i++] = 1; buf[i++] = -1; buf[i++] = 0; 
     buf[i++] = -1; buf[i++] = -1; buf[i++] = 0; 
     buf[i++] = 1; buf[i++] = 0; buf[i++] = 1; 
     buf[i++] = -1; buf[i++] = 0; buf[i++] = 1; 
     buf[i++] = 1; buf[i++] = 0; buf[i++] = -1; 
     buf[i++] = -1; buf[i++] = 0; buf[i++] = -1; 
     buf[i++] = 0; buf[i++] = 1; buf[i++] = 1; 
     buf[i++] = 0; buf[i++] = -1; buf[i++] = 1; 
     buf[i++] = 0; buf[i++] = 1; buf[i++] = -1; 
     buf[i++] = 0; buf[i++] = -1; buf[i++] = -1; 
    } 
    function noise2D(xin,yin) { 
     xin = +xin; yin = +yin; 
     var s = 0.0, i = 0, j = 0, 
      t = 0.0, 
      X0 = 0.0, Y0 = 0.0, 
      x0 = 0.0, y0 = 0.0, 
      i1 = 0, j1 = 0, 
      x1 = 0.0, y1 = 0.0, 
      x2 = 0.0, y2 = 0.0, 
      ii = 0, jj = 0, 
      gi0 = 0, gi1 = 0, gi2 = 0, 
      t0 = 0.0, t1 = 0.0, t2 = 0.0, 
      n0 = 0.0, n1 = 0.0, n2 = 0.0; 
     // Skew the input space to determine which simplex cell we're in 
     s = (xin+yin)*F2; // Hairy factor for 2D 
     i = floor(xin+s); j = floor(yin+s); 
     t = (i+j)*G2; 
     X0 = i-t; Y0 = j-t; // Unskew the cell origin back to (x;y) space 
     x0 = xin-X0; y0 = yin-Y0; // The x;y distances from the cell origin 
     // For the 2D case; the simplex shape is an equilateral triangle. 
     // Determine which simplex we are in. 
     i1 = (x0>y0?1:0); j1 = (x0>y0?0:1); // Offsets for second (middle) corner of simplex in (i;j) coords 
     // A step of (1;0) in (i;j) means a step of (1-c;-c) in (x;y); and 
     // a step of (0;1) in (i;j) means a step of (-c;1-c) in (x;y); where 
     // c = (3-sqrt(3))/6 
     x1 = x0-i1+G2; y1 = y0-j1+G2; // Offsets for middle corner in (x;y) unskewed coords 
     x2 = x0-1+2*G2; y2 = y0-1+2*G2; // Offsets for last corner in (x;y) unskewed coords 
     // Work out the hashed gradient indices of the three simplex corners 
     ii = i & 255; jj = j & 255; 
     gi0 = buf[ii+buf[jj]+512]; 
     gi1 = buf[ii+i1+buf[jj+j1]+512]; 
     gi2 = buf[ii+1+buf[jj+1]+512]; 
     // Calculate the contribution from the three corners 
     t0 = 0.5-x0*x0-y0*y0; t1 = 0.5-x1*x1-y1*y1; t2 = 0.5-x2*x2-y2*y2; 
     n0 = t0<0.0? 0.0: t0*t0*t0*t0*(buf[gi0]*x0+buf[gi0+1]*y0); // (x;y) of buf used for 2D gradient 
     n1 = t1<0.0? 0.0: t1*t1*t1*t1*(buf[gi1]*x1+buf[gi1+1]*y1); 
     n2 = t2<0.0? 0.0: t2*t2*t2*t2*(buf[gi2]*x2+buf[gi2+1]*y2); 
     // Add contributions from each corner to get the final noise value. 
     // The result is scaled to return values in the interval [-1,1]. 
     return 70.0 * (n0 + n1 + n2); 
    } 
    return { 
     init: init, 
     noise2D: noise2D 
    }; 
}; 

Консоль ошибок Firefox Javascript говорит только:

Warning: TypeError: asm.js type error: asm.js must end with a return export statement Source File: perlin_simplex.js Line: 9

У меня есть искали помощь в том, что может быть ошибкой, и найти только https://github.com/zbjornson/human-asmjs, что, как правило, очень полезно, но не помогает в этом конкретном случае.

В чем я ошибаюсь? Как может эта функция шума perlin быть asm.js-ised человеком?

+0

Handcoding asm.js? Что ты: гений или сумасшедший ?! –

ответ

13

Проблема заключается в том, содержащий следующие строки:

F2 = (sqrt(3.0)-1.0)*0.5; F3 = 1.0/3.0; 
G2 = (3.0-sqrt(3.0))/6.0; G3 = 1.0/6.0; 

только декларации допускается в рамках верхнего уровня модуля asm.js. Вы не можете определить переменную в области верхнего уровня.

В соответствии с spec вы можете назначать только глобальные переменные (среди других операторов импорта). Следовательно, вы не можете сделать следующие либо потому, что F2, F3, G2 и G3 являются не присвоенные буквенные значения:

var floor = stdlib.Math.floor, 
    sqrt = stdlib.Math.sqrt, 
    random = new stdlib.Float32Array(heap), 
    buf = new stdlib.Int32Array(heap), 
    F2 = (sqrt(3.0)-1.0)*0.5, F3 = 1.0/3.0, 
    G2 = (3.0-sqrt(3.0))/6.0, G3 = 1.0/6.0; 

Следовательно, вам нужно будет переместить определение F2, F3, G2 и G3 в функцию (возможно, функция init). Таким образом, ваш код должен выглядеть следующим образом:

function SimplexNoise(stdlib,foreign,heap) { 
    "use asm"; 

    var floor = stdlib.Math.floor, 
     sqrt = stdlib.Math.sqrt, 
     random = new stdlib.Float32Array(heap), 
     buf = new stdlib.Int32Array(heap), 
     F2 = 0.0, F3 = 0.0, 
     G2 = 0.0, G3 = 0.0; 

    function init() { 
     F2 = (sqrt(3.0)-1.0)*0.5; F3 = 1.0/3.0; 
     G2 = (3.0-sqrt(3.0))/6.0; G3 = 1.0/6.0; 
     // rest of init 
    } 

    function noise2D(xin,yin) { 
     // function body 
    } 

    return { 
     init: init, 
     noise2D: noise2D 
    }; 
}; 

человека asm.js делает вам сказать об этой проблеме, но они дают вам пример массива вместо простой переменной:

Note that these typed arrays cannot be modified outside of a function:

function MyModule(stdlib, foreign, heap) { 
    var arr = new stdlib.Int8Array(heap); 
    arr[0] = 1; // "asm.js must end with a return export statement" 
    // ... 
} 

Instead do something like this:

function MyModule(stdlib, foreign, heap) { 
    var arr = new stdlib.Int8Array(heap); 
    function init() { 
    arr[0] = 1; 
    } 

    return { 
    init: init 
    }; 
} 

Там вы идете. Разве не asm.js большая боль?

+1

Действительно, это была проблема. asm.js действительно большая боль, но в основном из-за плохой отчетности об ошибках. Приятно иметь возможность разделить мои быстрые шумовые функции, когда я заставлю их быть быстрыми. – Will

Смежные вопросы