📄 compliments of redikod 3d programming tutorial for mobile devices using m3g (jsr 184).htm
字号:
move the camera. This is done in the following method:</DIV>
<DIV> </DIV>
<DIV><FONT face="Courier New" color=#228b22>private void
moveCamera() {<BR>
// Check
controls<BR>
if(key[LEFT])<BR>
{<BR>
camRot += 5.0f;<BR>
}<BR> else
if(key[RIGHT])<BR>
{<BR>
camRot -= 5.0f;<BR>
}<BR>
<BR> // Set
rotation<BR>
cam.setOrientation(camRot, 0.0f, 1.0f,
0.0f);<BR>
<BR> // Calculate
trigonometry for camera
movement<BR> double
rads =
Math.toRadians(camRot);<BR>
camSine =
Math.sin(rads);<BR>
camCosine = Math.cos(rads);</FONT><BR></DIV>
<DIV> </DIV>
<DIV>As you can see this half of the method is pretty simple.
First we check if the user has pressed the LEFT or the RIGHT
joystick key and if he has we just increase or decrease the
rotation of the camera. That's simple enough. The next few
lines are interesting though. We want the head to turn as the
user presses right or left, so we'll rotate around the Y axis,
which means an orientation vector of 0.0f, 1.0f, 0.0f. After
we rotate the camera we calculate the new Sine and Cosine of
the angle, which is used later for movement calculation. Now
on to the next half of the method:
<DIV> </DIV>
<DIV><FONT face="Courier New"
color=#228b22>if(key[UP])<BR>
{<BR>
// Move
forward<BR>
cam.translate(-0.1f * (float)camSine, 0.0f, -0.1f *
(float)camCosine);<BR>
<BR>
// Bob
head<BR>
headDeg +=
0.5f;<BR>
<BR>
// A simple way to "bob" the camera as the user
moves<BR>
cam.translate(0.0f, (float)Math.sin(headDeg) / 40.0f,
0.0f);<BR>
}<BR> else
if(key[DOWN])<BR>
{<BR>
// Move
backward<BR>
cam.translate(0.1f * (float)camSine, 0.0f, 0.1f *
(float)camCosine);<BR>
<BR>
// Bob
head<BR>
headDeg -=
0.5f;<BR>
<BR>
// A simple way to "bob" the camera as the user
moves<BR>
cam.translate(0.0f, (float)Math.sin(headDeg) / 40.0f,
0.0f);<BR>
}</FONT></DIV>
<DIV><FONT face="Courier New"
color=#228b22> // If
the user presses the FIRE key, let's
quit<BR>
if(key[FIRE])<BR>
M3GMidlet.die();<BR> }</FONT></DIV></DIV>
<DIV><STRONG></STRONG> </DIV>
<DIV>Here we check for UP or DOWN. UP will move the camera
forward and DOWN will move it backwards. These are really
simple translations, but I'll explain them fast. The Camera
always starts looking down the negative Z axis, so to move the
camera forward, we only have to move it negative on the Z
axis. However, if we rotate the camera we can't just move it
along the Z axis anymore, it will look wrong. We have to move
the camera on the X axis as well so that we get the movement
we desire. This is attained by using trigonometrical
functions. Since this isn't a tutorial on 3D math I won't go
into more detail, after all you should already know this and
if you think it's hard then look up a good 3D math tutorial on
the internet.</DIV>
<DIV> </DIV>
<DIV>After every translation we also move the head with my
simple head-bobbing hack. I just supply the translate method
with a sine function along the Y axis, so that it looks like
the head is going up and down, that's why we either increase
or decrease the headDeg variable each time the camera is
moved. We also check for the FIRE key at the end, so that the
user can quit the application whenever he wants. (He can also
use the invisible EXIT command that I added when the canvas
was created).<BR>That's it! That's all our advanced camera
movement, now all that's left is to render the World
node!</DIV>
<DIV><BR> </DIV>
<DIV><STRONG>Rendering</STRONG><BR>Before we jump into code, I
have to tell you about immediate and retained mode rendering.
The retained mode is what we are using in this tutorial and it
basically is the mode you use when you render an entire World
node with all its cameras, lights and meshes. This is the
easiest mode to render in, but also the mode you have the
least control over your world. Immediate mode is when you
render a Group of meshes, a single mesh or vertex data
directly. This gives you much more control as with each
rendering you supply a transform matrix that transforms the
object before it's rendered. You can render a World node in
Immediate mode, by supplying a transform matrix to the render
method call, but then you'd be ignoring all the nifty effects
a World node has such as camera, background and others. I'll
go more into detail about the two different rendering modes in
later parts of this series. For now, let's see how we can
render a world.</DIV>
<DIV><BR> </DIV>
<DIV><STRONG>Graphics3D<BR></STRONG>All rendering in JSR 184
is done with the Graphics3D object. It can even hold camera
and light information, if you are rendering in immediate mode.
Let's not worry about that now though since that's an issue
I'll address later on.</DIV>
<DIV> </DIV>
<DIV>To render with a Graphics3D object, you first must bind
it to a graphics context. A graphics context basically means
any Graphics object that draws into something. It could be a
Graphics object of an Image if you want to render to an Image,
or it could be the main Graphics object obtained from the
getGraphics() method. By using the main Graphics object you
render directly to the screen, which is what we want to do
here. To get a Graphics3D object is simple, you just call the
Graphics3D.getInstance() method. You get only one Graphics3D
object per MIDlet, which is why you only obtain it from the
getInstance method. Binding is done with the bindTarget
method, and there are a few ways of using it. Here are a few
examples.</DIV>
<DIV> </DIV>
<DIV><FONT face="Courier New" color=#228b22><BR>//Here is our
Graphics3D object<BR>Graphics3D g3d =
Graphics3D.getInstance();</FONT></DIV>
<DIV><FONT face="Courier New" color=#228b22>// Bind to an
image<BR>Image img =
Image.createImage("myImage.png");<BR>Graphics g =
img.getGraphics();<BR>g3d.bindTarget(g);</FONT></DIV>
<DIV><FONT face="Courier New" color=#228b22>// Bind to the
main Graphics
object<BR>g3d.bindTarget(getGraphics());</FONT></DIV>
<DIV><FONT face="Courier New" color=#228b22>// We can also
supply rendering hints. Remember those? I talked about them at
the beginning.<BR>// This is done by using the other form of
the bindTarget method.<BR>// It takes a Graphics object to
begin with, as always, and then it needs a boolean<BR>// and
an integer mask of hints.<BR>// The boolean simply tells the
Graphics3D object if it should use a depth buffer<BR>// and
you'll probably always set it to 'true'. Here is how we'll use
it to bind<BR>// with our
hints:<BR>g3d.bindTarget(getGraphics(), true,
RENDERING_HINTS); <BR></FONT></DIV>
<DIV> </DIV>
<DIV>Now that you know how to bind your target, you also must
know that the target must be released each game loop. That
means that when you've rendered everything, you must release
the target. There are problems sometimes with releasing and
binding, so most people just keep the whole game loop within a
try/catch block and put the releaseTarget call in the finally
clause. That's how we'll do it in this example. Now, let's
take a look at the rendering method. To render something you
can use a variety of rendering methods, but we'll only be
interested in one today, the render(World) method. Simple huh?
Yeah, you only need to supply your world node and it'll render
it for you. Let's take a look at what our game loop will look
like:</DIV>
<DIV> </DIV>
<DIV><FONT face="Courier New" color=#228b22>/** Draws to
screen<BR> */<BR>
private void draw(Graphics g)<BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -