Why is my VBO updated on 2nd click? - iphone

I have this method (InvertPolygonMesh) which basically takes an array (my VBO) and inverts all vertices along the Z axis. This method is directly invoked by the click of a button (IBAction). Now for some odd reason the VBO doesn't change on the first click, but it does get inverted on every subsequent click after the 1st one.
Why is there no update for the 1st click?
Method is below:
-(void)InvertPolygonMesh
{
NSLog(#"Invert mesh data.");
glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferPhoto);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_meshVertexData), g_meshVertexData, GL_DYNAMIC_DRAW);
int index = 0;
bool edgeCase = false;
for (int row = 0; row < MAP_SIZE; row += STEP_SIZE)
{
for (int col = 0; col < MAP_SIZE; col += STEP_SIZE)
{
g_meshVertexData[index].vertex.z = 255 - g_meshVertexData[index].vertex.z;
++index;
}
}
}

i fixed this by calling glBindBuffer and glBufferData functions AFTER the mesh vertices have been updated. Resolved !!!

Related

How to select and drag an ellipse in old version of Processing?

//The following game has been designed as an educational resource
//for Key Stage 1 and 2 children. Children are the future of
//civil engineering, and to inspire them to get involved in the
//industry is important for innovation. However, today the
//national curriculum is very structured, and many children
//can find themselves falling behind even at the age of 7 or 8.
//It is essential that children can be supported with material
//they find difficult, and given the resources to learn in a
//fun and engaging manner.
//One of the topics that many children struggle to grasp is
//fractions. It is necessary to prevent young children feeling
//like STEM subjects are too difficult for them, so that they
//have the opportunity and confidence to explore science and
//engineering subjects as they move into secondary education and
//careers.
//This game intends to set a precedent for teaching complex
//subjects to children in a simple, but fun and interactive
//manner. It will show them that fractions can be fun, and that
//they are capable, building confidence once they return to
//the classroom.
//The game will work by challenging the user to split a group
//of balls into three buckets depending on the fraction
//displayed on the bucket.
int number_of_balls;
float bucket_1, bucket_2, bucket_3;
int bucket_1_correct, bucket_2_correct, bucket_3_correct;
PVector basket_position, basket_dimensions;
Ball[] array_of_balls;
int linethickness;
//Random generator to give number of balls, ensuring that
//they can be divided into the number of buckets available.
void setup()
{
size(500,500);
linethickness = 4;
number_of_balls = int(random(1,11))*6;
println(number_of_balls);
bucket_1 = 1/6;
bucket_2 = 1/2;
bucket_3 = 1/3;
//Working out the correct answers
bucket_1_correct = number_of_balls*bucket_1;
bucket_2_correct = number_of_balls*bucket_2;
bucket_3_correct = number_of_balls*bucket_3;
println (bucket_1, bucket_2, bucket_3);
println (bucket_1_correct, bucket_2_correct, bucket_3_correct);
//Creating the basket
basket_position = new PVector(width/4, height/8);
basket_dimensions = new PVector(width/2, height/4);
//Creating the balls & placing inside basket
array_of_balls = new Ball[number_of_balls];
for (int index=0; index<number_of_balls; index++)
{
array_of_balls[index] = new Ball();
}
}
//Drawing the balls and basket outline
void draw()
{
background (125,95,225);
for (int index=0; index<number_of_balls; index++)
{
array_of_balls[index].Draw();
}
noFill();
stroke(180,0,0);
strokeWeight(linethickness);
rect(basket_position.x, basket_position.y, basket_dimensions.x, basket_dimensions.y);
}
void mouseDragged()
{
if ((mouseX >= (ball_position.x - radius)) && (mouseX <= (ball_position.x + radius)) && (mouseY >= (ball_position.y - radius)) && (mouseY <= (ball_position.y + radius)))
{
ball_position = new PVector (mouseX, mouseY);
}
}
//Ball_class
int radius;
Ball()
{
radius = 10;
ball_position = new PVector (random(basket_position.x + radius + linethickness, basket_position.x + basket_dimensions.x - radius - linethickness), random(basket_position.y + radius + linethickness, basket_position.y + basket_dimensions.y - radius - linethickness));
colour = color(random(255), random(255), random(255));
}
void Draw()
{
noStroke();
fill(colour);
ellipse(ball_position.x,ball_position.y,radius*2,radius*2);
}
}
Thanks in advance for your help! I am using Processing 2.2.1 which I know is very out of date, so struggling to find help.
I have a piece of code that has created a number of balls, and I would like to be able to 'drag and drop' these to a different location on the screen as part of an educational game. I've tried playing around with mousePressed() and mouseDragged() but no luck yet. Any advice would be appreciated!
There are a lot of ways to approach this, but one way I could suggest is doing something like this:
// "Ellipse" object
function Ellipse (x, y, width, height) {
// Each Ellipse object has their own x, y, width, height, and "selected" values
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.selected = false;
// You can call the draw function whenever you want something done with the object
this.draw = function() {
// Draw ellipse
ellipse(this.x, this.y, this.width, this.height);
// Check if mouse is touching the ellipse using math
// https://www.desmos.com/calculator/7a9u1bpfvt
var xDistance = this.x - mouseX;
var yDistance = this.y - mouseY;
// Ellipse formula: (x^2)/a + (y^2)/b = r^2
// Assuming r = 1 and y = 0:
// 0 + (x^2)/a = 1 Substitute values
// ((width / 2)^2)/a = 1 x = width / 2 when y = 0
// a = (width / 2)^2 Move numbers around
// a = (width^2) / 4 Evaluate
var a = Math.pow(this.width, 2) / 4;
// Assuming r = 1 and x = 0:
// 0 + (y^2)/b = 1 Substitute values
// ((height / 2)^2)/b = 1 y = height / 2 when x = 0
// b = (height / 2)^2 Move numbers around
// b = (height^2) / 4 Evaluate
var b = Math.pow(this.height, 2) / 4;
// x^2
var x2 = Math.pow(xDistance, 2);
// y^2
var y2 = Math.pow(yDistance, 2);
// Check if coordinate is inside ellipse and mouse is pressed
if(x2 / a + y2 / b < 1 && mouseIsPressed) {
this.selected = true;
}
// If mouse is released, deselect the ellipse
if(!mouseIsPressed) {
this.selected = false;
}
// If selected, then move the ellipse
if(this.selected) {
// Moves ellipse with mouse
this.x += mouseX - pmouseX;
this.y += mouseY - pmouseY;
}
};
}
// New Ellipse object
var test = new Ellipse(100, 100, 90, 60);
draw = function() {
background(255);
// Do everything associated with that object
test.draw();
};
The math is a bit funky, and I might not be using the right version of Processing, but hopefully you found this at least slightly helpful :)
I'm kind of confused about what language you're using. Processing is a wrapper for Java, not JavaScript. Processing.js went up to version 1.6.6 and then was succeeded by p5.js. I'm going to assume you're using p5.js.
I don't know if this is a new thing in p5.js, but for easy, but not very user-friendly click-and-drag functionality I like to use the built-in variable mouseIsPressed.
If the ellipse coordinates are stored in an array of vectors, you might do something like this:
let balls = [];
let radius = 10;
function setup() {
createCanvas(400, 400);
for (let i = 0; i < 10; i++) {
balls.push(createVector(random(width), random(height)));
}
}
function draw() {
background(220);
for (let i = 0; i < balls.length && mouseIsPressed; i++) {
if (dist(mouseX, mouseY, balls[i].x, balls[i].y) < radius) {
balls[i] = createVector(mouseX, mouseY);
i = balls.length;
}
}
for (let i = 0; i < balls.length; i++) {
ellipse(balls[i].x, balls[i].y,
2 * radius, 2 * radius
);
}
}
This is the quickest way I could think of, but there are better ways to do it (at least, there are in p5.js). You could make a Ball class which has numbers for x, y, and radius, as well as a boolean for whether it's being dragged. In that class, you could make a method mouseOn() which detects whether the cursor is within the radius (if it's not a circle, you can use two radii: sq((this.x - mouseX)/r1) + sq((this.y - mouseY)/r2) < 1).
When the mouse is pressed, you can cycle through all the balls in the array of balls, and test each of them with mouseOn(), and set their drag boolean to true. When the mouse is released, you can set all of their drag booleans to false. Here's what it looks like in the current version of p5.js:
function mousePressed() {
for (let i = 0; i < balls.length; i++) {
balls[i].drag = balls[i].mouseOn();
if (balls[i].drag) {
i = balls.length;
}
}
}
function mouseReleased() {
for (let i = 0; i < balls.length; i++) {
balls[i].drag = false;
}
}
I hope this helps.
The way your code is right now doesn't work in the current version of Processing either, but it's a pretty quick fix. I'm going to show you a way to fix that, and hopefully it'll work in the earlier version.
Here's where I think the problem is: when you use mouseDragged(), you try to change ball_position, but you don't specify which ball's position. Here's one solution, changing the mouseDragged() block and the Ball class:
void mouseDragged() {
for (int i = 0; i < array_of_balls.length; i++) {
if ((mouseX > (array_of_balls[i].ball_position.x - array_of_balls[i].radius)) &&
(mouseX < (array_of_balls[i].ball_position.x + array_of_balls[i].radius)) &&
(mouseY > (array_of_balls[i].ball_position.y - array_of_balls[i].radius)) &&
(mouseY < (array_of_balls[i].ball_position.y + array_of_balls[i].radius))
) {
array_of_balls[i].ball_position = new PVector (mouseX, mouseY);
i = array_of_balls.length;
}
}
}
//Ball_class
class Ball {
int radius;
PVector ball_position;
color colour;
Ball() {
radius = 10;
ball_position = new PVector (random(basket_position.x + radius + linethickness, basket_position.x + basket_dimensions.x - radius - linethickness), random(basket_position.y + radius + linethickness, basket_position.y + basket_dimensions.y - radius - linethickness));
colour = color(random(255), random(255), random(255));
}
void Draw() {
noStroke();
fill(colour);
ellipse(ball_position.x, ball_position.y, radius*2, radius*2);
}
}
P.S. Since you're using a language based in Java, you should probably adhere to the finnicky parts of the language:
data types are very strict in Java. Avoid assigning anything that could possibly be a float to a variable that is declared as an int. For example, in your setup() block, you say bucket_1_correct = number_of_balls*bucket_1;. This might seem like not an issue, since number_of_balls*bucket_1 is always going to be a whole number. But since the computer rounds when saving bucket_1 = 1/6, multiplying it by 6 doesn't necessarily give a whole number. In this case, you can just use round(): bucket_1_correct = round(number_of_balls*bucket_1);
Regarding data types, you should always declare your variables with their data type. It's a little hard for me to tell, but it looks to me like you never declared ball_position or colour in your Ball class, and you never opened up the class with the typical class Ball {. This might have been a copy/paste error, though.

