How to draw a curved line using ccBezier? - cocos2d-iphone

I drew a line with -(void)draw method:
-(void)draw // code for line draw
{
glEnable(GL_LINE_SMOOTH);
CGPoint start;
start.x = 50;
start.y = 50;
CGPoint end;
end.x = 50;
end.y = 200;
if (pointOne.x>300){
pointOne.x = 300;
}
if (pointOne.y>200){
pointOne.y = 200;
}
ccDrawLine(start, pointOne);//get a line
[self Bezier:location.x:location.y:pointOne.x:pointOne.y];
}
and now I want to curve this line through Bezier in cocos2d. When I move finger that time line should draw the curve.
Bezier Code is:
- (void) Bezier:(NSInteger) CP_x:(NSInteger) CP_y:(NSInteger) end_x:(NSInteger) end_y
{
CGPoint start;
start.x = 50;
start.y = 50;
ccBezierConfig bezier;
bezier.controlPoint_1 = ccp(CP_x, CP_y);
bezier.controlPoint_2 = ccp(CP_x,CP_y);
bezier.endPosition = ccp(end_x,end_y);
}
How can I implement this line in bezier?

try this.
CCDrawBezier in last of your -(void)Bezier methord
ccDrawCubicBezier(StartPoint, controlPoint_1, controlPoint_2, EndPoint,NSInteger);

This is a method is wrote to my game.
//Bezier calculation on multiple points
//Can be set to any number of points
//The t parameter is the time 0 = start point -> 1 = end point.
//Made by Sebastian Winbladh
-(CGPoint)getBezerAtTime:(float)t array:(NSArray*)a{
int count = [a count];
float xPoints[count],yPoints[count];
int c=0;
//Makeup an array for our points
for(int i=0;i<count;i++){
CGPoint p = CGPointMake([[[a objectAtIndex:i] objectAtIndex:0] floatValue], [[[a objectAtIndex:i] objectAtIndex:1] floatValue]);
xPoints[i] = p.x;
yPoints[i] = p.y;
c++;
}
//Calculate our bezier curve here
while(c != 0){
for(int i=0;i<c-1;i++){
CGPoint p0 = CGPointMake(xPoints[i], yPoints[i]);
CGPoint p1 = CGPointMake(xPoints[i+1], yPoints[i+1]);
float dx = p1.x - p0.x;
float dy = p1.y - p0.y;
dx = p0.x + (dx * t);
dy = p0.y + (dy * t);
xPoints[i] = dx;
yPoints[i] = dy;
}c--;
}
return CGPointMake(xPoints[0], yPoints[0]);
}

Related

Use Kalman Filter to filt noise without delay opencv c++

