Использование 3D графики в J2ME. Простейшее 3D приложение


Введение

Возможность работать с 3D графикой программисты получили вместе с выходом MIDP 2.0, в состав которого был включен дополнительный пакет "Mobile 3D Graphics API" (или JSR 184). Фактически он является Java стандартом для работы с 3D графикой на портативных устройствах. Пакет имеет два уровня, верхний - retained mode и нижний - immediate mode. Первый позволяет работать с 3D сценами, используя виртуальную камеру и источники света. Второй - непосредственно рисовать объекты. Оба уровня при необходимости могут использоваться в одном приложении.

В этой статье будет рассмотрен immediate mode.

Для начала давайте перечислим классы, которые предоставляет в наше распоряжение 3D API. (В дополнение к API, JSR 184 также содержит структуры для описания сцен и соответствующий формат для эффективного представления и развертывания 3D контента. В JSR используется m3g формат файлов.)

3D API классы

AnimationControllerКонтролирует последовательность мультипликации
AnimationTrackСвязывает KeyframeSequence с AnimationController.
AppearanceНабор объектов для представления атрибутов рендеринга Mesh или Spring3D
BackgroundОпределяет способ очистки видео порта
CameraУзловой элемент сцены, определяющий положение камеры и экрана проекции
CompositingModeКласс Appearance, формирующий атрибуты композиции в пикселях
FogКласс Appearance, определяющий параметры тумана.
Graphics3DЕдиничный элемент 3D графики. Весь рендеринг осуществляется через метод render() этого класса.
GroupУзловой элемент графической сцены, позволяющий сохранять неупорядоченный набор других узлов как свои дочерние записи.
Image2DДвухмерное изображение, которое может использоваться в качестве текстуры, заднего плана или спрайта.
IndexBufferЭтот класс определяет, как нужно соединить вершины, для того чтобы получить геометрический объект.
KeyframeSequenceФормирует анимацию, как последовательность ключевых кадров с временными метками.
LightПредставляет различные виды источников света.
LoaderЗагружает графические узлы и узлы других компонентов в законченную графическую сцену.
MaterialФормирует атрибуты материала для правильного вычисления освещения.
MeshПредставляет трехмерный объект, определенный как полигонная поверхность.
MorphingMeshПредставляет трансформацию вершин полигонной поверхности.
NodeАбстрактный класс узлов графической сцены. Всего поддерживается пять видов узлов: Camera, Mesh, Sprite3D, Light, и Group.
Object3DАбстрактный класс для объекта, являющегося частью 3D мира.
PolygonModeФормирует параметры полигонов.
RayIntersectionСохраняет ссылку на пересечение Mesh или Sprite3D и информацию о точке пересечения.
SkinnedMeshПредставляет скелетную анимацию полигонной сети.
Sprite3DПредставляет 2D изображение в трехмерном пространстве.
Texture2DФормирует 2D рисунок текстуры и набор параметров, определяющих способ "прикрепления" текстуры.
Transformуниверсальная матрица вещественных чисел размером 4x4, представляющая трансформацию.
TransformableАбстрактный базовый класс для Node и Texture2D.
TriangleStripArrayОпределяет массив полос треугольников.
VertexArrayМассив целочисленных векторов, представляющих положение вершин, нормалей, цветов или текстурных координат.
VertexBufferСохраняет ссылки на VertexArrays, содержащий положение вершин, нормалей, цветов или текстурных координат для набора вершин.
WorldСпециальный узел группы, являющийся контейнером самого верхнего уровня для графической сцены.

Простейшее J2ME 3D приложение

Давайте напишем простейшее 3D приложение - вращающийся полигон. Наш полигон - кубик, на который натянута текстура. В листинге 1 приведен главный класс MIDlet-а. Он создает приложение и устанавливает таймер для запуска MyCanvas

<b>Листинг1. Класс MIDletMain</b>
 
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.util.*;
 
publicclass MIDletMainextends MIDlet{
static MIDletMain midlet;
MyCanvas d=new MyCanvas();
Timer iTimer=new Timer();
 
public MIDletMain(){
this.midlet= this;
}
 
public void startApp(){
Display.getDisplay(this).setCurrent(d);
iTimer.schedule(new MyTimerTask(),0,40);
}
 
public void pauseApp(){
}
 
public void destroyApp(boolean unconditional){
}
 
 
public static void quitApp(){
midlet.destroyApp(true);
midlet.notifyDestroyed();
midlet=null;
}
 
 
class MyTimerTaskextends TimerTask{
public void run(){
if( d!=null){
d.repaint();
}
}
}
}
 

В листинге 2 показан класс MyCanvas. Он содержит все операции с графикой. В методе init() создаются вершины, загружается и устанавливается текстура. Также там задаются вид и задний план. Метод paint() рисует и вращает куб.

<b>Листинг2. Класс MyCanvas</b>
import javax.microedition.lcdui.*;
import javax.microedition.m3g.*;
 
