Cs50 edges filter is failing to process corner and edges pixels - cs50

In the problem description, we were told to take outer pixels as having a value of "0".
I discriminate de outer pixels so as to do nothing with them, they won´t add a value, because multiplying by 0 gets 0.
I can´t seem to find where i went wrong. Can somebody give me a clue. Thanks a lot.
here is my code
// Detect edges
void edges(int height, int width, RGBTRIPLE image[height][width])
{
// Make copy
RGBTRIPLE copy[height][width];
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
copy[i][j] = image[i][j];
}
}
double gxB, gxR, gxG, gyR, gyB, gyG;
int GX[3][3] = {{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}};
int GY[3][3] = {{-1, -2, -1}, {0, 0, 0}, {1, 2, 1}};
// Loop through pixels
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
gxB = 0;
gxR = 0;
gxG = 0;
gyR = 0;
gyB = 0;
gyG = 0;
// Loop through 3x3 box
for (int row = (i - 1); row < (i + 2); row++)
{
for (int col = (j - 1); col < (j +2); col++)
{
// Discriminate border pixels
if (exists(row, col, height, width))
{
gxR += copy[row][col].rgbtRed * GX[row][col];
gxG += copy[row][col].rgbtGreen * GX[row][col];
gxB += copy[row][col].rgbtBlue * GX[row][col];
gyR += copy[row][col].rgbtRed * GY[row][col];
gyG += copy[row][col].rgbtGreen * GY[row][col];
gyB += copy[row][col].rgbtBlue * GY[row][col];
}
else
{
gxR += 0.0;
gxG += 0.0;
gxB += 0.0;
gyR += 0.0;
gyG += 0.0;
gyB += 0.0;
}
}
}
image[i][j].rgbtRed = trimm(round(sqrt((gxR * gxR) + (gyR * gyR))));
image[i][j].rgbtGreen = trimm(round(sqrt((gxG * gxG) + (gyG * gyG))));
image[i][j].rgbtBlue = trimm(round(sqrt((gxB * gxB) + (gyB * gyB))));
}
}
return;
}
bool exists(int ROW, int COL, int H, int W)
{
if (((ROW >= 0) && (ROW < H)) && ((COL >= 0) && (COL < W)))
{
return true;
}
else
{
return false;
}
}
int trimm(int x)
{
if (x < 256)
{
return x;
}
else
{
return 255;
}
}

Related

Unity - Infinite terrain gaps betwean chunks?

