Question

I Am trying to convert a project I've built in Processing [Java Mode] to be able to be viewed on the web.The project utilizes P3D rendering to display a 3D world that can be rotated and also can change 3 data sets (.tsv files) that map the location and size of earthquakes that occurred during three years. The following code works fine when ran in Java but when I run in Javascript mode I only get a blank gray screen. The HTML to embed the sketch into the canvas is correct and there are no errors so I am sure it is something within the code that that is not compatible with Javascript. Is there a way to just run the PDE as java without having to use Processing.js otherwise is there anything that is noticeably wrong with the code in regards to compatibility with processing.js?

Here is a link to the sketch that is not working if that helps .

Any suggestions as to what I should do is greatly appreciated. Thanks

float dial = 0.0;
FloatTable data;
FloatTable data2;
float dataMin, dataMax;
int rowCount;
int currentColumn = 0;
int columnCount;

int yearMin, yearMax;
int[] years;

int yearInterval = 10;
int volumeInterval = 10;
int volumeIntervalMinor=5;

PImage bg;
PImage texmap;
PFont font;
PImage img, img2;
PImage imgTitle;

int sDetail = 35;  // Sphere detail setting
float rotationX = 0;
float rotationY = 0;
float velocityX = 0;
float velocityY = 0;
float globeRadius = 750;
float pushBack = 0;

float[] cx, cz, sphereX, sphereY, sphereZ;
float sinLUT[];
float cosLUT[];
float SINCOS_PRECISION = 0.5;
int SINCOS_LENGTH = int(360.0 / SINCOS_PRECISION);

void setup() {
size(1300,1000, P3D);  
textSize(100);
texmap = loadImage("img/world32k.jpg");   
initializeSphere(sDetail);
setupstuff("2011.tsv");
}

void draw() {    

background(0);    
// drawTitle(); 
drawMain();
renderGlobe(); 
drawDial();

}
void setupstuff(String filename){
data = new FloatTable(filename);
rowCount=data.getRowCount();
columnCount = data.getColumnCount();
years = int(data.getRowNames());
yearMin = years[0];
yearMax = years[years.length - 1];
font = loadFont("Univers-Bold-12.vlw");
dataMin = 0;
dataMax = ceil( data.getTableMax()/volumeInterval)*volumeInterval;
img = loadImage("img/dialface.jpg");
img2 = loadImage("img/dial.png");
imgTitle = loadImage("Title.png");
imageMode(CENTER);
} 
void renderGlobe() {
pushMatrix();
translate(width * 0.33, height * 0.4, pushBack);
// pushMatrix();
noFill();
stroke(255,200);
strokeWeight(2);
smooth();
//popMatrix();
pointLight(201, 252, 276, width * 0.3, height * 0.2, 660);   
pushMatrix();
rotateX( radians(-rotationX) );  
rotateY( radians(180 - rotationY) );
fill(200);
noStroke();
textureMode(IMAGE);  
texturedSphere(globeRadius, texmap);
popMatrix();
drawDots(0);
popMatrix();
rotationX += velocityX;
rotationY += velocityY;
velocityX *= 0.95;
velocityY *= 0.95;

// Implements mouse control (interaction will be inverse when sphere is  upside down)
if(mousePressed){
velocityX += (mouseY-pmouseY) * 0.01;
velocityY -= (mouseX-pmouseX) * 0.01;
}
}

