A ball inside a sphere using Bullet - android

I'm new at Bullet and all 3D and phisycs stuffs, so don't be angry :)
I neen to create a big static rigid sphere and a little dynamic one inside. I want to use the big one like a bottle, so little sphere can move inside, but cann't leave the sphere, exept one plase on the top.
I have written 2 models in Blender (of course i've made a hole in big sphere), created a world and placed objects inside. But when i start the application, the little sphere just throw out of the big one with extreme speed.
Also I'm using Bullet with GDX library for Android, if it helps.
This code initializes the world.
public final btCollisionConfiguration collisionConfiguration;
public final btCollisionDispatcher dispatcher;
public final btBroadphaseInterface broadphase;
public final btConstraintSolver solver;
public final btCollisionWorld collisionWorld;
public PerformanceCounter performanceCounter;
public final Vector3 gravity;
public int maxSubSteps = 5;
public World() {
Vector3 gravity = new Vector3(0, -10, 0);
collisionConfiguration = new btDefaultCollisionConfiguration();
dispatcher = new btCollisionDispatcher(collisionConfiguration);
broadphase = new btDbvtBroadphase();
solver = new btSequentialImpulseConstraintSolver();
collisionWorld = new btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);
((btDynamicsWorld)collisionWorld).setGravity(gravity);
this.gravity = gravity;
}
And some code for creating a big sphere
final StillModel sphereS = ModelLoaderRegistry.loadStillModel(Gdx.files.internal("data/Ssphere.obj"));
sphereS.subMeshes[0].getMesh().scale(3f, 3f, 3f);
final BoundingBox sphereSBounds = new BoundingBox();
sphereS.getBoundingBox(sphereSBounds);
final Constructor sphereSConstructor = new Constructor(sphereS, 0f, new btSphereShape(sphereSBounds.getDimensions().x));
sphereSConstructor.bodyInfo.setM_restitution(1f);
world.addConstructor("sphereS", sphereSConstructor);
Code for a little sphere
final StillModel sphereModel = ModelLoaderRegistry.loadStillModel(Gdx.files.internal("data/sphere.obj"));
sphereModel.subMeshes[0].getMesh().scale(0.8f, 0.8f, 0.8f);
final BoundingBox sphereBounds = new BoundingBox();
sphereModel.getBoundingBox(sphereBounds);
final Constructor sphereConstructor = new Constructor(sphereModel, 0.25f, new btSphereShape(sphereBounds.getDimensions().x * 0.5f));
sphereConstructor.bodyInfo.setM_restitution(1f);
world.addConstructor("sphere", sphereConstructor);
Constructor class just creates btRigidBodyConstructionInfo and btCollisionShape objects, constructs spheres and place there in the world.
So, could you tell me how can i create an empty sphere with a ball inside?
P.S. Please, don't tell me to google, i've already done it
P.P.S Sorry for my english

Since your big sphere is not convex, you should not be using btSphereShape for it.
You could try btBvhTriangleMeshShape, or some of the other non-convex shapes.
It is a bit more complicated to construct, but looking at some examples might provide ideas. Anyway, there is no simple way to get what you want, because it is not even a regular empty sphere (I think the libgdx framework you are using only takes your sphereS model for rendering).

Model sphere = modelBuilder.createSphere(-100f, 100f, 100f, 20, 20, new Material(ColorAttribute.createDiffuse(Color.BLUE)),
VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal);
ModelInstance instance = new ModelInstance(sphere);
btBvhTriangleMeshShape sphereShape = new btBvhTriangleMeshShape(instance.model.meshParts);
btRigidBody.btRigidBodyConstructionInfo constructionInfo = new btRigidBody.btRigidBodyConstructionInfo(0, null, sphereShape, new Vector3(0,0,0));
btRigidBody body = new btRigidBody(constructionInfo);
body.setCollisionFlags(body.getCollisionFlags()| btCollisionObject.CollisionFlags.CF_STATIC_OBJECT);
dynamicsWorld.addRigidBody(body);
it works