So I am creating an endless terrain.
I can create the terrain but my chunks have gaps betwean them and they don't align properly.
I think the problem might be caused by my Noise Generation script, but I am not sure.
This is my Noise Generation script
public static class Noise_GENERATOR
{
public static float[,] GenerateNoise(int chunkSize, int octaves, int seed, float noiseScale, float persistence, float lacunarity, Vector2 offset)
{
float[,] noiseMap = new float[chunkSize, chunkSize];
System.Random prng = new System.Random(seed);
Vector2[] octaveOffsets = new Vector2[octaves];
float maxPossibleHeight = 0;
float amplitude = 1;
float frequency = 1;
for (int i = 0; i < octaves; i++)
{
float offsetX = prng.Next(-100000, 100000) + offset.x;
float offsetY = prng.Next(-100000, 100000) + offset.y;
octaveOffsets[i] = new Vector2(offsetX, offsetY);
maxPossibleHeight += amplitude;
amplitude *= persistence;
}
if (noiseScale <= 0)
{
noiseScale = 0.0001f;
}
float maxLocalNoiseHeight = float.MinValue;
float minLocalNoiseHeight = float.MaxValue;
float halfWidth = chunkSize / 2f;
float halfHeight = chunkSize / 2f;
for (int y = 0; y < chunkSize; y++)
{
for (int x = 0; x < chunkSize; x++)
{
amplitude = 1;
frequency = 1;
float noiseHeight = 0;
for (int i = 0; i < octaves; i++)
{
float sampleX = (x-halfWidth + octaveOffsets[i].x) / noiseScale * frequency;
float sampleY = (y-halfHeight + octaveOffsets[i].y) / noiseScale * frequency;
float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1;
noiseHeight += perlinValue * amplitude;
amplitude *= persistence;
frequency *= lacunarity;
}
if (noiseHeight > maxLocalNoiseHeight)
{
maxLocalNoiseHeight = noiseHeight;
}
else if (noiseHeight < minLocalNoiseHeight)
{
minLocalNoiseHeight = noiseHeight;
}
noiseMap[x, y] = noiseHeight;
float normalizedHeight = (noiseMap[x, y] + 1) / (maxPossibleHeight / 0.9f);
noiseMap[x, y] = Mathf.Clamp(normalizedHeight, 0, int.MaxValue);
}
}
return noiseMap;
}
}
To Generate the height of a mesh, I am using Animation Curve and multiplying it by elevationScale variable.
float height = heightCurve.Evaluate(noiseMap[x, y]) * elevationScale;
I thought about accesing each Terrain chunk and getting the height of the edges and matching them together but that would look really weird and I don't know how to do it properly.
EDIT: Here just in case my Mesh generator script and how I am creating the Terrain chunk
public static class Mesh_GENERATOR
{
public static MeshData GenerateChunkMesh(int chunkSize,float[,] noiseMapData,float elevationScale,AnimationCurve terrainCurve,int LODlevel )
{
float[,] noiseMap = noiseMapData;
AnimationCurve heightCurve = new AnimationCurve(terrainCurve.keys);
//Setup variables
Vector3[] vertices = new Vector3[chunkSize * chunkSize];
int[] triangles = new int[(chunkSize - 1) * (chunkSize - 1) * 6];
Vector2[] uvs = new Vector2[chunkSize * chunkSize];
int triangle = 0;
int levelOfDetailIncrement = (LODlevel == 0) ? 1 : LODlevel * 2;
int numberOfVerticesPerRow = (chunkSize) / levelOfDetailIncrement + 1;
for (int y = 0; y < chunkSize; y++)
{
for (int x = 0; x < chunkSize; x++)
{
int i = y * chunkSize + x;
//Create vertices at position and center mesh
float height = heightCurve.Evaluate(noiseMap[x, y]) * elevationScale;
Vector2 percentPosition = new Vector2(x / (chunkSize - 1f), y / (chunkSize -1f ));
Vector3 vertPosition = new Vector3(percentPosition.x * 2 - 1, 0, percentPosition.y * 2 - 1) * chunkSize/2;
vertPosition.y = height;
vertices[i] = vertPosition;
uvs[i] = new Vector2((float)x / chunkSize, (float)y / chunkSize);
//Construct triangles
if (x != chunkSize - 1 && y != chunkSize - 1)
{
triangles[triangle + 0] = i + chunkSize;
triangles[triangle + 1] = i + chunkSize + 1;
triangles[triangle + 2] = i;
triangles[triangle + 3] = i + chunkSize + 1;
triangles[triangle + 4] = i + 1;
triangles[triangle + 5] = i;
triangle += 6;
}
}
}
MeshData meshData = new MeshData(chunkSize, vertices, triangles, uvs);
return meshData;
}
}
public class MeshData
{
public int chunkSize;
public Vector3[] vertices;
public int[] triangles;
public Vector2[] uvs;
public Mesh mesh;
public MeshData(int chunkSize,Vector3[] vertices,int[] triangles, Vector2[] uvs)
{
this.chunkSize = chunkSize;
this.vertices = vertices;
this.triangles = triangles;
this.uvs = uvs;
}
public Mesh CreateMesh()
{
if(mesh == null) { mesh = new Mesh(); } else { mesh.Clear(); }
mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.uv = uvs;
mesh.RecalculateNormals();
return mesh;
}
}
And here is my TerrainChunk
public class TerrainChunk
{
GameObject meshObject;
Vector2 position;
Bounds bounds;
MeshRenderer meshRenderer;
MeshFilter meshFilter;
public TerrainChunk(Vector2 coord, int chunkSize, Transform parent,Material terrainMaterial)
{
position = coord * chunkSize;
bounds = new Bounds(position, Vector2.one * chunkSize);
Vector3 positionV3 = new Vector3(position.x , 0, position.y );
Debug.Log("CHUNK: COORD" + coord + "POSITION" + position + "POSITION3V" + positionV3);
meshObject = new GameObject("Terrain Chunk");
meshFilter = meshObject.AddComponent<MeshFilter>();
meshRenderer = meshObject.AddComponent<MeshRenderer>();
meshRenderer.material = terrainMaterial;
meshObject.transform.position = positionV3;
meshObject.transform.parent = parent;
SetVisible(false);
worldGenerator.RequestMapData(position,OnNoiseDataReceived);
}
void OnNoiseDataReceived(MapData mapData)
{
worldGenerator.RequestMeshData(mapData, OnMeshDataReceived);
}
void OnMeshDataReceived(MeshData meshData)
{
meshFilter.mesh = meshData.CreateMesh();
}
public void UpdateTerrainChunk(Vector2 viewerPosition, int maxRenderDistance)
{
float viewerDstFromNearestEdge = Mathf.Sqrt(bounds.SqrDistance(viewerPosition));
bool visible = viewerDstFromNearestEdge <= maxRenderDistance;
SetVisible(visible);
}
public void SetVisible(bool visible)
{
meshObject.SetActive(visible);
}
public bool IsVisible()
{
return meshObject.activeSelf;
}
}
}
If I undestand all your values and variables correctly.
The problem might lay in the Noise Generator.
You need to create the chunkSize to be bigger by 1 so if you are passing 250 you will need to pass 251, as the for loop in the Noise Generator stops at 249 and not 250. (I might be wrong about this ), If you do this the mesh generator will now have the right values for calculation.
So your chunksize variable should look like this
chunkSize = chunkSize + 1;
Now there will still be smaller gaps and the mesh will clip through each other, so to fix this you will need to position the Chunk and you do it this way ->
(If your coord serves as a direction in which the chunk will be created from your World generator object -> for example chunks pointing North will be with values x:0 y:1, chunks pointing West will be x:-1 y:0, NorthWest chunks x:-1 y:-1 and so on), you may need to change the 0.5f to your values so the chunks align properly.
Vector3 positionV3 = new Vector3(position.x + (coord.x + 0.5f), 0, position.y + (coord.y + 0.5f) );
There still may be some smaller gaps visible in the terrain, but this can be fixed by playing with the values, or you can try and access each Chunk and get the edge vertices and their heights and connect the chunks together this way.

