Adding clickable 3DObject Rajawali Cardboard - android

I'm trying to add a simple Sphere Object to my VR app using Rajawali Libraries. My app should show a simple View ( with RajawaliCardboardRenderer, a sphere with the texture of an images ).
The question is : can I simply add a sphere or a 3DObject to that sphere which is gonna be clickable?
Here's my code :
public class MyRenderer extends RajawaliCardboardRenderer {
private Sphere sphere,sphere2;
public MyRenderer(Context context) {
super(context);
}
#Override
protected void initScene() {
sphere = createPhotoSphereWithTexture(new Texture("photo", R.drawable.panorama));
sphere2 = new Sphere(24,24,24);
Material m = new Material();
m.setColor(0);
try {
m.addTexture(new Texture("photo",R.drawable.zvirbloniu_parkas));
} catch ( ATexture.TextureException e) {
e.printStackTrace();
}
sphere2.setMaterial(m);
getCurrentScene().addChild(sphere);
getCurrentScene().addChild(sphere2);
getCurrentCamera().setPosition(Vector3.ZERO);
getCurrentCamera().setFieldOfView(100);
}
#Override
protected void onRender(long ellapsedRealtime, double deltaTime) {
super.onRender(ellapsedRealtime, deltaTime);
sphere2.rotate(Vector3.Axis.Y, 1.0);
}
private static Sphere createPhotoSphereWithTexture(ATexture texture) {
Material material = new Material();
material.setColor(0);
try {
material.addTexture(texture);
} catch (ATexture.TextureException e) {
throw new RuntimeException(e);
}
Sphere sphere = new Sphere(50, 64, 32);
sphere.setScaleX(-1);
sphere.setMaterial(material);
return sphere;
}
}
Don't look at the form of the code, it is bad-written, it doesn't follow any pattern!

You need to attach the sphere2 as a child of the "scenario" sphere, in order to display it inside the scenario, something like this:
sphere = createPhotoSphereWithTexture(new Texture("photo", .drawable.panorama));
sphere2 = new Sphere(24,24,24);
...
sphere.addChild(sphere2);
getCurrentScene().addChild(sphere);

The object picking mechanism of Rajawali will handle child objects. You could either add your new spheres directly to the scene, or to the photo sphere as children, whichever you prefer.

Related

Custom Frame renderer for unique corner radius values in android [Xamarin.Forms]

I want to create a custom renderer for my frame control in fact of having a control which each corner radius values are unique, I have tried to create a custom renderer for frame control in many ways but I haven't found a "solid" solution for it, my custom renderer is not working, I also have tried to use Xamarin.Forms.PancackeView plugin but in my Xamarin.Forms version (4.3.0.991) it seems to have a bug or something related:
EXTRA:
I want to implement shadow in the control frame, but as you should know, frame control by default has shadow, but the shadow in my frame is not working, is there a bug or how can I implement shadow to the custom frame renderer?
Android code for custom Frame renderer:
[assembly: ExportRenderer(typeof(TagFrame), typeof(TagFrameCustomRendererAndroid))]
namespace Sortex.Droid.CRImplementations
{
public class TagFrameCustomRendererAndroid : FrameRenderer
{
public TagFrameCustomRendererAndroid(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
GradientDrawable gradientDrawable = new GradientDrawable();
float[] cornerRadius = { 100000, 100000, 0, 0, 0, 0, 100000, 100000 };
gradientDrawable.SetCornerRadii(cornerRadius);
SetBackgroundDrawable(gradientDrawable);
}
}
}
}
TagFrame class in the shared project:
public class TagFrame : Frame
{
}
I want to create a custom renderer for my frame control in fact of having a control which each corner radius values are unique,
According to your description, you want to custom render frame, then you can set different corner radius. If yes, I do one sample that you can take a look:
Firstly, create CustomFrame inherit Frame, has BindableProperty CornerRadiusProperty.
public class CustomFrame:Frame
{
public static new readonly BindableProperty CornerRadiusProperty = BindableProperty.Create(nameof(CustomFrame), typeof(CornerRadius), typeof(CustomFrame));
public CustomFrame()
{
// MK Clearing default values (e.g. on iOS it's 5)
base.CornerRadius = 0;
}
public new CornerRadius CornerRadius
{
get => (CornerRadius)GetValue(CornerRadiusProperty);
set => SetValue(CornerRadiusProperty, value);
}
}
Then going to Android platform,
using FrameRenderer = Xamarin.Forms.Platform.Android.AppCompat.FrameRenderer;
[assembly: ExportRenderer(typeof(CustomFrame), typeof(CustomFrameRenderer))]
namespace Framerender.Droid
{
public class CustomFrameRenderer: FrameRenderer
{
public CustomFrameRenderer(Context context)
: base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
{
base.OnElementChanged(e);
if (e.NewElement != null && Control != null)
{
UpdateCornerRadius();
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == nameof(CustomFrame.CornerRadius) ||
e.PropertyName == nameof(CustomFrame))
{
UpdateCornerRadius();
}
}
private void UpdateCornerRadius()
{
if (Control.Background is GradientDrawable backgroundGradient)
{
var cornerRadius = (Element as CustomFrame)?.CornerRadius;
if (!cornerRadius.HasValue)
{
return;
}
var topLeftCorner = Context.ToPixels(cornerRadius.Value.TopLeft);
var topRightCorner = Context.ToPixels(cornerRadius.Value.TopRight);
var bottomLeftCorner = Context.ToPixels(cornerRadius.Value.BottomLeft);
var bottomRightCorner = Context.ToPixels(cornerRadius.Value.BottomRight);
var cornerRadii = new[]
{
topLeftCorner,
topLeftCorner,
topRightCorner,
topRightCorner,
bottomRightCorner,
bottomRightCorner,
bottomLeftCorner,
bottomLeftCorner,
};
backgroundGradient.SetCornerRadii(cornerRadii);
}
}
}
}
Now, you can use CustomFrame in PCL.
<local:CustomFrame
BackgroundColor="Red"
CornerRadius="0,0,30,30"
HasShadow="True"
HeightRequest="100"
VerticalOptions="CenterAndExpand"
WidthRequest="100" />
Here is the sample at Github, you can also take a look:
https://github.com/CherryBu/CustomFrame
There are also one article about customframe:
https://progrunning.net/customizing-corner-radius/