JavaFX8 Timeline to scroll Grid of Circle Objects?

Using JavaFX8 and JDK 1.8.0_74 in IntelliJ, I created a basic pixel editor app. I have two windows(stages). One is a 32x128 matrix of Circle Objects placed in a Grid Pane and the other, a Tools widow; I have one Controller.java. Using the mouse, the Tools window provides tools to draw lines, rectangles, etc. and a menu for Setup, Files and Playlists. The Files menu presents the user with Open, SaveAs and Delete. To view a saved pixel art file, the user clicks Open and via the FileChooser, the selected file is opened and each Circle’s color property is displayed. The saved pixel art File can be sent via Wi-Fi to an RGB LED matrix that’s also 32x128.
To view pics and video go to: https://virtualartsite.wordpress.com/
I can scroll a displayed pixel art file left, right, up or dow using Timeline. However, I would also like to wrap the pixel image but have failed to eliminate small anomalies that appear at the beginning of the wrap while the remaining 95% of the wrap is correct?
The critical code for class WrapLeft is as follows:
public static void runAnimation() {
timeline = new Timeline(
new KeyFrame(Duration.millis(200), event -> {
wrapFileLeft(pixelArray);
}));
timeline.setCycleCount(100);
timeline.play();
}
public static void wrapFileLeft(Circle[][] pixelArray){
// save pixelArray[r][0] in pixelArrayTmp[r][0] and wrap to end, pixelArray[r][col-1]
Circle[] pixelArrayTmp = new Circle[row];
for (int r = 0; r < row; r++) {
pixelArrayTmp[r] = pixelArray[r][0];
}
// move all the pixelArray columns one column to the left
for (int c = 0; c < col-1; c++) {
for (int r = 0; r < row; r++) {
Color color = (Color) pixelArray[r][c+1].getFill();
pixelArray[r][c].setFill(color);
}
}
// move the pixelArrayTmp[r][0] column into the new, blank, end column of pixelArray[r][col-1]
for (int r = 0; r < row; r++) {
Color color = (Color) pixelArrayTmp[r].getFill();
pixelArray[r][col-1].setFill(color);
} } }
The logic is to temporarily save column 0, shift all the remaining columns to the left one position and replace column 127 with column 0. This is all done in one CycleCount(). The anomalies occur in the first four shifts left; the Circle Objects with colors other than black get changed to an adjacent color. But after four shifts, all remaining shifts appear to be correct?
My best guess is the logical order of execution gets out of order because I not using Timeline properly or trying to execute too much in a single KeyFrame? Increasing the duration doesn’t seem to affect the anomalies.
Thanks for your help.
Logically, your solution is wrong, you are storing referencing to circles in a temporary array, then changing the fill of the referenced circles, then using the updated referenced fill to set the new fill.
Instead of storing references to circles, store the fill values themselves.
public void wrapItLeft(Circle[][] pixelArray){
// save pixelArray[r][0] in pixelArrayTmp[r][0] and wrap to end, pixelArray[r][col-1]
Paint[] pixelArrayTmp = new Paint[N_ROWS];
for (int r = 0; r < N_ROWS; r++) {
pixelArrayTmp[r] = pixelArray[r][0].getFill();
}
// move all the pixelArray columns one column to the left
for (int c = 0; c < N_COLS-1; c++) {
for (int r = 0; r < N_ROWS; r++) {
Color color = (Color) pixelArray[r][c+1].getFill();
pixelArray[r][c].setFill(color);
}
}
// move the pixelArrayTmp[r][0] column into the new, blank, end column of pixelArray[r][col-1]
for (int r = 0; r < N_ROWS; r++) {
pixelArray[r][N_COLS-1].setFill(pixelArrayTmp[r]);
}
}