Related

How can i improve openCV people detecting algorithm

I am trying to write human detector, it works now, but sometimes it reacts on cats/boxes etc., also i got like 5 fps. So the question is, how can i improve my algorithm for better fps and detection accuracy.
I have tried to use this one:
http://www.pyimagesearch.com/2015/11/09/pedestrian-detection-opencv/
But i couldnt find any way i could use this on android.
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
List<MatOfPoint> list = new ArrayList<>();
Mat frame = new Mat();
Mat gray = new Mat();
Mat hierarchy = new Mat();
Mat originalFrame = inputFrame.rgba();
Imgproc.medianBlur(originalFrame,originalFrame,3);
Imgproc.cvtColor(originalFrame, gray, Imgproc.COLOR_RGB2GRAY, 0);
HOGDescriptor hog = new HOGDescriptor();
//Получаем стандартный определитель людей и устанавливаем его нашему дескриптору
MatOfFloat descriptors = HOGDescriptor.getDefaultPeopleDetector();
hog.setSVMDetector(descriptors);
MatOfRect locations = new MatOfRect();
MatOfDouble weights = new MatOfDouble();
hog.detectMultiScale(gray, locations, weights);
Point rectPoint1 = new Point();
Point rectPoint2 = new Point();
Point fontPoint = new Point();
if (locations.rows() > 0) {
List<Rect> rectangles = locations.toList();
for (Rect rect : rectangles) {
rectPoint1.x = rect.x;
rectPoint1.y = rect.y;
fontPoint.x = rect.x;
fontPoint.y = rect.y - 4;
rectPoint2.x = rect.x + rect.width;
rectPoint2.y = rect.y + rect.height;
final Scalar rectColor = new Scalar( 0 , 0 , 0 );
// Добавляем на изображения найденную информацию
Imgproc.rectangle(originalFrame, rectPoint1, rectPoint2, rectColor, 2);
}
}
frame.release();
gray.release();
hierarchy.release();
list.clear();
return originalFrame;
}
You're using the HOG+SVM approach to detect people; it is inherently going to be quite slow. Never the less, you can use some of the suggestions in this question How to speed up svm.predict?
Depending on your problem, i.e. if the camera is static and the pedestrians are moving you could opt for a background subtraction approach this is probably the most efficient way but bear in mind that this will pick up any objects that are moving in the scene, so you could include thresholds to remove small objects. Some background subtraction algorithms include mixture of gaussian (MOG) or MOG2 or GMG. Also, an important thing to note is that these approaches rely on creating a background model of the scene, i.e. they assume static pixels over time to be part of the background, hence, when a pedestrian stands still for a while in the scene they get embedded into the background resulting in miss detection. There are many papers out there that provide potential solutions to that problem so you might want to have a look at them, here is one that produces decent results: Static and Moving Object Detection Using Flux Tensor with Split Gaussian Models
Additionally, you could opt for a data driven approach, either get a good pre-trained model and do your detection using that or train one yourself using TensorFlow, Caffe or Torch and use the dnn opencv_contrib module to do the detection.

How can I Create A Reticle in center view using RajawaliVR

How can I create a reticle using the Cardboard SDK for Android Studio and RajawaliVR 3D Renderer?
I search through out many websites and the Rajawali wiki on github to try and find a solution that would keep a 3D object in the center of the users view with perfect orientation. I did stumble upon a link on the WIKI but it did not offer a solution that worked with RajawaliVR.
After some trial and error I came up with this solution
First create a 3D Object in the renderer
Sphere RETICLE = new Sphere(1, 50, 32);
Material sphereMaterial = new Material();
sphereMaterial.enableLighting(true);
sphereMaterial.setDiffuseMethod(new DiffuseMethod.Lambert());
RETICLE.setMaterial(sphereMaterial);
try{
sphereMaterial.addTexture(tExture);
} catch (ATexture.TextureException error){
Log.d("DEBUG", "TEXTURE ERROR");
}
Next you will need the following code placed in your renderer class
public void centerObject(Object3D obj){
float[] newPosition4 = new float[4];
float[] posVec4 = {0, 0, -3, 1.0f};
float[] HeadViewMatrix_inv = new float[16];
Matrix4 HeadViewMatrix4 = new Matrix4();
HeadViewMatrix4.setAll(mHeadViewMatrix);
HeadViewMatrix4 = HeadViewMatrix4.inverse();
HeadViewMatrix4.toFloatArray(HeadViewMatrix_inv);
Matrix.multiplyMV(newPosition4, 0, HeadViewMatrix_inv, 0, posVec4, 0);
obj.setPosition(newPosition4[0], newPosition4[1], newPosition4[2]);
obj.setLookAt(getCurrentCamera().getPosition());
}
You can then call the centerObject method from the onRender method or fram a handler. (The on render method gets called everytime a new frame is drawn.)
#Override
public void onRender(long elapsedTime, double deltaTime) {
super.onRender(elapsedTime, deltaTime);
if(RETICLE != null)centerObject(RETICLE);
}
Placing a null check before calling centerObject() is important because the scene may render before the object is created.
Rajawali WIKI Link
The Rajawali WIKI link above offered some great clues but the issue has been closed. I did comment there as well with my solution as to help provide a turn key solution for the next person facing the same problem.
I hope the helps some people. Please post better, Improved or other solutions so others may benefit.

Box2D(LibGDX) - strange behaviour of ball

I am trying to create simple tennis game. Each side has a wall. There are also a box and a ball. My environment doesn't have gravity. The box and the ball don't have any velocity. When the box contacts the ball(I move this by mouse with different speed), it(the ball) just changes its position and doesn't continue moving and sometimes these objects don't collide with each other:
I want the box can strike the ball using different angle and strength.
How can I do this? What should I change in the properties of the ball and the box?
The code snippet is below:
public void createBall(Vector2 position, Vector2 velocity, float angle, Object userData){
// First we create a body definition
BodyDef bodyDef = new BodyDef();
// We set our body to dynamic, for something like ground which doesnt move we would set it to StaticBody
bodyDef.type = BodyType.DynamicBody;
// Set our body's starting position in the world
bodyDef.position.set(position);
// Create our body in the world using our body definition
Body body = world.createBody(bodyDef);
body.setUserData(userData);
// Create a circle shape and set its radius to 6
CircleShape circle = new CircleShape();
circle.setRadius(10f);
PolygonShape poly = new PolygonShape();
poly.setAsBox(12, 12);
// Create a fixture definition to apply our shape to
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = circle;
fixtureDef.density = 0.0f;
fixtureDef.friction = 0.2f;
fixtureDef.restitution = 1f; // Make it bounce a little bit
fixtureDef.isSensor=false;
// Create our fixture and attach it to the body
Fixture f = body.createFixture(fixtureDef);
f.setUserData("ball");
circle.dispose();
}
private Body createBox(World world, float width, float height, float density) {
BodyDef def = new BodyDef();
def.type = BodyType.KinematicBody;
Body box = world.createBody(def);
PolygonShape poly = new PolygonShape();
poly.setAsBox(width/2, height/2);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = poly;
fixtureDef.density = 0.0f;
fixtureDef.friction = 0.3f;
fixtureDef.restitution = 0.1f; // Make it bounce a little bit
fixtureDef.isSensor=false;
// Create our fixture and attach it to the body
Fixture f = box.createFixture(fixtureDef);
f.setUserData("platform");
poly.dispose();
return box;
}
public void createWall(World world, Vector2 position, float hx, float hy){
// Create our body definition
BodyDef groundBodyDef =new BodyDef();
// Set its world position
groundBodyDef.position.set(position);
groundBodyDef.type=BodyType.StaticBody;
// Create a body from the defintion and add it to the world
Body groundBody = world.createBody(groundBodyDef);
// Create a polygon shape
PolygonShape groundBox = new PolygonShape();
// Set the polygon shape as a box which is twice the size of our view port and 20 high
// (setAsBox takes half-width and half-height as arguments)
groundBox.setAsBox(hx, hy);
// Create a fixture from our polygon shape and add it to our ground body
groundBody.createFixture(groundBox, 0.0f);
// Clean up after ourselves
groundBox.dispose();
}
You are moving your box by changing its position. But an important part of collision resolution is velocity. And your box's velocity is always zero (from box2d look point). Thus you experience strange collision resolution
I think your screen width and height are too large... if that's the case try using world width and height ... 20x12 units.. not 800x480 something .
Box2D doesn't like bodies, which fixtures has density 0. Usual, simulation performs somehow, but behaviour is not correct. Try value 0.3 for example.
Overlap problem may be solved by setting flag b2BodyDef::bullet. There description from Box2D reference:
bool b2BodyDef::bullet
Is this a fast moving body that should be prevented from tunneling through other moving bodies? Note that all bodies are prevented from tunneling through kinematic and static bodies. This setting is only considered on dynamic bodies.
Warning:
You should use this flag sparingly since it increases processing time.

