/
3D graphics on 3D graphics on

3D graphics on - PowerPoint Presentation

mitsue-stanley
mitsue-stanley . @mitsue-stanley
Follow
421 views
Uploaded On 2017-07-13

3D graphics on - PPT Presentation

Android projects based on native code Native OpenGL OGRE3D o n Android Native code What is native code C C code Using C C APIs ID: 569675

android native void ogre native android ogre void app code local window source state amp java surface groot static path library cmd

Share:

Link:

Embed:

Download Presentation from below link

Download Presentation The PPT/PDF document "3D graphics on" is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.


Presentation Transcript

Slide1

3D graphics on Android projects based on native code

Native

OpenGL

, OGRE3D

o

n

AndroidSlide2

Native code?What is native code?C/

C

++

code

Using

C/

C

++

API-s

directly

Why

we

need

it

,

what

should

be

moved

into

native

In

most

situations

native

code

should

be

avoided

Performance

critical

parts

Using

external

cross

platform

APIs

Native

calls

have

a

cost

!Slide3

Native code in an Android projectNeed

separate

SDK:

Android

NDK

Cross

compiling

tools

:

ndk-build

Must be

familiar

with

Java

Native

Interface

(JNI)

Have

to

place

native

code

in

./

jni

folder

Need

special

files

in

./

jni

:

Android.mk

Application.mk

(

optional

)

Have

to

call

ndk-build

before

project

build

Should

load

the

compiled

library

in

Java

code

Use

the

library

through

native

functions

(JNI)Slide4

Java Native Interface I.Allows execution of native

code

from

Java

Native

code

is

compiled

into

a

dynamic

library

Library

should

be

loaded

with

System.loadLibrary

(

String

libraryName

)

Library

is

accesed

through

native

function

calls

Native

functions

does

not

have

definition

,

they

are

implemented

in

the

native

code

:

package

test.jni

;

class

A{

static

{

System.loadLibrary

(”

myLibName

”);}

protected

native

void

myNativeFunc

()

;

protected

void

myFunc

(){

myNativeFunc

();}

}Slide5

Java Native Interface II.Native function declarations

are

special

:

Name

expresses

the

package

and

class

that

declared

it

have

special

input

parameters

Can

be

generated

with

javah

:

javah

test.jni.A

(

A.class

should

be

generated

first

)

javah

output:

#

ifdef

__

cplusplus

extern

"C"

{

#

endif

JNIEXPORT

void

JNICALL

Java_test_

jni

_A_

myNativeFunc

(

JNIEnv

*,

jobject

);

#

ifdef

__

cplusplus

}

#

endifSlide6

Java Native Interface III.Native code should be compiled

into

a

library

Compiled

library

should

be

accessible

by

the

Java

application

in

case

of

Android

it

should

be

packed

into

the

apkSlide7

Android native supportjavah can be used to

generate

native

function

declarations

ndk-build

can

be

used

to

compile

the

native

code

to

a

library

file

Ndk-build

needs

:

Source

files

containing

native

function

definitions

They

are

typically

located

in

./

jni

Android.mk

configuration

file

in

./

jni

This

configuration

file

should

be

properly

filled

After

ndk-build

the

project

can

be

built

as

usual

(

with

NetBeans

for

e.g

.)Slide8

Android.mk simpleLOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := myLibName

LOCAL_SRC_FILES :=

mySourceFile

.

cpp

include $(BUILD_SHARED_LIBRARY)

Name

of

the

library

file

to

be

created

Source

file

in

./

jni

that

contains

native

code

definitionsSlide9

Android.mk advancedLOCAL_PATH := $(call my-dir)include$(CLEAR_VARS)LOCAL_MODULE := OgreJNI

LOCAL_LDLIBS := -

landroid

-

lc

-lm -

ldl

-

llog

-

lEGL

-lGLESv2

LOCAL_LDLIBS += -L./../

MyAPI

/

lib

LOCAL_LDLIBS += -lMyAPILOCAL_STATIC_LIBRARIES := cpufeatures

LOCAL_CFLAGS := -I./../MyAPI/includeLOCAL_CFLAGS += -fexceptions

-frtti -x c++ -D___ANDROID___ -DANDROID -DZZIP_OMIT_CONFIG_HLOCAL_SRC_FILES :=