dragStart starts in the wrong position

I'm implementing the drag and drop in Libgdx with DragAndDrop class.
The actors that i have to move are in a grid (Table), centered in the screen.
The drag and drop starts if i click on the top-right corner of the screen, and not if i click on the actor itself! I can't figure out where is the problem.
This grid is a matrix:
for(int i = 0; i < Constants.ROWS; i++) {
for(int j = 0; j < Constants.COLS; j++) {
slots[i][j] = new Slot(Item.EMPTY, i, j);
}
}
Then i use the code above to create the table:
public class SlotsAreaActor extends Table {
public SlotsAreaActor(SlotsArea slotsArea, DragAndDrop dnd) {
// set the position of this actor in the screen
setPosition(Constants.SLOTS_AREA_ACTOR_X, Constants.SLOTS_AREA_ACTOR_Y);
// spaces all the row and the columns
defaults().space(Constants.ROWS_SPACE);
row().fill().expandX();
Slot[][] slots = slotsArea.getSlots();
for(int i = 0; i < slots.length; i++) {
for(int j = 0; j < slots[0].length; j++) {
SlotActor slotActor = new SlotActor(slots[i][j]);
dnd.addSource(new SlotSource(slotActor));
dnd.addTarget(new SlotTarget(slotActor));
add(slotActor);
}
row();
}
}
}
In the SlotActor class i set the bounds:
x = Constants.APP_WIDTH - Constants.ORIZONTAL_OFFSET - (Constants.TILE_SIZE * (Constants.COLS - slot.getX()));
y = Constants.APP_HEIGHT - Constants.VERTICAL_OFFSET - (Constants.TILE_SIZE * (Constants.ROWS - slot.getY()));
setBounds(x, y, Constants.TILE_SIZE, Constants.TILE_SIZE);
My formulas are wrong someway...
The Slot object holds its x (i, row) in the matrix, and y (j, column) in the matrix.
The Actor object holds the slot, and calculates its position in the screen with the formulas above.
Another question: what are float x and float y in the dragStart method?
UPDATE
The correct formula for y is:
y = Constants.APP_HEIGHT - Constants.VERTICAL_OFFSET - (Constants.TILE_SIZE * slot.getX());
But the dragStart still does not work. It is totally out of phase.
The dragging does not start when i click on the actor, but if i click on an area in the top-right corner of the screen.
UPDATE 2
The problem is the positioning of the Table. It is totally messed up.
UPDATE 3
With table.setDebug(true) i verified that the table is at the correct position. So... i really don't know what is happening.
For drag and drop i implemented as follows:
myActor.addListener(new DragListener(){
public void touchDragged(InputEvent event, float x, float y, int pointer){
myActor.moveBy(x-firstItem.getWidth()/2,y-firstItem.getHeight()/2);}});

