分享
 
 
 

3D编程指南第三部分:粒子系统和立即模式渲染(2)

王朝other·作者佚名  2008-05-31
窄屏简体版  字體: |||超大  

TutorialMidlet

import Javax.microedition.lcdui.Command;

import javax.microedition.lcdui.CommandListener;

import javax.microedition.lcdui.Display;

import javax.microedition.lcdui.Displayable;

import javax.microedition.midlet.MIDlet;

import javax.microedition.midlet.MIDletStateChangeException;

public class TutorialMidlet extends MIDlet implements CommandListener

{

// A variable that holds the unique display

private Display display = null;

// The canvas

private M3GCanvas canvas = null;

// The MIDlet itself

private static MIDlet self = null;

/** Called when the application starts, and when it is resumed.

* We ignore the resume here and allocate data for our canvas

* in the startApp method. This is generally very bad practice.

*/

protected void startApp() throws MIDletStateChangeException

{

// Allocate

display = Display.getDisplay(this);

canvas = new M3GCanvas(30);

// Add a quit command to the canvas

// This command won't be seen, as we

// are running in fullScreen mode

// but it's always nice to have a quit command

canvas.addCommand(new Command("Quit", Command.EXIT, 1));

// Set the listener to be the MIDlet

canvas.setCommandListener(this);

// Start canvas

canvas.start();

display.setCurrent(canvas);

// Set the self

self = this;

}

/** Called when the game should pause, sUCh as during a call */

protected void pauseApp()

{

}

/** Called when the application should shut down */

protected void destroyApp(boolean unconditional) throws MIDletStateChangeException

{

// Method that shuts down the entire MIDlet

notifyDestroyed();

}

/** Listens to commands and processes */

public void commandAction(Command c, Displayable d) {

// If we get an EXIT command we destroy the application

if(c.getCommandType() == Command.EXIT)

notifyDestroyed();

}

/** Static method that quits our application

* by using the static field 'self' */

public static void die()

{

self.notifyDestroyed();

}

}

M3GCanvas

import javax.microedition.lcdui.Graphics;

import javax.microedition.lcdui.game.GameCanvas;

import javax.microedition.m3g.Background;

import javax.microedition.m3g.Camera;

import javax.microedition.m3g.Graphics3D;

import javax.microedition.m3g.Light;

import javax.microedition.m3g.Transform;

public class M3GCanvas

extends GameCanvas