Android Libgdx memory leak on creating Actors

I've created an Android application to show about a hundred point objects using Libgdx modelBuilder. It works fine and models are rendered without any problem, but I needed to add a marker for every point model. To do that I've extended from Actor and in this class, I've created two textures representing the marker in normal and the selected mode when the user clicked the objects. The following is the LabelActor class which has been instantiated for each point model.
public class LabelActor extends Actor {
Texture texture;
Texture selectedTexture;
Sprite sprite;
private Vector3 distVector = new Vector3();
public LabelActor( String markerColor){
String path = "markers/point_marker_" + markerColor + ".png"";
String selected_path = "markers/point_marker_select.png";
texture = new Texture(Gdx.files.internal(path));
selectedTexture = new Texture(Gdx.files.internal(selected_path));
sprite = new Sprite(texture);
setBounds(sprite.getX(), sprite.getY(), sprite.getWidth(), sprite.getHeight());
}
#Override
protected void positionChanged() {
sprite.setPosition(getX(),getY());
super.positionChanged();
}
#Override
public void draw(Batch batch, float parentAlpha) {
if (selected){
batch.draw(selectedTexture, getX()-sprite.getWidth()/2, getY());
} else {
batch.draw(texture, getX()-sprite.getWidth()/2, getY());
}
}
}
The problem will be arisen on using the marker for these objects which causes a huge amount of memory usage. Loading a sphere model for each point objects takes about 14M of graphics memory but loading texture markers take 500M of memory on the device. I've used png icons located in the asset folders to create my textures but not using a Libgdx atlas. Is there any chance to create markers for this number of point objects to consume a little amount of memory?
Below is the image representing the view of the markers and point models.
Edit 1:
I've used AssetManager to load textures and create HashMap of them in the main screen then pass an array of two textures to each LabelActor class as Retron advised, but the memory is still overloaded.
public class LabelActor extends Actor {
Texture texture;
Texture selectedTexture;
Sprite sprite;
private Vector3 distVector = new Vector3();
public LabelActor(Texture[] textures){
texture = textures[0];
selectedTexture = textures[1];
sprite = new Sprite(texture);
setBounds(sprite.getX(), sprite.getY(), sprite.getWidth(), sprite.getHeight());
}
#Override
protected void positionChanged() {
sprite.setPosition(getX(),getY());
super.positionChanged();
}
#Override
public void draw(Batch batch, float parentAlpha) {
if (selected){
batch.draw(selectedTexture, getX()-sprite.getWidth()/2, getY());
infoWindow.draw(batch, parentAlpha);
} else {
batch.draw(texture, getX()-sprite.getWidth()/2, getY());
}
}
}
Part of main screen to load textures using AssetManager:
#Override
public void create() {
...
environment = new Environment();
environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1.0f));
pointLight = new PointLight().set(0.8f, 0.8f, 0.8f, 2f, 0f, 0f, 500f);
environment.add(pointLight);
assetManager = new AssetManager();
textureTitleList = new ArrayList<>();
for (FileHandle f: Gdx.files.internal("markers").list()){
assetManager.load("markers/" + f.name(), Texture.class);
textureTitleList.add(f.name());
}
}
private void loadModel() {
textureMap = new HashMap<>();
for (String fName: textureTitleList){
textureMap.put(fName, assetManager.get("markers/" + fName, Texture.class));
}
}
#Override
public void render() {
if (!isLoaded && assetManager.update()) {
loadModel();
isLoaded = true;
}
...
}
You must use AssetManager and load ONE texture from asset, not create new texture for every new actor.

Record opengl fbo made with c++ with java MediaCodec

I'm trying to record the contents of an fbo that i create and fill in c++
with the MediaCodec java object.
I understand that i need to get a Surface from MediaCodec and draw on it
with a frag shader, so i'm trying to feed the c++ fbo as uniform to the
shader.
At the moment i can write the video and if i draw all the pixels red with
the shader i got a red clip, so everything ok on the Shader=>Surface=>MediaCodec side.
To use my fbo i'm passing the GLunit of the texture of the fbo to the
java side with a jni function, and everything seems ok, but all i got
is just noise, like a not initializated texture.
So the question is:
is in any way possible to use a texture done with c++ as a input uniform
to a gles2 java shader?
and if yes, what is the correct flow to do so?
To clarify, i'm actually doing this in my GLSurfaceView.Renderer class:
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
Log.i("OF","onSurfaceCreated");
OFAndroid.onSurfaceCreated();
try{
((OFActivity)OFAndroid.getContext()).onGLSurfaceCreated();
}catch(Exception e){
Log.e("OF","couldn call onGLSurfaceCreated",e);
}
return;
}
#Override
public void onSurfaceChanged(GL10 gl, int w, int h) {
this.w = w;
this.h = h;
if(!setup && OFAndroid.unpackingDone){
try {
setup();
} catch (IOException e) {
e.printStackTrace();
}
}
OFGestureListener.swipe_Min_Distance = (int)(Math.max(w, h)*.04);
OFGestureListener.swipe_Max_Distance = (int)(Math.max(w, h)*.6);
OFAndroid.resize(w, h);
mRenderFbo = new RenderFbo(
800, 800, mSrfTexId);
mFboTexId = mRenderFbo.getFboTexId();
GlUtil.checkGlError("onSurfaceCreated_E");
}
#Override
public void onDrawFrame(GL10 gl) {
if(setup && OFAndroid.unpackingDone){
OFAndroid.render();
if (mRenderSrfTex != null) {
mRenderSrfTex.draw();
}
GlUtil.checkGlError("onDrawFrame_E RENDER SRF TEX");
}else if(!setup && OFAndroid.unpackingDone){
try {
setup();
} catch (IOException e) {
e.printStackTrace();
}
}else{
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
gl.glClearColor(.5f, .5f, .5f, 1.f);
}
}
public void setRecorder(MyRecorder recorder, int myTexID) {
texID = myTexID;
synchronized(this) {
if (recorder != null) {
mRenderSrfTex = new RenderSrfTex(
800, 804,
myTexID, recorder);
} else {
mRenderSrfTex = null;
}
}
}
where myTexID is the GLUint that i pass from c++ to java with jni, containing the GLUint of the fbo texture.
for reference to the classes myRecorder and RenderSrfTex see the classes at https://github.com/MorihiroSoft/Android_MediaCodecTest/tree/master/MediaCodecTest18/src/jp/morihirosoft/mediacodectest18
and here the sources of the relevant part of the framework, https://github.com/openframeworks/openFrameworks/blob/master/addons/ofxAndroid/ofAndroidLib/src/cc/openframeworks/OFAndroidWindow.java
The answer is absolutely yes, it's possible to pass via GLUint a textureID from c++ to Java, and here there is my solution to record openFrameworks ofFbo with MediaCodec https://github.com/rcavazza/openFramework-Android-Recording. Thanks fadden for the useful answers.

AndEngine add single image multiple time in different size

