Cocos2d-x Touch Event coordinate system - c++

I'm using cocos2d-x 3.7.1
I have a Node in my Scene, I'm adding child Nodes to that Node. (HexField is a subclass of Node)
int rhombusSizeX = 1;
int rhombusSizeY = 2;
for (int y = 0; y < rhombusSizeY; ++y){
for (int x = 0; x < rhombusSizeX; ++x){
HexField* field = HexField::create();
field->setPosition(Vec2(x*30 + y*15, y*30));
field->setName("HexField " + to_string(x) + "," + to_string(y));
auto listener = EventListenerTouchOneByOne::create();
listener->setSwallowTouches(true);
listener->onTouchBegan = CC_CALLBACK_2(HexField::onTouchBegan, field);
listener->onTouchMoved = CC_CALLBACK_2(HexField::onTouchMoved, field);
listener->onTouchEnded = CC_CALLBACK_2(HexField::onTouchEnded, field);
Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, field);
this->addChild(field, 1);
}
}
If there is only one HexField added
int rhombusSizeX = 1;
int rhombusSizeY = 1;
The touch->getLocation() in HexField::onTouchBegan is reported as expected in World Coordinates.
If there is more than one HexField added
int rhombusSizeX = 5;
int rhombusSizeY = 5;
touch->getLocation() returns coordinates relative to the "one before last" added HexField which in this case will be HexField 3,4.
Why is that so? Is it a bug?

I came to an answer now.
It all happened because I didn't call:
Director::getInstance()->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
after:
Director::getInstance()->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
Director::getInstance()->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, transform);
in my draw function.
Looks like that error escalated to other parts of my program causing some strange behavior.

Related

Function started with std::async crashes after quite a few iterations

I am trying to develop a simple evolution algorithm in C++. To make my calculations faster I decided to use async functions to run multiple calculations at once:
std::vector<std::future<int> > compute(8);
unsigned nptr = 0;
int syncp = 0;
while(nptr != network::networks.size()){
compute.at(syncp) = std::async(&network::analyse, &network::networks.at(nptr), data, width, height, sw, dFnum.at(idx));
syncp++;
if(syncp == 8){
syncp = 0;
for(unsigned i = 0; i < 8; i++){
compute.at(i).get();
}
}
nptr++;
}
This is how I start my calculating function. The function is called analyse, and for each "network" it assigns a score depending on how good it identifies the image.
This is part of the analyse function:
for(unsigned i = 0; i < entry.size(); i++){
double sum = 0;
data * d = &entry.at(i);
pattern * p = &pattern::patterns.at(d->patNo);
int sx = iWidth;
int sy = iHeight;
if(d->xPercentage*iWidth + d->xSpan*iWidth < sx) sx = d->xPercentage*iWidth + d->xSpan*iWidth;
if(d->yPercentage*iHeight + d->xSpan*iWidth < sy) sy = d->yPercentage*iHeight + d->xSpan*iWidth;
int xdisp = sx-d->xPercentage*iWidth;
int ydisp = sy-d->yPercentage*iHeight;
for(int x = d->xPercentage*iWidth; x < sx; x++){
for(int y = d->yPercentage*iHeight; y < sy; y++){
double xpl = x-d->xPercentage*iWidth;
double ypl = y-d->yPercentage*iHeight;
xpl /= xdisp;
ypl /= ydisp;
unsigned idx = (unsigned)(xpl*(p->width) + ypl*(p->height)*(p->width));
if(idx >= p->lweight.size()) idx = p->lweight.size()-1;
double weight = p->lweight.at(idx) - 5;
if(imageData[y*iWidth+x])
sum += weight;
else
sum -= 2*weight;
}
}
digitWeight[d->digit-1] += sum;
}
}
Now, there is no need to analyse the function itself - I'm sure it works, I have tested it on a single thread, and it runs just fine. The only problem is, after some time of execution, I get errors like segmentation fault, or vector range check error.
They mostly happen at this line:
digitWeight[d->digit-1] += sum;
Now, you can be sure that d->digit-1 is a valid range for this array.
The problem is that the value of the d pointer is different than it was here:
data * d = &entry.at(i);
It magically changes during the execution of the function, and starts pointing to different data, leading to errors. I have tried saving the value of d->digit to some variable and later use this variable, and it worked fine for just a while longer, before crashing on another shared resource, imageData this time.
I'm thinking this might be something related to data sharing - all async functions share the same array of data - it's a static vector. But this data is only read, not written anywhere, so why would it stop working? I know of something called mutex locking, but this would make no sense to lock this async functions, as it would run just as slow as a single threaded program would run.
I have also tried running the functions like this:
std::vector<std::thread*> threads(8);
unsigned nptr = 0;
int threadp = 0;
while(nptr != network::networks.size()){
threads.at(threadp) = new std::thread(&network::analyse, &network::networks.at(nptr), data, width, height, sw, dFnum.at(idx));
threadp++;
if(threadp == 8){
threadp = 0;
for(unsigned i = 0; i < 8; i++){
if(threads.at(i)->joinable()) threads.at(i)->join();
delete threads.at(i);
}
}
nptr++;
}
and it did work for a second, but after some time a very similar error appeared.
Data is a structure containing 7 integers, one of which is an ID of
pattern, and pattern is a class that contains two integers - width and height
and vector of chars.
Why does it happen on read-only data and how can I prevent it?
Here is an example of what happens:

