Unity - Improve Mesh generation and rendering performance - performance

since I just recently started looking into meshes, how they work, what they do and so on, I decided to use my own calculations to create a mesh of a circle. Unfortunately though, this is really, really slow!
So I am looking for tips on improvements, to make it slow only (because that's probably the best it will get...)
Here is the code I use to generate a circle:
public static void createCircle(MeshFilter meshFilter, float innerRadius, float outerRadius, Color color, float xPosition = 0, float yPosition = 0, float startDegree = 0, float endDegree = 360, int points = 100)
{
Mesh mesh = meshFilter.mesh;
mesh.Clear();
//These values will result in no (or very ugly in the case of points < 10) circle, so let's safe calculation and just return an empty mesh!
if (startDegree == endDegree || points < 10 || innerRadius >= outerRadius || innerRadius < 0 || outerRadius <= 0)
{
return;
}
//The points for the full circle shall be whatever is given but if its not the full circle we dont need all the points!
points = (int)(Mathf.Abs(endDegree - startDegree) / 360f * points);
//We always need an uneven number of points!
if (points % 2 != 0) { points++; }
Vector3[] vertices = new Vector3[points];
float degreeStepSize = (endDegree - startDegree) * 2 / (points - 3);
float halfRadStepSize = (degreeStepSize) * Mathf.Deg2Rad / 2f;
float startRad = Mathf.Deg2Rad * startDegree;
float endRad = Mathf.Deg2Rad * endDegree;
//Let's save the vector at the beginning and the one on the end to make a perfectly straight line
vertices[0] = new Vector3(Mathf.Sin(startRad) * outerRadius + xPosition, Mathf.Cos(startRad) * outerRadius + yPosition, 0);
vertices[vertices.Length - 1] = new Vector3(Mathf.Sin(endRad) * innerRadius + xPosition, Mathf.Cos(endRad) * innerRadius + yPosition, 0);
for (int i = 1; i < vertices.Length - 1; i++)
{
//Pure coinsidence that saved some calculatons. Half Step Size is the same as what would needed to be calculated here!
float rad = (i - 1) * halfRadStepSize + startRad;
if (i % 2 == 0)
{
vertices[i] = new Vector3(Mathf.Sin(rad) * outerRadius + xPosition, Mathf.Cos(rad) * outerRadius + yPosition, 0);
}
else
{
vertices[i] = new Vector3(Mathf.Sin(rad) * innerRadius + xPosition, Mathf.Cos(rad) * innerRadius + yPosition, 0);
}
}
mesh.vertices = vertices;
int[] tri = new int[(vertices.Length - 2) * 3];
for (int i = 0; i < (vertices.Length - 2); i++)
{
int index = i * 3;
if (i % 2 == 0)
{
tri[index + 0] = i + 0;
tri[index + 1] = i + 2;
tri[index + 2] = i + 1;
}
else
{
tri[index + 0] = i + 0;
tri[index + 1] = i + 1;
tri[index + 2] = i + 2;
}
}
mesh.triangles = tri;
Vector3[] normals = new Vector3[vertices.Length];
Color[] colors = new Color[vertices.Length];
for (int i = 0; i < vertices.Length; i++)
{
normals[i] = Vector3.forward;
colors[i] = color;
}
mesh.normals = normals;
mesh.colors = colors;
meshFilter.mesh = mesh;
}
I know I "could just use the LineRenderer shipped with Unity, it is faster then anything you'll ever write", but that's not the point here.
I am trying to understand meshes and see where I can tweak my code to improve it's performance.
Thanks for your help in advance!

You can almost double the speed by removing extra memory allocation. Since Vector3 is a value type, they are already allocated when you allocate the array. Vector3.forward also allocates a new Vector3 each time, and we can re-use it.
public static void createCircle(MeshFilter meshFilter, float innerRadius, float outerRadius, Color color, float xPosition = 0, float yPosition = 0, float startDegree = 0, float endDegree = 360, int points = 100)
{
Mesh mesh = meshFilter.mesh;
mesh.Clear();
//These values will result in no (or very ugly in the case of points < 10) circle, so let's safe calculation and just return an empty mesh!
if (startDegree == endDegree || points < 10 || innerRadius >= outerRadius || innerRadius < 0 || outerRadius <= 0)
{
return;
}
//The points for the full circle shall be whatever is given but if its not the full circle we dont need all the points!
points = (int)(Mathf.Abs(endDegree - startDegree) / 360f * points);
//We always need an uneven number of points!
if (points % 2 != 0) { points++; }
Vector3[] vertices = new Vector3[points];
float degreeStepSize = (endDegree - startDegree) * 2 / (points - 3);
float halfRadStepSize = (degreeStepSize) * Mathf.Deg2Rad / 2f;
float startRad = Mathf.Deg2Rad * startDegree;
float endRad = Mathf.Deg2Rad * endDegree;
//Let's save the vector at the beginning and the one on the end to make a perfectly straight line
vertices[0] = new Vector3(Mathf.Sin(startRad) * outerRadius + xPosition, Mathf.Cos(startRad) * outerRadius + yPosition, 0);
vertices[vertices.Length - 1] = new Vector3(Mathf.Sin(endRad) * innerRadius + xPosition, Mathf.Cos(endRad) * innerRadius + yPosition, 0);
for (int i = 1; i < vertices.Length - 1; i++)
{
//Pure coinsidence that saved some calculatons. Half Step Size is the same as what would needed to be calculated here!
float rad = (i - 1) * halfRadStepSize + startRad;
if (i % 2 == 0)
{
vertices[i].x = Mathf.Sin(rad) * outerRadius + xPosition;
vertices[i].y = Mathf.Cos(rad) * outerRadius + yPosition;
vertices[i].z = 0;
}
else
{
vertices[i].x = Mathf.Sin(rad) * innerRadius + xPosition;
vertices[i].y = Mathf.Cos(rad) * innerRadius + yPosition;
vertices[i].z = 0;;
}
}
mesh.vertices = vertices;
int[] tri = new int[(vertices.Length - 2) * 3];
for (int i = 0; i < (vertices.Length - 2); i++)
{
int index = i * 3;
if (i % 2 == 0)
{
tri[index + 0] = i + 0;
tri[index + 1] = i + 2;
tri[index + 2] = i + 1;
}
else
{
tri[index + 0] = i + 0;
tri[index + 1] = i + 1;
tri[index + 2] = i + 2;
}
}
mesh.triangles = tri;
Vector3[] normals = new Vector3[vertices.Length];
Color[] colors = new Color[vertices.Length];
var f = Vector3.forward;
for (int i = 0; i < vertices.Length; i++)
{
normals[i].x= f.x;
normals[i].y= f.y;
normals[i].z= f.z;
colors[i] = color;
}
mesh.normals = normals;
mesh.colors = colors;
meshFilter.mesh = mesh;
}

Related

Adjust flat map image for other projections

I'm using D3.js to create a globe. I have a working SVG wife-frame version, and I'm also trying to create a more detailed textured one, a two-mode thing.
The image I'm using from an API is square:
Which doesn't really work out well when projected to orthographic, it's a lot more "squished" towards the equator than it should be:
Not doing anything particularly special:
const dx = 2048;
const dy = 2048;
const width = 2048;
const height = 2048;
let sourceData = mapImage.getImageData(0, 0, dx, dy).data,
target = ctx.createImageData(width, height),
targetData = target.data;
for (let y = 0, i = -1; y < height; ++y) {
for (let x = 0; x < width; ++x) {
let p = projection.invert([x, y]);
if (p[0] > 180 || p[0] < -180 || p[1] > 90 || p[1] < -90) {
i += 4;
continue;
}
let q = ((90 - p[1]) / 180 * dy | 0) * dx + ((180 + p[0]) / 360 * dx | 0) << 2;
targetData[++i] = sourceData[q];
targetData[++i] = sourceData[++q];
targetData[++i] = sourceData[++q];
targetData[++i] = 255;
}
}
ctx.clearRect(0, 0, width, height);
ctx.putImageData(target, 0, 0);
I'm wondering if there's a straightforward way to make the additional adjustment for the stretching of the map image?
(Bonus points if you can also point me to why the space around the globe is not transparent? But that's not the main question here.)

How can you write an algorithm to properly fill a circle using lines from the center?

Currently I try to write code for calculating the parts of the screen you can see and those who can't because of objects that block light in 2d, like in Among Us:
The code should run on a processor with very low specs (at least in 2020), the C64. On such a simple CPU it's not possible to do such complex math fast enough for a game, so I came up with an idea: First of all, I make everything tile based, that makes processing easier and also means that I can just change entire characters or their color cells. Then I just write code for the PC in Processing (that's a coding language similar to Java but easier to use) to calculate how rays of light would move (the following graphic should make that more understandable), first just with a rectangle (and a single quadrant):
Then I wrote some completely messy assembler code for using the recorded coordinates to just keep filling the tiles with an inverted character based on the number of the ray currently being drawn on the ray until they hit an object (/ the tile it wants to fill is not inverted and not a space) and then just go to the next ray. I reduced the radius to 7 so it just takes up 256 bytes, useful for ASM. And that totally worked, I was able to fix every single bug and the result was quite impressive, since I needed to add pause statements or everything ran so fast that you couldn't see anything.
After that worked, I tried it with a circle, setting the points using this code:
int pointNum = ceil(radius * PI * 2); // calculates the circumference
for(int i = 0;i < pointNum;i++){
float angle = map(i, 0, pointNum, 0, PI*2);
setPixel(sin(angle) * radius, cos(angle) * radius);
}
I previously used the Bresenham circle algorithm but that didn't quite work so I tried a more simple way. So ...
All the marked black tiles never get hit by any light, which is a pretty big issue, because it wouldn't make much sense in a game that you just can't see those tiles. The code I used, written in Processing, is:
float[] xPoints = new float[0];
float[] yPoints = new float[0];
float[] xPointsT;
float[] yPointsT;
float[] xPointsHad = new float[0];
float[] yPointsHad = new float[0];
int pos = 0;
float interpolPos = 0;
int radius = 12;
float tileSize = 800.0 / (2*radius+1);
String output = " !byte ";
int pointNum = ceil(radius * PI * 2);
void setup() {
size(800, 800);
frameRate(60);
xPointsT = new float[0];
yPointsT = new float[0];
/*for(int i = 0;i <= radius;i++){
setPixel(radius, i);
setPixel(i, radius);
}*/ //Uncomment this and comment the next 4 lines to get the rectangle version
for(int i = 0;i < pointNum;i++){
float angle = map(i, 0, pointNum, 0, PI*2);
setPixel(sin(angle) * radius, cos(angle) * radius);
}
xPoints = concat(xPoints, xPointsT);
yPoints = concat(yPoints, yPointsT);
}
void draw(){
if(interpolPos > radius){
pos++;
interpolPos = 0;
println(output);
output = " !byte ";
}
float x=0, y=0;
float interpolMul = interpolPos / radius;
x = xPoints[pos] * interpolMul;
y = yPoints[pos] * interpolMul;
interpolPos+=1;//sorta the resolution
background(0);
stroke(255);
for(int i = 0;i < 2*radius+1;i++){
for(int j = 0;j < 2*radius+1;j++){
if((round(x) + radius) == i && (round(y) + radius) == j){
fill(0, 255, 0);
if(output != " !byte ")
output += ", ";
output += i-radius;
output += ", ";
output += j-radius;
xPointsHad = append(xPointsHad, i);
yPointsHad = append(yPointsHad, j);
}
else{
int fillVal = 0;
for(int k = 0; k < xPoints.length;k++){
if(round(xPoints[k])+radius == i && round(yPoints[k])+radius == j){
fillVal += 64;
}
}
fill(0, 0, fillVal);
if(fillVal == 0){
for(int k = 0; k < xPointsHad.length;k++){
if(round(xPointsHad[k]) == i && round(yPointsHad[k]) == j){
fill(128, 0, 0);
}
}
}
}
rect(i * tileSize, j * tileSize, tileSize, tileSize);
}
}
strokeWeight(3);
stroke(0, 255, 255, 64);
for(int i = 0;i < xPoints.length;i++){
line((float(radius)+0.5) * tileSize, (float(radius)+0.5) * tileSize, (float(radius)+0.5+xPoints[i]) * tileSize, (float(radius)+0.5+yPoints[i]) * tileSize);
}
strokeWeight(1);
fill(255, 255, 0);
ellipse((x + radius + 0.5) * tileSize, (y + radius + 0.5) * tileSize, 10, 10);
}
void setPixel(float _x, float _y){
for(int i = 0; i < xPoints.length;i++){
if(_x == xPoints[i] && _y == yPoints[i]){
return;
}
}
for(int i = 0; i < xPointsT.length;i++){
if(_x == xPointsT[i] && _y == yPointsT[i]){
return;
}
}
xPointsT = append(xPointsT, _x);
yPointsT = append(yPointsT, _y);
}
(Instructions to get the rectangle are in the code)
Those mentioned tiles seem to be never hit because the rays on them just jump over them, but what can I do to prevent that? You can decrease interpolPos+=x; to hit more tiles because that way your steps are smaller, but that wastes quite some space, so I don't think that's a good solution. Ideally you could also just decrease the number of coordinates you draw to get a smaller vision. Has anyone a good idea how to do that?
You have chosen wrong method to find all touched cells - instead of point-based way you need cell(squares)-based approach - ray intersects rectangle rather than point.
There is article of Amanatides and Woo "A Fast Voxel Traversal Algorithm for Ray Tracing" for 2D.
Practical implementation.
Example:
Quick-made tracing example. Rays emitted from left top corner go to blue points. If ray meets black cell obstacle, it stops. Pink cells are lighted by rays, grey ones are not.
Okay, I found something that worked for me in my situation: I just used the part that totally works (the rectangle) and then just make that a circle by ignoring every tile hit that's further away from the light source then the radius + 0.5, because without + .5 the circle looks weird. You can try it yourself, here's the code:
float[] xPoints = new float[0];
float[] yPoints = new float[0];
float[] xPointsT;
float[] yPointsT;
float[] xPointsHad = new float[0];
float[] yPointsHad = new float[0];
int pos = 0;
float interpolPos = 0;
int radius = 7;
float tileSize = 800.0 / (2*radius+1);
int pointNum = ceil(radius * PI * 2);
String standardOutput = " !align 15,0\n !byte ";
void setup() {
size(800, 800);
frameRate(60);
xPointsT = new float[0];
yPointsT = new float[0];
for(int i = 0;i <= radius;i++){
setPixel(radius, i);
setPixel(i, radius);
} //Uncomment this and comment the next 4 lines to get the rectangle version
/*for(int i = 0;i < pointNum;i++){
float angle = map(i, 0, pointNum, 0, PI*2);
setPixel(sin(angle) * radius, cos(angle) * radius);
}*/
xPoints = concat(xPoints, xPointsT);
yPoints = concat(yPoints, yPointsT);
xPointsT = new float[0];
yPointsT = new float[0];
}
void draw(){
if(interpolPos > radius){
pos++;
interpolPos = 0;
String output = standardOutput;
for(int i = 0;i < radius + 1;i++){
int indexPos = floor(map(i, 0, radius + 1, 0, xPointsT.length));
output += round(xPointsT[indexPos]);
output += ",";
output += round(yPointsT[indexPos]);
if(i < radius){
output += ", ";
}
}
println(output);
xPointsT = new float[0];
yPointsT = new float[0];
}
float x=0, y=0;
float interpolMul = interpolPos / radius;
x = xPoints[pos] * interpolMul;
y = yPoints[pos] * interpolMul;
interpolPos+=1;//sorta the resolution
background(0);
stroke(255);
for(int i = 0;i < 2*radius+1;i++){
for(int j = 0;j < 2*radius+1;j++){
if((round(x) + radius) == i && (round(y) + radius) == j && sqrt(sq(round(x)) + sq(round(y))) < radius + 0.5){
fill(0, 255, 0);
xPointsT = append(xPointsT, i-radius);
yPointsT = append(yPointsT, j-radius);
xPointsHad = append(xPointsHad, i);
yPointsHad = append(yPointsHad, j);
}
else{
int fillVal = 0;
for(int k = 0; k < xPoints.length;k++){
if(round(xPoints[k])+radius == i && round(yPoints[k])+radius == j){
fillVal += 64;
}
}
fill(0, 0, fillVal);
if(fillVal == 0){
for(int k = 0; k < xPointsHad.length;k++){
if(round(xPointsHad[k]) == i && round(yPointsHad[k]) == j){
fill(128, 0, 0);
}
}
}
}
rect(i * tileSize, j * tileSize, tileSize, tileSize);
}
}
strokeWeight(3);
stroke(0, 255, 255, 64);
for(int i = 0;i < xPoints.length;i++){
line((float(radius)+0.5) * tileSize, (float(radius)+0.5) * tileSize, (float(radius)+0.5+xPoints[i]) * tileSize, (float(radius)+0.5+yPoints[i]) * tileSize);
}
strokeWeight(1);
fill(255, 255, 0);
ellipse((x + radius + 0.5) * tileSize, (y + radius + 0.5) * tileSize, 10, 10);
}
void setPixel(float _x, float _y){
for(int i = 0; i < xPoints.length;i++){
if(_x == xPoints[i] && _y == yPoints[i]){
return;
}
}
for(int i = 0; i < xPointsT.length;i++){
if(_x == xPointsT[i] && _y == yPointsT[i]){
return;
}
}
xPointsT = append(xPointsT, _x);
yPointsT = append(yPointsT, _y);
}
Besides the main difference to ignore tiles that are not in the circle, I also changed that I store the coordinates not in a String but in two arrays, because then I use code to stretch them when there are fewer then radius + 1 points, so I don't have to store multiple circles with different sizes in the C64's RAM, so it meets my main requirements: It should fill every tile and it should be downscalable by ignoring some points at the end of rays. And is if efficient? Uh ... there could be a better solution that fills the circle with fewer rays, but I don't care too much. Still, if you have an idea, it would be nice if you could tell me, but otherwise this question is solved.
Edit: I forgot to add a picture. Don't be confused, I modified the code after posting it so you can also see the blue tiles on the circle.

How do I make a variable randomly equal 1 of 2 numbers? (Processing)

I'm trying for the first time to make Pong. I don't always want the ball to go to the bottom right by adding 3 every single time. How would I make it so it will either do 3, or -3, but no number in between? I know that "||" doesn't work for integers, and "random(-3,3) has the chance of giving me numbers like "0.1" which wouldn't really function in here.
Code:
float circleX = 640/2;
float circleY = 360/2;
float xSpeed = 3;
float ySpeed = 3;
float Color = (255);
float circleHeight = 32;
float circleWidth = 32;
float xAcceleration = -1.0;
float yAcceleration = -1.0;
float paddleColor = 255;
float MyPaddleX = 630;
float OpPaddleX = 10;
float MyPaddleWidth = 10;
float OpPaddleWidth = -10;
void setup() {
size(640, 360);
frameRate(60);
}
void draw() {
background(0);
//Ball
fill(Color);
ellipse(circleX, circleY, circleWidth, circleHeight);
xSpeed = //(WHAT TO PUT HERE?)
circleX = circleX + xSpeed;
circleY = circleY + ySpeed;
//My Paddle
fill(paddleColor);
rect(MyPaddleX,mouseY,MyPaddleWidth,100);
//Bouncing
if (circleX >= OpPaddleX && OpPaddleX + OpPaddleWidth >= circleX) {
xSpeed = xSpeed * xAcceleration;
}
// Top/Bottom Bouncing
if (circleY > height || circleY < 0) {
ySpeed = ySpeed * yAcceleration;
}
//My Paddle Bounceback
if (circleY >= mouseY && circleY <= mouseY + 100) {
if (circleX >= MyPaddleX && circleX <= MyPaddleX + 3)
xSpeed = xSpeed * xAcceleration;
}
//Opponent Paddle
fill(paddleColor);
rect(OpPaddleX,circleY - 50,OpPaddleWidth,100);
//if (circleX < OpPaddleX || circleX > MyPaddleX) {
// circleX = width/2;
// circleY = height/2;
// xSpeed = 0;
// ySpeed = 0;
//}
}
You can generate a number between 0 and 1 and then compare that generated number to 0.5 to "flip a coin" in your code.
Think about it this way: when you call random(1), you'll get a value between 0 and 1. Half of those values will be less than 0.5, the other half will be greater than (or equal to) 0.5.
So you can do something like this:
float x;
if(random(1) < .5){
x = -3;
}
else{
x = 3;
}
You could expand this to choose from more numbers using else if statements, or you could shorten it into a single line of code using the ternary operator:
float x = random(1) < .5 ? 3 : -3;

Fourier Shape Descriptors

I'm looking at a paper named "Shape Based Image Retrieval Using Generic Fourier Descriptors", but only have rudimentary knowledge of Fourier Descriptors. I am attempting to implement the algorithm on page 12 of the paper, and have some results which I can't really make too much sense out of.
If I create an small image, take calculate the FD for the image, and compare the FD to the same image which has been translated by a single pixel in the x and y directions, the descriptor is completely different, except for the first entry - which is exactly the same. Firstly, a question is, is should these descriptors be exactly the same (as the descriptor is apparently scale, rotation, and translation invariant) between the two images?
Secondly, in the paper, it mentions that descriptors of two separate images are compared by a simple Euclidean distance - therefore, by taking the Euclidean distance between the two descriptors mentioned above, the Euclidean distance would apparently be 0.
I quickly put together some Javascript code to test out the algorithm, which is below.
Does anybody have any input, ideas, ways to move forward?
Thanks,
Paul
var iShape = [
0, 0, 0, 0, 0,
0, 0, 255, 0, 0,
0, 255, 255, 255, 0,
0, 0, 255, 0, 0,
0, 0, 0, 0, 0
];
var ImageWidth = 5, ImageHeight = 5, MaxRFreq = 5, MaxAFreq = 5;
// Calculate centroid
var cX = 0, cY = 0, pCount = 0;
for (x = 0; x < ImageWidth; x++) {
for (y = 0; y < ImageHeight; y++) {
if (iShape[y * ImageWidth + x]) {
cX += x;
cY += y;
pCount++;
}
}
}
cX = cX / pCount;
cY = cY / pCount;
console.log("cX = " + cX + ", cY = " + cY);
// Calculate the maximum radius
var maxR = 0;
for (x = 0; x < ImageWidth; x++) {
for (y = 0; y < ImageHeight; y++) {
if (iShape[y * ImageWidth + x]) {
var r = Math.sqrt(Math.pow(x - cX, 2) + Math.pow(y - cY, 2));
if (r > maxR) {
maxR = r;
}
}
}
}
// Initialise real / imaginary table
var i;
var FR = [ ];
var FI = [ ];
for (r = 0; r < (MaxRFreq); r++) {
var rRow = [ ];
FR.push(rRow);
var aRow = [ ];
FI.push(aRow);
for (a = 0; a < (MaxAFreq); a++) {
rRow.push(0.0);
aRow.push(0.0);
}
}
var rFreq, aFreq, x, y;
for (rFreq = 0; rFreq < MaxRFreq; rFreq++) {
for (aFreq = 0; aFreq < MaxAFreq; aFreq++) {
for (x = 0; x < ImageWidth; x++) {
for (y = 0; y < ImageHeight; y++) {
var radius = Math.sqrt(Math.pow(x - maxR, 2) +
Math.pow(y - maxR, 2));
var theta = Math.atan2(y - maxR, x - maxR);
if (theta < 0.0) {
theta += (2 * Math.PI);
}
var iPixel = iShape[y * ImageWidth + x];
FR[rFreq][aFreq] += iPixel * Math.cos(2 * Math.PI * rFreq *
(radius / maxR) + aFreq * theta);
FI[rFreq][aFreq] -= iPixel * Math.sin(2 * Math.PI * rFreq *
(radius / maxR) + aFreq * theta);
}
}
}
}
// Initialise fourier descriptor table
var FD = [ ];
for (i = 0; i < (MaxRFreq * MaxAFreq); i++) {
FD.push(0.0);
}
// Calculate the fourier descriptor
for (rFreq = 0; rFreq < MaxRFreq; rFreq++) {
for (aFreq = 0; aFreq < MaxAFreq; aFreq++) {
if (rFreq == 0 && aFreq == 0) {
FD[0] = Math.sqrt(Math.pow(FR[0][0], 2) + Math.pow(FR[0][0], 2) /
(Math.PI * maxR * maxR));
} else {
FD[rFreq * MaxAFreq + aFreq] = Math.sqrt(Math.pow(FR[rFreq][aFreq], 2) +
Math.pow(FI[rFreq][aFreq], 2) / FD[0]);
}
}
}
for (i = 0; i < (MaxRFreq * MaxAFreq); i++) {
console.log(FD[i]);
}
There are three separate normalization techniques applied here in order to make the final descriptor invariant to 1) translation and 2) scale 3) rotation.
For the translation invariance part you need to find the centroid of the shape and calculate the vector of every contour point having the centroid as the origin. This is done by substracting the x and y coordinate of the centroid from each point's coordinates, respectively. So in your code the radius and theta of each point should be computes as follows:
var radius = Math.sqrt(Math.pow(x - cX, 2) + Math.pow(y - cY, 2));
var theta = Math.atan2(y - cY, x - cX);
For the scale invariance part you need to find the maximum magnitute(or radius as you say) of every vector (already normalized for translation invariance) and divide the magnitude of each point by the maximum magnitude value. An alternative way of achieving this is to divide every fourier coefficient with the zero-frequency coefficient (first coefficient) as the scale information is represented there. As I can see in you code and in the paper, this is implemented according to the second way I described.
Finally, the rotation invariance is achieved by only keeping the magnitude of the fourier coefficients as you can see in step 6 of the paper's pseudo-code.
In addition to all these, keep in mind that in order to apply the eucidean distance for the descriptor comparison, the length of the descriptor for every shape must be the same. In FFT, the number of the final coefficients depends on the number of the contour points of the shape. The solution I have found to this is to interpolate between points in order to reach a fixed number of points for every shape.
Hope I helped,
Lazaros

