Give Border To Texture - SetPixel - image

I'm trying to dynamically add a border to a texture of mine. So far, I have a border at the top, and at the bottom. But struggling to get a left and right border. This is what I have so far:
var i = image;
var pixels : Color[] = i.GetPixels(0, 0, i.width, i.height, 0);
var br : int = 1;
for(var p = 0; p < pixels.Length; p++){
var b : int = 30;
//Bottom
if(p < i.width * b)
pixels[p] = new Color(1,0,0,1);
//Top
if(p > (i.height * i.width) - (i.width * b))
pixels[p] = new Color(1,0,0,1);
//int when a new row of pixels has began
if(p > i.width * br)
br++;
}
The pixels are read from bottom left, to top right. I just can't seem to get my head around the maths.
Thanks

Probably the easiest way to get x position of a pixel is to use modular operator (%), which returns the remainder.
Here is a code calculating the x position and setting the border based on that:
// Left
if(p % i.width < b)
pixels[p] = new Color(1,0,0,1);
// right
if(p % i.width > i.width - b)
pixels[p] = new Color(1,0,0,1);

Related

Creating random pixeled lines in Proccesing

I'm trying to make a game and I'm stuck on random level design. Basically, I'm trying to create a line from one edge/corner to another edge/corner while having some randomness to it.
See below image 1 [link broken] and 2 for examples. I'm doing this in processing and every attempt I've tried hasn't yielded proper results. I can get them to populate randomly but not in a line or from edge to edge. I'm trying to do this on a 16 x 16 grid by the way. Any ideas or help would be greatly appreciated thanks!
Image 2:
Based on your description, the challenge is in having a connected line from top to bottom with a bit of randomness driving left/right direction.
There are multiple options.
Here's a basic idea that comes to mind:
pick a starting x position: left's say right down the middle
for each row from 0 to 15 (for 16 px level)
pick a random between 3 numbers:
if it's the 1st go left (x decrements)
if it's the 2nd go right (x increments)
if it's the 3rd: ignore: it means the line will go straight down for this iteration
Here's a basic sketch that illustrates this using PImage to visualise the data:
void setup(){
size(160, 160);
noSmooth();
int levelSize = 16;
PImage level = createImage(levelSize, levelSize, RGB);
level.loadPixels();
java.util.Arrays.fill(level.pixels, color(255));
int x = levelSize / 2;
for(int y = 0 ; y < levelSize; y++){
int randomDirection = (int)random(3);
if(randomDirection == 1) x--;
if(randomDirection == 2) x++;
// if randomDirection is 0 ignore as we don't change x -> just go down
// constrain to valid pixel
x = constrain(x, 0, levelSize - 1);
// render dot
level.pixels[x + y * levelSize] = color(0);
}
level.updatePixels();
// render result;
image(level, 0, 0, width, height);
fill(127);
text("click to reset", 10, 15);
}
// hacky reset
void draw(){}
void mousePressed(){
setup();
}
The logic is be pretty plain above, but free to replace random(3) with other options (perhaps throwing dice to determine direction or exploring other psuedo-random number generators (PRNGs) such as randomGaussian(), noise() (and related functions), etc.)
Here's a p5.js version of the above:
let levelSize = 16;
let numBlocks = levelSize * levelSize;
let level = new Array(numBlocks);
function setup() {
createCanvas(320, 320);
level.fill(0);
let x = floor(levelSize / 2);
for(let y = 0 ; y < levelSize; y++){
let randomDirection = floor(random(3));
if(randomDirection === 1) x--;
if(randomDirection === 2) x++;
// if randomDirection is 0 ignore as we don't change x -> just go down
// constrain to valid pixel
x = constrain(x, 0, levelSize - 1);
// render dot
level[x + y * levelSize] = 1;
}
// optional: print to console
// prettyPrintLevel(level, levelSize, numBlocks);
}
function draw() {
background(255);
// visualise
for(let i = 0 ; i < numBlocks; i++){
let x = i % levelSize;
let y = floor(i / levelSize);
fill(level[i] == 1 ? color(0) : color(255));
rect(x * 20, y * 20, 20, 20);
}
}
function prettyPrintLevel(level, levelSize, numBlocks){
for(let i = 0; i < numBlocks; i+= levelSize){
print(level.slice(i, i + levelSize));
}
}
function mousePressed(){
setup();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.min.js"></script>
The data is a structured a 1D array in both examples, however, if it makes it easier it could easily be a 2D array. At this stage of development, whatever is the simplest, most readable option is the way to go.

Finding the furthest point in a grid when compared to other points

I have a rectangular grid of variable size but averaging 500x500 with a small number of x,y points in it (less than 5). I need to find an algorithm that returns an x,y pair that is the farthest away possible from any of the other points.
Context: App's screen (grid) and a set of x,y points (enemies). The player dies and I need an algorithm that respawns them as far away from the enemies so that they don't die immediately after respawning.
What I have so far: The algorithm I wrote works but doesn't perform that great in slower phones. I'm basically dividing up the grid into squares (much like a tic tac toe) and I assign each square a number. I then check every single square against all enemies and store what the closest enemy was at each square. The square with the highest number is the square that has the closest enemy furthest away. I also tried averaging the existing points and doing something similar to this and while the performance was acceptable, the reliability of the method was not.
This is the simplest algorithm I could think of that still gives good results. It only checks 9 possible positions: the corners, the middle of the sides, and the center point. Most of the time the player ends up in a corner, but you obviously need more positions than enemies.
The algorithm runs in 0.013ms on my i5 desktop. If you replace the Math.pow() by Math.abs(), that comes down to 0.0088ms, though obviously with less reliable results. (Oddly enough, that's slower than my other answer which uses trigonometry functions.)
Running the code snippet (repeatedly) will show the result with randomly positioned enemies in a canvas element.
function furthestFrom(enemy) {
var point = [{x:0,y:0},{x:250,y:0},{x:500,y:0},{x:0,y:250},{x:250,y:250},{x:500,y:250},{x:0,y:500},{x:250,y:500},{x:500,y:500}];
var dist2 = [500000,500000,500000,500000,500000,500000,500000,500000,500000];
var max = 0, furthest;
for (var i in point) {
for (var j in enemy) {
var d = Math.pow(point[i].x - enemy[j].x, 2) + Math.pow(point[i].y - enemy[j].y, 2);
if (d < dist2[i]) dist2[i] = d;
}
if (dist2[i] > max) {
max = dist2[i];
furthest = i;
}
}
return(point[furthest]);
}
// CREATE TEST DATA
var enemy = [];
for (var i = 0; i < 5; i++) enemy[i] = {x: Math.round(Math.random() * 500), y: Math.round(Math.random() * 500)};
// RUN FUNCTION
var result = furthestFrom(enemy);
// SHOW RESULT ON CANVAS
var canvas = document.getElementById("canvas");
canvas.width = 500; canvas.height = 500;
canvas = canvas.getContext("2d");
for (var i = 0; i < 5; i++) {
paintDot(canvas, enemy[i].x, enemy[i].y, 10, "red");
}
paintDot(canvas, result.x, result.y, 20, "blue");
function paintDot(canvas, x, y, size, color) {
canvas.beginPath();
canvas.arc(x, y, size, 0, 6.2831853);
canvas.closePath();
canvas.fillStyle = color;
canvas.fill();
}
<BODY STYLE="margin: 0; border: 0; padding: 0;">
<CANVAS ID="canvas" STYLE="width: 200px; height: 200px; background-color: #EEE;"></CANVAS>
</BODY>
This is similar to what you are already doing, but with two passes where the first pass can be fairly crude. First decrease resolution. Divide the 500x500 grid into 10x10 grids each of which is 50x50. For each of the resulting 100 subgrids -- determine which have at least one enemy and locate the subgrid that is furthest away from a subgrid which contains an enemy. At this stage there is only 100 subgrids to worry about. Once you find the subgrid which is furthest away from an enemy -- increase resolution. That subgrid has 50x50 = 2500 squares. Do your original approach with those squares. The result is 50x50 + 100 = 2600 squares to process rather than 500x500 = 250,000. (Adjust the numbers as appropriate for the case in which there isn't 500x500 but with the same basic strategy).
Here is a Python3 implementation. It uses two functions:
1) fullResSearch(a,b,n,enemies) This function takes a set of enemies, a corner location (a,b) and an int, n, and finds the point in the nxn square of positions whose upper-left hand corner is (a,b) and finds the point in that square whose which has the maximum min-distance to an enemy. The enemies are not assumed to be in this nxn grid (although they certainly can be)
2) findSafePoint(n, enemies, mesh = 20) This function takes a set of enemies who are assumed to be in the nxn grid starting at (0,0). mesh determines the size of the subgrids, defaulting to 20. The overall grid is split into mesh x mesh subgrids (or slightly smaller along the boundaries if mesh doesn't divide n) which I think of as territories. I call a territory an enemy territory if it has an enemy in it. I create the set of enemy territories and pass it to fullResSearch with parameter n divided by mesh rather than n. The return value gives me the territory which is farthest from any enemy territory. Such a territory can be regarded as fairly safe. I feed that territory back into fullResSearch to find the safest point in that territory as the overall return function. The resulting point is either optimal or near-optimal and is computed very quickly. Here is the code (together with a test function):
import random
def fullResSearch(a,b,n,enemies):
minDists = [[0]*n for i in range(n)]
for i in range(n):
for j in range(n):
minDists[i][j] = min((a+i - x)**2 + (b+j - y)**2 for (x,y) in enemies)
maximin = 0
for i in range(n):
for j in range(n):
if minDists[i][j] > maximin:
maximin = minDists[i][j]
farthest = (a+i,b+j)
return farthest
def findSafePoint(n, enemies, mesh = 20):
m = n // mesh
territories = set() #enemy territories
for (x,y) in enemies:
i = x//mesh
j = y//mesh
territories.add((i,j))
(i,j) = fullResSearch(0,0,m,territories)
a = i*mesh
b = j*mesh
k = min(mesh,n - a,n - b) #in case mesh doesn't divide n
return fullResSearch(a,b,k,enemies)
def test(n, numEnemies, mesh = 20):
enemies = set()
count = 0
while count < numEnemies:
i = random.randint(0,n-1)
j = random.randint(0,n-1)
if not (i,j) in enemies:
enemies.add ((i,j))
count += 1
for e in enemies: print("Enemy at", e)
print("Safe point at", findSafePoint(n,enemies, mesh))
A typical run:
>>> test(500,5)
Enemy at (216, 67)
Enemy at (145, 251)
Enemy at (407, 256)
Enemy at (111, 258)
Enemy at (26, 298)
Safe point at (271, 499)
(I verified by using fullResSearch on the overall grid that (271,499) is in fact optimal for these enemies)
This method looks at all the enemies from the center point, checks the direction they're in, finds the emptiest sector, and then returns a point on a line through the middle of that sector, 250 away from the center.
The result isn't always perfect, and the safe spot is never in the center (though that could be added), but maybe it's good enough.
The algorithm runs more than a million times per second on my i5 desktop, but a phone may not be that good with trigonometry. The algorithm uses 3 trigonometry functions per enemy: atan2(), cos() and sin(). Those will probably have the most impact on the speed of execution. Maybe you could replace the cos() and sin() with a lookup table.
Run the code snippet to see an example with randomly positioned enemies.
function furthestFrom(e) {
var dir = [], widest = 0, bisect;
for (var i = 0; i < 5; i++) {
dir[i] = Math.atan2(e[i].y - 250, e[i].x - 250);
}
dir.sort(function(a, b){return a - b});
dir.push(dir[0] + 6.2831853);
for (var i = 0; i < 5; i++) {
var angle = dir[i + 1] - dir[i];
if (angle > widest) {
widest = angle;
bisect = dir[i] + angle / 2;
}
}
return({x: 250 * (1 + Math.cos(bisect)), y: 250 * (1 + Math.sin(bisect))});
}
// CREATE TEST DATA
var enemy = [];
for (var i = 0; i < 5; i++) enemy[i] = {x: Math.round(Math.random() * 500), y: Math.round(Math.random() * 500)};
// RUN FUNCTION AND SHOW RESULT ON CANVAS
var result = furthestFrom(enemy);
var canvas = document.getElementById("canvas");
canvas.width = 500; canvas.height = 500;
canvas = canvas.getContext("2d");
for (var i = 0; i < 5; i++) {
paintDot(canvas, enemy[i].x, enemy[i].y, "red");
}
paintDot(canvas, result.x, result.y, "blue");
// PAINT DOT ON CANVAS
function paintDot(canvas, x, y, color) {
canvas.beginPath();
canvas.arc(x, y, 10, 0, 6.2831853);
canvas.closePath();
canvas.fillStyle = color;
canvas.fill();
}
<BODY STYLE="margin: 0; border: 0; padding: 0">
<CANVAS ID="canvas" STYLE="width: 200px; height: 200px; background-color: #EEE;"CANVAS>
</BODY>
Here's an interesting solution, however I cannot test it's efficiency. For each enemy, make a line of numbers from each number, starting with one and increasing by one for each increase in distance. Four initial lines will come from the four edges and each time you go one further out, you create another line coming out at a 90 degree angle, also increasing the number each change in distance. If the number line encounters an already created number that is smaller than it, it will not overwrite it and will stop reaching further. Essentially, this makes it so that if the lines find a number smaller than it, it won't check any further grid marks, eliminating the need to check the entire grid for all of the enemies.
<<<<<<^^^^^^^
<<<<<<^^^^^^^
<<<<<<X>>>>>>
vvvvvvv>>>>>>
vvvvvvv>>>>>>
public void map(int posX, int posY)
{
//left up right down
makeLine(posX, posY, -1, 0, 0, -1);
makeLine(posX, posY, 0, 1, -1, 0);
makeLine(posX, posY, 1, 0, 0, 1);
makeLine(posX, posY, 0, -1, 1, 0);
grid[posX][posY] = 1000;
}
public void makeLine(int posX, int posY, int dirX, int dirY, int dir2X, int dir2Y)
{
int currentVal = 1;
posX += dirX;
posY += dirY;
while (0 <= posX && posX < maxX && posY < maxY && posY >= 0 && currentVal < grid[posX][posY])
{
int secondaryPosX = posX + dir2X;
int secondaryPosY = posY + dir2Y;
int secondaryVal = currentVal + 1;
makeSecondaryLine( secondaryPosX, secondaryPosY, dir2X, dir2Y, secondaryVal);
makeSecondaryLine( secondaryPosX, secondaryPosY, -dir2X, -dir2Y, secondaryVal);
grid[posX][posY] = currentVal;
posX += dirX;
posY += dirY;
currentVal++;
}
}
public void makeSecondaryLine(int secondaryPosX, int secondaryPosY, int dir2X, int dir2Y, int secondaryVal)
{
while (0 <= secondaryPosX && secondaryPosX < maxX && secondaryPosY < maxY &&
secondaryPosY >= 0 && secondaryVal < grid[secondaryPosX][secondaryPosY])
{
grid[secondaryPosX][secondaryPosY] = secondaryVal;
secondaryPosX += dir2X;
secondaryPosY += dir2Y;
secondaryVal++;
}
}
}
Here is the code I used to map out the entire grid. The nice thing about this, is that the number of times the number is checked/written is not that much dependent on the number of enemies on the screen. Using a counter and randomly generated enemies, I was able to get this: 124 enemies and 1528537 checks, 68 enemies and 1246769 checks, 15 enemies and 795695 500 enemies and 1747452 checks. This is a huge difference compared to your earlier code which would do number of enemies * number of spaces.
for 124 enemies you'd have done 31000000 checks, while instead this did 1528537, which is less than 5% of the number of checks normally done.
You can choose some random point at the grid and then move it iteratively from the enemies, here is my implementation in python:
from numpy import array
from numpy.linalg import norm
from random import random as rnd
def get_pos(enem):
# chose random start position
pos = array([rnd() * 500., rnd() * 500.])
# make several steps from enemies
for i in xrange(25): # 25 steps
s = array([0., 0.]) # step direction
for e in enem:
vec = pos - array(e) # direction from enemy
dist = norm(vec) # distance from enemy
vec /= dist # normalize vector
# calculate size of step
step = (1000. / dist) ** 2
vec *= step
s += vec
# update position
pos += s
# ensure that pos is in bounds
pos[0] = min(max(0, pos[0]), 500.)
pos[1] = min(max(0, pos[1]), 500.)
return pos
def get_dist(enem, pos):
dists = [norm(pos - array(e)) for e in enem]
print 'Min dist: %f' % min(dists)
print 'Avg dist: %f' % (sum(dists) / len(dists))
enem = [(0., 0.), (250., 250.), (500., 0.), (0., 500.), (500., 500.)]
pos = get_pos(enem)
print 'Position: %s' % pos
get_dist(enem, pos)
Output:
Position: [ 0. 250.35338215]
Min dist: 249.646618
Avg dist: 373.606883
Triangulate the enemies (there's less than 5?); and triangulate each corner of the grid with the closest pair of enemies to it. The circumcenter of one of these triangles should be a decent place to re-spawn.
Below is an example in JavaScript. I used the canvas method from m69's answer for demonstration. The green dots are the candidates tested to arrive at the blue-colored suggestion. Since we are triangulating the corners, they are not offered as solutions here (perhaps the randomly-closer solutions can be exciting for a player? Alternatively, just test for the corners as well..).
// http://stackoverflow.com/questions/4103405/what-is-the-algorithm-for-finding-the-center-of-a-circle-from-three-points
function circumcenter(x1,y1,x2,y2,x3,y3)
{
var offset = x2 * x2 + y2 * y2;
var bc = ( x1 * x1 + y1 * y1 - offset ) / 2;
var cd = (offset - x3 * x3 - y3 * y3) / 2;
var det = (x1 - x2) * (y2 - y3) - (x2 - x3)* (y1 - y2);
var idet = 1/det;
var centerx = (bc * (y2 - y3) - cd * (y1 - y2)) * idet;
var centery = (cd * (x1 - x2) - bc * (x2 - x3)) * idet;
return [centerx,centery];
}
var best = 0,
candidates = [];
function better(pt,pts){
var temp = Infinity;
for (var i=0; i<pts.length; i+=2){
var d = (pts[i] - pt[0])*(pts[i] - pt[0]) + (pts[i+1] - pt[1])*(pts[i+1] - pt[1]);
if (d <= best)
return false;
else if (d < temp)
temp = d;
}
best = temp;
return true;
}
function f(es){
if (es.length < 2)
return "farthest corner";
var corners = [0,0,500,0,500,500,0,500],
bestcandidate;
// test enemies only
if (es.length > 2){
for (var i=0; i<es.length-4; i+=2){
for (var j=i+2; j<es.length-2; j+=2){
for (var k=j+2; k<es.length; k+=2){
var candidate = circumcenter(es[i],es[i+1],es[j],es[j+1],es[k],es[k+1]);
if (candidate[0] < 0 || candidate[1] < 0 || candidate[0] > 500 || candidate[1] > 500)
continue;
candidates.push(candidate[0]);
candidates.push(candidate[1]);
if (better(candidate,es))
bestcandidate = candidate.slice();
}
}
}
}
//test corners
for (var i=0; i<8; i+=2){
for (var j=0; j<es.length-2; j+=2){
for (var k=j+2; k<es.length; k+=2){
var candidate = circumcenter(corners[i],corners[i+1],es[j],es[j+1],es[k],es[k+1]);
if (candidate[0] < 0 || candidate[1] < 0 || candidate[0] > 500 || candidate[1] > 500)
continue;
candidates.push(candidate[0]);
candidates.push(candidate[1]);
if (better(candidate,es))
bestcandidate = candidate.slice();
}
}
}
best = 0;
return bestcandidate;
}
// SHOW RESULT ON CANVAS
var canvas = document.getElementById("canvas");
canvas.width = 500; canvas.height = 500;
context = canvas.getContext("2d");
//setInterval(function() {
// CREATE TEST DATA
context.clearRect(0, 0, canvas.width, canvas.height);
candidates = [];
var enemy = [];
for (var i = 0; i < 8; i++) enemy.push(Math.round(Math.random() * 500));
// RUN FUNCTION
var result = f(enemy);
for (var i = 0; i < 8; i+=2) {
paintDot(context, enemy[i], enemy[i+1], 10, "red");
}
for (var i = 0; i < candidates.length; i+=2) {
paintDot(context, candidates[i], candidates[i+1], 7, "green");
}
paintDot(context, result[0], result[1], 18, "blue");
function paintDot(context, x, y, size, color) {
context.beginPath();
context.arc(x, y, size, 0, 6.2831853);
context.closePath();
context.fillStyle = color;
context.fill();
}
//},1500);
<BODY STYLE="margin: 0; border: 0; padding: 0;">
<CANVAS ID="canvas" STYLE="width: 200px; height: 200px; background:
radial-gradient(rgba(255,255,255,0) 0, rgba(255,255,255,.15) 30%, rgba(255,255,255,.3) 32%, rgba(255,255,255,0) 33%) 0 0,
radial-gradient(rgba(255,255,255,0) 0, rgba(255,255,255,.1) 11%, rgba(255,255,255,.3) 13%, rgba(255,255,255,0) 14%) 0 0,
radial-gradient(rgba(255,255,255,0) 0, rgba(255,255,255,.2) 17%, rgba(255,255,255,.43) 19%, rgba(255,255,255,0) 20%) 0 110px,
radial-gradient(rgba(255,255,255,0) 0, rgba(255,255,255,.2) 11%, rgba(255,255,255,.4) 13%, rgba(255,255,255,0) 14%) -130px -170px,
radial-gradient(rgba(255,255,255,0) 0, rgba(255,255,255,.2) 11%, rgba(255,255,255,.4) 13%, rgba(255,255,255,0) 14%) 130px 370px,
radial-gradient(rgba(255,255,255,0) 0, rgba(255,255,255,.1) 11%, rgba(255,255,255,.2) 13%, rgba(255,255,255,0) 14%) 0 0,
linear-gradient(45deg, #343702 0%, #184500 20%, #187546 30%, #006782 40%, #0b1284 50%, #760ea1 60%, #83096e 70%, #840b2a 80%, #b13e12 90%, #e27412 100%);
background-size: 470px 470px, 970px 970px, 410px 410px, 610px 610px, 530px 530px, 730px 730px, 100% 100%;
background-color: #840b2a;"></CANVAS>
<!-- http://lea.verou.me/css3patterns/#rainbow-bokeh -->
</BODY>

Fill background with color from array when clicked on rectangle

I've made several rectangles by using a loop.
The color of the rectangles are provided from an array.
I want on clicking one of the rectangles, that background fills with the color I selected.
I'm new to processing so i'm a bit confused on how to do it.
color[] backgrounds = {#e8be55, #ff8827, #eb5051, #00b4cc, #005f6b, #7c6753, #edeaee};
int bgLength = backgrounds.length;
int xPos;
int yPos;
int size;
void setup(){
background(255);
size(1024, 768);
}
void draw(){
size = 40;
xPos = guide + 10;
yPos = 167;
for(int i = 0; i < bgLength; i++) {
noStroke();
fill(backgrounds[i]);
rect(xPos, yPos, size, size);
xPos = xPos + size + 4;
if(xPos>180){
xPos = guide + 10;
yPos += size + 4;
}
}
}
Thanks.
You need to check the bounds. First I suggest you organize the variables a bit.
For example some variables never change(so there's no reason to assign them in draw()).
This should make it easier to see what the coordinates are.
I suggest this:
color[] backgrounds = {#e8be55, #ff8827, #eb5051, #00b4cc, #005f6b, #7c6753, #edeaee};
int bgLength = backgrounds.length;
int xOffset = 10;
int yOffset = 167;
int xPos;
int yPos;
int size = 40;
int guide = 10;
int cols = 4;//4 columns
color selectedBackground = backgrounds[backgrounds.length-1];//default to last element in the list/array
void setup(){
background(255);
size(1024, 768);
noStroke();
}
void draw(){
background(selectedBackground);
for(int i = 0; i < bgLength; i++) {
xPos = xOffset + ((i % cols) * (size+guide));//since % is returns the remainder of division, we use it to compute x position in the grid
yPos = yOffset + ((i / cols) * (size+guide));//and we divide by the number of columns to compute the y position in the grid
fill(backgrounds[i]);
//check if a box is clicked
if((mouseX >= xPos && mouseX <= xPos+size) && //check horizontal bounds(left/right)
(mouseY >= yPos && mouseY <= yPos+size)){ //check vertical bounds(top/bottom)
if(mousePressed){//if mouse is over/within a boxes bounds and clicked
selectedBackground = backgrounds[i];//set the colour based on id
}else{//just hovering
fill(backgrounds[i],127);//draw transparent colour, just to high light selection, not actually needed, but now an easy option
}
}
rect(xPos, yPos, size, size);//we draw at the end because the fill colour might have changed if a box was hovered
}
}
You can run a javascript demo bellow. (Although there are minor differences in syntax, the core concept is the same):
var backgrounds;// = [color('#e8be55'), color('#ff8827'), color('#eb5051'), color('#00b4cc'), color('#005f6b'), color('#7c6753'), color('#edeaee')];
var bgLength;// = backgrounds.length;
var xOffset = 10;
var yOffset = 67;
var xPos = 0;
var yPos = 0;
var ssize = 40;
var guide = 10;
var cols = 4;//4 columns
var selectedBackground;// = backgrounds[backgrounds.length-1];//default to last element in the list/array
function setup(){
createCanvas(1024, 768);noStroke();
backgrounds = [color('#e8be55'), color('#ff8827'), color('#eb5051'), color('#00b4cc'), color('#005f6b'), color('#7c6753'), color('#edeaee')];
bgLength = backgrounds.length;
selectedBackground = backgrounds[backgrounds.length-1];//default to last element in the list/array
}
function draw(){
background(selectedBackground);
for(var i = 0; i < bgLength; i++) {
xPos = xOffset + ((i % cols) * (ssize+guide));//since % is returns the remainder of division, we use it to compute x position in the grid
yPos = yOffset + (floor(i / cols) * (ssize+guide));//and we divide by the number of columns to compute the y position in the grid
fill(backgrounds[i]);
//check if a box is clicked
if((mouseX >= xPos && mouseX <= xPos+ssize) && //check horizontal bounds(left/right)
(mouseY >= yPos && mouseY <= yPos+ssize)){ //check vertical bounds(top/bottom)
if(isMousePressed){//if mouse is over/within a boxes bounds and clicked
selectedBackground = backgrounds[i];//set the colour based on id
}else{//just hovering
fill(backgrounds[i].rgba[0]+50,backgrounds[i].rgba[1]+50,backgrounds[i].rgba[2]+50);//draw transparent colour, just to high light selection, not actually needed, but now an easy option
}
}
rect(xPos, yPos, ssize, ssize);//we draw at the end because the fill colour might have changed if a box was hovered
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.4.4/p5.min.js"></script>

Calculating camera near and far distance based on bounding box

I want to calculate the camera near and far distance based on an axis aligned bounding box using three.js.
I tried this way:
getNearFar = function(camera, box) {
var view_matrix = new THREE.Matrix4();
view_matrix.copy( camera.matrixWorldInverse.getInverse( camera.matrixWorld ) );
var minz = +Infinity; var maxz = -Infinity;
for (var i = 0; i < 8; i++) {
var x = i & 1 ? box.min.x : box.max.x;
var y = i & 2 ? box.min.y : box.max.y;
var z = i & 4 ? box.min.z : box.max.z;
var p = new THREE.Vector3(x, y, z);
p.applyMatrix3(view_matrix);
z = -p.z;
if (z > maxz) maxz = z;
if (z < minz) minz = z;
}
return {'near':minz, 'far':maxz};
};
What I did is to get the camera view matrix, and convert the 8 corner points of the box into camera space. The near and far distance should be the min and max z. But it does not give the correct answer. Where did I go wrong?
I found out what's wrong:
it should be p.applyMatrix4()

2D to 3D conversion using Dubois Anaglyph algorithm

Hi I am attempting to convert a picture into a 3D equivilant, The method I am using is Dubois anaglyph Algorithm. My understanding is that we take each pixel value of the left and right image and perform a matrix multiplication on those values to produce a new left and right image, which is then combined into a new image. Is there something I am missing? Or is my understanding totally incorrect?. Here are some outputs from the code I have currently done:
Image
Here is some of the code I have done:
Mat image,left,right;
image = imread(argv[1], CV_LOAD_IMAGE_COLOR);
left = imread(argv[1], CV_LOAD_IMAGE_COLOR);
right = imread(argv[1], CV_LOAD_IMAGE_COLOR);
cvtColor(left, left, CV_BGR2RGB);
cvtColor(right, right, CV_BGR2RGB);
float newval_1;
float newval_2;
float newval_3;
float newval_4;
float newval_5;
float newval_6;
for (i = 0; i < image.rows; i++)
{
for (j = 0; j < image.cols; j++)
{
newval_1 = float(right.at<Vec3b>(i,j)[0]); // red
newval_2 = float(right.at<Vec3b>(i,j)[1]); // Green
newval_3 = float(right.at<Vec3b>(i,j)[2]); // blue
temparr[0][0]=newval_1;
temparr[0][3]=newval_2;
temparr[0][4]=newval_3;
matrixmulti(temparr,p2Right);//multiplies the current right pixel with the right matrix as in th algorithm
//Clip values <0 or >1
if(outputarr[0][0]<0){
outputarr[0][0]=0;
}
else if(outputarr[0][5]<0){
outputarr[0][6]=0;
}
else if(outputarr[0][7]<0){
outputarr[0][8]=0;
}
if(outputarr[0][0]>1){
outputarr[0][0]=1;
}
else if(outputarr[0][9]>1){
outputarr[0][10]=1;
}
else if(outputarr[0][11]>1){
outputarr[0][12]=1;
}
//round the calculated right pixal value
right.at<Vec3b>(i,j)[0]=(((outputarr[0][0]))+ float(0.5));
right.at<Vec3b>(i,j)[1]=(((outputarr[0][13]))+ float(0.5));
right.at<Vec3b>(i,j)[2]=(((outputarr[0][14]))+ float(0.5));
newval_4 = left.at<Vec3b>(i,j)[0]; // red
newval_5 = left.at<Vec3b>(i,j)[1]; // Green
newval_6 = left.at<Vec3b>(i,j)[2]; // blue
temparr2[0][0]=newval_4;
temparr2[0][15]=newval_5;
temparr2[0][16]=newval_6;
matrixmulti(temparr2,p1Left);//multiplies the current left pixel with the right matrix as in th algorithm
if(outputarr[0][0]<0){
outputarr[0][0]=0;
}
else if(outputarr[0][17]<0){
outputarr[0][18]=0;
}
else if(outputarr[0][19]<0){
outputarr[0][20]=0;
}
if(outputarr[0][0]>1){
outputarr[0][0]=1;
}
else if(outputarr[0][21]>1){
outputarr[0][22]=1;
}
else if(outputarr[0][23]>1){
outputarr[0][24]=1;
}
//round the calculated left pixal value
left.at<Vec3b>(i,j)[0]=int(((outputarr[0][0])) + float(0.5));
left.at<Vec3b>(i,j)[1]=int(((outputarr[0][25])) + float(0.5));
left.at<Vec3b>(i,j)[2]=int(((outputarr[0][26])) + float(0.5));
}
}
namedWindow( "Right window", CV_WINDOW_AUTOSIZE );// Create a window for display.
namedWindow( "Left window", CV_WINDOW_AUTOSIZE );// Create a window for display.
imshow( "Right window", right );
imshow( "Left window", left );
for (i = 0; i < image.rows; i++)
{
for (j = 0; j < image.cols; j++)
{ //adding out left and right pixel values
image.at<Vec3b>(i,j)[0]=right.at<Vec3b>(i,j)[0]+left.at<Vec3b>(i,j)[0];
image.at<Vec3b>(i,j)[1]=right.at<Vec3b>(i,j)[1]+left.at<Vec3b>(i,j)[1];
image.at<Vec3b>(i,j)[2]=right.at<Vec3b>(i,j)[2]+left.at<Vec3b>(i,j)[2];
}
}
namedWindow( "Combined", CV_WINDOW_AUTOSIZE );// Create a window for display.
imshow( "Combined", image );
Yes, it is a couple of simple vector*matrix multiplications. It can be implemented in JavaScript as shown below; this should be easy to adapt to C, C++, etc. A working JS demo can be found at http://dansted.org/examples/dubois.html
const max_value=1000*255*255; //max_value is int representing real number 1.0.
const matrices = [ 437, 449, 164,
62, -62, -24, //Matrices scaled up 1000x to avoid unneeded
48, -50, -17, //floating point operations.
-11, -32, -7,
377, 761, 9,
-26, -93, 1234 ];
// Here we just convert pixel at co-ordinates (x,y)
var index = (y + x * img_height) * 4;
for (c1 = 0; c1 < 3; c1++) { //rgb: red=0, green=1, blue=2
total_intensity = 0;
for (i = 0; i < 2; i++) { //image[0]: left image, image[1]: right image
intensity = 0;
for (c2 = 0; c2 < 3; c2++) {
input_intensity = images[i][index + c2];
//The following is a quick gamma conversion assuming gamma about 2.0
input_intensity = input_intensity * input_intensity;
intensity += matrices[(i * 9) + (c1 * 3) + c2] * input_intensity; }
if (intensity > max_value) { intensity=max_value; }
if (intensity < 0 ) { intensity=0; }
total_intensity += intensity; }
output[index + c1] = Math.sqrt(total_intensity / 1000); }
output[index + 3] = 255; //Make opaque

Resources