Graphing issues in data output

I have a program that is taking input from an external source (right now, a joystick), and then plotting it on a graph. The graph displays the last 60 frames of data, which is about 1-2 seconds.
here is the data input:
nextDataPoint(double x){
if (x > max){ max = x; }
if (x < min){ min = x; }
dataInput.enqueue(x) //dataInput is a QQueue<double>
while (dataInput.size() > 60){
dataInput.dequeue();
}
update(); //this triggers the paint event
}
here is the graphing function
graph function:
//this draws the min line and the max line
QPainter painter(this);
int lineDist = 25;
QPen myPen(Qt::black, 3);
QPoint maxText(10,20);
painter.drawText(maxText, "max");
QPoint maxLineLeft(0, lineDist);
QPoint maxLineRight(width(), lineDist);
painter.drawLine(maxLineLeft, maxLineRight);
QPoint minText(10, height()-10);
painter.drawText(minText, "min");
QPoint minLineLeft(0, height()-lineDist);
QPoint minLineRight(width(), height()-lineDist);
//this draws the actual graph
myPen.setColor(Qt::blue);
myPen.setWidth(2);
painter.setPen(myPen);
double dist = (double)(heigh() - 2*lineDist);
int stepSize = (int)((double)width() / 60.0);
int heightStep = (max-min)/dist;
double x;
QPoint lastPoint(0,0);
QPoint nextPoint(0,0);
int i = 0;
if (!dataInput.empty()){ //checks that there is data
if (dataInput.size() < 60) { //ignoring for sake of brevety
} else {
x = dataInput.at(i);
x = max - x; // this inverts the data, necessary because (0,0) is the upper left corner
x = (x-min)/heightStep;
nextPoint.setX(0);
nextPoint.setY(x+lineDist);
for (i = 1; i < 60; i++){
x = dataInput.at(i);
x = max - x;
x = (x-min)/heightStep;
lastPoint = nextPoint;
nextPoint.setX(i*stepSize);
nextPoint.setY(x+lineDist);
painter.drawLine(lastPoint, nextPoint);
}
}
}
So, with one joystick that I am testing with, this program works without issue. As I move the joystick, the program draws the blue line within the bounds listed on the screen. x is input as a number between 0 and 65535, and after moving the joystick around a little bit the system recognizes that as the max and the min, and then proceeds to function as expected.
The second "joystick" is less of a joystick and more of a pressure sensor. This outputs either x = 1023 or x is some number between 5 and 9. In this case however, the blue line appears on the same level as the max line, or when the data output is x in the single digits, the blue line appears below min. I haven't been able to figure out why this would be the case, the first joystick can also produce results of 0, but it never goes below the minimum line. What might be causing this particular issue?
Two changes were needed to correct the issues.
First, stepSize and heightStep were both changed from int to double.
second, the section
x = dataInput.at(i);
x = max - x;
x = (x-min)/heightStep;
nextPoint.setX(0);
nextPoint.setY(x+lineDist);
for (i = 1; i < 60; i++){
x = dataInput.at(i);
x = max - x;
x = (x-min)/heightStep;
lastPoint = nextPoint;
nextPoint.setX(i*stepSize);
nextPoint.setY(x+lineDist);
painter.drawLine(lastPoint, nextPoint);
}
was changed to:
x = dataInput.at(i);
x = (x-min)/heightStep;
nextPoint.setX(0);
nextPoint.setY(dist-x+lineDist);
for (i = 1; i < 60; i++){
x = dataInput.at(i);
x = (x-min)/heightStep;
lastPoint = nextPoint;
nextPoint.setX(i*stepSize);
nextPoint.setY(dist-x+lineDist);
painter.drawLine(lastPoint, nextPoint);
}
This solved the issue and made the system always draw the data between the min and max lines.