./MyCode/MainActivity.cppinclude $(BUILD_SHARED_LIBRARY)$(call import-module,android/cpufeatures)

Additional

used

libraries

Additional

library

path

Additional

include path

Source

file

not

in

./

jni

,

Several

source

files

can

be

listedSlide10

NetBeans/Eclipse native supportNetBeans does

not

provide

additional

support

for

native

code

in Android

Eclipse

Right

click

on project – Android Tools – Add native support

jni

folder

,

Android.mk

,

empty

cpp

file created

automatically

Android.mk

refers

to

new

cpp

file

Ndk-build

called

automatically

before

Java

buildSlide11

Pure Native Android Application I.At least

we

need

a

dummy

Java

Activity

to

call

our

native functionsWe also have a built in

„dummy” activityCalls „android_main”

native functionSeparate threadCallbacks

for window and input commandsandroid.app.NativeActivity

android_native_app_glue librarySlide12

Pure Native Android Application II.Android .

mk

LOCAL_STATIC_LIBRARIES :=

android_native_app_glue

include $(BUILD_SHARED_LIBRARY

)

$(

call import-

module,

android

/

native_app_glue

)

AndroidManifest.xml

<

uses-sdk

android:minSdkVersion="9" /><activity android:name

="android.app.NativeActivity"Slide13

Pure Native Android Application III.Source

file

example

:

void

android

_main

(

struct

android

_

app

*

state

) {

state->onAppCmd = handle_

cmd; state->onInputEvent =

handle_input;

while (1) { // Read all pending events. int ident; int events;

struct

android

_poll_source* source;

while ((ident = ALooper_pollAll(-1, NULL, &events

, (void**)&source)) >= 0) { // Process

this event. if (

source != NULL) { source->process(state, source);

} if (state->

destroyRequested) { return;

} } }}…Slide14

Pure Native Android Application IV.

void

handle

_

cmd