My task is to detect an orange ball in video. I detected by thresholding image on HSV colorspace and bounding box. Then I have center and radius of ball, with unit is pixel.
When ball is static, I expect center and radius will be static too, but reality, it has noise. I use Kalman Filter to filter noise and it works well. But it delay in real-time. I try to optimize covariance parameters but not work.
So could anyone help me static center and radius when ball is static and without delay?
Are you sure it is the Kalman Filter witch is causing the delay.
Otherwise you can try this lazy filter witch only is noise rejecting but blazingly fast. My suspicion however it is the HSV conversion.
class noiseFilter
{
private:
cv::Point2f ptLast;
float ptMaxTol;
public:
noiseFilter(float maxTol = 1.5f)
{
ptMaxTol = maxTol * maxTol; // we do the pow(2) here so we don't have to do a square root on every update
ptLast = cv::Point2f(0.0f, 0.0f);
}
cv::Point2f update(cv::Point2f &ptNew) // update filter with new found point
{
float dist = pDistance2(ptLast, ptNew);
if (dist > ptMaxTol) ptLast = ptNew; // update only if distance is more than threshold
return ptLast;
}
cv::Point2f getResult() // get result of filter
{
return ptLast;
}
private:
// calculate distance between 2 point without doing a sqrt
float pDistance2(cv::Point2f &p1, cv::Point2f &p2)
{
float dx = p1.x - p2.x;
float dy = p1.y - p2.y;
return (dx * dx + dy * dy);
}
};
int main()
{
cv::Point2f pt;
noiseFilter filter(2.1f); // initialize filter wit max 2.1 pixels noise rejection.
int x = 100, y = 120;
for (int i = 0; i < 100; i++)
{
// generate some noise with 2 pixels variation
pt.x = ((rand() % 200) - 100) * 0.01f + x;
pt.y = ((rand() % 200) - 100) * 0.01f + y;
cv::Point2f pts = filter.update(pt);
printf("input x=%6.2f y=%6.2f output x=%6.2f y=%6.2f\r\n", pt.x, pt.y, pts.x, pts.y);
// do som random big update on random intervals
if ((rand() % 50) == 1) {
x += 15;
printf("big update on X\r\n");
}
if ((rand() % 50) == 1){
y += 25;
printf("big update on Y\r\n");
}
}
return 0;
}
Below a noise filter with smoothing.
Works on slow and fast moving objects.
class noiseFilterSmooth
{
private:
static const int maxHist = 10;
cv::Point2f ptLast;
float ptMaxTol;
cv::Point2f hist[maxHist];
int histHead,histSize;
public:
noiseFilterSmooth(float maxTol = 1.5f)
{
histHead = histSize = 0;
ptMaxTol = maxTol * maxTol; // we do the pow(2) here so we don't have to do a square root on every update
ptLast = cv::Point2f(0.0f, 0.0f);
}
cv::Point2f& update(cv::Point2f &ptNew) // update filter with new found point
{
float dist = pDistance2(ptLast, ptNew);
if (dist > ptMaxTol) histSize = histHead = 0; // reset smoothing filter if distance is more than threshold
// update smoothing filter with last result
hist[histHead] = ptNew; // update smoothing filter with last
histHead = (histHead + 1) % maxHist;
if (histSize < maxHist) histSize++;
return getResult();
}
cv::Point2f& getResult() // get result of filter
{
float sumx = 0, sumy = 0;
for (int i = 0; i < histSize; i++)
{
sumx += hist[i].x;
sumy += hist[i].y;
}
ptLast.x = sumx / histSize;
ptLast.y = sumy / histSize;
return ptLast;
}
private:
// calculate distance between 2 point without doing a sqrt
float pDistance2(cv::Point2f &p1, cv::Point2f &p2)
{
float dx = p1.x - p2.x;
float dy = p1.y - p2.y;
return (dx * dx + dy * dy);
}
};

Calculating velocity using consistent speed in basic C++ engine

What I'm trying to achieve is a sprite moving to another sprite in a 2D environment. I started with the basic Mx = Ax - Bx deal. But I noticed that the closer to the target the sprite gets, the more it slows down. So I tried to create a percentage/ratio based on the velocity then each x and y gets their percent of a speed allowance, however, it's acting very strangely and only seems to work if Mx and My are positive
Here's the code extract:
ballX = ball->GetX();
ballY = ball->GetY();
targX = target->GetX();
targY = target->GetY();
ballVx = (targX - ballX);
ballVy = (targY - ballY);
percentComp = (100 / (ballVx + ballVy));
ballVx = (ballVx * percentComp)/10000;
ballVy = (ballVy * percentComp)/10000;
The /10000 is to slow the sprites movement
Assuming you want the sprite to move at a constant speed, you can do a linear fade on both the X and Y position, like this:
#include <stdio.h>
int main(int, char **)
{
float startX = 10.0f, startY = 20.0f;
float endX = 35.0f, endY = -2.5f;
int numSteps = 20;
for (int i=0; i<numSteps; i++)
{
float percentDone = ((float)i)/(numSteps-1);
float curX = (startX*(1.0f-percentDone)) + (endX*percentDone);
float curY = (startY*(1.0f-percentDone)) + (endY*percentDone);
printf("Step %i: percentDone=%f curX=%f curY=%f\n", i, percentDone, curX, curY);
}
return 0;
}
Thanks for the responses, I got it working now but normalising the vectors instead of the whole percent thing, here's what I have now:
ballX = ball->GetX();
ballY = ball->GetY();
targX = target->GetX();
targY = target->GetY();
ballVx = (targX - ballX);
ballVy = (targY - ballY);
vectLength = sqrt((ballVx*ballVx) + (ballVy*ballVy));
ballVx = (ballVx / vectLength)/10;
ballVy = (ballVy / vectLength)/10;

Sprite Orientation Cocos2d 3.0