implements Runnable {

// Thread-control

boolean running = false;

boolean done = true;

// If the game should end

public static boolean gameOver = false;

// Rendering hints

public static final int STRONG_RENDERING_HINTS = Graphics3D.ANTIALIAS Graphics3D.TRUE_COLOR Graphics3D.DITHER;

public static final int WEAK_RENDERING_HINTS = 0;

public static int RENDERING_HINTS = STRONG_RENDERING_HINTS;

// Key array

boolean[] key = new boolean[5];

// Key constants

public static final int FIRE = 0;

public static final int UP = FIRE + 1;

public static final int DOWN = UP + 1;

public static final int LEFT = DOWN + 1;

public static final int RIGHT = LEFT + 1;

// Global identity matrix

Transform identity = new Transform();

// Global Graphics3D object

Graphics3D g3d = null;

// The background

Background back = null;

// The global camera object

Camera cam = null;

// The particle system

ParticleSystem ps = null;

FountainEffect fx = null;

/** Constructs the canvas

*/

public M3GCanvas(int fps)

{

// We don't want to capture keys normally

super(true);

// We want a fullscreen canvas

setFullScreenMode(true);

// Load our camera

loadCamera();

// Load our background

loadBackground();

// Set up graphics 3d

setUp();

}

/** Prepares the Graphics3D engine for immediate mode rendering by adding a light */

private void setUp()

{

// Get the instance

g3d = Graphics3D.getInstance();

// Add a light to our scene, so we can see something

g3d.addLight(createAmbientLight(), identity);

}

/** Creates a simple ambient light */

private Light createAmbientLight()

{

Light l = new Light();

l.setMode(Light.AMBIENT);

l.setIntensity(1.0f);

return l;

}

/** When fullscreen mode is set, some devices will call

* this method to notify us of the new width/height.

* However, we don't really care about the width/height

* in this tutorial so we just let it be

*/

public void sizeChanged(int newWidth, int newHeight)

{

}

/** Loads our camera */

private void loadCamera()

{

// Create a new camera

cam = new Camera();

}

/** Loads the background */

private void loadBackground()

{

// Create a new background, set bg color to black

back = new Background();

back.setColor(0);

}

/** Draws to screen

*/

private void draw(Graphics g)

{

// Envelop all in a try/catch block just in case

try

{

// Get the Graphics3D context

g3d = Graphics3D.getInstance();

// First bind the graphics object. We use our pre-defined rendering hints.

g3d.bindTarget(g, true, RENDERING_HINTS);

// Clear background

g3d.clear(back);

// Bind camera at fixed position in origo

g3d.setCamera(cam, identity);

// Init particles

if(ps == null)

{

fx = new FountainEffect(90);

ps = new ParticleSystem(fx, 20);

}

// Emit the particles

ps.emit(g3d);

// Check controls for fountain rotation

if(key[LEFT])

fx.setAngle(fx.getAngle() + 5);

if(key[RIGHT])

fx.setAngle(fx.getAngle() - 5);

// Quit if user presses fire

if(key[FIRE])

TutorialMidlet.die();

}

catch(Exception e)

{

reportException(e);

}

finally

{

// Always remember to release!

g3d.releaseTarget();

}

}

/** Starts the canvas by firing up a thread

*/

public void start() {

Thread myThread = new Thread(this);

// Make sure we know we are running

running = true;

done = false;

// Start

myThread.start();

}

/** Run, runs the whole thread. Also keeps track of FPS

*/

public void run() {

while(running) {

try {

// Call the process method (computes keys)

process();

// Draw everything

draw(getGraphics());

flushGraphics();

// Sleep to prevent starvation

try{ Thread.sleep(30); } catch(Exception e) {}

}

catch(Exception e) {

reportException(e);

}

}

// Notify completion

done = true;

}

/**

* @param e

*/

private void reportException(Exception e) {

System.out.println(e.getMessage());

System.out.println(e);

e.printStackTrace();

}

/** Pauses the game

*/

public void pause() {}

/** Stops the game

*/

public void stop() { running = false; }

/** Processes keys

*/

protected void process()

{

int keys = getKeyStates();

if((keys & GameCanvas.FIRE_PRESSED) != 0)

key[FIRE] = true;

else

key[FIRE] = false;

if((keys & GameCanvas.UP_PRESSED) != 0)

key[UP] = true;

else

key[UP] = false;

if((keys & GameCanvas.DOWN_PRESSED) != 0)

key[DOWN] = true;

else

key[DOWN] = false;

if((keys & GameCanvas.LEFT_PRESSED) != 0)

key[LEFT] = true;

else

key[LEFT] = false;

if((keys & GameCanvas.RIGHT_PRESSED) != 0)

key[RIGHT] = true;

else

key[RIGHT] = false;

}

/** Checks if thread is running

*/

public boolean isRunning() { return running; }

/** checks if thread has finished its execution completely

*/

public boolean isDone() { return done; }

}

MeshFactory

import javax.microedition.lcdui.Image;

import javax.microedition.m3g.Appearance;

import javax.microedition.m3g.Image2D;

import javax.microedition.m3g.IndexBuffer;

import javax.microedition.m3g.Mesh;

import javax.microedition.m3g.PolygonMode;

import javax.microedition.m3g.Texture2D;

import javax.microedition.m3g.TriangleStripArray;

import javax.microedition.m3g.VertexArray;

import javax.microedition.m3g.VertexBuffer;

/**

* Static class that handles creation of code-generated Meshes

*/

public class MeshFactory