void initializeSphere(int res)
{
sinLUT = new float[SINCOS_LENGTH];
cosLUT = new float[SINCOS_LENGTH];

for (int i = 0; i < SINCOS_LENGTH; i++) {
sinLUT[i] = (float) Math.sin(i * DEG_TO_RAD * SINCOS_PRECISION);
cosLUT[i] = (float) Math.cos(i * DEG_TO_RAD * SINCOS_PRECISION);
}

float delta = (float)SINCOS_LENGTH/res;
float[] cx = new float[res];
float[] cz = new float[res];

// Calc unit circle in XZ plane
for (int i = 0; i < res; i++) {
cx[i] = -cosLUT[(int) (i*delta) % SINCOS_LENGTH];
cz[i] = sinLUT[(int) (i*delta) % SINCOS_LENGTH];
}

// Computing vertexlist vertexlist starts at south pole
int vertCount = res * (res-1) + 2;
int currVert = 0;

// Re-init arrays to store vertices
sphereX = new float[vertCount];
sphereY = new float[vertCount];
sphereZ = new float[vertCount];
float angle_step = (SINCOS_LENGTH*0.5f)/res;
float angle = angle_step;

// Step along Y axis
for (int i = 1; i < res; i++) {
float curradius = sinLUT[(int) angle % SINCOS_LENGTH];
float currY = -cosLUT[(int) angle % SINCOS_LENGTH];
for (int j = 0; j < res; j++) {
sphereX[currVert] = cx[j] * curradius;
sphereY[currVert] = currY;
sphereZ[currVert++] = cz[j] * curradius;
}
angle += angle_step;
}
sDetail = res;
}

// Draw texture sphere
void texturedSphere(float r, PImage t) {
int v1,v11,v2;
r = (r + 240 ) * 0.33;
beginShape(TRIANGLE_STRIP);
texture(t);
float iu=(float)(t.width-1)/(sDetail);
float iv=(float)(t.height-1)/(sDetail);
float u=0,v=iv;
for (int i = 0; i < sDetail; i++) {
vertex(0, -r, 0,u,0);
vertex(sphereX[i]*r, sphereY[i]*r, sphereZ[i]*r, u, v);
u+=iu;
}
vertex(0, -r, 0,u,0);
vertex(sphereX[0]*r, sphereY[0]*r, sphereZ[0]*r, u, v);
endShape();   

// Middle rings
int voff = 0;
for(int i = 2; i < sDetail; i++) {
v1=v11=voff;
voff += sDetail;
v2=voff;
u=0;
beginShape(TRIANGLE_STRIP);
texture(t);
for (int j = 0; j < sDetail; j++) {
vertex(sphereX[v1]*r, sphereY[v1]*r, sphereZ[v1++]*r, u, v);
vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2++]*r, u, v+iv);
u+=iu;
}

// Close each ring
v1=v11;
v2=voff;
vertex(sphereX[v1]*r, sphereY[v1]*r, sphereZ[v1]*r, u, v);
vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2]*r, u, v+iv);
endShape();
v+=iv;
}
u=0;

// Add the northern cap
beginShape(TRIANGLE_STRIP);
texture(t);
for (int i = 0; i < sDetail; i++) {
v2 = voff + i;
vertex(sphereX[v2]*r, sphereY[v2]*r, sphereZ[v2]*r, u, v);
vertex(0, r, 0,u,v+iv);    
u+=iu;
}
vertex(sphereX[voff]*r, sphereY[voff]*r, sphereZ[voff]*r, u, v);
endShape();

}
//draw dot
void drawDots(float r){
r = (r + 240 ) * 0.33;
blendMode(ADD);
stroke(255, 100, 0, 100);
rotateX( radians(-rotationX) );  
rotateY( radians(270 - rotationY) );


for(int row = 0; row<rowCount; row++){  
int col2 = 0;
int col3 = 1;
int col4 = 2;
float latY = data.getFloat(row, col2);
float longX = data.getFloat(row, col3);
float ricter = data.getFloat(row, col4);
pushMatrix();
rotateX(radians(-latY));
rotateY(radians(longX));
translate(0,0,r+250);
ellipse(0,0,ricter*ricter*ricter/20,ricter*ricter*ricter/20);
popMatrix(); 
println(latY); 
}
rotationX += velocityX;
rotationY += velocityY;
velocityX *= 0.95;
velocityY *= 0.95;
}
void drawDial(){
translate(width-250, height-250);
image(img, -9/2, 53/2, 830/2,626/2 );
if(keyPressed){
if (key == '1') {
dial = radians( 0 );
setupstuff("2011.tsv");
}
if (key == '2') {
dial = radians( 120 );
setupstuff("2012.tsv");
}
if (key == '3') {
dial = radians( 240 );
setupstuff("2010.tsv");
}
}

rotate(dial);
image(img2, 103/2, -65/2, 314/2, 400/2);
}
void drawMain(){
image(imgTitle, width-320, 170);
}
void drawTitle(){
pushMatrix();
fill(255,255, 255);
translate(width-300, 120);
textFont(font, 32);
text("Earthquakes", 10, 50);
popMatrix();
}

class FloatTable {
int rowCount;
int columnCount;
float[][] data;
String[] rowNames;
String[] columnNames;


FloatTable(String filename) {
String[] rows = loadStrings(filename);

String[] columns = split(rows[0], TAB);
columnNames = subset(columns, 1); // upper-left corner ignored
scrubQuotes(columnNames);
columnCount = columnNames.length;

rowNames = new String[rows.length-1];
data = new float[rows.length-1][];

// start reading at row 1, because the first row was only the column headers
for (int i = 1; i < rows.length; i++) {
  if (trim(rows[i]).length() == 0) {
    continue; // skip empty rows
  }
  if (rows[i].startsWith("#")) {
    continue;  // skip comment lines
  }

  // split the row on the tabs
  String[] pieces = split(rows[i], TAB);
  scrubQuotes(pieces);

  // copy row title
  rowNames[rowCount] = pieces[0];
  // copy data into the table starting at pieces[1]
  data[rowCount] = parseFloat(subset(pieces, 1));

  // increment the number of valid rows found so far
  rowCount++;      
}
// resize the 'data' array as necessary
data = (float[][]) subset(data, 0, rowCount);
}

void scrubQuotes(String[] array) {
for (int i = 0; i < array.length; i++) {
  if (array[i].length() > 2) {
    // remove quotes at start and end, if present
    if (array[i].startsWith("\"") && array[i].endsWith("\"")) {
      array[i] = array[i].substring(1, array[i].length() - 1);
    }
  }
  // make double quotes into single quotes
  array[i] = array[i].replaceAll("\"\"", "\"");
}
}


int getRowCount() {
return rowCount;
}


String getRowName(int rowIndex) {
return rowNames[rowIndex];
}
String[] getRowNames() {
return rowNames;
}
int getRowIndex(String name) {
for (int i = 0; i < rowCount; i++) {
  if (rowNames[i].equals(name)) {
    return i;
  }
}
//println("No row named '" + name + "' was found");
return -1;
}



int getColumnCount() {
return columnCount;
}

String getColumnName(int colIndex) {
return columnNames[colIndex];
}

String[] getColumnNames() {
return columnNames;
}

float getFloat(int rowIndex, int col) {

if ((rowIndex < 0) || (rowIndex >= data.length)) {
  throw new RuntimeException("There is no row " + rowIndex);
}
if ((col < 0) || (col >= data[rowIndex].length)) {
  throw new RuntimeException("Row " + rowIndex + " does not have a column " + col);
}
return data[rowIndex][col];
}

boolean isValid(int row, int col) {
if (row < 0) return false;
if (row >= rowCount) return false;
//if (col >= columnCount) return false;
if (col >= data[row].length) return false;
if (col < 0) return false;
return !Float.isNaN(data[row][col]);
}


float getColumnMin(int col) {
float m = Float.MAX_VALUE;
for (int row = 0; row < rowCount; row++) {
  if (isValid(row, col)) {
    if (data[row][col] < m) {
      m = data[row][col];
    }
  }
}
return m;
}


float getColumnMax(int col) {
float m = -Float.MAX_VALUE;
for (int row = 0; row < rowCount; row++) {
  if (isValid(row, col)) {
    if (data[row][col] > m) {
      m = data[row][col];
    }
  }
}
return m;
}


float getRowMin(int row) {
float m = Float.MAX_VALUE;
for (int col = 0; col < columnCount; col++) {
  if (isValid(row, col)) {
    if (data[row][col] < m) {
      m = data[row][col];
    }
  }
}
return m;
} 


float getRowMax(int row) {
float m = -Float.MAX_VALUE;
for (int col = 0; col < columnCount; col++) {
  if (isValid(row, col)) {
    if (data[row][col] > m) {
      m = data[row][col];
    }
  }
}
return m;
}


float getTableMin() {
float m = Float.MAX_VALUE;
for (int row = 0; row < rowCount; row++) {
  for (int col = 0; col < columnCount; col++) {
    if (isValid(row, col)) {
      if (data[row][col] < m) {
        m = data[row][col];
      }
    }
  }
}
return m;
}  


float getTableMax() {
float m = -Float.MAX_VALUE;
for (int row = 0; row < rowCount; row++) {
  for (int col = 0; col < columnCount; col++) {
    if (isValid(row, col)) {
      if (data[row][col] > m) {
        m = data[row][col];
      }
    }
  }
}
return m;
}
}
Was it helpful?