The sprite should be moving from north to south when the screens orientation is portrait.
Yet the sprite is going from east to west in portrait mode. When the screens orientation is landscape the sprite moves from east to west and i'm very confused about this. I'm trying to make the sprite move from up to down.
Code controlling the sprite
- (void)addMonster:(CCTime)dt
{
monster = [CCSprite spriteWithImageNamed:#"MarioTube_Body_Rev.png"];
int minY = monster.contentSize.height / 2;
int maxY = self.contentSize.height - monster.contentSize.height / 2;
int rangeY = maxY - minY;
int randomY = (arc4random() % rangeY) + minY;
monster.position = CGPointMake(self.contentSize.width + monster.contentSize.width/2, randomY);
[self addChild:monster];
int minDuration = 2.0;
int maxDuration = 4.0;
int rangeDuration = maxDuration - minDuration;
int randomDuration = (arc4random() % rangeDuration) + minDuration;
CCAction *actionMove = [CCActionMoveTo actionWithDuration:randomDuration position:CGPointMake(-monster.contentSize.width/2, randomY)];
CCAction *actionRemove = [CCActionRemove action];
[monster runAction:[CCActionSequence actionWithArray:#[actionMove,actionRemove]]];
}
So after player around with it i figured out it was simply changing some of the "heights" and widths around
- (void)addMonster:(CCTime)dt
{
monster = [CCSprite spriteWithImageNamed:#"MarioTube_Body_Rev.png"];
int minX = monster.contentSize.height/2 - monster.contentSize.height/2;
int maxX = self.contentSize.height;
int rangeX = maxX - minX;
int randomX = (arc4random() % rangeX) + minX;
monster.position = CGPointMake(randomX, self.contentSize.height + monster.contentSize.height/2);
[self addChild:monster];
int minDuration = 2.0;
int maxDuration = 4.0;
int rangeDuration = maxDuration - minDuration;
int randomDuration = (arc4random() % rangeDuration) + minDuration;
CCAction *actionMove = [CCActionMoveTo actionWithDuration:randomDuration position:CGPointMake(randomX, -monster.contentSize.height/100)];
CCAction *actionRemove = [CCActionRemove action];
[monster runAction:[CCActionSequence actionWithArray:#[actionMove,actionRemove]]];
}

Cocos2d Accelerometer Landscape

Im having trouble getting the accelerometer to work correctly in landscape mode with cocos2d. Everything works perfectly in portrait, but cant figure out how to flip it to correctly work in landscape. here is my code:
-(void) accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
float deceleration = 0.0f;
float sensativity = 15.0f;
float maxVelocity = 100;
playerVelocity.x = playerVelocity.x * deceleration + acceleration.x * sensativity;
playerVelocity.y = playerVelocity.y * deceleration + acceleration.y * sensativity;
if (playerVelocity.x > maxVelocity)
{
playerVelocity.x = maxVelocity;
}
else if (playerVelocity.x < - maxVelocity)
{
playerVelocity.x = - maxVelocity;
}
if (playerVelocity.y > maxVelocity)
{
playerVelocity.y = maxVelocity;
}
else if (playerVelocity.y < - maxVelocity)
{
playerVelocity.y = - maxVelocity;
}
}
-(void) update:(ccTime) delta
{
CGPoint pos = player.position;
pos.x += playerVelocity.x;
pos.y += playerVelocity.y;
CGSize screeSize = [[CCDirector sharedDirector]winSize];
float imageHalf = [player texture].contentSize.width * 0.5f;
float leftLimit = imageHalf;
float rightLimit = screeSize.width - imageHalf -20;
float bottomLimit = imageHalf;
float topLimit = screeSize.height - imageHalf - 20;
if (pos.y < bottomLimit) {
pos.y = bottomLimit;
}
else if (pos.y > topLimit){
pos.y = topLimit;
}
if (pos.x < leftLimit) {
pos.x = leftLimit;
}
else if (pos.x > rightLimit){
pos.x = rightLimit;
}
player.position = pos;
}
In landscape orientation, the accelerometer x and y values are flipped. Furthermore, in interface orientation landscape right, x is negative. In landscape left, y is negative:
// landscape right:
position.x = -acceleration.y
position.y = acceleration.x
// landscape left:
position.x = acceleration.y
position.y = -acceleration.x
Look at answer in this question
Best way for accelerometer usage in cocos2d game.

3D picking lwjgl

I have written some code to preform 3D picking that for some reason dosn't work entirely correct! (Im using LWJGL just so you know.)
This is how the code looks like:
if(Mouse.getEventButton() == 1) {
if (!Mouse.getEventButtonState()) {
Camera.get().generateViewMatrix();
float screenSpaceX = ((Mouse.getX()/800f/2f)-1.0f)*Camera.get().getAspectRatio();
float screenSpaceY = 1.0f-(2*((600-Mouse.getY())/600f));
float displacementRate = (float)Math.tan(Camera.get().getFovy()/2);
screenSpaceX *= displacementRate;
screenSpaceY *= displacementRate;
Vector4f cameraSpaceNear = new Vector4f((float) (screenSpaceX * Camera.get().getNear()), (float) (screenSpaceY * Camera.get().getNear()), (float) (-Camera.get().getNear()), 1);
Vector4f cameraSpaceFar = new Vector4f((float) (screenSpaceX * Camera.get().getFar()), (float) (screenSpaceY * Camera.get().getFar()), (float) (-Camera.get().getFar()), 1);
Matrix4f tmpView = new Matrix4f();
Camera.get().getViewMatrix().transpose(tmpView);
Matrix4f invertedViewMatrix = (Matrix4f)tmpView.invert();
Vector4f worldSpaceNear = new Vector4f();
Matrix4f.transform(invertedViewMatrix, cameraSpaceNear, worldSpaceNear);
Vector4f worldSpaceFar = new Vector4f();
Matrix4f.transform(invertedViewMatrix, cameraSpaceFar, worldSpaceFar);
Vector3f rayPosition = new Vector3f(worldSpaceNear.x, worldSpaceNear.y, worldSpaceNear.z);
Vector3f rayDirection = new Vector3f(worldSpaceFar.x - worldSpaceNear.x, worldSpaceFar.y - worldSpaceNear.y, worldSpaceFar.z - worldSpaceNear.z);
rayDirection.normalise();
Ray clickRay = new Ray(rayPosition, rayDirection);
Vector tMin = new Vector(), tMax = new Vector(), tempPoint;
float largestEnteringValue, smallestExitingValue, temp, closestEnteringValue = Camera.get().getFar()+0.1f;
Drawable closestDrawableHit = null;
for(Drawable d : this.worldModel.getDrawableThings()) {
// Calcualte AABB for each object... needs to be moved later...
firstVertex = true;
for(Surface surface : d.getSurfaces()) {
for(Vertex v : surface.getVertices()) {
worldPosition.x = (v.x+d.getPosition().x)*d.getScale().x;
worldPosition.y = (v.y+d.getPosition().y)*d.getScale().y;
worldPosition.z = (v.z+d.getPosition().z)*d.getScale().z;
worldPosition = worldPosition.rotate(d.getRotation());
if (firstVertex) {
maxX = worldPosition.x; maxY = worldPosition.y; maxZ = worldPosition.z;
minX = worldPosition.x; minY = worldPosition.y; minZ = worldPosition.z;
firstVertex = false;
} else {
if (worldPosition.x > maxX) {
maxX = worldPosition.x;
}
if (worldPosition.x < minX) {
minX = worldPosition.x;
}
if (worldPosition.y > maxY) {
maxY = worldPosition.y;
}
if (worldPosition.y < minY) {
minY = worldPosition.y;
}
if (worldPosition.z > maxZ) {
maxZ = worldPosition.z;
}
if (worldPosition.z < minZ) {
minZ = worldPosition.z;
}
}
}
}
// ray/slabs intersection test...
// clickRay.getOrigin().x + clickRay.getDirection().x * f = minX
// clickRay.getOrigin().x - minX = -clickRay.getDirection().x * f
// clickRay.getOrigin().x/-clickRay.getDirection().x - minX/-clickRay.getDirection().x = f
// -clickRay.getOrigin().x/clickRay.getDirection().x + minX/clickRay.getDirection().x = f
largestEnteringValue = -clickRay.getOrigin().x/clickRay.getDirection().x + minX/clickRay.getDirection().x;
temp = -clickRay.getOrigin().y/clickRay.getDirection().y + minY/clickRay.getDirection().y;
if(largestEnteringValue < temp) {
largestEnteringValue = temp;
}
temp = -clickRay.getOrigin().z/clickRay.getDirection().z + minZ/clickRay.getDirection().z;
if(largestEnteringValue < temp) {
largestEnteringValue = temp;
}
smallestExitingValue = -clickRay.getOrigin().x/clickRay.getDirection().x + maxX/clickRay.getDirection().x;
temp = -clickRay.getOrigin().y/clickRay.getDirection().y + maxY/clickRay.getDirection().y;
if(smallestExitingValue > temp) {
smallestExitingValue = temp;
}
temp = -clickRay.getOrigin().z/clickRay.getDirection().z + maxZ/clickRay.getDirection().z;
if(smallestExitingValue < temp) {
smallestExitingValue = temp;
}
if(largestEnteringValue > smallestExitingValue) {
//System.out.println("Miss!");
} else {
if (largestEnteringValue < closestEnteringValue) {
closestEnteringValue = largestEnteringValue;
closestDrawableHit = d;
}
}
}
if(closestDrawableHit != null) {
System.out.println("Hit at: (" + clickRay.setDistance(closestEnteringValue).x + ", " + clickRay.getCurrentPosition().y + ", " + clickRay.getCurrentPosition().z);
this.worldModel.removeDrawableThing(closestDrawableHit);
}
}
}
I just don't understand what's wrong, the ray are shooting and i do hit stuff that gets removed but the result of the ray are verry strange it sometimes removes the thing im clicking at, sometimes it removes things thats not even close to what im clicking at, and sometimes it removes nothing at all.
Edit:
Okay so i have continued searching for errors and by debugging the ray (by painting smal dots where it travles) i can now se that there is something oviously wrong with the ray that im sending out... it has its origin near the world center and always shots to the same position no matter where i direct my camera...
My initial toughts is that there might be some error in the way i calculate my viewMatrix (since it's not possible to get the viewmatrix from the glulookat method in lwjgl; I have to build it my self and I guess thats where the problem is at)...
Edit2:
This is how i calculate it currently:
private double[][] viewMatrixDouble = {{0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,1}};
public Vector getCameraDirectionVector() {
Vector actualEye = this.getActualEyePosition();
return new Vector(lookAt.x-actualEye.x, lookAt.y-actualEye.y, lookAt.z-actualEye.z);
}
public Vector getActualEyePosition() {
return eye.rotate(this.getRotation());
}
public void generateViewMatrix() {
Vector cameraDirectionVector = getCameraDirectionVector().normalize();
Vector side = Vector.cross(cameraDirectionVector, this.upVector).normalize();
Vector up = Vector.cross(side, cameraDirectionVector);
viewMatrixDouble[0][0] = side.x; viewMatrixDouble[0][1] = up.x; viewMatrixDouble[0][2] = -cameraDirectionVector.x;
viewMatrixDouble[1][0] = side.y; viewMatrixDouble[1][1] = up.y; viewMatrixDouble[1][2] = -cameraDirectionVector.y;
viewMatrixDouble[2][0] = side.z; viewMatrixDouble[2][1] = up.z; viewMatrixDouble[2][2] = -cameraDirectionVector.z;
/*
Vector actualEyePosition = this.getActualEyePosition();
Vector zaxis = new Vector(this.lookAt.x - actualEyePosition.x, this.lookAt.y - actualEyePosition.y, this.lookAt.z - actualEyePosition.z).normalize();
Vector xaxis = Vector.cross(upVector, zaxis).normalize();
Vector yaxis = Vector.cross(zaxis, xaxis);
viewMatrixDouble[0][0] = xaxis.x; viewMatrixDouble[0][1] = yaxis.x; viewMatrixDouble[0][2] = zaxis.x;
viewMatrixDouble[1][0] = xaxis.y; viewMatrixDouble[1][1] = yaxis.y; viewMatrixDouble[1][2] = zaxis.y;
viewMatrixDouble[2][0] = xaxis.z; viewMatrixDouble[2][1] = yaxis.z; viewMatrixDouble[2][2] = zaxis.z;
viewMatrixDouble[3][0] = -Vector.dot(xaxis, actualEyePosition); viewMatrixDouble[3][1] =-Vector.dot(yaxis, actualEyePosition); viewMatrixDouble[3][2] = -Vector.dot(zaxis, actualEyePosition);
*/
viewMatrix = new Matrix4f();
viewMatrix.load(getViewMatrixAsFloatBuffer());
}
Would be verry greatfull if anyone could verify if this is wrong or right, and if it's wrong; supply me with the right way of doing it...
I have read alot of threads and documentations about this but i can't seam to wrapp my head around it...
I just don't understand what's wrong, the ray are shooting and i do hit stuff that gets removed but things are not disappearing where i press on the screen.
OpenGL is not a scene graph, it's a drawing library. So after removing something from your internal representation you must redraw the scene. And your code is missing some call to a function that triggers a redraw.
Okay so i finaly solved it with the help from the guys at gamedev and a friend, here is a link to the answer where i have posted the code!