{

/** Creates a texture plane that is alpha-blended

*

* @param texFilename The name of the texture image file

* @param cullFlags The flags for culling. See PolygonMode.

* @param alpha The alpha value of blending. Is a full color in 0xAARRGGBB format

* @return The finished textured mesh

*/

public static Mesh createAlphaPlane(String texFilename, int cullFlags, int alpha)

{

// Create a normal mesh

Mesh mesh = createPlane(texFilename, cullFlags);

// Make it blended

MeshOperator.convertToBlended(mesh, alpha, Texture2D.FUNC_BLEND);

return mesh;

}

/**

* Creates a textured plane.

* @param texFilename The name of the texture image file

* @param cullFlags The flags for culling. See PolygonMode.

* @return The finished textured mesh

*/

public static Mesh createPlane(String texFilename, int cullFlags)

{

// The vertrices of the plane

short vertrices[] = new short[] {-1, -1, 0,

1, -1, 0,

1, 1, 0,

-1, 1, 0};

// Texture coords of the plane

short texCoords[] = new short[] {0, 255,

255, 255,

255, 0,

0, 0};

// The classes

VertexArray vertexArray, texArray;

IndexBuffer triangles;

// Create the model's vertrices

vertexArray = new VertexArray(vertrices.length/3, 3, 2);

vertexArray.set(0, vertrices.length/3, vertrices);

// Create the model's texture coords

texArray = new VertexArray(texCoords.length / 2, 2, 2);

texArray.set(0, texCoords.length / 2, texCoords);

// Compose a VertexBuffer out of the previous vertrices and texture coordinates

VertexBuffer vertexBuffer = new VertexBuffer();

vertexBuffer.setPositions(vertexArray, 1.0f, null);

vertexBuffer.setTexCoords(0, texArray, 1.0f/255.0f, null);

// Create indices and face lengths

int indices[] = new int[] {0, 1, 3, 2};

int[] stripLengths = new int[] {4};

// Create the model's triangles

triangles = new TriangleStripArray(indices, stripLengths);

// Create the appearance

Appearance appearance = new Appearance();

PolygonMode pm = new PolygonMode();

pm.setCulling(cullFlags);

appearance.setPolygonMode(pm);

// Create and set the texture

try

{

// Open image

Image texImage = Image.createImage(texFilename);

Texture2D theTexture = new Texture2D(new Image2D(Image2D.RGBA, texImage));

// Replace the mesh's original colors (no blending)

theTexture.setBlending(Texture2D.FUNC_REPLACE);

// Set wrapping and filtering

theTexture.setWrapping(Texture2D.WRAP_CLAMP, Texture2D.WRAP_CLAMP);

theTexture.setFiltering(Texture2D.FILTER_BASE_LEVEL, Texture2D.FILTER_NEAREST);

// Add texture to the appearance

appearance.setTexture(0, theTexture);

}

catch(Exception e)

{

// Something went wrong

System.out.println("Failed to create texture");

System.out.println(e);

}

// Finally create the Mesh

Mesh mesh = new Mesh(vertexBuffer, triangles, appearance);

// All done

return mesh;

}

}

MeshOperator

import javax.microedition.m3g.CompositingMode;

import javax.microedition.m3g.Mesh;

/**

* Performs some basic operations on Mesh objects

*/

public class MeshOperator

{

/** Sets the alpha blending of a mesh. Only meaningful if the mesh already is alpha blended */

public static void setMeshAlpha(Mesh m, int alpha)

{

m.getVertexBuffer().setDefaultColor(alpha);

}

/**

*

* @param m The mesh to convert to a blended one

* @param alpha The alpha color to blend with

* @param textureBlending The texture blending parameter.

*/

public static void convertToBlended(Mesh m, int alpha, int textureBlending)

{

// Set the alpha

setMeshAlpha(m, alpha);

// Fix the compositing mode

CompositingMode cm = new CompositingMode();

cm.setBlending(CompositingMode.ALPHA);

m.getAppearance(0).setCompositingMode(cm);

m.getAppearance(0).getTexture(0).setBlending(textureBlending);

}

}

Particle

/**

* Holds all the information of a particle.

* A particle's alpha is controlled directly by its life. Its alpha is always

* life * 255.

*/

public class Particle

{

// The life of the particle. Goes from 1.0f to 0.0f

private float life = 1.0f;

// The degradation of the particle

private float degradation = 0.1f;

// The velocities of the particle

private float[] vel = {0.0f, 0.0f, 0.0f};

// The position of the particle

private float[] pos = {0.0f, 0.0f, 0.0f};

// The color of the particle (RGB format 0xRRGGBB)

private int color = 0xffffff;

/** Empty initialization */

public Particle()

{

}

/**

* Initializes the particle

* @param velocity Sets the velocity

* @param position Sets the position

* @param color Sets the color (no alpha)

*/

public Particle(float[] velocity, float[] position, int color)

{

setVel(velocity);

setPos(position);

this.setColor(color);

}

/**

* @param life The life to set.

*/

void setLife(float life) {

this.life = life;

}

/**

* @return Returns the life.

*/

float getLife() {

return life;

}

/**

* @param vel The vel to set.

*/

void setVel(float[] tvel) {

System.arraycopy(tvel, 0, vel, 0, vel.length);

}

/**

* @return Returns the vel.

*/

float[] getVel() {

return vel;

}

/**

* @param pos The pos to set.

*/

void setPos(float[] tpos) {

System.arraycopy(tpos, 0, pos, 0, pos.length);

}

/**

* @return Returns the pos.

*/

float[] getPos() {

return pos;

}

/**

* @param color The color to set.

*/

void setColor(int color) {

this.color = color;

}

/**

* @return Returns the color.

*/

int getColor() {

return color;

}

/**

* @param degradation The degradation to set.

*/

public void setDegradation(float degradation) {

this.degradation = degradation;

}

/**

* @return Returns the degradation.

*/

public float getDegradation() {

return degradation;

}

}

ParticleEffect

import javax.microedition.m3g.Graphics3D;

/**

* The interface that determines which effect the particle engine will display.

* The ParticleEffect class also holds information about the bitmap used

* for displaying particles (if any)

*/

public interface ParticleEffect

{

// Initializes a particle

public void init(Particle p);

// Updates a particle

public void update(Particle p);

// Renders a particle

public void render(Particle p, Graphics3D g3d);

}

BitmapParticleEffect

import javax.microedition.m3g.Graphics3D;

import javax.microedition.m3g.Mesh;

import javax.microedition.m3g.PolygonMode;

import javax.microedition.m3g.Transform;

/**

* Represents a particle effect that uses a bitmap.

*/

public abstract class BitmapParticleEffect implements ParticleEffect

{

// The mesh

Mesh mesh = null;

// The transformation matrix

Transform trans = new Transform();

// The scale

float scale = 1.0f;

/** Initializes the bitmap used to render particles */

public BitmapParticleEffect(String filename, float scale)

{

// Load the plane with the wanted texture

mesh = MeshFactory.createAlphaPlane(filename, PolygonMode.CULL_BACK, 0xffffffff);

// Make sure we set the scale

this.scale = scale;

}

/**

* @see ParticleEffect#render(Particle, Graphics3D)

*/

public void render(Particle p, Graphics3D g3d)

{

// Calculate the alpha

int alpha = (int)(255 * p.getLife());

// Create the color

int color = p.getColor() (alpha << 24);

// Set alpha

MeshOperator.setMeshAlpha(mesh, color);

// Transform

trans.setIdentity();

trans.postScale(scale, scale, scale);

float[] pos = p.getPos();

trans.postTranslate(pos[0], pos[1], pos[2]);

// Render

g3d.render(mesh, trans);

}

}

FountainEffect

import java.util.Random;

/*

* Created on 2005-aug-31

*/

/**

* Creates a nice fountain effect for the particles, that shoots particles

* in a certain direction, determined by its angle. The angle can be changed in real-time.

*/