Processing, simple "raytracing" engine "target VM failed to initialize"

I've been trying to fix this thing for a while now but it doesn't seem to work; "Could not run the sketch (Target VM failed to initialize)."
I'll post the full code down below.
In the draw(), there are three for loops.
for(int i = 0; i<objectAmount; i++) {
circles[i].drawObj();
}
The first one creates the circles, while the second nested ones take care of collision and drawing the lines;
for(int i = 0; i<rayAmount; i++) {
rays[i].update();
for(int j = 0; j<objectAmount; j++) {
rays[i].collide(circles[j]);
}
line(rays[i].xPos, rays[i].yPos, rays[i].xEnd, rays[i].yEnd);
}
the .collide takes point on the 'ray' and moves closer to the circle until it reaches some value, where it marks the line's end, which is then used by the line() function to draw it to the circle.
For some reason, when I implemented the .collide function, everything stopped working unless I set the amount of rays to one, in which case no rays would appear but the circle generation would follow along just fine.
int rayAmount = 45;
int angleCorrect = 360/rayAmount;
int objectAmount = 10;
Ray[] rays = new Ray[rayAmount];
Object[] circles = new Object[objectAmount];
void setup() {
size(600, 400, P2D);
for(int i = 0; i<rayAmount; i++) {
rays[i] = new Ray(i*angleCorrect);
}
for(int i = 0; i<objectAmount; i++) {
circles[i] = new Object(random(0, 600), random(0, 400), random(20, 100));
}
}
void draw() {
background(255);
stroke(100);
for(int i = 0; i<objectAmount; i++) {
circles[i].drawObj();
}
for(int i = 0; i<rayAmount; i++) {
rays[i].update();
for(int j = 0; j<objectAmount; j++) {
rays[i].collide(circles[j]);
}
line(rays[i].xPos, rays[i].yPos, rays[i].xEnd, rays[i].yEnd);
}
}
class Ray {
float xPos, yPos, Angle, xEnd, yEnd;
Ray(float angle) {
xPos = mouseX;
yPos = mouseY;
Angle = angle;
}
void update() {
xPos = mouseX;
yPos = mouseY;
//xEnd = xPos + 100 * cos(radians(Angle));
//yEnd = yPos + 100 * sin(radians(Angle));
}
void collide(Object other) {
float newXEnd = this.xEnd;
float newYEnd = this.yEnd;
float distToObject = sqrt(pow(other.xPos-this.xPos, 2) + pow(other.yPos-this.yPos, 2));
while(distToObject > 1) {
newXEnd = newXEnd + distToObject * cos(radians(Angle));
newYEnd = newYEnd + distToObject * sin(radians(Angle));
distToObject = sqrt(pow(other.xPos-newXEnd, 2) + pow(other.yPos-newYEnd, 2));
}
this.xEnd = newXEnd;
this.yEnd = newYEnd;
}
}
class Object {
float xPos, yPos, radius;
Object(float x, float y, float r) {
xPos = x;
yPos = y;
radius = r;
}
void drawObj() {
stroke(100);
circle(xPos, yPos, radius);
}
}