publicclass MyCanvasextends Canvas{
 
private Graphics3D graphics3d;
private Camera camera;
private Light light;
private float angle= 0.0f;
private Transform transform=new Transform();
private Background background=new Background();
private VertexBuffer vbuffer;
private IndexBuffer indexbuffer;
private Appearance appearance;
private Material material=new Material();
private Image image;
 
public MyCanvas(){
// Устанавливаем Displayable для прослушивания команд от пользователя
setCommandListener(new CommandListener(){
public void commandAction(Command c, Displayable d){
if(c.getCommandType()== Command.EXIT){
MIDletMain.quitApp();}}
});
try{ init();}
catch(Exception e){ e.printStackTrace();}
}
 
/**
* Инициализация.
*/
private void init() throws Exception{
addCommand(new Command("Exit", Command.EXIT,1));
graphics3d= Graphics3D.getInstance();
 
camera=new Camera();
camera.setPerspective( 60.0f,
(float)getWidth()/(float)getHeight(),
1.0f,
1000.0f);
 
light=new Light();
light.setColor(0xffffff);
light.setIntensity(1.25f);
 
short[] vert={
5,5,5,-5,5,5,5,-5,5,-5,-5,5,
-5,5,-5,5,5,-5,-5,-5,-5,5,-5,-5,
-5,5,5,-5,5,-5,-5,-5,5,-5,-5,-5,
5,5,-5,5,5,5,5,-5,-5,5,-5,5,
5,5,-5,-5,5,-5,5,5,5,-5,5,5,
5,-5,5,-5,-5,5,5,-5,-5,-5,-5,-5};
 
VertexArray vertArray=new VertexArray(vert.length/3,3,2);
vertArray.set(0, vert.length/3, vert);
 
// Задаем нормали куба
byte[] norm={
0,0,127,0,0,127,0,0,127,0,0,127,
0,0,-127,0,0,-127,0,0,-127,0,0,-127,
-127,0,0,-127,0,0,-127,0,0,-127,0,0,
127,0,0,127,0,0,127,0,0,127,0,0,
0,127,0,0,127,0,0,127,0,0,127,0,
0,-127,0,0,-127,0,0,-127,0,0,-127,0};
 
VertexArray normArray=new VertexArray(norm.length/3,3,1);
normArray.set(0, norm.length/3, norm);
 
// Задаем текстурные координаты
short[] tex={
1,0,0,0,1,1,0,1,
1,0,0,0,1,1,0,1,
1,0,0,0,1,1,0,1,
1,0,0,0,1,1,0,1,
1,0,0,0,1,1,0,1,
1,0,0,0,1,1,0,1};
 
VertexArray texArray=new VertexArray(tex.length/2,2,2);
texArray.set(0, tex.length/2, tex);
 
int[] stripLen={4,4,4,4,4,4};
 
// VertexBuffer для нашего объекта
VertexBuffer vb= vbuffer=new VertexBuffer();
vb.setPositions(vertArray, 1.0f,null);
vb.setNormals(normArray);
vb.setTexCoords(0, texArray, 1.0f,null);
 
indexbuffer=new TriangleStripArray(0, stripLen);
 
// изображение для текстуры
image= Image.createImage("/pic1.png");
Image2D image2D=new Image2D( Image2D.RGB, image);
Texture2D texture=new Texture2D( image2D);
texture.setFiltering(Texture2D.FILTER_NEAREST,
Texture2D.FILTER_NEAREST);
texture.setWrapping(Texture2D.WRAP_CLAMP,
Texture2D.WRAP_CLAMP);
texture.setBlending(Texture2D.FUNC_MODULATE);
 
// создаем вид
appearance=new Appearance();
appearance.setTexture(0, texture);
appearance.setMaterial(material);
material.setColor(Material.DIFFUSE,0xFFFFFFFF);
material.setColor(Material.SPECULAR,0xFFFFFFFF);
material.setShininess(100.0f);
 
background.setColor(0xffffcc);
}
 
protected void paint(Graphics g){
graphics3d.bindTarget(g,true,
Graphics3D.DITHER|
Graphics3D.TRUE_COLOR);
graphics3d.clear(background);
 
// устанавливаем камеру
Transform transform=new Transform();
transform.postTranslate(0.0f, 0.0f, 30.0f);
graphics3d.setCamera(camera, transform);
 
// Устанавливаем имточники света
graphics3d.resetLights();
graphics3d.addLight(light, transform);
 
// Задаем вращение
angle+= 1.0f;
transform.setIdentity();
transform.postRotate(angle, 1.0f, 1.0f, 1.0f);
 
graphics3d.render(vbuffer, indexbuffer, appearance, transform);
graphics3d.releaseTarget();
}
}

Конечно, эта статья не в коей мере не претендует на руководство по созданию 3D игр, но она позволяет увидеть всю простоту и доступность создания 3D приложений для телефонов.

Статья основана на документе
"Developing Mobile 3D Graphics for J2ME (JSR-184)"
by Mikko Kontio
.
Перевод: aRix




Наши соцсети

Подписаться Facebook Подписаться Вконтакте Подписаться Twitter Подписаться Google Подписаться Telegram

Популярное

Ссылки

Новости [1] [2] [3]... Android/ iOS/ J2ME[1] [2] [3]) Android / Архив

Рейтинг@Mail.ru Яндекс.Метрика
MobiLab.ru © 2005-2018
При использовании материалов сайта ссылка на www.mobilab.ru обязательна