Solution

UPDATE

Your error about Float might be related to this line:

return !Float.isNaN(data[row][col]);

Javascript is not going to recognize Float, that is a Java construct and not fully implemented within Processing. You need to find something else to make that comparison such as: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN

Similarly all the statements like the following

float m = Float.MAX_VALUE;

are not going to work with ProcessingJS. You might want to look at: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Infinity

ProcessingJS is extremely difficult to debug so you need to make sure you avoid everything that is only Java and not fully implemented in Processing. You need to also avoid variable name clash. Read the following to get an idea about what else could go wrong: http://processingjs.org/articles/p5QuickStart.html#thingstoknowusingpjs

Also the following method does not have a closing brace:

float getTableMin() {
    float m = Float.MAX_VALUE;
    for (int row = 0; row < rowCount; row++) {
      for (int col = 0; col < columnCount; col++) {
        if (isValid(row, col)) {
          if (data[row][col] < m) {
            m = data[row][col];
          }
        }
      }
    }
    return m;

Fix that by adding a closing brace like so:

float getTableMin() {
    float m = Float.MAX_VALUE;
    for (int row = 0; row < rowCount; row++) {
      for (int col = 0; col < columnCount; col++) {
        if (isValid(row, col)) {
          if (data[row][col] < m) {
            m = data[row][col];
          }
        }
      }
    }
    return m;
}  

This is why it helps to have properly formatted code. In your Processing IDE, select your code and then hit Ctrl-t, that should auto-format your code to something more easily readable.

By the way, your code wouldn't even run in Java mode without this fix. It will throw an unexpected token: float exception for the method in question.

UPDATE 2

To be able to get rid of your Float related code, you can change the following line

return !Float.isNaN(data[row][col]);

to

return isNaN(data[row][col]);

And you can change all instances of Float.MAX_VALUE; to Number.MAX_VALUE;.

After changing all the instances to Javascript friendly code, I too get the error you're getting. I will try to see if I can figure it out and update the answer.

OTHER TIPS

Instead of using fullscreen() use this code:


size(window.innerWidth, window.innerHeight, P3D);

NOTE: Does not work in IE. If IE:

void setup() {
    if (window.innerWidth) {
        wW = window.innerWidth;
        wH = window.innerHeight;
    } else {
        var cW = document.body.offsetWidth;
        var cH = document.body.offsetHeight;
        window.resizeTo(500,500);
        var barsW = 500 - document.body.offsetWidth;
        var barsH = 500 - document.body.offsetHeight;
        wW = barsW + cW;
        wH = barsH + cH;
        window.resizeTo(wW,wH);
    }
    size(wW,wH,P3D);
}

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top