Get shapes on screen

I have created a grid of thumbs. When a certain thumb is pressed I want the image that is linked to the thumb added on screen. I know i'm supposed to write the loadImages in setup(), but i'm a bit confused on how to do this.
PShape[] Quotes = new PShape[6];
int qLength = Quotes.length;
setup() {
size(1024, 768);
}
draw() {
stroke(bruin);
strokeWeight(5);
fill(wit);
rectMode(CORNER);
rect(guide, 280, bBorder, 145);
noStroke();
fill(bruin);
rect(guide, 280, bBorder, 40);
textFont(kaffeesatzFont);
textSize(30);
fill(wit);
text("Quotes", 80, 308);
createGridQ();
}
void createGridQ(){
xOffset = 30;
yOffset = 325;
xSize = 50;
ySize = 38;
padding = 10;
xPos = padding + xOffset;
yPos = yOffset;
cols = 3;
for(int j = 0; j < qLength; j++){
// Grid
xPos = xOffset + ((j % cols) * (xSize+padding));
yPos = yOffset + ((j / cols) * (ySize+padding));
Quotes[j] = loadShape("Q" + j + ".svg");
shape(Quotes[j], xPos, yPos);
if((mouseX >= xPos) && (mouseX <= xPos+xSize) &&
(mouseY >= yPos) && (mouseY <= yPos+ySize)){
cursor(HAND);
if (mousePressed){
cursor(HAND);
Quotes[j] = loadShape("Q" + j + "groot" + ".svg");
shape(Quotes[j], width/5, height/2-200);
}
}
}
}
You can load an image by declaring a PImage and loading it from a web url or by placing it into your data or source directory (where your .pde files are) and then loading it from there.
PImage img;
img = loadImage("laDefense.jpg");
Processing loadImage Reference
So, replace "laDefense.jpg" with the name of the image you want to use and place that image into your data folder. After that, you can place the image in the scene and manipulate it as you would a shape.

Resources