How can you get a sprite to follow another sprite in Java?

Here is the code for the initial character:
public class Player extends Mob {
private InputHandler input;
private int colour = Colours.get(-1, 111, 145, 543);
private int scale = 1;
protected boolean isSwimming = false;
private int tickCount = 0;
public Player(Level level, int x, int y, InputHandler input) {
super(level, "Player", x, y, 1);
this.input = input;
}
public void tick() {
int xa = 0;
int ya = 0;
if (input.up.isPressed()) {
ya--;
}
if (input.down.isPressed()) {
ya++;
}
if (input.left.isPressed()) {
xa--;
}
if (input.right.isPressed()) {
xa++;
}
if (xa != 0 || ya != 0) {
move(xa, ya);
isMoving = true;
} else {
isMoving = false;
}
if (level.getTile(this.x >> 3, this.y >> 3).getId() == 3) {
isSwimming = true;
}
if (isSwimming && level.getTile(this.x >> 3, this.y >> 3).getId() != 3) {
isSwimming = false;
}
tickCount++;
this.scale = 1;
}
public void render(Screen screen) {
int xTile = 0;
int yTile = 28;
int walkingSpeed = 4;
int flipTop = (numSteps >> walkingSpeed) & 1;
int flipBottom = (numSteps >> walkingSpeed) & 1;
if (movingDir == 1) {
xTile += 2;
} else if (movingDir > 1) {
xTile += 4 + ((numSteps >> walkingSpeed) & 1) * 2;
flipTop = (movingDir - 1) % 2;
}
int modifier = 8 * scale;
int xOffset = x - modifier / 2;
int yOffset = y - modifier / 2 - 4;
if (isSwimming) {
int waterColour = 0;
yOffset += 4;
if (tickCount % 60 < 15) {
waterColour = Colours.get(-1, -1, 225, -1);
} else if (15 <= tickCount % 60 && tickCount % 60 < 30) {
yOffset -= 1;
waterColour = Colours.get(-1, 225, 115, -1);
} else if (30 <= tickCount % 60 && tickCount % 60 < 45) {
waterColour = Colours.get(-1, 115, -1, 225);
} else {
waterColour = Colours.get(-1, 225, 115, -1);
}
screen.render(xOffset, yOffset + 3, 0 + 27 * 32, waterColour, 0x00, 1);
screen.render(xOffset + 8, yOffset + 3, 0 + 27 * 32, waterColour, 0x01, 1);
}
// upper body
screen.render(xOffset + (modifier * flipTop), yOffset, xTile + yTile * 32, colour, flipTop, scale);
screen.render(xOffset + modifier - (modifier * flipTop), yOffset, (xTile + 1) + yTile * 32, colour, flipTop,
scale);
if (!isSwimming) {
// lower body
screen.render(xOffset + (modifier * flipBottom), yOffset + modifier, xTile + (yTile + 1) * 32, colour,
flipBottom, scale);
screen.render(xOffset + modifier - (modifier * flipBottom), yOffset + modifier,
(xTile + 1) + (yTile + 1) * 32, colour, flipBottom, scale);
}
}
public boolean hasCollided(int xa, int ya) {
int xMin = 0;
int xMax = 7;
int yMin = 1;
int yMax = 7;
for (int x = xMin; x < xMax; x++) {
if (isSolidTile(xa, ya, x, yMin)) {
return true;
}
}
for (int x = xMin; x < xMax; x++) {
if (isSolidTile(xa, ya, x, yMax)) {
return true;
}
}
for (int y = yMin; y < yMax; y++) {
if (isSolidTile(xa, ya, xMin, y)) {
return true;
}
}
for (int y = yMin; y < yMax; y++) {
if (isSolidTile(xa, ya, xMax, y)) {
return true;
}
}
return false;
}
}
can get another character to load at a given location; however, I cannot figure out an algorithm to have it follow the initial player. In other words the second one will follow these same collision and commands. Any help understanding is appreciated, thank you!

Dynamic programming money change

I have two functions recursive and iterative to calculate money change; in the iterative version I needed to check for if the money is multiple of change (money modulus change is zero): is there a way to do iterative without checking for modulus?
public static int MoneyChangeRecur(int money, int[] changes)
{
int minChange = 0;
if (money == 0) return 0;
int min = int.MaxValue;
for (int i = 0; i < changes.Length; i++)
{
if (money >= changes[i])
{
minChange = MoneyChangeRecur(money - changes[i], changes);
if (minChange + 1 <= min)
{
min = minChange + 1;
}
}
}
return min;
}
static int IterativeMoneychange(int money)
{
int[] ar = new int[money + 1];
int[] change = { 6, 5, 1 };
int min = 9999;
int index = 0;
for (int i = 0; i < money+1; i++)
{
min = 99999;
index = 0;
bool modSet = false;
for (int j= 0; j <change.Length; j++)
{
if (i >= change[j])
{
int mod=(i % change[j]);
if(mod==0&&change[j]!=1)
{
if (!modSet) min = 99999;
if ((i-change[j] )< min)
{
min = (i - change[j]);
modSet = true;
}
}
else
{
if ((i - change[j]) < min)
{
min = (i - change[j]);
modSet = false;
}
}
}
}
if (min != 99999)// min = 0;
ar[i] = ar[min] +1;
}
return ar[money];
}enter code here

j2me program to create a GRID menu?

I want to create a list of operation's in a grid view. For example visit this URL.
http://cdn-static.cnet.co.uk/i/product_media/40000186/nokia1616_01.jpg
You can look at this question or this page(and use LWUIT or CustomItems) or extend "canvas".In this way you need to two pictures for every operation in grid view.One for normal state and another for highlighted.Here is a simple canvas that represents 4 operations in 2*2 grid:
public class GridCanvas extends Canvas {
int highlightedRow = 0;
int highlightedColumn = 0;
Image[][] normalImageMat;
Image[][] highlightedImageMat;
Image[][] imageMat;
int gridColumnNo;
int gridRowNo;
/**
* constructor
*/
public GridCanvas() {
gridColumnNo = 2;
gridRowNo = 2;
normalImageMat = new Image[gridRowNo][gridColumnNo];
highlightedImageMat = new Image[gridRowNo][gridColumnNo];
imageMat = new Image[gridRowNo][gridColumnNo];
try {
for (int i = 0; i < gridRowNo; i++) {
for (int j = 0; j < gridColumnNo; j++) {
normalImageMat[i][j] = Image.createImage("/hello/normalImage" + i + j + ".png");
}
}
for (int i = 0; i < gridRowNo; i++) {
for (int j = 0; j < gridColumnNo; j++) {
highlightedImageMat[i][j] = Image.createImage("/hello/highlightedImage" + i + j + ".png");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* paint
*/
public void paint(Graphics g) {
g.setColor(255, 255, 255);
g.fillRect(0, 0, getWidth(), getHeight());
for (int i = 0; i < gridRowNo; i++) {
System.arraycopy(normalImageMat[i], 0, imageMat[i], 0, 2);
}
imageMat[highlightedRow][highlightedColumn] = highlightedImageMat[highlightedRow][highlightedColumn];
int width = 0;
int height = 0;
for (int i = 0; i < gridRowNo; i++) {
for (int j = 0; j < gridColumnNo; j++) {
g.drawImage(imageMat[i][j], width, height, 0);
width = width + imageMat[i][j].getWidth();
}
width = 0;
height = height + imageMat[0][0].getHeight();
}
}
/**
* Called when a key is pressed.
*/
protected void keyPressed(int keyCode) {
int gameAction = this.getGameAction(keyCode);
if (gameAction == RIGHT) {
highlightedColumn = Math.min(highlightedColumn + 1, gridColumnNo - 1);
} else if (gameAction == LEFT) {
highlightedColumn = Math.max(highlightedColumn - 1, 0);
} else if (gameAction == UP) {
highlightedRow = Math.max(0, highlightedRow - 1);
} else if (gameAction == DOWN) {
highlightedRow = Math.min(gridRowNo - 1, highlightedRow + 1);
}
repaint();
}
}
In real samples you would to detect gridColumnNo and gridRowNo due to screen and your icons dimensions.
If you can not go with LWUIT (license, library size, etc) and do not want to leave the screen rendering to LCDUI (CustomItem), you should extend Canvas.
I have shared code for an adaptive grid at http://smallandadaptive.blogspot.com.br/2010/12/touch-menu.html Feel free to use it.
At this sample all items are Strings, but you can change the TouchItem to draw Images instead.

Resources