I have 2 Achartengine XYSeries problems

I’m having 2 problems with a simple XYSeries line graph.
When the absolute value of the difference between the last plotted point and the next plotted point is less than 11 the label on the next plotted point goes missing. I want all the labels to display.
I have some (not all) missing vertical grid lines and don’t see why. I want a vertical grid line for every XY coordinate.
Thanks for the help. Here's the code.
String glucoseLegendText = getString(R.string.glucose_legend_text);
XYSeries series = new XYSeries(glucoseLegendText);
datasource = new HistoryDataSource(this);
datasource.open();
Cursor c = datasource.getQuery();
c.moveToFirst();
int cnt = c.getCount();
int minValue = 0;
int maxValue = 0;
for (int i = 0; i < cnt; i++) {
int glucoseValue = c.getInt(2);
series.add(i, glucoseValue);
if (i == 0 || glucoseValue < minValue)
minValue = glucoseValue;
if (glucoseValue > maxValue)
maxValue = glucoseValue;
c.moveToNext();
}
datasource.close();
XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
dataset.addSeries(series);
XYSeriesRenderer renderer = new XYSeriesRenderer();
renderer.setColor(Color.BLUE);
renderer.setPointStyle(PointStyle.CIRCLE);
renderer.setFillPoints(true);
renderer.setLineWidth(3);
renderer.setDisplayChartValues(true);
renderer.setChartValuesTextSize(15);
renderer.setChartValuesTextAlign(Align.LEFT);
XYMultipleSeriesRenderer mRenderer = new XYMultipleSeriesRenderer();
mRenderer.addSeriesRenderer(renderer);
mRenderer.setShowGrid(true);
mRenderer.setGridColor(Color.BLACK);
mRenderer.setXLabels(cnt); // to control number of grid lines
mRenderer.setYLabels(cnt); // to control number of grid lines
mRenderer.setXLabelsColor(Color.YELLOW);
mRenderer.setPointSize(5);
mRenderer.setYLabelsAlign(Align.RIGHT);
mRenderer.setLegendTextSize(15);
mRenderer.setZoomButtonsVisible(true);
mRenderer.setYAxisMin(minValue - 2); // buffer bottom
mRenderer.setYAxisMax(maxValue + 3); // buffer top
// Populate the X labels with the dates and times
c.moveToFirst();
for (int d = 0; d < cnt; d++) {
timeStamp = c.getString(1);
date = timeStamp.substring(0, 5);
time = timeStamp.substring(9, 14);
if (date.equals(dateLast)) {
mRenderer.addXTextLabel(d, "\n" + time);
} else
mRenderer.addXTextLabel(d, "\n" + time + "\n" + date);
dateLast = date;
c.moveToNext();
}
c.close();
GraphicalView gview = ChartFactory.getTimeChartView(this, dataset,
mRenderer, "");
LinearLayout layout = (LinearLayout) findViewById(R.id.Chart);
layout.addView(gview);
For the first question, you can control the labels display using
renderer.setXLabels(approximateNumberOfLabels);
For the second question, the grid lines are displayed along the labels.