(

struct

android

_

app

*

app

, int32_t

cmd

) {

switch (cmd) {

case APP_CMD_INIT_WINDOW: …}

int32_t handle_input(struct android

_app* app, AInputEvent* event) { if(AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {

float

x =

AMotionEvent

_

getX(event, 0); …

return 1; } return

0;}Slide15

OpenGL in native code I.Move performance critical rendering parts to native code

Keep the window and GUI on the Java side

Some features are easier to access from JavaSlide16

OpenGL in native code II.

We

need

Anctivity

with

a

Surface

View

:

public

class

NativeEglExample

extends

Activity

implements

SurfaceHolder.Callback

{

public

void

onCreate(

Bundle

savedInstanceState) {

super.onCreate

(

savedInstanceState

);

nativeOnCreate

();

setContentView

(

R.layout.main

);

SurfaceView

surfaceView

= (

SurfaceView

)

findViewById

(

R.id.surfaceview

);

surfaceView.getHolder

().

addCallback

(

this

);

}

protected

void

onResume

() {

super.onResume

();

nativeOnResume

();

}

protected

void

onPause

() {

super.onPause

();

nativeOnPause

();

}

protected

void

onStop

() {

super.on

Stop

();

nativeOnStop

();

}

...Slide17

OpenGL in native code III.

public

void

surfaceChanged

(

SurfaceHolder

holder

, int

format

,

int

w, int h) {

nativeSetSurface

(

holder.getSurface

());

}

public

void

surfaceCreated

(

SurfaceHolder

holder

) {

}

public

void

surfaceDestroyed

(

SurfaceHolder

holder

) {

nativeSetSurface

(null);

}

public

static

native

void

nativeOnCreate

();

public

static

native

void

nativeOnResume

();

public

static

native

void

nativeOnPause

();

public

static

native

void

nativeOnStop

();

public

static

native

void

nativeSetSurface

(

Surface

surface

);

static

{

System.loadLibrary

("

nativeegl

");

}

}Slide18

OpenGL in native code IV.

Native code:

void JNICALL …_

nativeOnCreate

(

JNIEnv

*

jenv

,

jobject

obj

){

//do your initializations

}

void JNICALL …_

nativeOnResume

(

JNIEnv

*

jenv

,

jobject

obj

){

//do your initializations

//

you can start a

main

loop thread here that calls render()

}

Slide19

OpenGL in native code V.

static

ANativeWindow

*window = 0

;

JNIEXPORT

void JNICALL

…_

nativeSetSurface

(

JNIEnv

*

jenv

,

jobject

obj

,

jobject

surface)

{

if (surface

==

0)

{

ANativeWindow_release

(window);

}

else {

window

= ANativeWindow_fromSurface

(

jenv

, surface);

initializeGLWindow

();

}

return;

}

Slide20

OpenGL in native code VI.

v

oid

initializeGLWindow

()

{

const

EGLint

attribs

[] = {

EGL_SURFACE_TYPE, EGL_WINDOW_BIT,

EGL_BLUE_SIZE, 8,

EGL_GREEN_SIZE, 8,

EGL_RED_SIZE, 8,

EGL_NONE

};

EGLDisplay

display;

EGLConfig

config

;

EGLint

numConfigs

;

EGLint

format;

EGLSurface

surface;

EGLContext

context;

EGLint

width;

EGLint

height;

GLfloat

ratio

;

Slide21

OpenGL in native code VII.

display

=

eglGetDisplay

(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY);

eglInitialize

(display

, 0, 0);

eglChooseConfig

(display

,

attribs

, &

config

, 1, &

numConfigs

);

eglGetConfigAttrib

(display,

config

, EGL_NATIVE_VISUAL_ID, &format);

ANativeWindow_setBuffersGeometry

(window, 0, 0, format);

surface

=

eglCreateWindowSurface

(display,

config

,

window, 0);

context

=

eglCreateContext

(display,

config

, 0, 0);

eglMakeCurrent

(display

, surface, surface, context);

eglQuerySurface

(display

, surface, EGL_WIDTH, &width);

eglQuerySurface

(display

, surface, EGL_HEIGHT, &height);

glViewport

(0

, 0, width, height);

ratio = (

GLfloat

) width / height;

glMatrixMode

(GL_PROJECTION);

glLoadIdentity

();

glFrustumf

(-ratio, ratio, -1, 1, 1, 10);

//other

GL initialization

}

Slide22

OpenGL in native code VIII.

v

oid render()

{

//regular GL draw calls

glClear

(GL_COLOR_BUFFER_BIT

| GL_DEPTH_BUFFER_BIT);

glMatrixMode

(GL_MODELVIEW);

glLoadIdentity

();

glTranslatef

(0, 0, -3.0f);

//draw with arrays, no

glBegin

/

glEnd

in GLES

glEnableClientState

(GL_VERTEX_ARRAY);

glEnableClientState

(GL_COLOR_ARRAY);

glFrontFace

(GL_CW);

glVertexPointer

(3, GL_FIXED, 0, vertices);

glColorPointer

(4, GL_FIXED, 0, colors);

glDrawElements

(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, indices);

eglSwapBuffers

(_display, _surface

);

}Slide23

OpenGL in native code IX.

void JNICALL …_

nativeOnStop

(

JNIEnv

*

jenv

,

jobject

obj

){

//do

final cleanup

}

void JNICALL …_

nativeOnPause

(

JNIEnv

*

jenv

,

jobject

obj

){

//do your

app state save if necessary

// you can

end your main

thread

here

}Slide24

OpenGL in native code X. (Threads)

Create a thread:

#

include <

pthread.h

>

pthread_t

_

threadId

;

pthread_create

(&_

threadId

, 0,

threadStartCallback

, 0

);Wait thread to terminate:

pthread_join(_threadId, 0);Render thread example:

void* threadStartCallback(void *arg){

while(running) //we can terminate this thread if needed render(); pthread_exit(0); return 0;}Slide25

Pure native OpenGL app I.No Java code is writtenWe use the native app glueandroid_main is called in its separate threadno additional threading needed on the native sideGUI creation and accessing Android features is much harderSlide26

Pure native OpenGL app II.static ANativeWindow *window = 0;void

android

_main(

struct

android

_

app

*

state

)

{

state-

>

onAppCmd

=

handle_cmd; state->

onInputEvent = handle_input; while

(1) { int ident, events

; struct android_poll_source* source; while ((ident = ALooper_pollAll(-1, NULL, &events, (void**)&source)) >= 0) { if

(source != NULL)

{

source-

>process(state, source

); } if (state->

destroyRequested) { return; } } render

(); // same as before }}

void handle_cmd

(struct android_app* app, int32_t cmd) {

switch (cmd) {

case APP_CMD_INIT_WINDOW:

window = state->window; initializeGLWindow() ;//same as before…

}Slide27

Using Ogre on AndroidNow we can use native code in our Android appWhy not use Ogre3D?It is possible …

Still under development (Ogre 1.9)

We have to compile Ogre for Android, instructions:

http://www.ogre3d.org/tikiwiki/CMake%20Quick%20Start%20Guide?tikiversion=Android

We should test if Ogre works on our device

Run the compiled

OgreSampleBrowser

Also available on Google Play (before any build)

In current state (Ogre 1.9 RC1) GLES2 render system is working GLES1 is not

It won’t run on emulator

Min Android 2.3.3Slide28

Ogre3D with Java activity I.Similar to native OpenGL with Java ActivityInitialization, window initialization and rendering is different

Native code

:

static Ogre::Root*

gRoot

= NULL;

void

JNICALL …_

nativeOnCreate

(

JNIEnv

*

jenv

,

jobject

obj

,

jobject

assetManager

){

gRoot

= new Ogre::Root();

gGLESPlugin

= OGRE_NEW GLES2Plugin ();

gRoot

->

installPlugin(

gGLESPlugin

);

gOctreePlugin

= OGRE_NEW

OctreePlugin

();

gRoot

-

>

installPlugin

(

gOctreePlugin

);

//load additional

plugins

(

particlefx

, overlay)

gRoot

-

>

setRenderSystem

(

gRoot

->

getAvailableRenderers

().at(0));

gRoot

-

>

initialise

(false);

//enable loading media files from the

apk

asset folder

assetMgr

=

AAssetManager_fromJava

(

env

,

assetManager

);

if

(

assetMgr

)

{

ArchiveManager

::

getSingleton

().

addArchiveFactory

( new

APKFileSystemArchiveFactory

(

assetMgr

) );

ArchiveManager

::

getSingleton

().

addArchiveFactory

( new

APKZipArchiveFactory

(

assetMgr

) );

}

//

do your

initializations

}Slide29

Ogre3D with Java activity II.

static

ANativeWindow

*window = 0

;

static Ogre::

RenderWindow

*

gRenderWnd

= NULL;

JNIEXPORT

void JNICALL

…_

nativeSetSurface

(

JNIEnv

*

jenv

,

jobject

obj

,

jobject

surface)

{

if (surface

==

0)

{

ANativeWindow_release

(window); }

else {

window

=

ANativeWindow_fromSurface

(

jenv

, surface);

initializeOgreWindow

();

}

return;

}

Slide30

Ogre3D with Java activity III.void initializeOgreWindow

()

{

//create render window based on an existing window

Ogre::

NameValuePairList

opt;

opt["

externalWindowHandle

"] = Ogre::

StringConverter

::

toString

((

int

)

nativeWnd

); AConfiguration* config = AConfiguration_new

(); AConfiguration_fromAssetManager(config, assetMgr);

opt["androidConfig"] = Ogre::StringConverter::toString((int)config); gRenderWnd = Ogre::Root::getSingleton().createRenderWindow("OgreWindow", 0, 0, false, &opt);

ResourceGroupManager

::

getSingleton

().addResourceLocation("/models"

, "APKFileSystem"); ResourceGroupManager::getSingleton().addResourceLocation(

"/material", "APKFileSystem"

); ResourceGroupManager::getSingleton().initialiseAllResourceGroups();

//usual scene graph initialization Ogre::SceneManager* pSceneMgr = gRoot->

createSceneManager(Ogre::ST_GENERIC); Ogre::Camera* pCamera = pSceneMgr->createCamera

("MyCam"); pCamera->

setPosition(100,100,500); pCamera->lookAt(0,0,0); Ogre::Viewport* vp = gRenderWnd->addViewport

(pCamera); vp->setBackgroundColour(Ogre::ColourValue

(1,0,0)); …}Slide31

Ogre3D with Java activity IV.void render()

{

if(

gRenderWnd

!= NULL &&

gRenderWnd

->

isActive

())

{

try

{

gRenderWnd

->

windowMovedOrResized

();

gRoot

->

renderOneFrame

();

}

catch(Ogre::

RenderingAPIException ex) {} }

}Slide32

Ogre3D with Java activity V.Android.mk

LOCAL_PATH

:= $(call my-dir)

include

$(CLEAR_VARS)

LOCAL_MODULE

:=

OgreJNI

LOCAL_LDLIBS :=

-

landroid

-

lc

-lm -

ldl

-

llog

-

lEGL

-lGLESv2

LOCAL_LDLIBS +=

-

L$(OGRE_ANDROID_PATH)/lib

LOCAL_LDLIBS += -L$(OGRE_ANDROID_PATH)/

AndroidDependencies

/lib/armeabi-v7a

LOCAL_LDLIBS += -

lPlugin_OctreeSceneManagerStatic -lRenderSystem_GLES2Static

-lOgreMainStatic

LOCAL_LDLIBS += -lzzip

-lz

-lFreeImage -lfreetype

-lOIS

LOCAL_LDLIBS += -l$(OGRE_ANDROID_PATH)/

systemlibs

/armeabi-v7a/

libsupc

++.a

LOCAL_LDLIBS += -l$(OGRE_ANDROID_PATH)/

systemlibs

/armeabi-v7a/

libstdc

++.a

LOCAL_STATIC_LIBRARIES

:=

cpufeatures

LOCAL_CFLAGS

:= -DGL_GLEXT_PROTOTYPES=1

LOCAL_CFLAGS

+=

-

I$(OGRE_ANDROID_PATH)

OgreMain

/include

LOCAL_CFLAGS +=

-I$(OGRE_ANDROID_PATH)

RenderSystems

/GLES2/include

LOCAL_CFLAGS +=

-I$(OGRE_ANDROID_PATH)

RenderSystems

/GLES2/include/EGL

LOCAL_CFLAGS += -

I$(ANDROID_NDK)/sources/

cpufeatures

LOCAL_CFLAGS +=

-I$(OGRE_ANDROID_PATH)

PlugIns

/

OctreeSceneManager

/include

LOCAL_CFLAGS

+= -

I$(OGRE_ANDROID_PATH)

AndroidDependencies

/include

LOCAL_CFLAGS +=

-I$(OGRE_ANDROID_PATH)

AndroidDependencies

/include/OIS

LOCAL_CFLAGS += -

fexceptions

-

frtti

-x

c++

-D___ANDROID___ -DANDROID -DZZIP_OMIT_CONFIG_H

LOCAL_SRC_FILES

:=

MainActivity.cpp

include

$(BUILD_SHARED_LIBRARY)

$(

call import-

module,android

/

cpufeatures

)Slide33

Using Ogre in pure native app I.

Similar to

pure native OpenGL application

Code:

//

globals

RenderWindow

*

gRenderWindow

= NULL;

Root*

gRoot

= NULL;

static

ANativeWindow

*window =

NULL;Slide34

Using Ogre in pure native app II.

void

android_main

(

struct

android_app

* state) {

app_dummy

();

gRoot

= new Ogre::Root();

gRoot

>installPlugin(OGRE_NEW GLES2Plugin());

gRoot >installPlugin(OGRE_NEW OctreePlugin()); gRoot

>setRenderSystem(root->getAvailableRenderers().at(0)); gRoot

>initialise(false); ArchiveManager::getSingleton().addArchiveFactory( new APKFileSystemArchiveFactory(state->activity->assetManager) ); ArchiveManager

::

getSingleton

().

addArchiveFactory

( new APKZipArchiveFactory(state->activity->assetManager) );

state->onAppCmd = handleCmd; int ident, events;

struct android_poll_source* source; while (true){

while ((ident = ALooper_pollAll(0, NULL, &events, (void**)&source)) >= 0){

if (source != NULL) source->process(state, source); if (state->destroyRequested != 0) return; }

if(renderWindow != NULL && renderWindow->isActive()){

gRenderWindow->windowMovedOrResized();

gRoot->renderOneFrame(); } }}Slide35

Using Ogre in pure native app III.

void

handleCmd

(

struct

android_app

* app, int32_t

cmd

){

switch (

cmd

){

case APP_CMD_SAVE_STATE:

break;

case APP_CMD_INIT_WINDOW

:

window = state->window;

initializeOgreWindow

(); //same as above break; case APP_CMD_TERM_WINDOW:

if(gRoot && gRenderWindow) static_cast<AndroidEGLWindow*>(gRenderWindow)->_destroyInternalResources(); break;

}

}Slide36

The End