How to animate window output from 2D array of x and y screen co-ordinates

I have a set of 2D array(IntMatrix to be exact) that possess values in certain index (if value is 1, it will print to screen).
The following is how I populated the 2D array when i press a button.
case IDC_SOLVE_BUTTON:
trysolve = 1;
solve2D.resize(inRowCount);
for (int i = 0; i < inRowCount; i++){
solve2D[i].resize(inColCount);
}
solve2D[0][3] = 1;
solve2D[1][3] = 1;
solve2D[1][4] = 1;
solve2D[1][5] = 1;
solve2D[2][5] = 1;
Now that I have values in some of the array indices, I know how to print them onto my window as shown below :
for (int rowId = 0; rowId < inRowCount; rowId++){
for (int colId = 0; colId < inColCount; colId++){
check = (colId*inColCount) + (rowId);
if (solve2D[rowId][colId] == 1){
solvecheck = (colId*inColCount) + (rowId);
startCol = colId * 10;
startRow = rowId * 10;
RECT cell = { startCol, startRow, startCol + dCol, startRow + dRow };
FillRect(hdc, &cell, tBrush);
}
}
Now important question is how do i exactly animate the printing ? Such that it will print one RECTANGLE, then print the subsequent RECTANGLE one second later. Any way i can set a timer and update the window at the printing segment of the code ??
Appreiciate some guidiance in this. Please help !
You can use the Sleep function to make the program wait for 1 second before continuing. As follows:
Sleep(1000);
Notice that the parameter is in milli-seconds, so you need 1000 to represent one second.
Place this function call in the suitable place of your code and you'll be done.

munmap_chunk() - Invalid pointer error

I'm writing a renderer using low-level SDL functions to learn how it all works. I am now trying to do polygon drawing, but I run into errors possibly due to my inexperience with C++. When running the code I get a munmap_chunk() - Invalid pointer error. Searching reveals that it is most likely due to free()-ing the memory twice. The error happens when returning from the function. I realize that the error comes from automatically free()ing memory which has been automatically free()d before, but I'm not experienced enough with C++ to spot the error. Any clues?
My code:
void DrawPolygon (const vector<vec3> & verts, vec3 color){
// 0. Project to the screen
vector<ivec2> vertices(verts.size());
for(int i = 0; i < verts.size(); i++){
VertexShader(verts.at(i), vertices.at(i));
}
// 1. Find max and min y-value of the polygon
// and compute the number of rows it occupies.
int miny = vertices[0].y;
int maxy = vertices[0].y;
for (int i = 1; i < 3; i++){
if (vertices[i].y < miny){
miny = vertices[i].y;
}
if (vertices[i].y > maxy){
maxy = vertices[i].y;
}
}
int rows = abs(maxy - miny) + 1;
// 2. Resize leftPixels and rightPixels
// so that they have an element for each row.
vector<ivec2> leftPixels(rows);
vector<ivec2> rightPixels(rows);
// 3. Initialize the x-coordinates in leftPixels
// to some really large value and the x-coordinates
// in rightPixels to some really small value.
for(int i = 0; i < rows; i++){
leftPixels[i].x = std::numeric_limits<int>::max();
rightPixels[i].x = std::numeric_limits<int>::min();
leftPixels[i].y = miny + i;
rightPixels[i].y = miny + i;
}
// 4. Loop through all edges of the polygon and use
// linear interpolation to find the x-coordinate for
// each row it occupies. Update the corresponding
// values in rightPixels and leftPixels.
for(int i = 0; i < 3; i++){
ivec2 a = vertices[i];
ivec2 b = vertices[(i+1)%3];
// find the number of pixels to draw
ivec2 delta = glm::abs(a - b);
int pixels = glm::max(delta.x, delta.y) + 1;
// interpolate to find the pixels
vector<ivec2> line (pixels);
Interpolate(a, b, line);
for(int j = 0; j < pixels; j++){
ivec2 p = line[j];
ivec2 cmpl = leftPixels[p.y - miny];
ivec2 cmpr = rightPixels[p.y - miny];
if(p.x < cmpl.x){
leftPixels[p.y - miny].x = p.x;
//leftPixels[p.y - miny] = cmpl;
}
if(p.x > cmpr.x){
rightPixels[p.y - miny].x = p.x;
//cmpr.x = p.x;
//rightPixels[p.y - miny] = cmpr;
}
}
}
for(int i = 0; i < leftPixels.size(); i++){
ivec2 l = leftPixels.at(i);
ivec2 r = rightPixels.at(i);
// y coord the same, iterate over x
int y = l.y;
for(int x = l.x; x <= r.x; x++){
PutPixelSDL(screen, x, y, color);
}
}
}
Using valgrind gives me this output (this is the first error it reports). Weirdly, the program recovers and keeps running with the expected result, apparently not getting the same error again:
==5706== Invalid write of size 4
==5706== at 0x40AD61: DrawPolygon(std::vector<glm::detail::tvec3<float>, std::allocator<glm::detail::tvec3<float> > > const&, glm::detail::tvec3<float>) (in /home/actimia/prog/dgi14/lab3/ThirdLab)
==5706== by 0x409C78: Draw() (in /home/actimia/prog/dgi14/lab3/ThirdLab)
==5706== by 0x409668: main (in /home/actimia/prog/dgi14/lab3/ThirdLab)
I think my previous post on similar topic would be useful.
https://stackoverflow.com/a/22658693/2724703
From your Valgrind report, it look like your program is doing memory corruption due to overflow. This does not seems like "double free" error(this is overflow scenario). You have mentioned that sometime valgrind is not reporting any error this makes this problem more difficult. However there is certainly a memory corruption and you must fix them. Memory error sometime occur intermittent due to various reason(different input parameter, multi-threaded, change of execution sequence).

C++ Heap Corruption: Local heap variable causing issues

I am working on some simple terrain with DirectX9 by manually assembling the verts for the ground.
On the part of my code where I set up the indices I get an error though:
Windows has triggered a breakpoint in test.exe.
This may be due to a corruption of the heap, which indicates a bug in test.exe or any of the DLLs it has loaded.
Here is the part of my code that is giving me problems, and I'm almost 100% sure that it is linked to my indices pointer, but I delete it when I'm finished... so I'm not sure what the problem is.
int total = widthQuads * heightQuads * 6;
DWORD *indices = new DWORD[totalIdx];
for (int y = 0; y < heightQuads; y++)
{
for (int x = 0; x < widthQuads; x++)
{ //Width of nine:
int lowerLeft = x + y * 9;
int lowerRight = (x + 1) + y * 9;
int topLeft = x + (y + 1) * 9;
int topRight = (x + 1) + (y + 1) * 9;
//First triangle:
indices[counter++] = topLeft;
indices[counter++] = lowerRight;
indices[counter++] = lowerLeft;
//Second triangle:
indices[counter++] = topLeft;
indices[counter++] = topRight;
indices[counter++] = lowerRight;
}
}
d3dDevice->CreateIndexBuffer(sizeof(DWORD)* total, 0, D3DFMT_INDEX16,
D3DPOOL_MANAGED, &groundindex, 0);
void* mem = 0;
groundindex->Lock(0, 0, &mem, 0);
memcpy(mem, indices, total * sizeof (DWORD));
groundindex->Unlock();
delete[] indices;
When I remove this block my program runs OK.
The code you've given looks OK - with one caveat: the initial value of counter is not in the code itself. So either you don't start at counter = 0, or some other piece of code is stomping on your indices buffer.
That's the beauty of heap corruptions. There is no guarantee that the bug is in the removed portion on the code. It may simply hide the bug that exists somewhere else in your code.
int total = widthQuads * heightQuads * 6;
DWORD *indices = new DWORD[totalIdx];
Shouldn't you be doing "new DWORD[total];" here?