I am new in AndEngine. I am using following code to display an image of a ball.
private ITextureRegion mBallTextureRegion;
private Sprite ball1;
#Override
public void onCreateResources() {
ITexture ball = new BitmapTexture(this.getTextureManager(),
new IInputStreamOpener() {
#Override
public InputStream open() throws IOException {
return getAssets().open("gfx/ball.png");
}
});
this.mBallTextureRegion = TextureRegionFactory.extractFromTexture(ring1);
....................
....................
}
#Override
protected Scene onCreateScene() {
final Scene scene = new Scene();
scene.attachChild(backgroundSprite);
...........
ball1 = new Sprite(192, 63, this.mBallTextureRegion, getVertexBufferObjectManager());
scene.attachChild(ball1);
..............
...........
}
Now, depending on the game level I want to add multiple ball of different size in the scene. Is it possible to add ITextureRegion mBallTextureRegion multiple time in different size(using different magnifying it)? If it is, then how? Please help me this sample code.
if you want to resize a Sprite,AnimatedSprite,Text,etc...
//the original image x2, 2f because the parameter is float
youSprite.setScale(2f);
if you use a texture region in more sprites:
Sprite youSprite;
//set deepCopy() in you texture to optimized memory
youSprite= new Sprite(0,0,youTexture.deepCopy(),mEnginge.getVertexTextureManager());
and if you want generate random position of each ball use "Random" variable.
best regards.

Is it possible to render an Android View to an OpenGL FBO or texture?

Is it possible to render a View (say, a WebView) to an FBO so it can be used as a texture in an OpenGL composition?
I brought together a complete demo project which renders a view to GL textures in real time in an efficient way which can be found in this repo. It shows how to render WebView to GL texture in real time as an example.
Also a brief code for this can look like the following (taken from the demo project from the repo above):
public class GLWebView extends WebView {
private ViewToGLRenderer mViewToGLRenderer;
...
// drawing magic
#Override
public void draw( Canvas canvas ) {
//returns canvas attached to gl texture to draw on
Canvas glAttachedCanvas = mViewToGLRenderer.onDrawViewBegin();
if(glAttachedCanvas != null) {
//translate canvas to reflect view scrolling
float xScale = glAttachedCanvas.getWidth() / (float)canvas.getWidth();
glAttachedCanvas.scale(xScale, xScale);
glAttachedCanvas.translate(-getScrollX(), -getScrollY());
//draw the view to provided canvas
super.draw(glAttachedCanvas);
}
// notify the canvas is updated
mViewToGLRenderer.onDrawViewEnd();
}
...
}
public class ViewToGLRenderer implements GLSurfaceView.Renderer{
private SurfaceTexture mSurfaceTexture;
private Surface mSurface;
private int mGlSurfaceTexture;
private Canvas mSurfaceCanvas;
...
#Override
public void onDrawFrame(GL10 gl){
synchronized (this){
// update texture
mSurfaceTexture.updateTexImage();
}
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height){
releaseSurface();
mGlSurfaceTexture = createTexture();
if (mGlSurfaceTexture > 0){
//attach the texture to a surface.
//It's a clue class for rendering an android view to gl level
mSurfaceTexture = new SurfaceTexture(mGlSurfaceTexture);
mSurfaceTexture.setDefaultBufferSize(mTextureWidth, mTextureHeight);
mSurface = new Surface(mSurfaceTexture);
}
}
public Canvas onDrawViewBegin(){
mSurfaceCanvas = null;
if (mSurface != null) {
try {
mSurfaceCanvas = mSurface.lockCanvas(null);
}catch (Exception e){
Log.e(TAG, "error while rendering view to gl: " + e);
}
}
return mSurfaceCanvas;
}
public void onDrawViewEnd(){
if(mSurfaceCanvas != null) {
mSurface.unlockCanvasAndPost(mSurfaceCanvas);
}
mSurfaceCanvas = null;
}
}
The demo output screenshot:
Yes is it certainly possible, I have written up a how-to here;
http://www.felixjones.co.uk/neo%20website/Android_View/
However for static elements that won't change, the bitmap option may be better.
At least someone managed to render text this way:
Rendering Text in OpenGL on Android
It describes the method I used for rendering high-quality dynamic text efficiently using OpenGL ES 1.0, with TrueType/OpenType font files.
[...]
The whole process is actually quite easy. We generate the bitmap (as a texture), calculate and store the size of each character, as well as it's location on the texture (UV coordinates). There are some other finer details, but we'll get to that.
OpenGL ES 2.0 Version: https://github.com/d3kod/Texample2

Categories

Resources