Author Topic: Floormapper problem :(  (Read 9389 times)

0 Members and 1 Guest are viewing this topic.

Offline GfxFreak

  • ZX 81
  • *
  • Posts: 8
  • Karma: 0
    • View Profile
Floormapper problem :(
« on: August 18, 2013 »
Hi there I have a question.

I wanted an old program effect (FloorMapper).
I just do not understand the algo.

Could someone explain to me how it works?

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: Floormapper problem :(
« Reply #1 on: August 19, 2013 »
Depends on how much degree of freedom you want.
Do you want a simple Trailblazer effect where you can only move left/right and front/back,
do you want to keep the floor fixed but rotate around the y-axis
or do you want a completely arbitrary 3d plane?
Challenge Trophies Won:

Offline GfxFreak

  • ZX 81
  • *
  • Posts: 8
  • Karma: 0
    • View Profile
Re: Floormapper problem :(
« Reply #2 on: August 19, 2013 »
Hi I would first like the technology behind the trailblazer.
The technic for the 3D Plane sounds like also interesting :)

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: Floormapper problem :(
« Reply #3 on: August 19, 2013 »
Have you managed to get your zooming chessboard to work?
A perspective floor is basically the same, except that you change the scale-factor in every row.
So the upper rows appear further away and the lower ones nearer to the front.
Challenge Trophies Won:

Offline GfxFreak

  • ZX 81
  • *
  • Posts: 8
  • Karma: 0
    • View Profile
Re: Floormapper problem :(
« Reply #4 on: August 20, 2013 »
@hellfire

Yes, I managed.
But i have problems with the different quad scale+moving  looks horrible.

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: Floormapper problem :(
« Reply #5 on: August 20, 2013 »
What's probably not completely trivial is the fact that you can't pick the zoom factor directly from your row loop counter.
That's because depth (and that's what changes the scale from one row to the next) can't be interpolated linearly.
If you do, you'll end up with a fancy curved surface, like this:


Instead you'll have to pick some depth value for the top- and bottom-scanline and interpolate 1/depth, like this:
Code: [Select]
float startZ= 100.0; // top scanline = further away
float endZ= 10.0;    // bottom scanline = near

// interpolate 1/z
startZ= 1.0f / startZ;
endZ= 1.0f / endZ;
float deltaz= (endZ - startZ) / height;

int centerx= width/2;   // center column of the screen

for (int y=0; y<height; y++)
{
   // get z from interpolated 1/z and use as scale factor
   float scale= 8192.0 / startZ; // constant defines checker tiling

   int u= -centerx * scale;   // assume u=0 in the center
   int v= scale * 512.0;      // random scale factor for v to get approx. square checkers
   int deltau= scale;         // keep values as integer in the inner loop

   // add movement to u/v
   u += moveX;      // left/right
   v += moveY;      // front/back

   for (int x=0; x<width; x++)
   {
      // get checker color from u/v
      int color= (u>>24&1) ^ (v>>24&1);
      dst[x]= palette[ color ];
      // interpolate u (v keeps constant)
      u+=deltau;
   }

   dst+= width;         // pointer to next scanline
   startZ += deltaz;    // interpolate depth
}
Which results in this:


At this point you may realize that the whole u/v-interpolation always delivers the same coordinates, the only thing that changes are the offsets which makes the checker board move.
So it's possible to calculate these values only once and store them into a buffer.
This way you can use the weirdest functions, eg. this.

« Last Edit: August 20, 2013 by hellfire »
Challenge Trophies Won:

Offline flightcrank

  • C= 64
  • **
  • Posts: 37
  • Karma: 24
    • View Profile
Re: Floormapper problem :(
« Reply #6 on: August 21, 2013 »
nice post hellfire this is pure gold. i was wondering about rendering a texture mapped floor, without a 3d engine. Ill have a crack at this when i get some spare time.

I believe the SNES had a special hardware gfx  mode (mode7) that did something like this. for games such as F-Zero.
Challenge Trophies Won:

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: Floormapper problem :(
« Reply #7 on: August 21, 2013 »
I believe the SNES had a special hardware gfx  mode (mode7) that did something like this. for games such as F-Zero.
Kind of. While the NES could only scroll a tile-based background layer, the SNES could also scale and rotate it.
To get perspective one had to adjust the scaling for every scanline - basically just like in the example above but the inner loop was done by the hardware.
Challenge Trophies Won:

Offline ninogenio

  • Pentium
  • *****
  • Posts: 1668
  • Karma: 133
    • View Profile
Re: Floormapper problem :(
« Reply #8 on: August 30, 2013 »
really cool stuff there hellfire,

i remember a while back messing around with hardware accelerated mode 7 on the gba, some of the fake 3d that could be done at really good speed was impressive. but i never really thought about how it worked under the surface cheers for that!
« Last Edit: August 30, 2013 by ninogenio »
Challenge Trophies Won:

Offline Optimus

  • DBF Aficionado
  • ******
  • Posts: 2456
  • Karma: 128
    • View Profile
    • Optimouse Demo Site
Re: Floormapper problem :(
« Reply #9 on: September 08, 2013 »
I was thinking about this recently, how to go from a regular rotozoomer to a X rotated floormapper.
In a rotozoomer you just linearly interpolate with the same two fixed point values every pixel, which you recalculate only after each frame.
The X rotated zoomer, I had to devide those interpolators by z each line, so I recalculated them each line but for each pixel on a line it's again the same.
I am working on this cause I am trying to make this effect on CPC, figuring out how I can even precalculate stuff so that I don't have to do divisions per line.  But on PC it's fine.

Here is my last code, SDL, C++

Code: [Select]
// main.h

#ifndef MAIN_H
#define MAIN_H

#define ScreenWidth 800
#define ScreenHeight 600

#define TextureWidth 256
#define TextureHeight 256

#define PI 3.14159265359f

#define FP_MUL 65536
#define FP_SHR 16

#endif


//main.cpp

#include <stdio.h>
#include <math.h>
#include <SDL.h>

#include "main.h"

#undef main

SDL_Surface *screen;

bool exw=false;

unsigned int texture[TextureWidth * TextureHeight];
float zFactor[ScreenHeight];

unsigned int time;

// ---- Demo Init ----

void initZfactor(float z0, float z1)
{
    float dz = (z1 - z0) / ScreenHeight;
    for (int y=0; y<ScreenHeight; y++)
    {
        if (z0 > 0)
            zFactor[y] = z0;
        else
            zFactor[y] = 0;
        z0 += dz;
    }
}

void init()
{
    int i = 0;
    for (int y=0; y<TextureHeight; y++)
    {
        for (int x=0; x<TextureWidth; x++)
        {
            texture[i++] = x ^ y;
        }
    }
}


// ========================================
// ======== Effect subs start here ========
// ========================================

int xduz[ScreenHeight];
int xdvz[ScreenHeight];
int yduz[ScreenHeight];
int ydvz[ScreenHeight];

void effect(SDL_Surface *screen)
{
  unsigned int *vram = (unsigned int*)screen->pixels;
  float angle = ((time / 1000.0f) * (2.0f * PI)) * 0.1f;

    float x0 = sin(angle) + 1.0f;
    float x1 = cos(angle) + 1.0f;
    initZfactor(x0, x1);

    const int du = cos(angle) * FP_MUL;
    const int dv = sin(angle) * FP_MUL;

    int xdu = du;
    int xdv = dv;
    int ydu = dv;
    int ydv = -du;

for (int y=0; y<ScreenHeight; y++)
{
    if (zFactor[y]!=0)
        {
            xduz[y] = xdu / zFactor[y];
            xdvz[y] = xdv / zFactor[y];
            yduz[y] = ydu / zFactor[y];
            ydvz[y] = ydv / zFactor[y];

            int ddu = 0 - xduz[y] * (ScreenWidth / 2) - yduz[y] * (-ScreenHeight / 2 + y);
            int ddv = 0 - xdvz[y] * (ScreenWidth / 2) - ydvz[y] * (-ScreenHeight / 2 + y);
            int u = ddu;
            int v = ddv;

            for (int x=0; x<ScreenWidth; x++)
            {
                unsigned int c = texture[((u >> FP_SHR) & (TextureHeight - 1)) * TextureWidth + ((v >> FP_SHR) & (TextureWidth - 1))];
                *vram++ = (c << 16) | (c << 8) | c;
                u += xduz[y];
                v += xdvz[y];
            }
            //ddu += (ydu / zFactor[y]);
            //ddv += (ydv / zFactor[y]);
        }
}
}

// ------------------------------
// --- Keyboard/Mouse control ---
// ------------------------------

void keyCommands()
{
SDL_Event event;

while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
exw=true;
break;

case SDL_KEYDOWN:
if (event.key.keysym.sym==SDLK_ESCAPE)
exw=true;
break;
}
}
}


// ---- Demo Main ----

void demo()
{
do{
    time = SDL_GetTicks();
effect(screen);
SDL_Flip(screen);
keyCommands();
}while(exw==false);
}


int main(int argc, char* argv[])
{
    screen = SDL_SetVideoMode(ScreenWidth, ScreenHeight, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
init();
demo();

  return 0;
}


Challenge Trophies Won:

Offline hellfire

  • Sponsor
  • Pentium
  • *******
  • Posts: 1294
  • Karma: 466
    • View Profile
    • my stuff
Re: Floormapper problem :(
« Reply #10 on: September 09, 2013 »
I am working on this cause I am trying to make this effect on CPC
Interesting!
I barely know anything about the CPC architecture but I guess it's far from strong enough to actually fill the whole screen with texels from interpolated uvs. So how do you do that?
From the top of my head I'd probably try a different approach and check where the uv-interpolation hits a new tile (so kind of a ray-caster) and fill the gaps with alternating colors to produce a checker board.
Challenge Trophies Won:

Offline flightcrank

  • C= 64
  • **
  • Posts: 37
  • Karma: 24
    • View Profile
Re: Floormapper problem :(
« Reply #11 on: June 06, 2014 »
Can we start again with the theory of this floor mapper problem. I would like to understand this from the ground up but have gotten well confused. I'm not really interested in any code right now just the theory of how to implement this.
But I say I'm using the processing language for its simplicity in getting pixels on the screen.

Ok, this is the point I'm up to now. I've implemented some code to generate a checker texture. which can be found here
https://gist.github.com/flightcrank/7387beda0e8a644e5351
This is the image it produces.



Now I understand how the UV co-ordinate system works. I have made a small program that can can stretch or shrink this checker-board texture to any size window.

now I'm stuck as to how to proceed. What is the step by step theory behind the floormapper ? do you draw the texture one half at a time from the centre of the screen ? infact i just want to take this slow. hellfire made an image where the texture was curved like this



Then he corrected the problem with some more code. How would I got about getting that curved checkerboard image above. From there I would then like to get the final result, but I don't want to go to far and get to confused.

Ill say again i'm after more of the theory of how it works. not really any code.
« Last Edit: June 06, 2014 by flightcrank »
Challenge Trophies Won: