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.
Related
When I draw more around 100-200 textures all in the same screen, the device becomes very slow and the app crashes without any exceptions. Could you please let me know any best way to have 100 textures without compromising the performance.
I am using the TextureRegion from TextureAtlas.
MainGame
public void render(SpriteBatch sb) {
// TODO Auto-generated method stub
// System.out.println("BallPoolGame Screen - render");
batch = sb;
sb.setProjectionMatrix(camera.combined);
sb.begin();
sb.draw(BACKGROUND_BALL_POOL, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
cellManager.draw(sb);
ballManager.draw(sb);
sb.end();
}
private void setGameTextures() {
gameScreenAtlas = new TextureAtlas("data/texturetutorialpack.pack");
RED_BALL = gameScreenAtlas.findRegion("redball");
// RED_BALL.getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);
BLUE_BALL = gameScreenAtlas.findRegion("blueball");
// BLUE_BALL.getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);
GREEN_BALL = gameScreenAtlas.findRegion("greenball");
// GREEN_BALL.getTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear);
}
CellManager
public void draw(SpriteBatch sb){
batch=sb;
showImageTexture(MODEL1,207,1);
if(showSelectedCell){
if(allPossiblePathSize>0)
setupBoardCellTexture();
showImage(CELL_SELECTED, rowCoordinate[cellRow], colCoordinate[cellCol]);
}
}
private void setupBoardCellTexture(){
for(CellGrid c : masterGrid){
if(cellTextureIndicator[c.getRow()][c.getCol()]==1){
showImage(CELL_ALL_PATH_TEXTURE,c.getRowCoordinate() ,c.getColCoordinate() );
}
}
}
private void showImage(TextureRegion tr, float rowCoordinate, float colCoordinate) {
batch.draw(tr, colCoordinate,rowCoordinate);
}
BallManager
public void draw(SpriteBatch sb) {
batch = sb;
setupBoardBallTexture();
if (moveTheBall) {
updateBallPosition();
showImage(ball.getTextureRegion(), moveRow + 6, moveCol + 6);
}
squeezeBalls.draw(sb);
}
You are missing some essential data about your app to answer than question:
How big is one texture on average (Size: widthxheight)
On which device is this error occuring (some devices might have less fillrate than others)
What texture filter does the TextureAtlas use (LINEAR, NEAREST, ...)
I guess that you are trying to draw many textures event if they are out of sight. If that is the case you have to implement a check if the cell is visible to the camera.
Another guess would be that you are trying to draw too many elements with the LINEAR TextureFilter. When using linear as a texture filter the gpu needs to sample way more points then with nearest (i think it was 4 times the samples; so in theory your gpu draws 400-800 textures; depending on images size that are too much for mobile gpu fillrates)
Try to describe more circumstances then i can give probably more insight in your problem.
I am creating an app using AndEngine for the first time. My app is animation-oriented i.e. it has a number of images which on click animate. Most of these animations are frame by frame animations. I am using AndEngine because I require some animations with particle system, gravity and other stuff. Can someone help me with a simple onclick animation code in AndEngine or maybe point me to some good tutorial since all AndEngine tutorials are game tutorials that do not have frame by frame animation. Any help would be appreciated.
Before starting: note that this answer is using the TexturePacker extension for AndEngine.
For my frame by frame animations I am using a program called Texture Packer, which is supported by AndEngine. You actually just drag all your images to there, and it exports 3 files you need to use inside your project. The file are: .xml , .java , .png
By doing that i'm creating a big bitmap (try to stay below or equal to 2048x2048) with all the frames inside of it.
After assuming you have those files created, you need to copy them to your project. the .png and .xml go into the same directory, most likely under assets/gfx/ ... and the .java file should be located in the src directory with the rest of your classes.
Now lets check out some code..
First of all we will need to load all the textures from the files.. we will do that using the following code:
Those are the variables we will use to create our animatable object.
private TexturePack dustTexturePack;
private TexturePackTextureRegionLibrary dustTexturePackLibrary;
public TiledTextureRegion dust;
The following code actually loads the single textures from the bitmap into our variable
try {
dustTexturePack = new TexturePackLoader(activity.getTextureManager(),"gfx/Animations/Dust Animation/").loadFromAsset(activity.getAssets(),"dust_anim.xml");
dustTexturePack.loadTexture();
dustTexturePackLibrary = dustTexturePack.getTexturePackTextureRegionLibrary();
} catch (TexturePackParseException e) {
Debug.e(e);
}
TexturePackerTextureRegion[] obj = new TexturePackerTextureRegion[dustTexturePackLibrary.getIDMapping().size()];
for (int i = 0; i < dustTexturePackLibrary.getIDMapping().size(); i++) {
obj[i] = dustTexturePackLibrary.get(i);
}
dust = new TiledTextureRegion(dustTexturePack.getTexture(), obj);
As you can see, we are using the TiledTextureRegion object. what we've done until now is actually loading the textures, and giving our TiledTextureRegion object all the info needed about the regions of the smaller images located in our big bitmap.
Later on, to use this in any part of our game, we can do the following: (notice that my "dust" variable is located inside a ResourceManager class, and therefore its public - this info is given for the next code)
AnimatedSprite dustAnimTiledSprite = new AnimatedSprite(500, 125, resourcesManager.dust, vbom);
myScene.attachChild(dustAnimTiledSprite);
At last, to animated the object in a specific given time, we just use the simple method animate, just like this :
dustAnimTiledSprite.animate(40, 0);
(In this case, the duration of each frame is 40, and there is 0 loops - will be animated once)
** Not too sure what's the difference between AnimatedSprite to TiledSprite. but this is how I show simple animations in my game.
I hope this is what you were looking for. good luck
This is sprite sheet with 8 frames
Player.sprite.animate(
new long[] { 100, 100 }, 7, 8,
false, new IAnimationListener() {
public void onAnimationStarted(
AnimatedSprite pAnimatedSprite,
int pInitialLoopCount) {
}
public void onAnimationLoopFinished(
AnimatedSprite pAnimatedSprite,
int pRemainingLoopCount,
int pInitialLoopCount) {
}
public void onAnimationFrameChanged(
AnimatedSprite pAnimatedSprite,
int pOldFrameIndex,
int pNewFrameIndex) {
}
public void onAnimationFinished(
AnimatedSprite pAnimatedSprite) {
Player.sprite.animate(
new long[] { 100,
100, 100,
100, 100,
100, 100 },
0, 6, true);
}
});
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
i want to load a 3d .obj file in live wallpaper and animate it. i use RAJAWALI library to load it. the problem is that the the 3d obj file is load and animate successfully but Loading background image are not loaded in some android devices. code is follow:
protected void initScene() {
DirectionalLight localDirectionalLight = new DirectionalLight(0.0F, 0.6F, 0.4F);
localDirectionalLight.setPower(3.0F);
PointLight mLight = new PointLight();
mLight.setPosition(0, 0, 0);
mLight.setPower(13);
Plane plane = new Plane(70, 70, 1, 1, 1);
plane.addLight(mLight);
plane.setMaterial(new SimpleMaterial());
plane.addTexture(mTextureManager.addTexture(BitmapFactory.decodeResource(mContext.getResources(), R.drawable.pozadina)));
addChild(plane);
plane.setZ(10);
try
{
ObjParser localObjParser = new ObjParser(this.mContext.getResources(), this.mTextureManager, R.raw.allah);
localObjParser.parse();
this.strela = localObjParser.getParsedObject();
this.strela.addLight(localDirectionalLight);
if (this.tekstura == null)
{
BitmapFactory.Options localOptions2 = new BitmapFactory.Options();
localOptions2.inPurgeable = true;
this.strela.setColor(Color.WHITE);
}
this.strela.setScale(2.0F);
addChild(this.strela);
this.mCamera.setPosition(0.0F, 0.0F, -50.0F);
this.mCamera.setFarPlane(1000.0F);
Number3D localNumber3D = new Number3D(0.0F, 1.0F, 0.0F);
localNumber3D.normalize();
this.mAnim = new RotateAnimation3D(localNumber3D, 360.0F);
this.mAnim.setDuration(10000L);
this.mAnim.setRepeatCount(-1);
this.mAnim.setTransformable3D(this.strela);
return;
}
catch (Exception localException)
{
while (true)
localException.printStackTrace();
}
}
it give problem on SAMSUNG NEXUS android v4.1.
please help how can i do it?
This is tested and working on Galaxy S3. So it should work for you as well. I use it in my wallpapers. Try this:
SimpleMaterial localSimpleMaterial = new SimpleMaterial();
Bitmap localBitmap = BitmapFactory.decodeResource(this.mContext.getResources(), R.drawable.image);
localSimpleMaterial.addTexture(this.mTextureManager.addTexture(localBitmap));
Plane localPlane = new Plane(10.0F, 10.0F, 1, 1);
localPlane.setRotZ(-90.0F);
localPlane.setScale(3.7F);
localPlane.setPosition(0.0F, 0.0F, 10.0F);
localPlane.setMaterial(localSimpleMaterial);
addChild(localPlane);
Just make sure that your image is power of two, i.e., 256x256, 512x512, etc. Let me know how it works for you.
Edit: Also make sure you import rajawali.primitives not rajawali.math
Is the issue solved?
What are those devices on which the plane is not rendered? Are those Samsung?
Also please tell me is it rendered in grey color or not rendered at all?
I am asking because I ran into same problem where the solution was to adjust the mip-mapping. It took time as I was a beginner then, but there was a very simple solution:
Textures are not displayed on the sphere for Samsung Galaxy SL
This time i'm having an issue with the actual rendering of my model. I can load it all through the Libgdx loadObj() function, and render it using GL10_Triangles, however i keep getting missing triangles in my model (it seems like only half the models are being rendered). I've tried the old ObjLoad function (commented out) and also the different render styles but nothing seems to work.
And yes I have checked the model in Blender and the model is complete without missing faces.
See the print screen below, and the code below that.
Any help would be fantastic, it's very frustrating as i'm so close to getting this to work.
And here's the code.
public class LifeCycle implements ApplicationListener {
Mesh model;
private PerspectiveCamera camera;
public void create() {
InputStream stream = null;
camera = new PerspectiveCamera(45, 4, 4);
try
{
stream = Gdx.files.internal("Hammer/test_hammer.obj").read();
//model = ModelLoaderOld.loadObj(stream);
model = ObjLoader.loadObj(stream,true);
stream.close();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Gdx.gl.glEnable(GL10.GL_DEPTH_TEST);
Gdx.gl10.glTranslatef(0.0f, 0.0f, -3.0f);
}
protected float rotateZ = 0.1f;
protected float increment = 0.1f;
public void render()
{
Gdx.app.log("LifeCycle", "render()");
Gdx.gl.glClearColor(0.0f, 0.0f, 0.5f, 1.0f);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
camera.update();
camera.apply(Gdx.gl10);
Gdx.gl10.glTranslatef(0.0f, 0.0f, -3.0f);
Gdx.gl10.glRotatef(rotateZ, rotateZ, 5.0f, rotateZ);
model.render(GL10.GL_TRIANGLES);
rotateZ += increment;
System.out.println(""+rotateZ);
}
}
This actually looks like the OBJ file stores quads instead of triangles, but your loading routine just reads them as triangles (just reads the first 3 index groups of a face). Whereas Blender might (and should) be smart enough to handle quads, your loader routine isn't. So either write a better OBJ loader (but I guess this isn't your class), configure your OBJ loader to treat quads correctly (if possible), or export the model as triangles instead of quads (if possible).