Boundry detect paper sheet opencv

I am new in openCV, I already detect edge of paper sheet but my result image is blurred after draw lines on edge, How I can draw lines on edges of paper sheet so my image quality remain unaffected.
what I am Missing..
My code is below.
Many thanks.
-(void)forOpenCV
{
if( imageView.image != nil )
{
cv::Mat greyMat=[self cvMatFromUIImage:imageView.image];
vector<vector<cv::Point> > squares;
cv::Mat img= [self debugSquares: squares: greyMat ];
imageView.image =[self UIImageFromCVMat: img];
}
}
- (cv::Mat) debugSquares: (std::vector<std::vector<cv::Point> >) squares : (cv::Mat &)image
{
NSLog(#"%lu",squares.size());
// blur will enhance edge detection
Mat blurred(image);
medianBlur(image, blurred, 9);
Mat gray0(image.size(), CV_8U), gray;
vector<vector<cv::Point> > contours;
// find squares in every color plane of the image
for (int c = 0; c < 3; c++)
{
int ch[] = {c, 0};
mixChannels(&image, 1, &gray0, 1, ch, 1);
// try several threshold levels
const int threshold_level = 2;
for (int l = 0; l < threshold_level; l++)
{
// Use Canny instead of zero threshold level!
// Canny helps to catch squares with gradient shading
if (l == 0)
{
Canny(gray0, gray, 10, 20, 3); //
// Dilate helps to remove potential holes between edge segments
dilate(gray, gray, Mat(), cv::Point(-1,-1));
}
else
{
gray = gray0 >= (l+1) * 255 / threshold_level;
}
// Find contours and store them in a list
findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
// Test contours
vector<cv::Point> approx;
for (size_t i = 0; i < contours.size(); i++)
{
// approximate contour with accuracy proportional
// to the contour perimeter
approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);
// Note: absolute value of an area is used because
// area may be positive or negative - in accordance with the
// contour orientation
if (approx.size() == 4 &&
fabs(contourArea(Mat(approx))) > 1000 &&
isContourConvex(Mat(approx)))
{
double maxCosine = 0;
for (int j = 2; j < 5; j++)
{
double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1]));
maxCosine = MAX(maxCosine, cosine);
}
if (maxCosine < 0.3)
squares.push_back(approx);
}
}
}
}
NSLog(#"%lu",squares.size());
for( size_t i = 0; i < squares.size(); i++ )
{
cv:: Rect rectangle = boundingRect(Mat(squares[i]));
if(i==squares.size()-1)////Detecting Rectangle here
{
const cv::Point* p = &squares[i][0];
int n = (int)squares[i].size();
NSLog(#"%d",n);
line(image, cv::Point(507,418), cv::Point(507+1776,418+1372), Scalar(255,0,0),2,8);
polylines(image, &p, &n, 1, true, Scalar(255,255,0), 5, CV_AA);
fx1=rectangle.x;
fy1=rectangle.y;
fx2=rectangle.x+rectangle.width;
fy2=rectangle.y+rectangle.height;
line(image, cv::Point(fx1,fy1), cv::Point(fx2,fy2), Scalar(0,0,255),2,8);
}
}
return image;
}
Instead of
Mat blurred(image);
you need to do
Mat blurred = image.clone();
Because the first line does not copy the image, but just creates a second pointer to the same data.
When you blurr the image, you are also changing the original.
What you need to do instead is, to create a real copy of the actual data and operate on this copy.
The OpenCV reference states:
by using a copy constructor or assignment operator, where on the right side it can
be a matrix or expression, see below. Again, as noted in the introduction, matrix assignment is O(1) operation because it only copies the header and increases the reference counter.
Mat::clone() method can be used to get a full (a.k.a. deep) copy of the matrix when you need it.
The first problem is easily solved by doing the entire processing on a copy of the original image. That way, after you get all the points of the square you can draw the lines on the original image and it will not be blurred.
The second problem, which is cropping, can be solved by defining a ROI (region of interested) in the original image and then copying it to a new Mat. I've demonstrated that in this answer:
// Setup a Region Of Interest
cv::Rect roi;
roi.x = 50
roi.y = 10
roi.width = 400;
roi.height = 450;
// Crop the original image to the area defined by ROI
cv::Mat crop = original_image(roi);
cv::imwrite("cropped.png", crop);