TiledSprite not working as expected

I can't seem to get TiledSprite to work as I expect. There are no manuals, and the examples in AndEngineExamples is of no help.
Consider this code:
#Override
public void onLoadResources() {
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");
mBlockAtlas = new BitmapTextureAtlas(512, 512, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
mBlockTexture = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mBlockAtlas, getApplicationContext(), "num_plasma.png", 0, 0, 3, 3);
getTextureManager().loadTexture(mBlockAtlas);
}
This loads a 512x512 texture that I've - manually - divided into 3x3 tiles just for testing purposes. Now, doing this:
public Scene onLoadScene() {
mScene = new Scene();
mScene.setBackground(new ColorBackground(0.5f, 0.1f, 0.6f));
TiledSprite foo, foo2;
foo = new TiledSprite(0, 0, mBlockTexture);
foo.setCurrentTileIndex(1);
foo2 = new TiledSprite(0, 200, mBlockTexture);
foo2.setCurrentTileIndex(5);
mScene.attachChild(foo);
mScene.attachChild(foo2);
return mScene;
}
This puts up two sprites on the screen (as expected), but they both shows the same tile (5)!
How are one supposed to do if you have a bunch of sprites using the same texture but showing different tiles?
I think you need to deepCopy() the Texture when you are creating the Sprites, like
foo2 = new TiledSprite(0, 200, mBlockTexture.deepCopy());

Integer Array Handling

I have a 2D game that uses two integer arrays to track x and y coordinates as shown below:
private int gridX[] = { 0,0,0,0,0 }
private int gridY[] = { 0,0,0,0,0 }
The problem is I can have a LOT of objects on the screen that needs to be tracked. Is there a way to add integers / create new blocks as needed? IE in a loop, do something like
gridX[].add(); or something like that. I'm relatively new to java and droid development and I'm having trouble finding a good tutorial or example that shows how to do this without having to initialize the gridX and gridY to sizes of 100 or so.
This is important, as I am about 90% sure that all those unused 0's are causing androids garbage cleanup to lag my application.
Why dont you use an array list instead of an Integer array?
that way you can dynamically add items to the list
ArrayList<Integer> myList = new ArrayList<Integer>();
myList.add(1);
myList.add(2);
Why not also use the Point class?
List<Point> points = new ArrayList<Point>();
points.add(new Point(0, 0));
points.add(new Point(50, 70));
Point point = points.get(1);
Log.d("MyApp", String.format("The point is: (%d, %d)", point.x, point.y);
This way you are keeping track of your x and y coordinates together and there is less opportunity for error.

Categories

Resources