Hi all i was trying to port Rajawali engine https://github.com/MasDennis/Rajawali
for b4a but i stuck on point where GlSurfaceView return null point exception and i start to think that i'm on totaly wrong way
with my English is hard for me to explain :sign0013: so i will post the code
I think if we can fix this this will be very useful for the b4a community
ackage com.cyberbg.rajawali;
import android.graphics.Color;
import android.view.ViewGroup;
import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.BA.ActivityObject;
import anywheresoftware.b4a.BA.Author;
import anywheresoftware.b4a.BA.ShortName;
import anywheresoftware.b4a.BA.Version;
import rajawali.lights.ALight;
import rajawali.lights.DirectionalLight;
import rajawali.primitives.Sphere;
import rajawali.renderer.RajawaliRenderer;
@ShortName(value = "cgbRajawali")
@Author(value = "gogo")
@Version(value = 1.0f)
@ActivityObject
public class Start {
private RajawaliRenderer render;
private BA ba;
private ViewGroup Panel;
public void initScene() {
}
public void initialize(BA ba_, ViewGroup panel){
ba=ba_;
Panel=panel;
render=new RajawaliRenderer(ba_.activity.getApplicationContext());
}
private Sphere sphere;
public void Work(){
ALight Eyelight = new DirectionalLight();
sphere=new Sphere(0.8f, 24, 24);
Eyelight.setPower(1f);
Eyelight.setPosition(0, 0, 0);
Eyelight.setColor(Color.GREEN);
//sphere.setMaterial(material);
sphere.setColor(Color.RED);
sphere.setPosition(1.5f, 0.7f, 0.5f);
//cube.addTexture(mTextureManager.addTexture(texture));
//sphere.addTexture(mTextureManager.addTexture(texture));
sphere.setDoubleSided(false);
sphere.setBackSided(false);
sphere.addLight(Eyelight);
sphere.setRotX(0);
sphere.setRotY(90);
//cube.addLight(light);
//addChild(cube);
render.addChild(sphere);
render.startRendering();
anywheresoftware.b4a.BALayout.LayoutParams lp = new anywheresoftware.b4a.BALayout.LayoutParams(0, 0,
Panel.getLayoutParams().width, Panel.getLayoutParams().height);
//*******************!!!!!!!!!!!! null pointer exception here**********
Panel.addView(render.getSurfaceView(), lp);// null pointer exception here
}
}
the log from b4a
** Activity (main) Pause, UserClosed = true **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
main_activity_keypress (B4A line: 84)
ra.Work
java.lang.NullPointerException
at android.view.ViewGroup.addViewInner(ViewGroup.java:3458)
at android.view.ViewGroup.addView(ViewGroup.java:3330)
at android.view.ViewGroup.addView(ViewGroup.java:3306)
at com.cyberbg.rajawali.Start.Work(Start.java:85)
at com.cyberbg.speedometer.main._activity_keypress(main.java:330)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:169)
at com.cyberbg.speedometer.main.onKeyDown(main.java:156)
at android.view.KeyEvent.dispatch(KeyEvent.java:2609)
at android.app.Activity.dispatchKeyEvent(Activity.java:2373)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1832)
at android.view.ViewRootImpl.deliverKeyEventPostIme(ViewRootImpl.java:3949)
at android.view.ViewRootImpl.handleImeFinishedEvent(ViewRootImpl.java:3915)
at android.view.ViewRootImpl$ViewRootHandler.handleMessage(ViewRootImpl.java:3126)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:153)
at android.app.ActivityThread.main(ActivityThread.java:4987)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:821)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:584)
at dalvik.system.NativeStart.main(Native Method)
java.lang.NullPointerException
here is the RajawaliRenderer class code
package rajawali.renderer;
import java.util.Collections;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import rajawali.BaseObject3D;
import rajawali.Camera;
import rajawali.animation.TimerManager;
import rajawali.filters.IPostProcessingFilter;
import rajawali.materials.AMaterial;
import rajawali.materials.SimpleMaterial;
import rajawali.materials.SkyboxMaterial;
import rajawali.materials.TextureInfo;
import rajawali.materials.TextureManager;
import rajawali.math.Number3D;
import rajawali.primitives.Cube;
import rajawali.renderer.plugins.IRendererPlugin;
import rajawali.util.FPSUpdateListener;
import rajawali.util.ObjectColorPicker.ColorPickerInfo;
import rajawali.util.RajLog;
import rajawali.visitors.INode;
import rajawali.visitors.INodeVisitor;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.opengl.Matrix;
import android.service.wallpaper.WallpaperService;
import android.util.Log;
import android.view.MotionEvent;
import android.view.WindowManager;
public class RajawaliRenderer implements GLSurfaceView.Renderer, INode {
protected final int GL_COVERAGE_BUFFER_BIT_NV = 0x8000;
protected Context mContext;
protected float mEyeZ = 4.0f;
protected float mFrameRate;
protected double mLastMeasuredFPS;
protected FPSUpdateListener mFPSUpdateListener;
protected SharedPreferences preferences;
protected int mViewportWidth, mViewportHeight;
protected WallpaperService.Engine mWallpaperEngine;
protected GLSurfaceView mSurfaceView;
protected Timer mTimer;
protected int mFrameCount;
private long mStartTime = System.nanoTime();
protected float[] mVMatrix = new float[16];
protected float[] mPMatrix = new float[16];
protected List<BaseObject3D> mChildren;
protected boolean mEnableDepthBuffer = true;
protected TextureManager mTextureManager;
protected PostProcessingRenderer mPostProcessingRenderer;
/**
* Deprecated. Use setSceneCachingEnabled(false) instead.
*/
@Deprecated
protected boolean mClearChildren = true;
/**
* The camera currently in use.
* Not thread safe for speed, should
* only be used by GL thread (onDrawFrame() and render())
* or prior to rendering such as initScene().
*/
protected Camera mCamera;
/**
* List of all cameras in the scene.
*/
protected List<Camera> mCameras;
/**
* Temporary camera which will be switched to by the GL thread.
* Guarded by mNextCameraLock
*/
protected Camera mNextCamera;
private final Object mNextCameraLock = new Object();
protected float mRed, mBlue, mGreen, mAlpha;
protected Cube mSkybox;
protected TextureInfo mSkyboxTextureInfo;
protected static int mMaxLights = 1;
protected ColorPickerInfo mPickerInfo;
protected List<IPostProcessingFilter> mFilters;
protected boolean mReloadPickerInfo;
protected static boolean mFogEnabled;
protected boolean mUsesCoverageAa;
public static boolean supportsUIntBuffers = false;
protected boolean mSceneInitialized;
/**
* Scene caching stores all textures and relevant OpenGL-specific
* data. This is used when the OpenGL context needs to be restored.
* The context typically needs to be restored when the application
* is re-activated or when a live wallpaper is rotated.
*/
private boolean mSceneCachingEnabled;
protected List<IRendererPlugin> mPlugins;
public RajawaliRenderer(Context context) {
RajLog.i("IMPORTANT: Rajawali's coordinate system has changed. It now reflects");
RajLog.i("the OpenGL standard. Please invert the camera's z coordinate or");
RajLog.i("call mCamera.setLookAt(0, 0, 0).");
AMaterial.setLoaderContext(context);
mContext = context;
mChildren = Collections.synchronizedList(new CopyOnWriteArrayList<BaseObject3D>());
mFilters = Collections.synchronizedList(new CopyOnWriteArrayList<IPostProcessingFilter>());
mPlugins = Collections.synchronizedList(new CopyOnWriteArrayList<IRendererPlugin>());
mCamera = new Camera();
mCameras = Collections.synchronizedList(new CopyOnWriteArrayList<Camera>());
addCamera(mCamera);
mCamera.setZ(mEyeZ);
mAlpha = 0;
mSceneCachingEnabled = true;
mPostProcessingRenderer = new PostProcessingRenderer(this);
mFrameRate = getRefreshRate();
}
/**
* Sets the camera currently being used to display the scene.
*
* @param mCamera Camera object to display the scene with.
*/
public void setCamera(Camera camera) {
synchronized (mNextCameraLock) {
mNextCamera = camera;
}
}
/**
* Sets the camera currently being used to display the scene.
*
* @param camera Index of the camera to use.
*/
public void setCamera(int camera) {
setCamera(mCameras.get(camera));
}
/**
* Fetches the camera currently being used to display the scene.
* Note that the camera is not thread safe so this should be used
* with extreme caution.
*
* @return Camera object currently used for the scene.
* @see {@link RajawaliRenderer#mCamera}
*/
public Camera getCamera() {
return this.mCamera;
}
/**
* Fetches the specified camera.
*
* @param camera Index of the camera to fetch.
* @return Camera which was retrieved.
*/
public Camera getCamera(int camera) {
return mCameras.get(camera);
}
/**
* Adds a camera to the renderer.
*
* @param camera Camera object to add.
* @return int The index the new camera was added at.
*/
public int addCamera(Camera camera) {
mCameras.add(camera);
return (mCameras.size() - 1);
}
/**
* Replaces a camera in the renderer at the specified location
* in the list. This does not validate the index, so if it is not
* contained in the list already, an exception will be thrown.
*
* @param camera Camera object to add.
* @param location Integer index of the camera to replace.
*/
public void replaceCamera(Camera camera, int location) {
mCameras.set(location, camera);
}
/**
* Adds a camera with the option to switch to it immediately
*
* @param camera The Camera to add.
* @param useNow Boolean indicating if we should switch to this
* camera immediately.
* @return int The index the new camera was added at.
*/
public int addCamera(Camera camera, boolean useNow) {
int index = addCamera(camera);
if (useNow) setCamera(camera);
return index;
}
/**
* Replaces a camera at the specified index with an option to switch to it
* immediately.
*
* @param camera The Camera to add.
* @param location The index of the camera to replace.
* @param useNow Boolean indicating if we should switch to this
* camera immediately.
*/
public void replaceCamera(Camera camera, int location, boolean useNow) {
replaceCamera(camera, location);
if (useNow) setCamera(camera);
}
public void requestColorPickingTexture(ColorPickerInfo pickerInfo) {
mPickerInfo = pickerInfo;
}
public void onDrawFrame(GL10 glUnused) {
synchronized (mNextCameraLock) {
//Check if we need to switch the camera, and if so, do it.
if (mNextCamera != null) {
mCamera = mNextCamera;
mNextCamera = null;
mCamera.setProjectionMatrix(mViewportWidth, mViewportHeight);
}
}
render();
++mFrameCount;
if (mFrameCount % 50 == 0) {
long now = System.nanoTime();
double elapsedS = (now - mStartTime) / 1.0e9;
double msPerFrame = (1000 * elapsedS / mFrameCount);
mLastMeasuredFPS = 1000 / msPerFrame;
//RajLog.d("ms / frame: " + msPerFrame + " - fps: " + mLastMeasuredFPS);
mFrameCount = 0;
mStartTime = now;
if(mFPSUpdateListener != null)
mFPSUpdateListener.onFPSUpdate(mLastMeasuredFPS);
}
}
private void render() {
int clearMask = GLES20.GL_COLOR_BUFFER_BIT;
ColorPickerInfo pickerInfo = mPickerInfo;
mTextureManager.validateTextures();
if (pickerInfo != null) {
if(mReloadPickerInfo) pickerInfo.getPicker().reload();
mReloadPickerInfo = false;
pickerInfo.getPicker().bindFrameBuffer();
GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
} else {
if (mFilters.size() == 0)
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
else {
if (mPostProcessingRenderer.isEnabled())
mPostProcessingRenderer.bind();
}
GLES20.glClearColor(mRed, mGreen, mBlue, mAlpha);
}
if (mEnableDepthBuffer) {
clearMask |= GLES20.GL_DEPTH_BUFFER_BIT;
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glDepthFunc(GLES20.GL_LESS);
GLES20.glDepthMask(true);
GLES20.glClearDepthf(1.0f);
}
if (mUsesCoverageAa) {
clearMask |= GL_COVERAGE_BUFFER_BIT_NV;
}
GLES20.glClear(clearMask);
mVMatrix = mCamera.getViewMatrix();
mPMatrix = mCamera.getProjectionMatrix();
if (mSkybox != null) {
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
GLES20.glDepthMask(false);
mSkybox.setPosition(mCamera.getX(), mCamera.getY(), mCamera.getZ());
mSkybox.render(mCamera, mPMatrix, mVMatrix, pickerInfo);
if (mEnableDepthBuffer) {
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glDepthMask(true);
}
}
mCamera.updateFrustum(mPMatrix,mVMatrix); //update frustum plane
for (int i = 0; i < mChildren.size(); i++)
mChildren.get(i).render(mCamera, mPMatrix, mVMatrix, pickerInfo);
if (pickerInfo != null) {
pickerInfo.getPicker().createColorPickingTexture(pickerInfo);
pickerInfo.getPicker().unbindFrameBuffer();
pickerInfo = null;
mPickerInfo = null;
render();
} else if (mPostProcessingRenderer.isEnabled()) {
mPostProcessingRenderer.render();
}
for (int i = 0, j = mPlugins.size(); i < j; i++)
mPlugins.get(i).render();
}
public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep, float yOffsetStep, int xPixelOffset, int yPixelOffset) {
}
public void onTouchEvent(MotionEvent event) {
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
mViewportWidth = width;
mViewportHeight = height;
mCamera.setProjectionMatrix(width, height);
GLES20.glViewport(0, 0, width, height);
}
/* Called when the OpenGL context is created or re-created. Don't set up your scene here,
* use initScene() for that.
*
* @see rajawali.renderer.RajawaliRenderer#initScene
* @see android.opengl.GLSurfaceView.Renderer#onSurfaceCreated(javax.microedition.khronos.opengles.GL10, javax.microedition.khronos.egl.EGLConfig)
*
*/
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
supportsUIntBuffers = gl.glGetString(GL10.GL_EXTENSIONS).indexOf("GL_OES_element_index_uint") > -1;
GLES20.glFrontFace(GLES20.GL_CCW);
GLES20.glCullFace(GLES20.GL_BACK);
if (!mSceneInitialized) {
mTextureManager = new TextureManager(mContext);
initScene();
}
if (!mSceneCachingEnabled) {
mTextureManager.reset();
if (mChildren.size() > 0) {
mChildren.clear();
}
if (mPlugins.size() > 0) {
mPlugins.clear();
}
} else if(mSceneCachingEnabled && mSceneInitialized) {
mTextureManager.reload();
reloadChildren();
if(mSkybox != null)
mSkybox.reload();
if(mPostProcessingRenderer.isInitialized())
mPostProcessingRenderer.reload();
reloadPlugins();
mReloadPickerInfo = true;
}
mSceneInitialized = true;
Log.i("cgb", "cgb******************************onSurfaceCreated(GL10 gl, EGLConfig config)**************");
startRendering();
}
private void reloadChildren() {
for (int i = 0; i < mChildren.size(); i++)
mChildren.get(i).reload();
}
private void reloadPlugins() {
for (int i = 0, j = mPlugins.size(); i < j; i++)
mPlugins.get(i).reload();
}
/**
* Scene construction should happen here, not in onSurfaceCreated()
*/
protected void initScene() {
Log.i("cgb", "cgb******************************init scene**************");
}
protected void destroyScene() {
mSceneInitialized = false;
for (int i = 0; i < mChildren.size(); i++)
mChildren.get(i).destroy();
mChildren.clear();
for (int i = 0, j = mPlugins.size(); i < j; i++)
mPlugins.get(i).destroy();
mPlugins.clear();
Log.i("cgb", "cgb******************************destroy scene**************");
}
public void startRendering() {
if (mTimer != null) {
mTimer.cancel();
mTimer.purge();
Log.i("cgb", "cgb******************************Start rendering**************");
}
mTimer = new Timer();
mTimer.schedule(new RequestRenderTask(), 0, (long) (1000 / mFrameRate));
}
/**
* Stop rendering the scene.
*
* @return true if rendering was stopped, false if rendering was already
* stopped (no action taken)
*/
protected boolean stopRendering() {
Log.i("cgb", "cgb******************************Stop rendering**************");
if (mTimer != null) {
mTimer.cancel();
mTimer.purge();
mTimer = null;
return true;
}
return false;
}
public void onVisibilityChanged(boolean visible) {
if (!visible) {
stopRendering();
} else
startRendering();
}
public void onSurfaceDestroyed() {
stopRendering();
TimerManager.getInstance().clear();
if (mTextureManager != null)
mTextureManager.reset();
destroyScene();
}
public void setSharedPreferences(SharedPreferences preferences) {
this.preferences = preferences;
}
private class RequestRenderTask extends TimerTask {
public void run() {
if (mSurfaceView != null) {
mSurfaceView.requestRender();
}
}
}
public Number3D unProject(float x, float y, float z) {
x = mViewportWidth - x;
y = mViewportHeight - y;
float[] m = new float[16], mvpmatrix = new float[16],
in = new float[4],
out = new float[4];
Matrix.multiplyMM(mvpmatrix, 0, mPMatrix, 0, mVMatrix, 0);
Matrix.invertM(m, 0, mvpmatrix, 0);
in[0] = (x / (float)mViewportWidth) * 2 - 1;
in[1] = (y / (float)mViewportHeight) * 2 - 1;
in[2] = 2 * z - 1;
in[3] = 1;
Matrix.multiplyMV(out, 0, m, 0, in, 0);
if (out[3]==0)
return null;
out[3] = 1/out[3];
return new Number3D(out[0] * out[3], out[1] * out[3], out[2] * out[3]);
}
public float getFrameRate() {
return mFrameRate;
}
public void setFrameRate(int frameRate) {
setFrameRate((float)frameRate);
}
public void setFrameRate(float frameRate) {
this.mFrameRate = frameRate;
if (stopRendering()) {
// Restart timer with new frequency
startRendering();
}
}
public float getRefreshRate() {
return ((WindowManager) mContext
.getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay()
.getRefreshRate();
}
public WallpaperService.Engine getEngine() {
return mWallpaperEngine;
}
public void setEngine(WallpaperService.Engine engine) {
this.mWallpaperEngine = engine;
}
public GLSurfaceView getSurfaceView() {
Log.i("cgb", "cgb******************************get_SufraceView()**************");
return mSurfaceView;
}
public void setSurfaceView(GLSurfaceView surfaceView) {
this.mSurfaceView = surfaceView;
}
public Context getContext() {
return mContext;
}
public TextureManager getTextureManager() {
return mTextureManager;
}
public void addChild(BaseObject3D child) {
mChildren.add(child);
}
public void clearChildren() {
mChildren.clear();
}
public void addPlugin(IRendererPlugin plugin) {
mPlugins.add(plugin);
}
public void clearPlugins() {
mPlugins.clear();
}
protected void setSkybox(int resourceId) {
mCamera.setFarPlane(1000);
mSkybox = new Cube(700, true, false);
mSkybox.setDoubleSided(true);
mSkyboxTextureInfo = mTextureManager.addTexture(BitmapFactory.decodeResource(mContext.getResources(), resourceId));
SimpleMaterial material = new SimpleMaterial();
material.addTexture(mSkyboxTextureInfo);
mSkybox.setMaterial(material);
}
protected void setSkybox(int front, int right, int back, int left, int up, int down) {
mCamera.setFarPlane(1000);
mSkybox = new Cube(700, true);
Bitmap[] textures = new Bitmap[6];
textures[0] = BitmapFactory.decodeResource(mContext.getResources(), left);
textures[1] = BitmapFactory.decodeResource(mContext.getResources(), right);
textures[2] = BitmapFactory.decodeResource(mContext.getResources(), up);
textures[3] = BitmapFactory.decodeResource(mContext.getResources(), down);
textures[4] = BitmapFactory.decodeResource(mContext.getResources(), front);
textures[5] = BitmapFactory.decodeResource(mContext.getResources(), back);
mSkyboxTextureInfo = mTextureManager.addCubemapTextures(textures);
SkyboxMaterial mat = new SkyboxMaterial();
mat.addTexture(mSkyboxTextureInfo);
mSkybox.setMaterial(mat);
}
protected void updateSkybox(int resourceId) {
mTextureManager.updateTexture(mSkyboxTextureInfo, BitmapFactory.decodeResource(mContext.getResources(), resourceId));
}
protected void updateSkybox(int front, int right, int back, int left, int up, int down) {
Bitmap[] textures = new Bitmap[6];
textures[0] = BitmapFactory.decodeResource(mContext.getResources(), left);
textures[1] = BitmapFactory.decodeResource(mContext.getResources(), right);
textures[2] = BitmapFactory.decodeResource(mContext.getResources(), up);
textures[3] = BitmapFactory.decodeResource(mContext.getResources(), down);
textures[4] = BitmapFactory.decodeResource(mContext.getResources(), front);
textures[5] = BitmapFactory.decodeResource(mContext.getResources(), back);
mTextureManager.updateCubemapTextures(mSkyboxTextureInfo, textures);
}
public boolean removeChild(BaseObject3D child) {
return mChildren.remove(child);
}
public boolean removePlugin(IRendererPlugin plugin) {
return mPlugins.remove(plugin);
}
public int getNumPlugins() {
return mPlugins.size();
}
public List<IRendererPlugin> getPlugins() {
return mPlugins;
}
public boolean hasPlugin(IRendererPlugin plugin) {
return mPlugins.contains(plugin);
}
public int getNumChildren() {
return mChildren.size();
}
public List<BaseObject3D> getChildren() {
return mChildren;
}
protected boolean hasChild(BaseObject3D child) {
return mChildren.contains(child);
}
public void addPostProcessingFilter(IPostProcessingFilter filter) {
if(mFilters.size() > 0)
mFilters.remove(0);
mFilters.add(filter);
mPostProcessingRenderer.setEnabled(true);
mPostProcessingRenderer.setFilter(filter);
}
public void accept(INodeVisitor visitor) {
visitor.apply(this);
for (int i = 0; i < mChildren.size(); i++)
mChildren.get(i).accept(visitor);
}
public void removePostProcessingFilter(IPostProcessingFilter filter) {
mFilters.remove(filter);
}
public void clearPostProcessingFilters() {
mFilters.clear();
mPostProcessingRenderer.unbind();
mPostProcessingRenderer.destroy();
mPostProcessingRenderer = new PostProcessingRenderer(this);
}
public int getViewportWidth() {
return mViewportWidth;
}
public int getViewportHeight() {
return mViewportHeight;
}
public void setBackgroundColor(float red, float green, float blue, float alpha) {
mRed = red;
mGreen = green;
mBlue = blue;
mAlpha = alpha;
}
public void setBackgroundColor(int color) {
setBackgroundColor(Color.red(color) / 255f, Color.green(color) / 255f, Color.blue(color) / 255f, Color.alpha(color) / 255f);
}
public boolean getSceneInitialized() {
return mSceneInitialized;
}
public void setSceneCachingEnabled(boolean enabled) {
mSceneCachingEnabled = enabled;
}
public boolean getSceneCachingEnabled() {
return mSceneCachingEnabled;
}
public void setFogEnabled(boolean enabled) {
mFogEnabled = enabled;
mCamera.setFogEnabled(enabled);
}
public void setUsesCoverageAa(boolean value) {
mUsesCoverageAa = value;
}
public static boolean isFogEnabled() {
return mFogEnabled;
}
public static int getMaxLights() {
return mMaxLights;
}
public static void setMaxLights(int maxLights) {
RajawaliRenderer.mMaxLights = maxLights;
}
public void setFPSUpdateListener(FPSUpdateListener listener) {
mFPSUpdateListener = listener;
}
public static int checkGLError(String message) {
int error = GLES20.glGetError();
if(error != GLES20.GL_NO_ERROR)
{
StringBuffer sb = new StringBuffer();
if(message != null)
sb.append("[").append(message).append("] ");
sb.append("GLES20 Error: ");
sb.append(GLU.gluErrorString(error));
RajLog.e(sb.toString());
}
return error;
}
public int getNumTriangles() {
int triangleCount = 0;
for (int i = 0; i < mChildren.size(); i++) {
if (mChildren.get(i).getGeometry() != null && mChildren.get(i).getGeometry().getVertices() != null && mChildren.get(i).isVisible())
triangleCount += mChildren.get(i).getGeometry().getVertices().limit() / 9;
}
return triangleCount;
}
}
for b4a but i stuck on point where GlSurfaceView return null point exception and i start to think that i'm on totaly wrong way
with my English is hard for me to explain :sign0013: so i will post the code
I think if we can fix this this will be very useful for the b4a community
ackage com.cyberbg.rajawali;
import android.graphics.Color;
import android.view.ViewGroup;
import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.BA.ActivityObject;
import anywheresoftware.b4a.BA.Author;
import anywheresoftware.b4a.BA.ShortName;
import anywheresoftware.b4a.BA.Version;
import rajawali.lights.ALight;
import rajawali.lights.DirectionalLight;
import rajawali.primitives.Sphere;
import rajawali.renderer.RajawaliRenderer;
@ShortName(value = "cgbRajawali")
@Author(value = "gogo")
@Version(value = 1.0f)
@ActivityObject
public class Start {
private RajawaliRenderer render;
private BA ba;
private ViewGroup Panel;
public void initScene() {
}
public void initialize(BA ba_, ViewGroup panel){
ba=ba_;
Panel=panel;
render=new RajawaliRenderer(ba_.activity.getApplicationContext());
}
private Sphere sphere;
public void Work(){
ALight Eyelight = new DirectionalLight();
sphere=new Sphere(0.8f, 24, 24);
Eyelight.setPower(1f);
Eyelight.setPosition(0, 0, 0);
Eyelight.setColor(Color.GREEN);
//sphere.setMaterial(material);
sphere.setColor(Color.RED);
sphere.setPosition(1.5f, 0.7f, 0.5f);
//cube.addTexture(mTextureManager.addTexture(texture));
//sphere.addTexture(mTextureManager.addTexture(texture));
sphere.setDoubleSided(false);
sphere.setBackSided(false);
sphere.addLight(Eyelight);
sphere.setRotX(0);
sphere.setRotY(90);
//cube.addLight(light);
//addChild(cube);
render.addChild(sphere);
render.startRendering();
anywheresoftware.b4a.BALayout.LayoutParams lp = new anywheresoftware.b4a.BALayout.LayoutParams(0, 0,
Panel.getLayoutParams().width, Panel.getLayoutParams().height);
//*******************!!!!!!!!!!!! null pointer exception here**********
Panel.addView(render.getSurfaceView(), lp);// null pointer exception here
}
}
the log from b4a
** Activity (main) Pause, UserClosed = true **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
main_activity_keypress (B4A line: 84)
ra.Work
java.lang.NullPointerException
at android.view.ViewGroup.addViewInner(ViewGroup.java:3458)
at android.view.ViewGroup.addView(ViewGroup.java:3330)
at android.view.ViewGroup.addView(ViewGroup.java:3306)
at com.cyberbg.rajawali.Start.Work(Start.java:85)
at com.cyberbg.speedometer.main._activity_keypress(main.java:330)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:169)
at com.cyberbg.speedometer.main.onKeyDown(main.java:156)
at android.view.KeyEvent.dispatch(KeyEvent.java:2609)
at android.app.Activity.dispatchKeyEvent(Activity.java:2373)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1832)
at android.view.ViewRootImpl.deliverKeyEventPostIme(ViewRootImpl.java:3949)
at android.view.ViewRootImpl.handleImeFinishedEvent(ViewRootImpl.java:3915)
at android.view.ViewRootImpl$ViewRootHandler.handleMessage(ViewRootImpl.java:3126)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:153)
at android.app.ActivityThread.main(ActivityThread.java:4987)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:821)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:584)
at dalvik.system.NativeStart.main(Native Method)
java.lang.NullPointerException
here is the RajawaliRenderer class code
package rajawali.renderer;
import java.util.Collections;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import rajawali.BaseObject3D;
import rajawali.Camera;
import rajawali.animation.TimerManager;
import rajawali.filters.IPostProcessingFilter;
import rajawali.materials.AMaterial;
import rajawali.materials.SimpleMaterial;
import rajawali.materials.SkyboxMaterial;
import rajawali.materials.TextureInfo;
import rajawali.materials.TextureManager;
import rajawali.math.Number3D;
import rajawali.primitives.Cube;
import rajawali.renderer.plugins.IRendererPlugin;
import rajawali.util.FPSUpdateListener;
import rajawali.util.ObjectColorPicker.ColorPickerInfo;
import rajawali.util.RajLog;
import rajawali.visitors.INode;
import rajawali.visitors.INodeVisitor;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.opengl.Matrix;
import android.service.wallpaper.WallpaperService;
import android.util.Log;
import android.view.MotionEvent;
import android.view.WindowManager;
public class RajawaliRenderer implements GLSurfaceView.Renderer, INode {
protected final int GL_COVERAGE_BUFFER_BIT_NV = 0x8000;
protected Context mContext;
protected float mEyeZ = 4.0f;
protected float mFrameRate;
protected double mLastMeasuredFPS;
protected FPSUpdateListener mFPSUpdateListener;
protected SharedPreferences preferences;
protected int mViewportWidth, mViewportHeight;
protected WallpaperService.Engine mWallpaperEngine;
protected GLSurfaceView mSurfaceView;
protected Timer mTimer;
protected int mFrameCount;
private long mStartTime = System.nanoTime();
protected float[] mVMatrix = new float[16];
protected float[] mPMatrix = new float[16];
protected List<BaseObject3D> mChildren;
protected boolean mEnableDepthBuffer = true;
protected TextureManager mTextureManager;
protected PostProcessingRenderer mPostProcessingRenderer;
/**
* Deprecated. Use setSceneCachingEnabled(false) instead.
*/
@Deprecated
protected boolean mClearChildren = true;
/**
* The camera currently in use.
* Not thread safe for speed, should
* only be used by GL thread (onDrawFrame() and render())
* or prior to rendering such as initScene().
*/
protected Camera mCamera;
/**
* List of all cameras in the scene.
*/
protected List<Camera> mCameras;
/**
* Temporary camera which will be switched to by the GL thread.
* Guarded by mNextCameraLock
*/
protected Camera mNextCamera;
private final Object mNextCameraLock = new Object();
protected float mRed, mBlue, mGreen, mAlpha;
protected Cube mSkybox;
protected TextureInfo mSkyboxTextureInfo;
protected static int mMaxLights = 1;
protected ColorPickerInfo mPickerInfo;
protected List<IPostProcessingFilter> mFilters;
protected boolean mReloadPickerInfo;
protected static boolean mFogEnabled;
protected boolean mUsesCoverageAa;
public static boolean supportsUIntBuffers = false;
protected boolean mSceneInitialized;
/**
* Scene caching stores all textures and relevant OpenGL-specific
* data. This is used when the OpenGL context needs to be restored.
* The context typically needs to be restored when the application
* is re-activated or when a live wallpaper is rotated.
*/
private boolean mSceneCachingEnabled;
protected List<IRendererPlugin> mPlugins;
public RajawaliRenderer(Context context) {
RajLog.i("IMPORTANT: Rajawali's coordinate system has changed. It now reflects");
RajLog.i("the OpenGL standard. Please invert the camera's z coordinate or");
RajLog.i("call mCamera.setLookAt(0, 0, 0).");
AMaterial.setLoaderContext(context);
mContext = context;
mChildren = Collections.synchronizedList(new CopyOnWriteArrayList<BaseObject3D>());
mFilters = Collections.synchronizedList(new CopyOnWriteArrayList<IPostProcessingFilter>());
mPlugins = Collections.synchronizedList(new CopyOnWriteArrayList<IRendererPlugin>());
mCamera = new Camera();
mCameras = Collections.synchronizedList(new CopyOnWriteArrayList<Camera>());
addCamera(mCamera);
mCamera.setZ(mEyeZ);
mAlpha = 0;
mSceneCachingEnabled = true;
mPostProcessingRenderer = new PostProcessingRenderer(this);
mFrameRate = getRefreshRate();
}
/**
* Sets the camera currently being used to display the scene.
*
* @param mCamera Camera object to display the scene with.
*/
public void setCamera(Camera camera) {
synchronized (mNextCameraLock) {
mNextCamera = camera;
}
}
/**
* Sets the camera currently being used to display the scene.
*
* @param camera Index of the camera to use.
*/
public void setCamera(int camera) {
setCamera(mCameras.get(camera));
}
/**
* Fetches the camera currently being used to display the scene.
* Note that the camera is not thread safe so this should be used
* with extreme caution.
*
* @return Camera object currently used for the scene.
* @see {@link RajawaliRenderer#mCamera}
*/
public Camera getCamera() {
return this.mCamera;
}
/**
* Fetches the specified camera.
*
* @param camera Index of the camera to fetch.
* @return Camera which was retrieved.
*/
public Camera getCamera(int camera) {
return mCameras.get(camera);
}
/**
* Adds a camera to the renderer.
*
* @param camera Camera object to add.
* @return int The index the new camera was added at.
*/
public int addCamera(Camera camera) {
mCameras.add(camera);
return (mCameras.size() - 1);
}
/**
* Replaces a camera in the renderer at the specified location
* in the list. This does not validate the index, so if it is not
* contained in the list already, an exception will be thrown.
*
* @param camera Camera object to add.
* @param location Integer index of the camera to replace.
*/
public void replaceCamera(Camera camera, int location) {
mCameras.set(location, camera);
}
/**
* Adds a camera with the option to switch to it immediately
*
* @param camera The Camera to add.
* @param useNow Boolean indicating if we should switch to this
* camera immediately.
* @return int The index the new camera was added at.
*/
public int addCamera(Camera camera, boolean useNow) {
int index = addCamera(camera);
if (useNow) setCamera(camera);
return index;
}
/**
* Replaces a camera at the specified index with an option to switch to it
* immediately.
*
* @param camera The Camera to add.
* @param location The index of the camera to replace.
* @param useNow Boolean indicating if we should switch to this
* camera immediately.
*/
public void replaceCamera(Camera camera, int location, boolean useNow) {
replaceCamera(camera, location);
if (useNow) setCamera(camera);
}
public void requestColorPickingTexture(ColorPickerInfo pickerInfo) {
mPickerInfo = pickerInfo;
}
public void onDrawFrame(GL10 glUnused) {
synchronized (mNextCameraLock) {
//Check if we need to switch the camera, and if so, do it.
if (mNextCamera != null) {
mCamera = mNextCamera;
mNextCamera = null;
mCamera.setProjectionMatrix(mViewportWidth, mViewportHeight);
}
}
render();
++mFrameCount;
if (mFrameCount % 50 == 0) {
long now = System.nanoTime();
double elapsedS = (now - mStartTime) / 1.0e9;
double msPerFrame = (1000 * elapsedS / mFrameCount);
mLastMeasuredFPS = 1000 / msPerFrame;
//RajLog.d("ms / frame: " + msPerFrame + " - fps: " + mLastMeasuredFPS);
mFrameCount = 0;
mStartTime = now;
if(mFPSUpdateListener != null)
mFPSUpdateListener.onFPSUpdate(mLastMeasuredFPS);
}
}
private void render() {
int clearMask = GLES20.GL_COLOR_BUFFER_BIT;
ColorPickerInfo pickerInfo = mPickerInfo;
mTextureManager.validateTextures();
if (pickerInfo != null) {
if(mReloadPickerInfo) pickerInfo.getPicker().reload();
mReloadPickerInfo = false;
pickerInfo.getPicker().bindFrameBuffer();
GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
} else {
if (mFilters.size() == 0)
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
else {
if (mPostProcessingRenderer.isEnabled())
mPostProcessingRenderer.bind();
}
GLES20.glClearColor(mRed, mGreen, mBlue, mAlpha);
}
if (mEnableDepthBuffer) {
clearMask |= GLES20.GL_DEPTH_BUFFER_BIT;
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glDepthFunc(GLES20.GL_LESS);
GLES20.glDepthMask(true);
GLES20.glClearDepthf(1.0f);
}
if (mUsesCoverageAa) {
clearMask |= GL_COVERAGE_BUFFER_BIT_NV;
}
GLES20.glClear(clearMask);
mVMatrix = mCamera.getViewMatrix();
mPMatrix = mCamera.getProjectionMatrix();
if (mSkybox != null) {
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
GLES20.glDepthMask(false);
mSkybox.setPosition(mCamera.getX(), mCamera.getY(), mCamera.getZ());
mSkybox.render(mCamera, mPMatrix, mVMatrix, pickerInfo);
if (mEnableDepthBuffer) {
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glDepthMask(true);
}
}
mCamera.updateFrustum(mPMatrix,mVMatrix); //update frustum plane
for (int i = 0; i < mChildren.size(); i++)
mChildren.get(i).render(mCamera, mPMatrix, mVMatrix, pickerInfo);
if (pickerInfo != null) {
pickerInfo.getPicker().createColorPickingTexture(pickerInfo);
pickerInfo.getPicker().unbindFrameBuffer();
pickerInfo = null;
mPickerInfo = null;
render();
} else if (mPostProcessingRenderer.isEnabled()) {
mPostProcessingRenderer.render();
}
for (int i = 0, j = mPlugins.size(); i < j; i++)
mPlugins.get(i).render();
}
public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep, float yOffsetStep, int xPixelOffset, int yPixelOffset) {
}
public void onTouchEvent(MotionEvent event) {
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
mViewportWidth = width;
mViewportHeight = height;
mCamera.setProjectionMatrix(width, height);
GLES20.glViewport(0, 0, width, height);
}
/* Called when the OpenGL context is created or re-created. Don't set up your scene here,
* use initScene() for that.
*
* @see rajawali.renderer.RajawaliRenderer#initScene
* @see android.opengl.GLSurfaceView.Renderer#onSurfaceCreated(javax.microedition.khronos.opengles.GL10, javax.microedition.khronos.egl.EGLConfig)
*
*/
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
supportsUIntBuffers = gl.glGetString(GL10.GL_EXTENSIONS).indexOf("GL_OES_element_index_uint") > -1;
GLES20.glFrontFace(GLES20.GL_CCW);
GLES20.glCullFace(GLES20.GL_BACK);
if (!mSceneInitialized) {
mTextureManager = new TextureManager(mContext);
initScene();
}
if (!mSceneCachingEnabled) {
mTextureManager.reset();
if (mChildren.size() > 0) {
mChildren.clear();
}
if (mPlugins.size() > 0) {
mPlugins.clear();
}
} else if(mSceneCachingEnabled && mSceneInitialized) {
mTextureManager.reload();
reloadChildren();
if(mSkybox != null)
mSkybox.reload();
if(mPostProcessingRenderer.isInitialized())
mPostProcessingRenderer.reload();
reloadPlugins();
mReloadPickerInfo = true;
}
mSceneInitialized = true;
Log.i("cgb", "cgb******************************onSurfaceCreated(GL10 gl, EGLConfig config)**************");
startRendering();
}
private void reloadChildren() {
for (int i = 0; i < mChildren.size(); i++)
mChildren.get(i).reload();
}
private void reloadPlugins() {
for (int i = 0, j = mPlugins.size(); i < j; i++)
mPlugins.get(i).reload();
}
/**
* Scene construction should happen here, not in onSurfaceCreated()
*/
protected void initScene() {
Log.i("cgb", "cgb******************************init scene**************");
}
protected void destroyScene() {
mSceneInitialized = false;
for (int i = 0; i < mChildren.size(); i++)
mChildren.get(i).destroy();
mChildren.clear();
for (int i = 0, j = mPlugins.size(); i < j; i++)
mPlugins.get(i).destroy();
mPlugins.clear();
Log.i("cgb", "cgb******************************destroy scene**************");
}
public void startRendering() {
if (mTimer != null) {
mTimer.cancel();
mTimer.purge();
Log.i("cgb", "cgb******************************Start rendering**************");
}
mTimer = new Timer();
mTimer.schedule(new RequestRenderTask(), 0, (long) (1000 / mFrameRate));
}
/**
* Stop rendering the scene.
*
* @return true if rendering was stopped, false if rendering was already
* stopped (no action taken)
*/
protected boolean stopRendering() {
Log.i("cgb", "cgb******************************Stop rendering**************");
if (mTimer != null) {
mTimer.cancel();
mTimer.purge();
mTimer = null;
return true;
}
return false;
}
public void onVisibilityChanged(boolean visible) {
if (!visible) {
stopRendering();
} else
startRendering();
}
public void onSurfaceDestroyed() {
stopRendering();
TimerManager.getInstance().clear();
if (mTextureManager != null)
mTextureManager.reset();
destroyScene();
}
public void setSharedPreferences(SharedPreferences preferences) {
this.preferences = preferences;
}
private class RequestRenderTask extends TimerTask {
public void run() {
if (mSurfaceView != null) {
mSurfaceView.requestRender();
}
}
}
public Number3D unProject(float x, float y, float z) {
x = mViewportWidth - x;
y = mViewportHeight - y;
float[] m = new float[16], mvpmatrix = new float[16],
in = new float[4],
out = new float[4];
Matrix.multiplyMM(mvpmatrix, 0, mPMatrix, 0, mVMatrix, 0);
Matrix.invertM(m, 0, mvpmatrix, 0);
in[0] = (x / (float)mViewportWidth) * 2 - 1;
in[1] = (y / (float)mViewportHeight) * 2 - 1;
in[2] = 2 * z - 1;
in[3] = 1;
Matrix.multiplyMV(out, 0, m, 0, in, 0);
if (out[3]==0)
return null;
out[3] = 1/out[3];
return new Number3D(out[0] * out[3], out[1] * out[3], out[2] * out[3]);
}
public float getFrameRate() {
return mFrameRate;
}
public void setFrameRate(int frameRate) {
setFrameRate((float)frameRate);
}
public void setFrameRate(float frameRate) {
this.mFrameRate = frameRate;
if (stopRendering()) {
// Restart timer with new frequency
startRendering();
}
}
public float getRefreshRate() {
return ((WindowManager) mContext
.getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay()
.getRefreshRate();
}
public WallpaperService.Engine getEngine() {
return mWallpaperEngine;
}
public void setEngine(WallpaperService.Engine engine) {
this.mWallpaperEngine = engine;
}
public GLSurfaceView getSurfaceView() {
Log.i("cgb", "cgb******************************get_SufraceView()**************");
return mSurfaceView;
}
public void setSurfaceView(GLSurfaceView surfaceView) {
this.mSurfaceView = surfaceView;
}
public Context getContext() {
return mContext;
}
public TextureManager getTextureManager() {
return mTextureManager;
}
public void addChild(BaseObject3D child) {
mChildren.add(child);
}
public void clearChildren() {
mChildren.clear();
}
public void addPlugin(IRendererPlugin plugin) {
mPlugins.add(plugin);
}
public void clearPlugins() {
mPlugins.clear();
}
protected void setSkybox(int resourceId) {
mCamera.setFarPlane(1000);
mSkybox = new Cube(700, true, false);
mSkybox.setDoubleSided(true);
mSkyboxTextureInfo = mTextureManager.addTexture(BitmapFactory.decodeResource(mContext.getResources(), resourceId));
SimpleMaterial material = new SimpleMaterial();
material.addTexture(mSkyboxTextureInfo);
mSkybox.setMaterial(material);
}
protected void setSkybox(int front, int right, int back, int left, int up, int down) {
mCamera.setFarPlane(1000);
mSkybox = new Cube(700, true);
Bitmap[] textures = new Bitmap[6];
textures[0] = BitmapFactory.decodeResource(mContext.getResources(), left);
textures[1] = BitmapFactory.decodeResource(mContext.getResources(), right);
textures[2] = BitmapFactory.decodeResource(mContext.getResources(), up);
textures[3] = BitmapFactory.decodeResource(mContext.getResources(), down);
textures[4] = BitmapFactory.decodeResource(mContext.getResources(), front);
textures[5] = BitmapFactory.decodeResource(mContext.getResources(), back);
mSkyboxTextureInfo = mTextureManager.addCubemapTextures(textures);
SkyboxMaterial mat = new SkyboxMaterial();
mat.addTexture(mSkyboxTextureInfo);
mSkybox.setMaterial(mat);
}
protected void updateSkybox(int resourceId) {
mTextureManager.updateTexture(mSkyboxTextureInfo, BitmapFactory.decodeResource(mContext.getResources(), resourceId));
}
protected void updateSkybox(int front, int right, int back, int left, int up, int down) {
Bitmap[] textures = new Bitmap[6];
textures[0] = BitmapFactory.decodeResource(mContext.getResources(), left);
textures[1] = BitmapFactory.decodeResource(mContext.getResources(), right);
textures[2] = BitmapFactory.decodeResource(mContext.getResources(), up);
textures[3] = BitmapFactory.decodeResource(mContext.getResources(), down);
textures[4] = BitmapFactory.decodeResource(mContext.getResources(), front);
textures[5] = BitmapFactory.decodeResource(mContext.getResources(), back);
mTextureManager.updateCubemapTextures(mSkyboxTextureInfo, textures);
}
public boolean removeChild(BaseObject3D child) {
return mChildren.remove(child);
}
public boolean removePlugin(IRendererPlugin plugin) {
return mPlugins.remove(plugin);
}
public int getNumPlugins() {
return mPlugins.size();
}
public List<IRendererPlugin> getPlugins() {
return mPlugins;
}
public boolean hasPlugin(IRendererPlugin plugin) {
return mPlugins.contains(plugin);
}
public int getNumChildren() {
return mChildren.size();
}
public List<BaseObject3D> getChildren() {
return mChildren;
}
protected boolean hasChild(BaseObject3D child) {
return mChildren.contains(child);
}
public void addPostProcessingFilter(IPostProcessingFilter filter) {
if(mFilters.size() > 0)
mFilters.remove(0);
mFilters.add(filter);
mPostProcessingRenderer.setEnabled(true);
mPostProcessingRenderer.setFilter(filter);
}
public void accept(INodeVisitor visitor) {
visitor.apply(this);
for (int i = 0; i < mChildren.size(); i++)
mChildren.get(i).accept(visitor);
}
public void removePostProcessingFilter(IPostProcessingFilter filter) {
mFilters.remove(filter);
}
public void clearPostProcessingFilters() {
mFilters.clear();
mPostProcessingRenderer.unbind();
mPostProcessingRenderer.destroy();
mPostProcessingRenderer = new PostProcessingRenderer(this);
}
public int getViewportWidth() {
return mViewportWidth;
}
public int getViewportHeight() {
return mViewportHeight;
}
public void setBackgroundColor(float red, float green, float blue, float alpha) {
mRed = red;
mGreen = green;
mBlue = blue;
mAlpha = alpha;
}
public void setBackgroundColor(int color) {
setBackgroundColor(Color.red(color) / 255f, Color.green(color) / 255f, Color.blue(color) / 255f, Color.alpha(color) / 255f);
}
public boolean getSceneInitialized() {
return mSceneInitialized;
}
public void setSceneCachingEnabled(boolean enabled) {
mSceneCachingEnabled = enabled;
}
public boolean getSceneCachingEnabled() {
return mSceneCachingEnabled;
}
public void setFogEnabled(boolean enabled) {
mFogEnabled = enabled;
mCamera.setFogEnabled(enabled);
}
public void setUsesCoverageAa(boolean value) {
mUsesCoverageAa = value;
}
public static boolean isFogEnabled() {
return mFogEnabled;
}
public static int getMaxLights() {
return mMaxLights;
}
public static void setMaxLights(int maxLights) {
RajawaliRenderer.mMaxLights = maxLights;
}
public void setFPSUpdateListener(FPSUpdateListener listener) {
mFPSUpdateListener = listener;
}
public static int checkGLError(String message) {
int error = GLES20.glGetError();
if(error != GLES20.GL_NO_ERROR)
{
StringBuffer sb = new StringBuffer();
if(message != null)
sb.append("[").append(message).append("] ");
sb.append("GLES20 Error: ");
sb.append(GLU.gluErrorString(error));
RajLog.e(sb.toString());
}
return error;
}
public int getNumTriangles() {
int triangleCount = 0;
for (int i = 0; i < mChildren.size(); i++) {
if (mChildren.get(i).getGeometry() != null && mChildren.get(i).getGeometry().getVertices() != null && mChildren.get(i).isVisible())
triangleCount += mChildren.get(i).getGeometry().getVertices().limit() / 9;
}
return triangleCount;
}
}