public class FountainEffect extends BitmapParticleEffect

{

// The angle of particle emission

private int angle = 90;

// The sine and cosine of the current angle

private float[] trig = {1.0f, 0.0f};

// The emitting origin

private float[] pos = {0.0f, 0.0f, 0.0f};

// The randomizer

Random rand = null;

/**

* @param angle The angle of particle emission

*/

public FountainEffect(int angle)

{

// Init the bitmap

super("/res/particle.png", 0.05f);

// Set the angle

setAngle(angle);

// Get randomizer

rand = new Random();

}

/**

* @see ParticleEffect#init(Particle)

*/

public void init(Particle p)

{

// Set the particle's life

p.setLife(1.0f);

// Set the particle's position

p.setPos(pos);

// Create the particle's velocties

float[] vel = new float[3];

// We want velocities from 0.2f to 1.0f

float xyvel = rand.nextFloat() * 0.8f + 0.2f;

// We want the particle to die slowly

p.setDegradation(xyvel / 18);

// Set velocities according to trigonometry with a small deviation

vel[0] = xyvel * trig[1] + rand.nextFloat() * 0.125f - 0.0625f;

vel[1] = xyvel * trig[0] + rand.nextFloat() * 0.125f - 0.0625f;

// No movement in depth

vel[2] = 0.0f;

// Set the velocity

p.setVel(vel);

// Set the random color

int r = (int)(120 * rand.nextFloat()) + 135;

int g = (int)(120 * rand.nextFloat()) + 135;

int b = (int)(120 * rand.nextFloat()) + 135;

int col = (r << 16) (g << 8) b;

p.setColor(col);

}

/**

* @see ParticleEffect#update(Particle)

*/

public void update(Particle p)

{

// Simply update position

float[] ppos = p.getPos();

float[] vel = p.getVel();

ppos[0] += vel[0];

ppos[1] += vel[1];

ppos[2] += vel[2];

// Update life

p.setLife(p.getLife() - p.getDegradation());

// Check life. If it is dead, we just reinit it

if(p.getLife() < -0.001f)

{

init(p);

}

}

/**

* @param angle The angle to set.

*/

public void setAngle(int angle) {

this.angle = angle;

trig[0] = (float)Math.sin(Math.toRadians(angle));

trig[1] = (float)Math.cos(Math.toRadians(angle));

}

/**

* @return Returns the angle.

*/

public int getAngle() {

return angle;

}

/**

* @param pos The pos to set.

*/

void setEmittingOrigin(float[] pos) {

this.pos = pos;

}

/**

* @return Returns the pos.

*/

float[] getEmittingOrigin() {

return pos;

}

}

ParticleSystem

import javax.microedition.m3g.Graphics3D;

/**

* Manages emission of particles in our 3D world

*/

public class ParticleSystem

{

// The effect

private ParticleEffect effect = null;

// The particles

Particle[] parts = null;

/**

* Creates a particle system that emits particles according to a defined effect.

* @param effect The effect that controls the behaviour of the particles

* @param numParticles The number of particles to emit

*/

public ParticleSystem(ParticleEffect effect, int numParticles)

{

// Copy the effect

setEffect(effect);

// Init the particles

parts = new Particle[numParticles];

for(int i = 0; i < numParticles; i++)

{

parts[i] = new Particle();

effect.init(parts[i]);

}

}

/** The method that does it all. Needs to be called every tick of a game loop */

public void emit(Graphics3D g3d)

{

for(int i = 0; i < parts.length; i++)

{

getEffect().update(parts[i]);

getEffect().render(parts[i], g3d);

}

}

/**

* @param effect The effect to set.

*/

public void setEffect(ParticleEffect effect) {

this.effect = effect;

}

/**

* @return Returns the effect.

*/

public ParticleEffect getEffect() {

return effect;

}

}

原文地址:http://developer.sonyeriCsson.com/site/global/techsupport/tipstrickscode/mobilejava3d/p_java3d_tutorial_part3_compliments_redikod.jsp

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有