Anoying Null Pointer Exception
in
Programming Questions
•
1 year ago
Hi there.
I've been trying to generate an array to support a flocking bunch of points in 3d, which seems to be kind what you should do if you want to reduce processing time per agent.
After a while, I'm bumping against a NullPointerException which I haven't been able to trace.
Any ideas on where should I look at?
Just for the record, I'm not too advanced on processing (but very enthusiastic) so, please, don't make too complex answers... Thanks!
Oh... there goes my code (which is not entirely mine, but I'll give the credits when I finish it... up to now...
//Libraries
import processing.opengl.*;
import peasy.*;
//Global variables
float align = 5; // Distance for Flockers to follow each other.
float avoid = 1; // Distance to move away from each other
float cohesion = 2; // A factor to keep the Flockers crowding
float multiplier = 25; // an adjustment multiplier
int maxFlockers = 10000; //maximum number of Flockers to be generated
PeasyCam cam; // The camera to be used
float minDist = 100; //The local area for the Flockers to be aware of
public PVector velocity; // A public vector to transfer values and draw with them
public int gridSize = 50; // A measure for the onscreen grid
public int Rows, Cols, Stacks, Cells;// Integers to store the number of gridcells per axis
ArrayList[] FlockersCollection; // The array to store the arraylists
///////////////////////////////////////////////////////////////////////////////////////
// SETUP /////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
void setup() {
size(1000, 1000, P3D); //sets the size and renderer for the process.
//size(1000,1000,OPENGL);//I'm using the default Processing 3D to be able to share the sketches.
// But the final results will be rendered with OpenGL to achieve better results (like round points)
noSmooth();
int depth = width;
cam = new PeasyCam(this, width, height, depth, depth*2.5); //generate the camera
//define the array to put agents in
Rows = (width / gridSize);
Cols = (height / gridSize);
Stacks = (depth / gridSize);
Cells = (Rows*Cols*Stacks)+1; // The total number of cells, plus 1 just in case
FlockersCollection = new ArrayList[Cells+1];
////////////////////////////////////
//// Initialise the array cells ////
////////////////////////////////////
for (int i = 0; i<= Cells-1; i++) {
FlockersCollection[i] = new ArrayList();
}
//////////////////////////////////////////////////////////
////// GENERATE THE AGENTS, AND FILL THE ARRAYLISTS //////
//////////////////////////////////////////////////////////
for (int n = 0; n < maxFlockers-1; n++) {
//Define the variables to use: Position only
int AlocX = int(random(width));
int AlocY = int(random(height));
int AlocZ = int(random(depth));
//Check the cell containing the agent and assign it there
int XCell = floor(AlocX / gridSize);
int YCell = floor(AlocY / gridSize);
int ZCell = floor(AlocZ / gridSize);
// Control the agent is not out of bounds
if (XCell > Rows) XCell = Rows;
if (YCell > Cols) YCell = Cols;
if (ZCell > Stacks) ZCell = Stacks;
if (XCell < 1) XCell = 1;
if (YCell < 1) YCell = 1;
if (ZCell < 1) ZCell = 1;
//Calculate the cell number
int Cell = (XCell + (YCell*Rows) + (ZCell*Cols*Rows));
//Define the location vector
PVector Aloc = new PVector (AlocX, AlocY, AlocZ);
//Generate Flockers and store them within the array (FlockerPop)
Flocker F = new Flocker(
//Variables incorporated
Aloc
);
FlockersCollection[Cell].add(F);
}
}
///////////////////////////////////////////////////////////////////////////////////////
// DRAW /////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
void draw() {
////// The good old fashioned black background //////
background(0);
////// DRAW THE FLOCKERS AND RUN THE BEHAVIOURS INCLUDED
for (ArrayList FlockerPop : FlockersCollection) {
for (int i = 0; i < FlockerPop.size(); i ++ ) { // Bloody null pointer exception
Flocker F = (Flocker)FlockerPop.get(i);
F.run();
}
}
}
//////////////////////////////////////////////////////////////////////////////////////
// CLASS: AGENT.....................................................................//
//////////////////////////////////////////////////////////////////////////////////////
class Flocker {
////// GLOBAL VARIABLES //////
// To store position
PVector Floc;
//To store velocity
PVector Fvel = new PVector(random(-10, 10), random(-10, 10), random(-10, 10));
// To store the mass of the object
float Fsize;
// To store the acceleration, responsable for the steering behaviour
PVector Facc = new PVector (0, 0, 0);
//To define the third dimension of the box
int depth = height;
//Add some noise by using a controlled randomness
float noiseScale = 0.3;
int lastCell, newCell; //to designate the arrays
/////////////////////////
////// CONSTRUCTOR //////
/////////////////////////
Flocker(
// Position
PVector _Floc
)
{
// Push variables to local
Floc = _Floc;
//Find the cell containing the Flocker
int XCell = floor(Floc.x/gridSize);
int YCell = floor(Floc.y/gridSize);
int ZCell = floor(Floc.z/gridSize);
//Check the range and correct it if necessary
if (XCell > Rows) XCell = Rows;
if (YCell > Cols) YCell = Cols;
if (ZCell > Stacks) ZCell = Stacks;
if (XCell < 1) XCell = 1;
if (YCell < 1) YCell = 1;
if (ZCell < 1) ZCell = 1;
//Enumerate the corresponding cell
lastCell = (XCell + (YCell*Rows) + (ZCell*Cols*Rows));
}
///////////////////////////////////////////////////////////////
////// FUNCTIONS //////////////////////////////////////////////
///////////////////////////////////////////////////////////////
////// Run calls what the flocker will do /////////////////////
///////////////////////////////////////////////////////////////
void run() {
flockIt(); // Move the object with local awarenes
updatePos(); // Keep the Flocker on the working area
display(); // Draw the Flocker
updateCell();
}
///////////////////////////////////////////////////////////////////////////
// UPDATECELL : Calculate and update which cell the agent is into /////////
///////////////////////////////////////////////////////////////////////////
void updateCell() {
// Check the location and calculate the corresponding grid space
// Find the cell containing the Flocker
int XCell = floor(Floc.x/gridSize);
int YCell = floor(Floc.y/gridSize);
int ZCell = floor(Floc.z/gridSize);
// Check the range and correct it if necessary
if (XCell > Rows) XCell = Rows;
if (YCell > Cols) YCell = Cols;
if (ZCell > Stacks) ZCell = Stacks;
if (XCell < 1) XCell = 1;
if (YCell < 1) YCell = 1;
if (ZCell < 1) ZCell = 1;
// Enumerate the corresponding cell
newCell = (XCell + (YCell*Rows) + (ZCell*Cols*Rows));
if(newCell < 1) newCell = 1;
if(newCell >= Cells) newCell = Cells-1;
print(" | " + XCell + ","+ YCell + "," + ZCell + " - Cells:" + lastCell+ " -> " + newCell);
// Check if there has been a change in the grid cell allocation
if (newCell != lastCell) {
// Remove the agent from current list and add to new list
int index = FlockersCollection[lastCell].indexOf(this);
print(" | index:" + index);
FlockersCollection[lastCell].remove(index);
FlockersCollection[newCell].add(this);
print(newCell + "/"+Rows*Cols*Stacks + " | ");
//update lastCell
lastCell = newCell;
}
}
///////////////////////////////////////////////////////////////
////// And the meaty piece of all: Flock //////////////////////
///////////////////////////////////////////////////////////////
void flockIt() {
for (int j = 0; j < FlockersCollection[lastCell].size(); j++) {
Flocker F = (Flocker) FlockersCollection[lastCell].get(j);
float FlockerDist = PVector.dist(Floc, F.Floc);
if (FlockerDist > 0) {
if (FlockerDist < minDist) {
if (FlockerDist < align*multiplier) {
PVector addVec = F.Fvel.get();
addVec.mult(FlockerDist);
Facc.add(addVec);
Facc.normalize();
}
if (FlockerDist < avoid*multiplier) {
PVector addVec = F.Floc.get();
addVec.mult(2);
addVec.sub(Floc);
addVec.mult(FlockerDist);
Facc.sub(addVec);
Facc.normalize();
}
if (FlockerDist < cohesion*multiplier) {
PVector addVec = F.Floc.get();
addVec.add(Floc);
addVec.mult(1/FlockerDist);
Facc.add(addVec);
Facc.normalize();
}
}
}
}
}
///////////////////////////////////////////////////////////////
////// This function will update the flocker's position ///////
///////////////////////////////////////////////////////////////
void updatePos() {
//Produce the steering behaviour, responsable for the dampened changes
Fvel.add(Facc);
//Add some noise to the vector components
Fvel.x = random(1-noiseScale, 1+noiseScale)*(Fvel.x);
Fvel.y = random(1-noiseScale, 1+noiseScale)*(Fvel.y);
Fvel.z = random(1-noiseScale, 1+noiseScale)*(Fvel.z);
//Limit the speed with graphic purposes
Fvel.limit(random(5, 7));
velocity = Fvel;
Floc.add(Fvel);
//if the X coord is out of the boundary, move it to the other boundary
if (Floc.x > width) {
Floc.x = 0;
}
if (Floc.x < 0) {
Floc.x = width;
}
//if the Y coord is out of the boundary, move it to the other boundary
if (Floc.y > height) {
Floc.y = 0;
}
if (Floc.y < 0) {
Floc.y = height;
}
//if the Z coord is out of the boundary, move it to the other boundary
if (Floc.z > depth) {
Floc.z = 0;
}
if (Floc.z < 0) {
Floc.z = depth;
}
}
//////////////////////////////////////////////////////////////
////// Display renders the shape to the Flocker //////////////
//////////////////////////////////////////////////////////////
void display() {
//Use the current position to map zones by colours
stroke((map(velocity.x, 0, 5, 0, 250)), (map(velocity.y, 0, 5, 0, 250)), (map(velocity.z, 0, 5, 0, 250)));
//Draw a point
//strokeWeight(1);
//point(Floc.x, Floc.y, Floc.z);
PVector end = new PVector(Floc.x, Floc.y, Floc.z);
velocity.mult(1);
end.sub(velocity);
//Draw a line which represents the direction of the Flocker
line(Floc.x, Floc.y, Floc.z, end.x, end.y, end.z);
}
}
1