|
-
FK founder & general loiterer
Forcing precision
Does anyone know a way of getting more precision out of the trig functions in flash.. Im playing on a mode7 engine that starts to get jerky doe to lack of precision / rounding error.....
-
Pumpkin Carving 2008
In what context of trig are there precision errors? When using atan, sin, cos, etc?
Colin Moock uses this:
Code:
function trim (theNumber, decPlaces) {
if (decPlaces>=0) {
var temp = Math.pow(10, decPlaces);
return Math.round(theNumber*temp)/temp;
}
}
//test function
trace (trim(1.1265, 2));
However, I think using Math.Pow repeatedly in a mode7 engine would be too much of a hit to the cpu, so I'd stay at a consistent 3 decimal places for best results:
Code:
function trim (theNumber) {
return Math.round(theNumber*1000)/1000;
}
//test function
trace(trim(1.1555)); // 1.156
Is this what you're after?
The 'Boose':
ASUS Sabertooth P67 TUF
Intel Core i7-2600K Quad-Core Sandy Bridge 3.4GHz Overclocked to 4.2GHz
8GB G.Skill Ripjaws 1600 DDR3
ASUS ENGTX550 TI DC/DI/1GD5 GeForce GTX 550 Ti (Fermi) 1GB 1GDDR5 (Overclocked to 1.1GHz)
New addition: OCZ Vertex 240GB SATA III SSD
WEI Score: 7.6
-
FK founder & general loiterer
I want to get more precision out of the sin and cos.... as the forground objects get highly scaled the lack of precision makes them appear very jerky.
-
Pumpkin Carving 2008
I do believe I'll be needing an example to understand you, unless someone else can help you better. Sorry.
The 'Boose':
ASUS Sabertooth P67 TUF
Intel Core i7-2600K Quad-Core Sandy Bridge 3.4GHz Overclocked to 4.2GHz
8GB G.Skill Ripjaws 1600 DDR3
ASUS ENGTX550 TI DC/DI/1GD5 GeForce GTX 550 Ti (Fermi) 1GB 1GDDR5 (Overclocked to 1.1GHz)
New addition: OCZ Vertex 240GB SATA III SSD
WEI Score: 7.6
-
His problem is that the flash Number type cannot hold enough data and roundoff errors are making the objects appear out of place.
I really don't see a way to get around this, perhaps tween them to their new positions instead of jerking them there to smooth out the motion even if its inaccurate.
I would be hard pressed to find a way to make the math more accurate without completely destroying performance.
The greatest pleasure in life is doing what people say you cannot do.
- Walter Bagehot
The height of cleverness is to be able to conceal it.
- Francois de La Rochefoucauld
-
....he's amazing!!!
If you're getting precision errors it's not necessarily the math functions that are the cause.
Without seeing your code I couldn't say, but make sure you aren't storing variables in properties that automatically round themselves off, such as a movieclips _x or _y or _rotation.
If the math functions are failing, it could be the use of large numbers with a great amount of precision. 1.000000564 is ok, but 1,000,000.000000564 will get rounded off, there may be a workaround for that if it's definitely the problem.
The best thing to do is trace out the values, get right to the place where the precision is being lost and work from there.
-
an example code wouldn´t hurt. For example in this engine I rounded off even PI and calculated everything with just 3.14 (because it runs faster)
instead of Math.PI or 3.14159265358979323846... and still everything looked just fine.
-
FK founder & general loiterer
totally agree....just took me a moment to get it show ready...
what I am making is a mode7 racing game ... well hopefully. Based upon the fred heintz engine. I am however trying to make it with a track that is 5760 x 2880..
you can see a demo at http://www.markfennell.com/projects/motogp.swf
I am using matrix.tx to move the source track into a 2880 x 2880 bitmap source image that is then read by the mode7 engine to generate the display, but as you can see in the demo there is a tiny jitter in the movement which I believe is a precision error.... (of course it might not be too!)
Code:
package mode7 {
import flash.display.*;
import flash.filters.BlurFilter;
import flash.ui.Keyboard;
import flash.ui.Mouse;
import flash.filters.ColorMatrixFilter;
import flash.filters.BitmapFilter;
import flash.events.*;
import flash.utils.*;
import flash.text.*;
import flash.geom.*;
import Constants
public class Mode7 extends Sprite
{
private var _nbMs:Number;
private var _worldScale:Number = 55000;
private var _horizon:Number = 200;// sets alpha in distance
private var _horizonScale:Number = 10;//
private var offsetRotation:Number = Constants.OFFSET_ROTATION
private var _xcam:Number
private var _ycam:Number = 30;
private var _nbScans:Number = 0
private var _scanSteps:Number;
private var _bmpd:BitmapData;
private var container:Sprite;
private var hiRes:Boolean = true
private var offsetX:Number = Constants.OFFSET_X
private var offsetY:Number = Constants.OFFSET_Y
private var sliceArray:Array = []
private var i:int
private var j:int
private var track:Sprite
private var trackMatrix:Matrix
// ***********************************
// MODE7
// ***********************************
public function Mode7()
{
track = new Track()
trackMatrix = new Matrix()
_bmpd = new BitmapData(2880, 2880, false, 0x000000)
//_bmpd = new TrackBitmap(0,0)
}
// Mode7 Init
public function init(_container:Sprite)
{
container = _container;
// create new scanlines
if (!hiRes) {
// low def
_scanSteps = 2;
_nbScans = (Constants._resoDy >> 1);
} else {
// high def
_scanSteps = 1;
_nbScans = Constants._resoDy;
}
// create and place scan lines
for (i=0; i<_nbScans; i++) {
var slice = new Sprite()
slice.x = offsetX+(Constants._resoDx*0.5);
slice.y = offsetY+(i*_scanSteps);
if (i > Constants.HORIZON) slice.alpha = Math.min(1, i*0.03)
else slice.visible = false
container.addChild(slice)
sliceArray.push(slice)
}
j=0
}
// Mode7 Main. Draw a scan line after another (horizontal rectangles)
public function render(_angleX:Number, _angleY:Number, _xcam:Number, _zcam:Number)
{
trackMatrix.tx = (Constants.MAP_WIDTH/2+_xcam) // assumes center of map and translates the track
//trackMatrix.ty = Constants.MAP_HEIGHT/2+_zcam
_bmpd.draw(track,trackMatrix, null, null, null, false)
var i;
var x2;
var x2b;
var colX;
var colZ;
var rayX;
var rayY;
var rayZ;
var cfX;
var angleX;
var dist;
var leCos;
var sinus;
var cosinus;
var matrix:Matrix;
sinus = Math.sin;
cosinus = Math.cos;
matrix = new Matrix();
matrix.rotate(_angleY*Math.PI/180.0);
x2 = (Constants._resoDx*0.5)/200.0;
cfX = (40.0/_nbScans)*Math.PI/180.0;
angleX = (_angleX*Math.PI/180.0)-(cfX*_nbScans*0.5);
rayX = sinus(_angleY*Math.PI/180.0);
rayZ = cosinus(_angleY*Math.PI/180.0);
i = -1;
while (++i<_nbScans)
{
sliceArray[i].graphics.clear();
angleX += cfX;
rayY = sinus(angleX);// dot prod ray (rayX, rayY, rayZ) with plane (0.0, 1.0, 0.0)
if (rayY<0.0) {
// over horizon
continue;
}
dist = (Constants._ycam/rayY);// distance to hit point on plane
leCos = cosinus(angleX)*dist;
//if (Math.random() > 0.99) trace(rayX*leCos)
colX = -Constants.MAP_WIDTH/2-(rayX*leCos);// x of hit point on plane
colZ = _zcam-(rayZ*leCos);// z of hit point on plane
matrix.tx = (colX*matrix.a)+(colZ*matrix.c);
matrix.ty = (colX*matrix.b)+(colZ*matrix.d);
x2b = (x2*dist);
// scale src
sliceArray[i].scaleX = (Constants.WORLD_SCALE/dist) * 0.01;// scale tgt
sliceArray[i].graphics.beginBitmapFill(_bmpd,matrix,true,true);
sliceArray[i].graphics.moveTo(-x2b,0);
sliceArray[i].graphics.lineTo(x2b,0);
sliceArray[i].graphics.lineTo(x2b,1);
sliceArray[i].graphics.lineTo(-x2b,_scanSteps);
sliceArray[i].graphics.endFill();
}
}
}
}
-
ism
why would it be a precision error. does it stop when you reduce the size of the bitmap? i don't remember seeing this happen with fred heintz's original .fla
Graphics Attract, Motion Engages, Gameplay Addicts
XP Pro | P4 2.8Ghz | 2Gb | 80Gb,40Gb | 128Mb DDR ATI Radeon 9800 Pro
-
FK founder & general loiterer
no this is a modification of freds original fla, his original can handle a maximum image size of 2880 x 2880.
Im using a source image 5760 x 2880 that then I 'scroll' into my source bitmap... it is the scrolling that causes the jump.....
I'm scrolling with a matrix.tx and then drawing the resultant scroll onto the source bitmap if that makes sense?
-
ism
rather than scroll the huge bitmap (coz i don't think you'll get a solution for your rounding) have you considered tiling the image. i think strille created a version of the mode7 engine that used tiles.
Graphics Attract, Motion Engages, Gameplay Addicts
XP Pro | P4 2.8Ghz | 2Gb | 80Gb,40Gb | 128Mb DDR ATI Radeon 9800 Pro
-
Senior Member
If I was trying to write a mode7 rasterizer that supported source images greater than 2880x2880, I would use copypixels to continually refresh the map texture so that it is a 2880x2880 window centered around the camera and then add another layer of indirection between camera coordinates and world coordinates. Camera coordinates would always be relative to the (0,0) point of my texture, so binding a camera to a world object (like the biker) would have to translate by the difference between my textures(0,0) point and whatever point I consider (0,0) in global coordinates. The copypixels window would always move in integer steps of pixels, but the camera & world coordinates would be floating point.
TBH, I would choose to avoid the problem by keeping textures below 2880x2880. After a bit of Mode7 experimentation/implementation, I found that I didn't need as high resolution of a texture as I originally expected. Stretching or clipping the map texture so that it fit into 2880x2880, and then changing my scaling factor between texels and gameplay units ("meters") was a workable compromise.
A third alternative I have noticed, is that embedded bitmapdatas appear to be exempt from the 2880x2880 limit. I was able to get a Mode7 engine running on textures on the order of 5K by 5K without any trickery, as long as the source image was embedded and not created at runtime via new BitmapData(). This was not an option I could use in my final game because I needed to be able to clone my source texture and twiddle pixels at runtime, and a 5Kx5K texture couldn't be cloned. But if your game never needs to change the contents and you can stomach the huge embed, maybe this could work for you.
-
FK founder & general loiterer
hey rachil0
this is the approach that I am using.... though I am using bitmap draw to copy from the source movieclip into a 2880 by 2880 space.
however Ill try your approach as well... Ill see how I go embedding a big image into the game 
thanks for the comments
-
FK founder & general loiterer
embedding a BIG bitmap has solved my problem, many thanks for that suggestion it seems so simple not that I look back at it!!
-
SaphuA
Just to add a possibilty; you could always steal the Math functions from Java
-
Senior Member
I think the problem is that you try to translate the image after you scale it, something flash can't do. In flash, matrices are always translated before they are scaled, no matter what order you call the functions or set the variables in.
To fix it, you need to multiply the tx and ty with the scale. Try the following code instead (I'm not certain it will work, but it might):
matrix.tx = (colX*matrix.a*scaleX)+(colZ*matrix.c);
matrix.ty = (colX*matrix.b*scaleX)+(colZ*matrix.d);
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|