Compare commits
10 commits
f1bbb1e1b6
...
4a3c9b2873
Author | SHA1 | Date | |
---|---|---|---|
4a3c9b2873 | |||
10366c2a09 | |||
3310008a0d | |||
beda272f18 | |||
34293981b0 | |||
53096517c9 | |||
e9f919052c | |||
28a1256a88 | |||
fa66324833 | |||
011cd891c1 |
9 changed files with 506 additions and 190 deletions
52
TODO.txt
52
TODO.txt
|
@ -1,10 +1,5 @@
|
||||||
|
- allow car to be flipped upside down on start? with start block transform
|
||||||
- maybe change sticker to fan? could me more fun: TEST and see
|
- maybe change sticker to fan? could me more fun: TEST and see
|
||||||
- based viewing distance idea: limit number of rendered map triangles to N, keep
|
|
||||||
sorting the triangle array by distance continually! e.g. in each frame handle
|
|
||||||
one of the N visible triangles like this -- in the non-visible triangles
|
|
||||||
find one that is closer than this and switch them (if found).
|
|
||||||
- sky images could be just composed of 4x4 normal images? then we only need
|
|
||||||
one type of image
|
|
||||||
- map actually in ASCII format? how will humans edit it?
|
- map actually in ASCII format? how will humans edit it?
|
||||||
- make a simple rendering setting:
|
- make a simple rendering setting:
|
||||||
- will exclude images and only draw solid colors, let's say only 16, so that
|
- will exclude images and only draw solid colors, let's say only 16, so that
|
||||||
|
@ -16,19 +11,7 @@
|
||||||
- then iterate over the strip that should have the sky texture and only draw
|
- then iterate over the strip that should have the sky texture and only draw
|
||||||
to pixels where depth buffer was not overwritten (this step can be left out
|
to pixels where depth buffer was not overwritten (this step can be left out
|
||||||
in case we have depth buffer or sky turned off)
|
in case we have depth buffer or sky turned off)
|
||||||
TOTAL SIZE OF TEXTURES:
|
|
||||||
- 64 x 64 x 2 = 8192, 6 x floor + 2 x wall + 1 x car = 8 * 8192 = 73728
|
|
||||||
- (128 x 128 x 1) x 3 background = 49152
|
|
||||||
- total = 122880
|
|
||||||
- OK so materials (final?):
|
|
||||||
- concrete: normal \
|
|
||||||
- accelerator: accelerates (adds some constant to speed?) > same wall texture?
|
|
||||||
- maybe jumppad (big "fan")? /
|
|
||||||
- dirt: a bit slippery (maybe also a bit slows down?) \
|
|
||||||
- magnet: pulls car downwards (allows riding on ceiling etc.) > same wall texture?
|
|
||||||
- ice: extremely slippery (can barely turn) /
|
|
||||||
- camera behavior? what if car is riding upside down (on magnet) etc?
|
- camera behavior? what if car is riding upside down (on magnet) etc?
|
||||||
- track size: 64x64x64
|
|
||||||
- EFFICINT MAP DRAWING:
|
- EFFICINT MAP DRAWING:
|
||||||
- map will be subdivided into subblocks (probably 16x16x16 or 8x8x8), only
|
- map will be subdivided into subblocks (probably 16x16x16 or 8x8x8), only
|
||||||
nearest subblocks (and possibly only those in viewing direction will be
|
nearest subblocks (and possibly only those in viewing direction will be
|
||||||
|
@ -41,14 +24,6 @@ TOTAL SIZE OF TEXTURES:
|
||||||
subblocks we want to draw.
|
subblocks we want to draw.
|
||||||
- THIS??? Draw further blocks in a simplified way, e.g. just splatting literal
|
- THIS??? Draw further blocks in a simplified way, e.g. just splatting literal
|
||||||
squares with constant color? See how it looks :)
|
squares with constant color? See how it looks :)
|
||||||
- Architecture (modules):
|
|
||||||
- map: loads map n stuff
|
|
||||||
- racing engine (depends on map): handles physics of car with given inputs
|
|
||||||
- rendering engine (depends on map): hanles rendering of the map
|
|
||||||
- game (depends on all): joins it all together
|
|
||||||
- settings, constants etc.
|
|
||||||
- individual frontends
|
|
||||||
- ...?
|
|
||||||
- Textures: size? format? They will likely take a lot of mem, weak computers
|
- Textures: size? format? They will likely take a lot of mem, weak computers
|
||||||
will have to do without them.
|
will have to do without them.
|
||||||
- possibility of simple procedural textures to save space! <-- SOUNDS NICE
|
- possibility of simple procedural textures to save space! <-- SOUNDS NICE
|
||||||
|
@ -140,4 +115,27 @@ TOTAL SIZE OF TEXTURES:
|
||||||
|
|
||||||
BUGS:
|
BUGS:
|
||||||
|
|
||||||
DONE:
|
HANDLED:
|
||||||
|
|
||||||
|
- track size: 64x64x64
|
||||||
|
- sky images could be just composed of 4x4 normal images? then we only need
|
||||||
|
one type of image
|
||||||
|
TOTAL SIZE OF TEXTURES:
|
||||||
|
- 64 x 64 x 2 = 8192, 6 x floor + 2 x wall + 1 x car = 8 * 8192 = 73728
|
||||||
|
- (128 x 128 x 1) x 3 background = 49152
|
||||||
|
- total = 122880
|
||||||
|
- OK so materials (final?):
|
||||||
|
- concrete: normal \
|
||||||
|
- accelerator: accelerates (adds some constant to speed?) > same wall texture?
|
||||||
|
- maybe jumppad (big "fan")? /
|
||||||
|
- dirt: a bit slippery (maybe also a bit slows down?) \
|
||||||
|
- magnet: pulls car downwards (allows riding on ceiling etc.) > same wall texture?
|
||||||
|
- ice: extremely slippery (can barely turn) /
|
||||||
|
- Architecture (modules):
|
||||||
|
- map: loads map n stuff
|
||||||
|
- racing engine (depends on map): handles physics of car with given inputs
|
||||||
|
- rendering engine (depends on map): hanles rendering of the map
|
||||||
|
- game (depends on all): joins it all together
|
||||||
|
- settings, constants etc.
|
||||||
|
- individual frontends
|
||||||
|
- ...?
|
||||||
|
|
110
assets.h
110
assets.h
|
@ -16,8 +16,6 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
|
|
||||||
// TODO: images should be 64x64 indexed, sky will be composed of 2x2 normal images
|
|
||||||
|
|
||||||
static const uint8_t map1[] =
|
static const uint8_t map1[] =
|
||||||
{
|
{
|
||||||
LCR_MAP_MAGIC_NUMBER,
|
LCR_MAP_MAGIC_NUMBER,
|
||||||
|
@ -26,86 +24,54 @@ static const uint8_t map1[] =
|
||||||
10,
|
10,
|
||||||
0,
|
0,
|
||||||
|
|
||||||
|
LCR_MAP_BLOCK(LCR_BLOCK_START,1,1,1,0,0),
|
||||||
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_RAMP,36,0,32,LCR_BLOCK_MATERIAL_CONCRETE,0),
|
LCR_MAP_BLOCK(LCR_BLOCK_FULL,0,0,0,LCR_BLOCK_MATERIAL_CONCRETE,0),
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_RAMP_34,20,0,32,LCR_BLOCK_MATERIAL_CONCRETE,0),
|
LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_FILL,15,1,20,0,0),
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_RAMP_12,32,0,37,LCR_BLOCK_MATERIAL_CONCRETE,0),
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_RAMP_14,32,0,20,LCR_BLOCK_MATERIAL_CONCRETE,0),
|
|
||||||
|
|
||||||
/*
|
LCR_MAP_BLOCK(LCR_BLOCK_FULL,0,0,20,LCR_BLOCK_MATERIAL_CONCRETE,0),
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_FULL_ACCEL,0,0,0,LCR_BLOCK_MATERIAL_CONCRETE,0),
|
LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_FILL,10,15,1,0,0),
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_HOLLOW,63,1,1,0,0),
|
|
||||||
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_FULL_ACCEL,0,0,63,LCR_BLOCK_MATERIAL_CONCRETE,0),
|
LCR_MAP_BLOCK(LCR_BLOCK_RAMP,0,1,19,LCR_BLOCK_MATERIAL_CONCRETE,0),
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_HOLLOW,63,1,1,0,0),
|
LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_FILL,8,1,1,0,0),
|
||||||
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_FULL_ACCEL,0,0,0,LCR_BLOCK_MATERIAL_CONCRETE,0),
|
LCR_MAP_BLOCK(LCR_BLOCK_RAMP,8,1,5,LCR_BLOCK_MATERIAL_CONCRETE,LCR_BLOCK_TRANSFORM_ROT_270),
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_HOLLOW,1,1,63,0,0),
|
LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_FILL,1,1,8,0,0),
|
||||||
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_FULL_ACCEL,63,0,0,LCR_BLOCK_MATERIAL_CONCRETE,0),
|
LCR_MAP_BLOCK(LCR_BLOCK_LEFT,5,1,5,LCR_BLOCK_MATERIAL_CONCRETE,LCR_BLOCK_TRANSFORM_ROT_90),
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_HOLLOW,1,1,63,0,0),
|
LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_FILL,10,2,1,0,0),
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_FULL_ACCEL,32,32,32,LCR_BLOCK_MATERIAL_CONCRETE,0),
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_HOLLOW,4,4,4,0,0),
|
|
||||||
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_FULL,50,20,20,LCR_BLOCK_MATERIAL_GRASS,0),
|
LCR_MAP_BLOCK(LCR_BLOCK_LEFT,9,0,20,LCR_BLOCK_MATERIAL_CONCRETE,0),
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_HOLLOW,5,5,5,0,0),
|
LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_FILL,8,1,8,0,0),
|
||||||
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_FULL,10,10,10,LCR_BLOCK_MATERIAL_GRASS,0),
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_HOLLOW,3,3,3,0,0),
|
|
||||||
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_FULL,2,25,50,LCR_BLOCK_MATERIAL_GRASS,0),
|
LCR_MAP_BLOCK(LCR_BLOCK_FULL,15,0,0,LCR_BLOCK_MATERIAL_GRASS,0),
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_HOLLOW,3,3,3,0,0),
|
LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_FILL,10,1,15,0,0),
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
LCR_MAP_BLOCK(LCR_BLOCK_FULL,25,0,0,LCR_BLOCK_MATERIAL_ICE,0),
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_FULL,0,0,0,LCR_BLOCK_MATERIAL_GRASS,0),
|
LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_FILL,10,1,15,0,0),
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_HOLLOW,40,1,1,0,0),
|
|
||||||
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_FULL,63,63,0,LCR_BLOCK_MATERIAL_GRASS,0),
|
LCR_MAP_BLOCK(LCR_BLOCK_FULL,35,0,0,LCR_BLOCK_MATERIAL_DIRT,0),
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_HOLLOW,1,1,40,0,0),
|
LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_FILL,10,1,15,0,0),
|
||||||
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_FULL,0,15,0,LCR_BLOCK_MATERIAL_GRASS,0),
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_HOLLOW,7,4,8,0,0),
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_FULL,0,15,0,LCR_BLOCK_MATERIAL_GRASS,0),
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_CUBOID_HOLLOW,7,4,8,0,0),
|
|
||||||
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_FULL,32,32,32,LCR_BLOCK_MATERIAL_CONCRETE,0),
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_FULL,33,32,32,LCR_BLOCK_MATERIAL_GRASS,0),
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_RAMP_CURVED_WALL,34,32,32,LCR_BLOCK_MATERIAL_GRASS,0),
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_RAMP_CURVED_WALL,35,32,32,LCR_BLOCK_MATERIAL_CONCRETE,LCR_BLOCK_TRANSFORM_ROT_90),
|
|
||||||
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_FULL,63,35,32,LCR_BLOCK_MATERIAL_CONCRETE,0),
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_FULL,0,35,32,LCR_BLOCK_MATERIAL_ICE,0),
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_FULL,40,35,32,LCR_BLOCK_MATERIAL_DIRT,0),
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_FULL,41,35,32,LCR_BLOCK_MATERIAL_CONCRETE,0),
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_FULL,42,35,32,LCR_BLOCK_MATERIAL_CONCRETE,0),
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_FULL,43,35,32,LCR_BLOCK_MATERIAL_CONCRETE,0),
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_FULL,44,35,32,LCR_BLOCK_MATERIAL_CONCRETE,0),
|
|
||||||
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_BOTTOM_LEFT,34,32,33,LCR_BLOCK_MATERIAL_CONCRETE,LCR_BLOCK_TRANSFORM_ROT_90),
|
|
||||||
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_FULL,32,33,32,LCR_BLOCK_MATERIAL_CONCRETE,0),
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_FULL,33,33,32,LCR_BLOCK_MATERIAL_CONCRETE,0),
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_FULL,32,33,33,LCR_BLOCK_MATERIAL_CONCRETE,0),
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_FULL,33,33,33,LCR_BLOCK_MATERIAL_CONCRETE,0),
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_FULL,32,32,33,LCR_BLOCK_MATERIAL_CONCRETE,0),
|
|
||||||
LCR_MAP_BLOCK(LCR_BLOCK_FULL,33,32,33,LCR_BLOCK_MATERIAL_CONCRETE,0),
|
|
||||||
*/
|
|
||||||
LCR_MAP_TERMINATOR
|
LCR_MAP_TERMINATOR
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LCR_IMAGE_SIZE 64 ///< one-dimension resolution of bitmap image
|
#define LCR_IMAGE_SIZE 64 ///< one-dimension resolution of bitmap image
|
||||||
#define LCR_IMAGE_STORE_SIZE (LCR_IMAGE_SIZE * LCR_IMAGE_SIZE + 256 * 2)
|
#define LCR_IMAGE_STORE_SIZE (LCR_IMAGE_SIZE * LCR_IMAGE_SIZE + 256 * 2)
|
||||||
|
|
||||||
// TODO: put this into struct
|
|
||||||
uint16_t _LCR_currentImagePalette[256];
|
struct
|
||||||
const uint8_t *_LCR_currentImagePixel;
|
{
|
||||||
const uint8_t *_LCR_currentImage;
|
uint16_t palette[256];
|
||||||
|
const uint8_t *pixel;
|
||||||
|
const uint8_t *image;
|
||||||
|
} LCR_currentImage;
|
||||||
|
|
||||||
#define LCR_IMAGE_WALL_CONCRETE 0
|
#define LCR_IMAGE_WALL_CONCRETE 0
|
||||||
#define LCR_IMAGE_WALL_WOOD 1
|
#define LCR_IMAGE_WALL_WOOD 1
|
||||||
|
@ -6192,17 +6158,17 @@ static const uint8_t LCR_images[] =
|
||||||
|
|
||||||
void LCR_loadImage(unsigned int index)
|
void LCR_loadImage(unsigned int index)
|
||||||
{
|
{
|
||||||
_LCR_currentImage = LCR_images + index * LCR_IMAGE_STORE_SIZE;
|
LCR_currentImage.image = LCR_images + index * LCR_IMAGE_STORE_SIZE;
|
||||||
|
|
||||||
for (int i = 0; i < 256; ++i)
|
for (int i = 0; i < 256; ++i)
|
||||||
{
|
{
|
||||||
_LCR_currentImagePalette[i] = *_LCR_currentImage;
|
LCR_currentImage.palette[i] = *LCR_currentImage.image;
|
||||||
_LCR_currentImage++;
|
LCR_currentImage.image++;
|
||||||
_LCR_currentImagePalette[i] |= ((uint16_t) (*_LCR_currentImage)) << 8;
|
LCR_currentImage.palette[i] |= ((uint16_t) (*LCR_currentImage.image)) << 8;
|
||||||
_LCR_currentImage++;
|
LCR_currentImage.image++;
|
||||||
}
|
}
|
||||||
|
|
||||||
_LCR_currentImagePixel = _LCR_currentImage;
|
LCR_currentImage.pixel = LCR_currentImage.image;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6213,11 +6179,11 @@ void LCR_imageChangeBrightness(int up)
|
||||||
{
|
{
|
||||||
if (up)
|
if (up)
|
||||||
for (int i = 0; i < 256; ++i)
|
for (int i = 0; i < 256; ++i)
|
||||||
_LCR_currentImagePalette[i] |= 0x18e3;
|
LCR_currentImage.palette[i] |= 0x18e3;
|
||||||
else
|
else
|
||||||
for (int i = 0; i < 256; ++i)
|
for (int i = 0; i < 256; ++i)
|
||||||
_LCR_currentImagePalette[i] =
|
LCR_currentImage.palette[i] =
|
||||||
((_LCR_currentImagePalette[i] >> 1) & 0x7bef);
|
((LCR_currentImage.palette[i] >> 1) & 0x7bef);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6229,7 +6195,7 @@ uint16_t LCR_sampleImage(int x, int y)
|
||||||
// TODO: bottleneck, later on optimize here
|
// TODO: bottleneck, later on optimize here
|
||||||
x = (y % LCR_IMAGE_SIZE) * LCR_IMAGE_SIZE + (x % LCR_IMAGE_SIZE);
|
x = (y % LCR_IMAGE_SIZE) * LCR_IMAGE_SIZE + (x % LCR_IMAGE_SIZE);
|
||||||
x += (x < 0) * (LCR_IMAGE_SIZE * LCR_IMAGE_SIZE);
|
x += (x < 0) * (LCR_IMAGE_SIZE * LCR_IMAGE_SIZE);
|
||||||
return _LCR_currentImagePalette[_LCR_currentImage[x]];
|
return LCR_currentImage.palette[LCR_currentImage.image[x]];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6238,8 +6204,8 @@ uint16_t LCR_sampleImage(int x, int y)
|
||||||
*/
|
*/
|
||||||
uint16_t LCR_getNextImagePixel(void)
|
uint16_t LCR_getNextImagePixel(void)
|
||||||
{
|
{
|
||||||
uint16_t r = _LCR_currentImagePalette[*_LCR_currentImagePixel];
|
uint16_t r = LCR_currentImage.palette[*LCR_currentImage.pixel];
|
||||||
_LCR_currentImagePixel++;
|
LCR_currentImage.pixel++;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
|
#define LCR_SETTING_LOG_LEVEL 2
|
||||||
|
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
|
@ -67,12 +69,30 @@ int main(int argc, char *argv[])
|
||||||
SDL_WINDOWPOS_UNDEFINED, LCR_SETTING_RESOLUTION_X, LCR_SETTING_RESOLUTION_Y,
|
SDL_WINDOWPOS_UNDEFINED, LCR_SETTING_RESOLUTION_X, LCR_SETTING_RESOLUTION_Y,
|
||||||
SDL_WINDOW_SHOWN);
|
SDL_WINDOW_SHOWN);
|
||||||
|
|
||||||
|
if (!window)
|
||||||
|
{
|
||||||
|
fputs("ERROR: couldn't create window",stderr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
renderer = SDL_CreateRenderer(window,-1,0);
|
renderer = SDL_CreateRenderer(window,-1,0);
|
||||||
|
|
||||||
|
if (!renderer)
|
||||||
|
{
|
||||||
|
fputs("ERROR: couldn't create renderer",stderr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
texture =
|
texture =
|
||||||
SDL_CreateTexture(renderer,SDL_PIXELFORMAT_RGB565,SDL_TEXTUREACCESS_STATIC,
|
SDL_CreateTexture(renderer,SDL_PIXELFORMAT_RGB565,SDL_TEXTUREACCESS_STATIC,
|
||||||
LCR_SETTING_RESOLUTION_X,LCR_SETTING_RESOLUTION_Y);
|
LCR_SETTING_RESOLUTION_X,LCR_SETTING_RESOLUTION_Y);
|
||||||
|
|
||||||
|
if (!texture)
|
||||||
|
{
|
||||||
|
fputs("ERROR: couldn't create texture",stderr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
screenSurface = SDL_GetWindowSurface(window);
|
screenSurface = SDL_GetWindowSurface(window);
|
||||||
|
|
||||||
SDL_ShowCursor(0);
|
SDL_ShowCursor(0);
|
||||||
|
|
29
game.h
29
game.h
|
@ -94,6 +94,25 @@ uint8_t LCR_gameStep(uint32_t timeMs);
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#define LCR_LOG0(s) ;
|
||||||
|
#define LCR_LOG1(s) ;
|
||||||
|
#define LCR_LOG2(s) ;
|
||||||
|
|
||||||
|
#if LCR_SETTING_LOG_LEVEL > 0
|
||||||
|
#undef LCR_LOG0
|
||||||
|
#define LCR_LOG0(s) LCR_log(s);
|
||||||
|
|
||||||
|
#if LCR_SETTING_LOG_LEVEL > 1
|
||||||
|
#undef LCR_LOG1
|
||||||
|
#define LCR_LOG1(s) LCR_log(s);
|
||||||
|
|
||||||
|
#if LCR_SETTING_LOG_LEVEL > 2
|
||||||
|
#undef LCR_LOG2
|
||||||
|
#define LCR_LOG2(s) LCR_log(s);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#define LCR_CONTROL_MODE_FREECAM 0x00
|
#define LCR_CONTROL_MODE_FREECAM 0x00
|
||||||
#define LCR_CONTROL_MODE_DRIVE 0x01
|
#define LCR_CONTROL_MODE_DRIVE 0x01
|
||||||
|
|
||||||
|
@ -144,7 +163,7 @@ static inline void LCR_drawPixelXYSafe(unsigned int x, unsigned int y,
|
||||||
|
|
||||||
void LCR_gameInit(void)
|
void LCR_gameInit(void)
|
||||||
{
|
{
|
||||||
LCR_log("initializing");
|
LCR_LOG0("initializing");
|
||||||
|
|
||||||
for (int i = 0; i < LCR_KEYS_TOTAL; ++i)
|
for (int i = 0; i < LCR_KEYS_TOTAL; ++i)
|
||||||
LCR_keyStates[i] = 0;
|
LCR_keyStates[i] = 0;
|
||||||
|
@ -162,10 +181,13 @@ void LCR_gameInit(void)
|
||||||
|
|
||||||
void LCR_gameEnd(void)
|
void LCR_gameEnd(void)
|
||||||
{
|
{
|
||||||
|
LCR_LOG0("ending");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t LCR_gameStep(uint32_t time)
|
uint8_t LCR_gameStep(uint32_t time)
|
||||||
{
|
{
|
||||||
|
LCR_LOG2("game step start");
|
||||||
|
|
||||||
for (int i = 0; i < LCR_KEYS_TOTAL; ++i)
|
for (int i = 0; i < LCR_KEYS_TOTAL; ++i)
|
||||||
LCR_keyStates[i] = LCR_keyPressed(i) ?
|
LCR_keyStates[i] = LCR_keyPressed(i) ?
|
||||||
(LCR_keyStates[i] < 255 ? LCR_keyStates[i] + 1 : 255) : 0;
|
(LCR_keyStates[i] < 255 ? LCR_keyStates[i] + 1 : 255) : 0;
|
||||||
|
@ -188,6 +210,7 @@ if ((LCR_racing.tick % 32) == 0)
|
||||||
|
|
||||||
while (time >= LCR_game.nextRacingTickTime)
|
while (time >= LCR_game.nextRacingTickTime)
|
||||||
{
|
{
|
||||||
|
LCR_LOG2("gonna step racing engine");
|
||||||
unsigned int input = 0;
|
unsigned int input = 0;
|
||||||
|
|
||||||
if (LCR_game.controlMode != LCR_CONTROL_MODE_FREECAM)
|
if (LCR_game.controlMode != LCR_CONTROL_MODE_FREECAM)
|
||||||
|
@ -205,6 +228,8 @@ if ((LCR_racing.tick % 32) == 0)
|
||||||
|
|
||||||
if (time >= LCR_game.nextRenderFrameTime)
|
if (time >= LCR_game.nextRenderFrameTime)
|
||||||
{
|
{
|
||||||
|
LCR_LOG2("gonna render next frame");
|
||||||
|
|
||||||
LCR_GameUnit physicsInterpolationParam = LCR_GAME_UNIT -
|
LCR_GameUnit physicsInterpolationParam = LCR_GAME_UNIT -
|
||||||
((LCR_game.nextRacingTickTime - time) * LCR_GAME_UNIT) /
|
((LCR_game.nextRacingTickTime - time) * LCR_GAME_UNIT) /
|
||||||
LCR_RACING_TICK_MS;
|
LCR_RACING_TICK_MS;
|
||||||
|
@ -278,6 +303,8 @@ LCR_GameUnit physicsInterpolationParam = LCR_GAME_UNIT -
|
||||||
if (sleep)
|
if (sleep)
|
||||||
LCR_sleep(sleep);
|
LCR_sleep(sleep);
|
||||||
|
|
||||||
|
LCR_LOG2("game step end");
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
94
map.h
94
map.h
|
@ -84,7 +84,6 @@
|
||||||
#define LCR_BLOCK_RAMP_CURVED_SHORT 0x0a
|
#define LCR_BLOCK_RAMP_CURVED_SHORT 0x0a
|
||||||
#define LCR_BLOCK_RAMP_CURVED_WALL 0x0b
|
#define LCR_BLOCK_RAMP_CURVED_WALL 0x0b
|
||||||
|
|
||||||
|
|
||||||
#define LCR_BLOCK_FULL_ACCEL 0x20
|
#define LCR_BLOCK_FULL_ACCEL 0x20
|
||||||
#define LCR_BLOCK_FULL_FAN 0x30
|
#define LCR_BLOCK_FULL_FAN 0x30
|
||||||
|
|
||||||
|
@ -105,7 +104,7 @@ struct
|
||||||
{
|
{
|
||||||
uint16_t blockCount;
|
uint16_t blockCount;
|
||||||
uint8_t blocks[LCR_SETTING_MAP_MAX_BLOCKS * LCR_BLOCK_SIZE];
|
uint8_t blocks[LCR_SETTING_MAP_MAX_BLOCKS * LCR_BLOCK_SIZE];
|
||||||
uint32_t startPos;
|
uint8_t startPos[4]; ///< Initial position and rotation.
|
||||||
|
|
||||||
uint8_t environment;
|
uint8_t environment;
|
||||||
|
|
||||||
|
@ -149,6 +148,20 @@ void LCR_mapBlockGetCoords(const uint8_t block[LCR_BLOCK_SIZE],
|
||||||
*z = (block[2] >> 4) | ((block[3] & 0x03) << 4);
|
*z = (block[2] >> 4) | ((block[3] & 0x03) << 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t LCR_mapBlockOppositeTransform(uint8_t transform)
|
||||||
|
{
|
||||||
|
if (!(transform & LCR_BLOCK_TRANSFORM_FLIP_H))
|
||||||
|
{
|
||||||
|
if ((transform & 0x60) == LCR_BLOCK_TRANSFORM_ROT_90)
|
||||||
|
return ((transform & (~0x60)) | LCR_BLOCK_TRANSFORM_ROT_270);
|
||||||
|
|
||||||
|
if ((transform & 0x60) == LCR_BLOCK_TRANSFORM_ROT_270)
|
||||||
|
return ((transform & (~0x60)) | LCR_BLOCK_TRANSFORM_ROT_90);
|
||||||
|
}
|
||||||
|
|
||||||
|
return transform;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t LCR_mapBlockGetTransform(const uint8_t block[LCR_BLOCK_SIZE])
|
uint8_t LCR_mapBlockGetTransform(const uint8_t block[LCR_BLOCK_SIZE])
|
||||||
{
|
{
|
||||||
return block[3] & 0xf0;
|
return block[3] & 0xf0;
|
||||||
|
@ -172,6 +185,15 @@ uint32_t LCR_mapBlockCoordsToCoordNumber(uint8_t x, uint8_t y, uint8_t z)
|
||||||
return LCR_mapBlockGetCoordNumber(b);
|
return LCR_mapBlockGetCoordNumber(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int LCR_rampHeight4ths(uint8_t rampType)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(rampType == LCR_BLOCK_RAMP_14) +
|
||||||
|
(rampType == LCR_BLOCK_RAMP) * 4 +
|
||||||
|
(rampType == LCR_BLOCK_RAMP_12 || rampType == LCR_BLOCK_RAMP_34) * 2 +
|
||||||
|
(rampType == LCR_BLOCK_RAMP_34);
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t *LCR_getMapBlockAtCoordNumber(uint32_t coord)
|
uint8_t *LCR_getMapBlockAtCoordNumber(uint32_t coord)
|
||||||
{
|
{
|
||||||
// binary search the block:
|
// binary search the block:
|
||||||
|
@ -205,6 +227,8 @@ uint8_t *LCR_getMapBlockAtCoordNumber(uint32_t coord)
|
||||||
*/
|
*/
|
||||||
uint8_t _LCR_mapAddBlock(const uint8_t block[LCR_BLOCK_SIZE])
|
uint8_t _LCR_mapAddBlock(const uint8_t block[LCR_BLOCK_SIZE])
|
||||||
{
|
{
|
||||||
|
LCR_LOG2("adding map block");
|
||||||
|
|
||||||
if (LCR_currentMap.blockCount >= LCR_SETTING_MAP_MAX_BLOCKS)
|
if (LCR_currentMap.blockCount >= LCR_SETTING_MAP_MAX_BLOCKS)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -261,7 +285,11 @@ uint8_t _LCR_mapAddBlock(const uint8_t block[LCR_BLOCK_SIZE])
|
||||||
*/
|
*/
|
||||||
uint8_t LCR_mapLoad(const uint8_t *map)
|
uint8_t LCR_mapLoad(const uint8_t *map)
|
||||||
{
|
{
|
||||||
LCR_currentMap.startPos = 0;
|
LCR_LOG0("loading map")
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; ++i)
|
||||||
|
LCR_currentMap.startPos[i] = 0;
|
||||||
|
|
||||||
LCR_currentMap.blockCount = 0;
|
LCR_currentMap.blockCount = 0;
|
||||||
|
|
||||||
if (map[0] != LCR_MAP_MAGIC_NUMBER1 || map[1] != LCR_MAP_MAGIC_NUMBER2)
|
if (map[0] != LCR_MAP_MAGIC_NUMBER1 || map[1] != LCR_MAP_MAGIC_NUMBER2)
|
||||||
|
@ -326,6 +354,15 @@ uint8_t LCR_mapLoad(const uint8_t *map)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case LCR_BLOCK_START:
|
||||||
|
LCR_mapBlockGetCoords(map,
|
||||||
|
LCR_currentMap.startPos,
|
||||||
|
LCR_currentMap.startPos + 1,
|
||||||
|
LCR_currentMap.startPos + 2);
|
||||||
|
|
||||||
|
LCR_currentMap.startPos[3] = LCR_mapBlockGetTransform(map) & 0x60;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (!_LCR_mapAddBlock(map)) // normal block
|
if (!_LCR_mapAddBlock(map)) // normal block
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -333,16 +370,10 @@ uint8_t LCR_mapLoad(const uint8_t *map)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
map += 4;
|
map += LCR_BLOCK_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// process and remove special blocks:
|
LCR_LOG2("map loaded")
|
||||||
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
// sort the blocks (for fast searching):
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -425,6 +456,20 @@ void _LCR_addBlockShapeByte(uint8_t *bytes, uint8_t *byteCount,
|
||||||
*byteCount += 1;
|
*byteCount += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Macro that transforms coordinates according to block transformation.
|
||||||
|
*/
|
||||||
|
#define LCR_TRANSFORM_COORDS(trans,cx,cy,cz,maxXZ,maxY)\
|
||||||
|
if (trans & LCR_BLOCK_TRANSFORM_FLIP_H) cx = maxXZ - cx;\
|
||||||
|
if (trans & 0x20) { /* for both 90 and 270 */ \
|
||||||
|
cx ^= cz; cz ^= cx; cx ^= cz; /* swap */ \
|
||||||
|
cx = maxXZ - cx; } \
|
||||||
|
if (trans & 0x40) { /* for both 180 and 270 */ \
|
||||||
|
cx = maxXZ - cx; \
|
||||||
|
cz = maxXZ - cz; } \
|
||||||
|
if (trans & LCR_BLOCK_TRANSFORM_FLIP_V) \
|
||||||
|
cy = maxY - cy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Gets a shape of given map block type as a 3D model composed of triangles. The
|
Gets a shape of given map block type as a 3D model composed of triangles. The
|
||||||
model is returned as an array of byte triplets (triangles), with each byte
|
model is returned as an array of byte triplets (triangles), with each byte
|
||||||
|
@ -522,11 +567,7 @@ void LCR_mapGetBlockShape(uint8_t blockType, uint8_t transform,
|
||||||
case LCR_BLOCK_RAMP_14:
|
case LCR_BLOCK_RAMP_14:
|
||||||
case LCR_BLOCK_RAMP_34:
|
case LCR_BLOCK_RAMP_34:
|
||||||
{
|
{
|
||||||
uint8_t top =
|
uint8_t top = LCR_rampHeight4ths(blockType);
|
||||||
(blockType == LCR_BLOCK_RAMP_14) +
|
|
||||||
(blockType == LCR_BLOCK_RAMP) * 4 +
|
|
||||||
(blockType == LCR_BLOCK_RAMP_12 || blockType == LCR_BLOCK_RAMP_34) * 2 +
|
|
||||||
(blockType == LCR_BLOCK_RAMP_34);
|
|
||||||
|
|
||||||
ADD(0,0,0) ADD(0,top,6) ADD(0,0,6) // side
|
ADD(0,0,0) ADD(0,top,6) ADD(0,0,6) // side
|
||||||
ADD(6,0,0) ADD(6,0,6) ADD(6,top,6) // side
|
ADD(6,0,0) ADD(6,0,6) ADD(6,top,6) // side
|
||||||
|
@ -550,25 +591,8 @@ void LCR_mapGetBlockShape(uint8_t blockType, uint8_t transform,
|
||||||
uint8_t x, y, z, tmp;
|
uint8_t x, y, z, tmp;
|
||||||
|
|
||||||
_LCR_decodeMapBlockCoords(bytes[i],&x,&y,&z);
|
_LCR_decodeMapBlockCoords(bytes[i],&x,&y,&z);
|
||||||
|
|
||||||
if (transform & LCR_BLOCK_TRANSFORM_FLIP_H)
|
|
||||||
x = 6 - x;
|
|
||||||
|
|
||||||
if (transform & 0x20) // for both 90 and 270
|
LCR_TRANSFORM_COORDS(transform,x,y,z,6,4)
|
||||||
{
|
|
||||||
tmp = z;
|
|
||||||
z = x;
|
|
||||||
x = 6 - tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (transform & 0x40) // for both 180 and 270
|
|
||||||
{
|
|
||||||
x = 6 - x;
|
|
||||||
z = 6 - z;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (transform & LCR_BLOCK_TRANSFORM_FLIP_V)
|
|
||||||
y = 4 - y;
|
|
||||||
|
|
||||||
bytes[i] = _LCR_encodeMapBlockCoords(x,y,z);
|
bytes[i] = _LCR_encodeMapBlockCoords(x,y,z);
|
||||||
}
|
}
|
||||||
|
|
298
racing.h
298
racing.h
|
@ -15,18 +15,22 @@ typedef int32_t LCR_GameUnit; ///< abstract game unit
|
||||||
#define LCR_RACING_INPUT_LEFT 0x08
|
#define LCR_RACING_INPUT_LEFT 0x08
|
||||||
|
|
||||||
#define LCR_PHYSICS_UNIT 2048 ///< length of map square for physics engine
|
#define LCR_PHYSICS_UNIT 2048 ///< length of map square for physics engine
|
||||||
|
|
||||||
|
#define TPE_RESHAPE_TENSION_LIMIT 10
|
||||||
|
#define TPE_RESHAPE_ITERATIONS 5
|
||||||
|
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "tinyphysicsengine.h"
|
#include "tinyphysicsengine.h"
|
||||||
|
|
||||||
// TODO: move some of this to constants?
|
// TODO: move some of this to constants?
|
||||||
#define LCR_GRAVITY (LCR_PHYSICS_UNIT / 100)
|
|
||||||
#define LCR_CAR_FORWARD_FRICTION (TPE_F / 11)
|
#define LCR_GRAVITY (LCR_PHYSICS_UNIT / 140)
|
||||||
#define LCR_CAR_TURN_FRICTION (4 * TPE_F / 4)
|
#define LCR_CAR_FORWARD_FRICTION (TPE_F / 9)
|
||||||
#define LCR_CAR_ELASTICITY (TPE_F / 100)
|
#define LCR_CAR_TURN_FRICTION (TPE_F)
|
||||||
#define LCR_CAR_ACCELERATION (LCR_PHYSICS_UNIT / 15)
|
#define LCR_CAR_ELASTICITY (TPE_F / 110)
|
||||||
#define LCR_CAR_TURN_SPEED (LCR_GAME_UNIT / 20)
|
#define LCR_CAR_ACCELERATION (LCR_PHYSICS_UNIT / 16)
|
||||||
#define LCR_CAR_TURN_MAX (LCR_GAME_UNIT / 4)
|
#define LCR_CAR_TURN_SPEED (LCR_GAME_UNIT / 18)
|
||||||
|
#define LCR_CAR_TURN_MAX ((7 * LCR_GAME_UNIT) / 24)
|
||||||
|
|
||||||
#define LCR_CAR_JOINTS 5
|
#define LCR_CAR_JOINTS 5
|
||||||
#define LCR_CAR_CONNECTIONS 10
|
#define LCR_CAR_CONNECTIONS 10
|
||||||
|
@ -43,9 +47,13 @@ struct
|
||||||
Lower bits record current collisions, higher
|
Lower bits record current collisions, higher
|
||||||
bits the previous state (for averaging). */
|
bits the previous state (for averaging). */
|
||||||
|
|
||||||
|
TPE_Vec3 carPositions[2]; ///* Current and previous position in game units.
|
||||||
|
TPE_Vec3 carRotations[2]; ///* Current and previous rotation in game units.
|
||||||
|
|
||||||
|
|
||||||
|
TPE_Vec3 carOKPositions[LCR_CAR_JOINTS];
|
||||||
|
uint8_t carNotOKCount;
|
||||||
|
|
||||||
TPE_Vec3 carPositions[2]; ///* Current and previous position.
|
|
||||||
TPE_Vec3 carRotations[2]; ///* Current and previous rotation.
|
|
||||||
|
|
||||||
LCR_GameUnit wheelRotation;
|
LCR_GameUnit wheelRotation;
|
||||||
LCR_GameUnit wheelSteer;
|
LCR_GameUnit wheelSteer;
|
||||||
|
@ -61,17 +69,100 @@ TPE_Vec3 _LCR_racingBlockEnvFunc(TPE_Vec3 point, const uint8_t *block)
|
||||||
{
|
{
|
||||||
uint8_t bx, by, bz;
|
uint8_t bx, by, bz;
|
||||||
LCR_mapBlockGetCoords(block,&bx,&by,&bz);
|
LCR_mapBlockGetCoords(block,&bx,&by,&bz);
|
||||||
|
|
||||||
|
TPE_Vec3 blockOffset = TPE_vec3(
|
||||||
|
(((int) bx) - LCR_MAP_SIZE_BLOCKS / 2) * LCR_PHYSICS_UNIT,
|
||||||
|
(((int) by) - LCR_MAP_SIZE_BLOCKS / 2) * (LCR_PHYSICS_UNIT / 2),
|
||||||
|
(((int) bz) - LCR_MAP_SIZE_BLOCKS / 2) * LCR_PHYSICS_UNIT);
|
||||||
|
|
||||||
TPE_Vec3 center = TPE_vec3(
|
point = TPE_vec3Minus(point,blockOffset); // shift to origin
|
||||||
(((int) bx) - LCR_MAP_SIZE_BLOCKS / 2) * LCR_PHYSICS_UNIT
|
|
||||||
+ LCR_PHYSICS_UNIT / 2,
|
|
||||||
(((int) by) - LCR_MAP_SIZE_BLOCKS / 2) * (LCR_PHYSICS_UNIT / 2)
|
|
||||||
+ LCR_PHYSICS_UNIT / 4,
|
|
||||||
(((int) bz) - LCR_MAP_SIZE_BLOCKS / 2) * LCR_PHYSICS_UNIT
|
|
||||||
+ LCR_PHYSICS_UNIT / 2);
|
|
||||||
|
|
||||||
return TPE_envAABox(point,center,TPE_vec3(LCR_PHYSICS_UNIT / 2,
|
uint8_t transform =
|
||||||
LCR_PHYSICS_UNIT / 4,LCR_PHYSICS_UNIT / 2));
|
LCR_mapBlockOppositeTransform(LCR_mapBlockGetTransform(block));
|
||||||
|
|
||||||
|
LCR_TRANSFORM_COORDS(transform,point.x,point.y,point.z,LCR_PHYSICS_UNIT,
|
||||||
|
(LCR_PHYSICS_UNIT / 2))
|
||||||
|
|
||||||
|
point = TPE_vec3Minus(point,
|
||||||
|
TPE_vec3(LCR_PHYSICS_UNIT / 2,LCR_PHYSICS_UNIT / 4,LCR_PHYSICS_UNIT / 2));
|
||||||
|
|
||||||
|
switch (block[0])
|
||||||
|
{
|
||||||
|
case LCR_BLOCK_FULL:
|
||||||
|
case LCR_BLOCK_BOTTOM:
|
||||||
|
case LCR_BLOCK_LEFT:
|
||||||
|
case LCR_BLOCK_BOTTOM_LEFT:
|
||||||
|
case LCR_BLOCK_BOTTOM_LEFT_FRONT:
|
||||||
|
case LCR_BLOCK_FULL_ACCEL:
|
||||||
|
case LCR_BLOCK_FULL_FAN:
|
||||||
|
{
|
||||||
|
TPE_Vec3
|
||||||
|
offset = TPE_vec3(0,0,0),
|
||||||
|
size = TPE_vec3(LCR_PHYSICS_UNIT / 2,LCR_PHYSICS_UNIT / 4,
|
||||||
|
LCR_PHYSICS_UNIT / 2);
|
||||||
|
|
||||||
|
if (block[0] == LCR_BLOCK_BOTTOM ||
|
||||||
|
block[0] == LCR_BLOCK_BOTTOM_LEFT ||
|
||||||
|
block[0] == LCR_BLOCK_BOTTOM_LEFT_FRONT)
|
||||||
|
{
|
||||||
|
offset.y -= LCR_PHYSICS_UNIT / 8;
|
||||||
|
size.y = LCR_PHYSICS_UNIT / 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block[0] == LCR_BLOCK_LEFT ||
|
||||||
|
block[0] == LCR_BLOCK_BOTTOM_LEFT ||
|
||||||
|
block[0] == LCR_BLOCK_BOTTOM_LEFT_FRONT)
|
||||||
|
{
|
||||||
|
offset.x -= LCR_PHYSICS_UNIT / 4;
|
||||||
|
size.x = LCR_PHYSICS_UNIT / 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block[0] == LCR_BLOCK_BOTTOM_LEFT_FRONT)
|
||||||
|
{
|
||||||
|
offset.z -= LCR_PHYSICS_UNIT / 4;
|
||||||
|
size.z = LCR_PHYSICS_UNIT / 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
point = TPE_envAABox(point,offset,size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case LCR_BLOCK_RAMP:
|
||||||
|
case LCR_BLOCK_RAMP_34:
|
||||||
|
case LCR_BLOCK_RAMP_12:
|
||||||
|
case LCR_BLOCK_RAMP_14:
|
||||||
|
{
|
||||||
|
TPE_Unit sides[6];
|
||||||
|
sides[0] = -1 * LCR_PHYSICS_UNIT / 2;
|
||||||
|
sides[1] = -1 * LCR_PHYSICS_UNIT / 4;
|
||||||
|
|
||||||
|
sides[2] = LCR_PHYSICS_UNIT / 2;
|
||||||
|
sides[3] = -1 * LCR_PHYSICS_UNIT / 4;
|
||||||
|
|
||||||
|
sides[4] = LCR_PHYSICS_UNIT / 2;
|
||||||
|
sides[5] = -1 * LCR_PHYSICS_UNIT / 4 +
|
||||||
|
LCR_rampHeight4ths(block[0]) * (LCR_PHYSICS_UNIT / 8);
|
||||||
|
|
||||||
|
point = TPE_envAATriPrism(point,TPE_vec3(0,0,0),sides,LCR_PHYSICS_UNIT,2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
point = TPE_vec3(0,0,LCR_MAP_SIZE_BLOCKS * LCR_PHYSICS_UNIT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
point = TPE_vec3Plus(point,
|
||||||
|
TPE_vec3(LCR_PHYSICS_UNIT / 2,LCR_PHYSICS_UNIT / 4,LCR_PHYSICS_UNIT / 2));
|
||||||
|
|
||||||
|
transform = LCR_mapBlockOppositeTransform(transform);
|
||||||
|
|
||||||
|
LCR_TRANSFORM_COORDS(transform,point.x,point.y,point.z,LCR_PHYSICS_UNIT,
|
||||||
|
(LCR_PHYSICS_UNIT / 2))
|
||||||
|
|
||||||
|
point = TPE_vec3Plus(point,blockOffset); // shift back
|
||||||
|
|
||||||
|
return point;
|
||||||
}
|
}
|
||||||
|
|
||||||
TPE_Vec3 _LCR_racingEnvironmentFunction(TPE_Vec3 point, TPE_Unit maxDist)
|
TPE_Vec3 _LCR_racingEnvironmentFunction(TPE_Vec3 point, TPE_Unit maxDist)
|
||||||
|
@ -82,6 +173,10 @@ TPE_Vec3 _LCR_racingEnvironmentFunction(TPE_Vec3 point, TPE_Unit maxDist)
|
||||||
(LCR_PHYSICS_UNIT * LCR_MAP_SIZE_BLOCKS) / 2,
|
(LCR_PHYSICS_UNIT * LCR_MAP_SIZE_BLOCKS) / 2,
|
||||||
LCR_PHYSICS_UNIT * LCR_MAP_SIZE_BLOCKS)),point)
|
LCR_PHYSICS_UNIT * LCR_MAP_SIZE_BLOCKS)),point)
|
||||||
|
|
||||||
|
// without this check we might try to get block outside the map
|
||||||
|
if (_pBest.x == point.x && _pBest.y == point.y && _pBest.z == point.z)
|
||||||
|
return _pBest;
|
||||||
|
|
||||||
if (maxDist <= LCR_PHYSICS_UNIT / 4) // considering half of square height
|
if (maxDist <= LCR_PHYSICS_UNIT / 4) // considering half of square height
|
||||||
{
|
{
|
||||||
/* Here we only check the 8 closest blocks => relatively fast. */
|
/* Here we only check the 8 closest blocks => relatively fast. */
|
||||||
|
@ -142,7 +237,8 @@ TPE_Vec3 _LCR_racingEnvironmentFunction(TPE_Vec3 point, TPE_Unit maxDist)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("oof\n");
|
LCR_LOG1("collision checking all blocks (shouldn't happen often!)");
|
||||||
|
|
||||||
const uint8_t *block = LCR_currentMap.blocks;
|
const uint8_t *block = LCR_currentMap.blocks;
|
||||||
|
|
||||||
/* Full check of all map blocks, slow, shouldn't happen often! */
|
/* Full check of all map blocks, slow, shouldn't happen often! */
|
||||||
|
@ -195,6 +291,8 @@ LCR_GameUnit _LCR_racingSmoothRot(LCR_GameUnit angleNew, LCR_GameUnit angleOld)
|
||||||
*/
|
*/
|
||||||
void LCR_racingRestart(void)
|
void LCR_racingRestart(void)
|
||||||
{
|
{
|
||||||
|
LCR_LOG0("restarting race");
|
||||||
|
|
||||||
LCR_racing.tick = 0;
|
LCR_racing.tick = 0;
|
||||||
|
|
||||||
TPE_bodyActivate(&(LCR_racing.carBody));
|
TPE_bodyActivate(&(LCR_racing.carBody));
|
||||||
|
@ -208,15 +306,43 @@ void LCR_racingRestart(void)
|
||||||
|
|
||||||
LCR_racing.carRotations[0] = TPE_vec3(0,0,0);
|
LCR_racing.carRotations[0] = TPE_vec3(0,0,0);
|
||||||
LCR_racing.carRotations[1] = LCR_racing.carRotations[0];
|
LCR_racing.carRotations[1] = LCR_racing.carRotations[0];
|
||||||
|
|
||||||
|
TPE_bodyMoveTo(&(LCR_racing.carBody),
|
||||||
|
TPE_vec3(
|
||||||
|
(((TPE_Unit) LCR_currentMap.startPos[0]) - LCR_MAP_SIZE_BLOCKS / 2)
|
||||||
|
* LCR_PHYSICS_UNIT + LCR_PHYSICS_UNIT / 2,
|
||||||
|
(((TPE_Unit) LCR_currentMap.startPos[1]) - LCR_MAP_SIZE_BLOCKS / 2)
|
||||||
|
* LCR_PHYSICS_UNIT / 2 + LCR_PHYSICS_UNIT / 4,
|
||||||
|
(((TPE_Unit) LCR_currentMap.startPos[2]) - LCR_MAP_SIZE_BLOCKS / 2)
|
||||||
|
* LCR_PHYSICS_UNIT + LCR_PHYSICS_UNIT / 2));
|
||||||
|
|
||||||
|
// TODO: allow also flipping the car upside down on start?
|
||||||
|
if (LCR_currentMap.startPos[3])
|
||||||
|
TPE_bodyRotateByAxis(&(LCR_racing.carBody),
|
||||||
|
TPE_vec3(0,
|
||||||
|
LCR_currentMap.startPos[3] == LCR_BLOCK_TRANSFORM_ROT_90 ? 3 * TPE_F / 4 :
|
||||||
|
(LCR_currentMap.startPos[3] == LCR_BLOCK_TRANSFORM_ROT_180 ? TPE_F / 2 :
|
||||||
|
(TPE_F / 4)),0));
|
||||||
|
|
||||||
|
for (int i = 0; i < LCR_CAR_JOINTS; ++i)
|
||||||
|
LCR_racing.carOKPositions[i] = TPE_vec3(0,0,0);
|
||||||
|
|
||||||
|
LCR_racing.carNotOKCount = 0;
|
||||||
|
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Initializes the racing module, only call once.
|
Initializes the racing module, only call once.
|
||||||
*/
|
*/
|
||||||
void LCR_racingInit(void)
|
void LCR_racingInit(void)
|
||||||
{
|
{
|
||||||
LCR_log("initializing racing engine");
|
LCR_LOG0("initializing racing engine");
|
||||||
|
|
||||||
// make the car body:
|
// make the car body:
|
||||||
TPE_makeCenterRectFull(LCR_racing.carJoints,
|
TPE_makeCenterRectFull(LCR_racing.carJoints,
|
||||||
|
@ -257,6 +383,8 @@ void LCR_racingInit(void)
|
||||||
void LCR_racingGetCarTransform(LCR_GameUnit position[3],
|
void LCR_racingGetCarTransform(LCR_GameUnit position[3],
|
||||||
LCR_GameUnit rotation[3], LCR_GameUnit interpolationParam)
|
LCR_GameUnit rotation[3], LCR_GameUnit interpolationParam)
|
||||||
{
|
{
|
||||||
|
LCR_LOG2("getting car transform");
|
||||||
|
|
||||||
TPE_Vec3 v;
|
TPE_Vec3 v;
|
||||||
|
|
||||||
#if LCR_SETTING_SMOOTH_ANIMATIONS
|
#if LCR_SETTING_SMOOTH_ANIMATIONS
|
||||||
|
@ -326,11 +454,28 @@ void _LCR_racingWheelAccelerate(unsigned int wheel, TPE_Vec3 dir)
|
||||||
(dir.z * LCR_CAR_ACCELERATION) / TPE_F;
|
(dir.z * LCR_CAR_ACCELERATION) / TPE_F;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int _LCR_racingCarShapeOK(void)
|
||||||
|
{
|
||||||
|
int r = 1;
|
||||||
|
|
||||||
|
for (int i = 0; i < LCR_racing.carBody.jointCount; ++i)
|
||||||
|
r &= TPE_connectionTension(TPE_dist(
|
||||||
|
LCR_racing.carBody.joints[
|
||||||
|
LCR_racing.carBody.connections[i].joint1].position,
|
||||||
|
LCR_racing.carBody.joints[
|
||||||
|
LCR_racing.carBody.connections[i].joint2].position),
|
||||||
|
LCR_racing.carBody.connections[i].length) < TPE_F / 16; // TODO: const
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Updates the racing physics world, call every LCR_RACING_TICK_MS milliseconds.
|
Updates the racing physics world, call every LCR_RACING_TICK_MS milliseconds.
|
||||||
*/
|
*/
|
||||||
void LCR_racingStep(unsigned int input)
|
void LCR_racingStep(unsigned int input)
|
||||||
{
|
{
|
||||||
|
LCR_LOG2("racing step start");
|
||||||
|
|
||||||
TPE_Vec3 carForw, carRight, carUp;
|
TPE_Vec3 carForw, carRight, carUp;
|
||||||
|
|
||||||
carForw = TPE_vec3Normalized(TPE_vec3Plus(
|
carForw = TPE_vec3Normalized(TPE_vec3Plus(
|
||||||
|
@ -438,35 +583,35 @@ void LCR_racingStep(unsigned int input)
|
||||||
(!(input & LCR_RACING_INPUT_RIGHT)))
|
(!(input & LCR_RACING_INPUT_RIGHT)))
|
||||||
LCR_racing.wheelSteer /= 2;
|
LCR_racing.wheelSteer /= 2;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if ((LCR_racing.wheelCollisions & 0x0f) != 0x0f) // EXPERIMENTAL: don't apply gravity with all wheels on ground
|
if ((LCR_racing.wheelCollisions & 0x0f) != 0x0f) // EXPERIMENTAL: don't apply gravity with all wheels on ground
|
||||||
TPE_bodyApplyGravity(&(LCR_racing.carBody),LCR_GRAVITY);
|
TPE_bodyApplyGravity(&(LCR_racing.carBody),LCR_GRAVITY);
|
||||||
|
|
||||||
LCR_racing.wheelCollisions <<= 4;
|
LCR_racing.wheelCollisions <<= 4;
|
||||||
|
|
||||||
|
LCR_LOG2("gonna step physics engine");
|
||||||
TPE_worldStep(&(LCR_racing.physicsWorld));
|
TPE_worldStep(&(LCR_racing.physicsWorld));
|
||||||
|
LCR_LOG2("stepping physics engine done");
|
||||||
|
|
||||||
if (TPE_vec3Dot(carUp,TPE_vec3Minus(LCR_racing.carBody.joints[4].position,
|
|
||||||
LCR_racing.carBody.joints[0].position)) < 0)
|
|
||||||
{
|
|
||||||
/* if the car falls on its roof the center joint may flip to the other
|
|
||||||
side, here we fix it */
|
|
||||||
|
|
||||||
LCR_racing.carBody.joints[4].position = TPE_vec3Plus(TPE_vec3Times(carUp,
|
|
||||||
LCR_GAME_UNIT / 4),LCR_racing.carBody.joints[4].position);
|
|
||||||
}
|
|
||||||
|
|
||||||
TPE_Vec3 tmpVec = LCR_racing.carPositions[0];
|
TPE_Vec3 tmpVec = LCR_racing.carPositions[0];
|
||||||
|
|
||||||
LCR_racing.carPositions[0] = // average position of 4 wheels to get car pos
|
TPE_Vec3 wheelAverage =
|
||||||
_LCR_TPE_vec3DividePlain(
|
_LCR_TPE_vec3DividePlain(
|
||||||
TPE_vec3TimesPlain(
|
TPE_vec3Plus(
|
||||||
TPE_vec3Plus(
|
|
||||||
TPE_vec3Plus(
|
TPE_vec3Plus(
|
||||||
LCR_racing.carBody.joints[0].position,
|
LCR_racing.carBody.joints[0].position,
|
||||||
LCR_racing.carBody.joints[1].position),
|
LCR_racing.carBody.joints[1].position),
|
||||||
TPE_vec3Plus(
|
TPE_vec3Plus(
|
||||||
LCR_racing.carBody.joints[2].position,
|
LCR_racing.carBody.joints[2].position,
|
||||||
LCR_racing.carBody.joints[3].position)
|
LCR_racing.carBody.joints[3].position)),4);
|
||||||
),LCR_GAME_UNIT),4 * LCR_PHYSICS_UNIT);
|
|
||||||
|
LCR_racing.carPositions[0] =
|
||||||
|
_LCR_TPE_vec3DividePlain(
|
||||||
|
TPE_vec3TimesPlain(
|
||||||
|
wheelAverage,LCR_GAME_UNIT),
|
||||||
|
LCR_PHYSICS_UNIT);
|
||||||
|
|
||||||
LCR_racing.carPositions[0] = // smooth the position
|
LCR_racing.carPositions[0] = // smooth the position
|
||||||
TPE_vec3KeepWithinBox(LCR_racing.carPositions[1],LCR_racing.carPositions[0],
|
TPE_vec3KeepWithinBox(LCR_racing.carPositions[1],LCR_racing.carPositions[0],
|
||||||
|
@ -483,12 +628,93 @@ void LCR_racingStep(unsigned int input)
|
||||||
LCR_racing.carRotations[1] = LCR_racing.carRotations[0];
|
LCR_racing.carRotations[1] = LCR_racing.carRotations[0];
|
||||||
LCR_racing.carRotations[0] = tmpVec;
|
LCR_racing.carRotations[0] = tmpVec;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TPE_Unit angle =
|
||||||
|
TPE_vec3Dot(carUp,TPE_vec3Normalized(TPE_vec3Minus(
|
||||||
|
LCR_racing.carBody.joints[4].position,
|
||||||
|
LCR_racing.carBody.joints[0].position)));
|
||||||
|
|
||||||
|
if (angle < TPE_F / 4) // TODO: magic constant
|
||||||
|
{
|
||||||
|
LCR_LOG2("roof squeezed, applying anti force")
|
||||||
|
|
||||||
|
tmpVec = TPE_vec3Times(carUp,LCR_PHYSICS_UNIT / 16); // TODO: 16 magic con.
|
||||||
|
|
||||||
|
if (angle <= 0)
|
||||||
|
{
|
||||||
|
LCR_LOG1("roof flipped over, fixing")
|
||||||
|
LCR_racing.carBody.joints[4].position = wheelAverage;
|
||||||
|
angle = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
angle = TPE_F - 4 * angle; // 4 comes from above TPE_F / 4
|
||||||
|
|
||||||
|
tmpVec = TPE_vec3Times(tmpVec,angle);
|
||||||
|
|
||||||
|
// accelerate roof and wheels away from each other
|
||||||
|
for (int i = 0; i < LCR_CAR_JOINTS; ++i)
|
||||||
|
{
|
||||||
|
LCR_racing.carBody.joints[i].velocity[0] += (i == 4 ? 1 : -1) * tmpVec.x;
|
||||||
|
LCR_racing.carBody.joints[i].velocity[1] += (i == 4 ? 1 : -1) * tmpVec.y;
|
||||||
|
LCR_racing.carBody.joints[i].velocity[2] += (i == 4 ? 1 : -1) * tmpVec.z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((LCR_racing.carBody.flags & TPE_BODY_FLAG_UNRESOLVED) ||
|
||||||
|
!_LCR_racingCarShapeOK())
|
||||||
|
{
|
||||||
|
// car not OK
|
||||||
|
|
||||||
|
if (LCR_racing.carNotOKCount > 8) // TODO: constant
|
||||||
|
{
|
||||||
|
LCR_LOG1("car not OK for some time, fixing");
|
||||||
|
|
||||||
|
for (int i = 0; i < LCR_CAR_JOINTS; ++i)
|
||||||
|
{
|
||||||
|
if (LCR_racing.carNotOKCount < 30) // TODO: const
|
||||||
|
{
|
||||||
|
// for a while try to smoothly iterate towards previous OK position
|
||||||
|
LCR_racing.carBody.joints[i].position =
|
||||||
|
TPE_vec3Plus(LCR_racing.carBody.joints[i].position,
|
||||||
|
LCR_racing.carOKPositions[i]);
|
||||||
|
|
||||||
|
LCR_racing.carBody.joints[i].position.x /= 2;
|
||||||
|
LCR_racing.carBody.joints[i].position.y /= 2;
|
||||||
|
LCR_racing.carBody.joints[i].position.z /= 2;
|
||||||
|
}
|
||||||
|
else // hard set the pos (iteration may be infinite due to sim.)
|
||||||
|
LCR_racing.carBody.joints[i].position = LCR_racing.carOKPositions[i];
|
||||||
|
|
||||||
|
for (int j = 0; j < 3; ++j) // lower speed a bit
|
||||||
|
LCR_racing.carBody.joints[i].velocity[j] =
|
||||||
|
(7 * ((int) LCR_racing.carBody.joints[i].velocity[j])) / 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LCR_racing.carNotOKCount += LCR_racing.carNotOKCount < 32 ? 1 : 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// car OK
|
||||||
|
// LCR_racing.carNotOKCount -= LCR_racing.carNotOKCount ? 1 : 0;
|
||||||
|
LCR_racing.carNotOKCount = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < LCR_CAR_JOINTS; ++i)
|
||||||
|
LCR_racing.carOKPositions[i] = LCR_racing.carBody.joints[i].position;
|
||||||
|
}
|
||||||
|
|
||||||
LCR_racing.tick++;
|
LCR_racing.tick++;
|
||||||
|
|
||||||
|
LCR_LOG2("racing step end");
|
||||||
}
|
}
|
||||||
|
|
||||||
void LCR_physicsDebugDraw(LCR_GameUnit camPos[3], LCR_GameUnit camRot[2],
|
void LCR_physicsDebugDraw(LCR_GameUnit camPos[3], LCR_GameUnit camRot[2],
|
||||||
LCR_GameUnit camFov)
|
LCR_GameUnit camFov)
|
||||||
{
|
{
|
||||||
|
LCR_LOG2("drawing physics debug overlay");
|
||||||
|
|
||||||
TPE_Vec3 cPos, cRot, cView;
|
TPE_Vec3 cPos, cRot, cView;
|
||||||
|
|
||||||
cPos.x = (camPos[0] * LCR_PHYSICS_UNIT) / LCR_GAME_UNIT;
|
cPos.x = (camPos[0] * LCR_PHYSICS_UNIT) / LCR_GAME_UNIT;
|
||||||
|
@ -504,7 +730,7 @@ void LCR_physicsDebugDraw(LCR_GameUnit camPos[3], LCR_GameUnit camRot[2],
|
||||||
cView.z = (camFov * TPE_F) / LCR_GAME_UNIT;
|
cView.z = (camFov * TPE_F) / LCR_GAME_UNIT;
|
||||||
|
|
||||||
TPE_worldDebugDraw(&(LCR_racing.physicsWorld),_LCR_drawPhysicsDebugPixel,
|
TPE_worldDebugDraw(&(LCR_racing.physicsWorld),_LCR_drawPhysicsDebugPixel,
|
||||||
cPos,cRot,cView,16,LCR_PHYSICS_UNIT / 4);
|
cPos,cRot,cView,16,LCR_PHYSICS_UNIT / 4,LCR_racing.tick * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // guard
|
#endif // guard
|
||||||
|
|
61
renderer.h
61
renderer.h
|
@ -16,7 +16,8 @@
|
||||||
|
|
||||||
/// Renderer specific unit, length of one map square.
|
/// Renderer specific unit, length of one map square.
|
||||||
#define LCR_RENDERER_UNIT (S3L_F / 2)
|
#define LCR_RENDERER_UNIT (S3L_F / 2)
|
||||||
// ^ just S3L_F leaves some tris bugging
|
// NOTE: ^ S3L_F sometimes makes some triangles bug, S3L_F/2 seems to fix it
|
||||||
|
// but it's more jerky, maybe try to apply anti-overflow in S3L?
|
||||||
|
|
||||||
#define LCR_RENDERER_CHUNK_RESOLUTION 4 // do not change
|
#define LCR_RENDERER_CHUNK_RESOLUTION 4 // do not change
|
||||||
#define LCR_RENDERER_LOD_BLOCKS 64 // do not change
|
#define LCR_RENDERER_LOD_BLOCKS 64 // do not change
|
||||||
|
@ -30,6 +31,10 @@
|
||||||
#define LCR_RENDERER_MODEL_COUNT 10
|
#define LCR_RENDERER_MODEL_COUNT 10
|
||||||
#define LCR_RENDERER_CAR_SCALE (LCR_RENDERER_UNIT / 4)
|
#define LCR_RENDERER_CAR_SCALE (LCR_RENDERER_UNIT / 4)
|
||||||
|
|
||||||
|
/** For some reason the map model is a bit misaligned with physics world, this
|
||||||
|
kinda hotfixes it -- later try to discover source of this bug. TODO */
|
||||||
|
#define _LCR_MAP_MODEL_SCALE 1034
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
S3L_Scene scene;
|
S3L_Scene scene;
|
||||||
|
@ -86,6 +91,8 @@ struct
|
||||||
void LCR_rendererSetCarTransform(LCR_GameUnit position[3],
|
void LCR_rendererSetCarTransform(LCR_GameUnit position[3],
|
||||||
LCR_GameUnit rotation[3])
|
LCR_GameUnit rotation[3])
|
||||||
{
|
{
|
||||||
|
LCR_LOG2("setting car transform");
|
||||||
|
|
||||||
LCR_renderer.carModel->transform.translation.x =
|
LCR_renderer.carModel->transform.translation.x =
|
||||||
(position[0] * LCR_RENDERER_UNIT) / LCR_GAME_UNIT;
|
(position[0] * LCR_RENDERER_UNIT) / LCR_GAME_UNIT;
|
||||||
LCR_renderer.carModel->transform.translation.y =
|
LCR_renderer.carModel->transform.translation.y =
|
||||||
|
@ -266,7 +273,7 @@ S3L_Index _LCR_rendererAddMapVert(S3L_Unit x, S3L_Unit y, S3L_Unit z)
|
||||||
return LCR_renderer.mapModel.vertexCount - 1;
|
return LCR_renderer.mapModel.vertexCount - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
LCR_log("couldn't add map vertex!");
|
LCR_LOG0("couldn't add map vertex!");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -474,7 +481,7 @@ uint8_t _LCR_rendererCheckMapTriCover(const S3L_Index *t1,
|
||||||
*/
|
*/
|
||||||
void _LCR_cullHiddenMapTris(void)
|
void _LCR_cullHiddenMapTris(void)
|
||||||
{
|
{
|
||||||
LCR_log("culling invisible triangles");
|
LCR_LOG1("culling invisible triangles");
|
||||||
|
|
||||||
int n = 0; // number of removed elements
|
int n = 0; // number of removed elements
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -562,7 +569,7 @@ void _LCR_cullHiddenMapTris(void)
|
||||||
|
|
||||||
void _LCR_makeMapChunks(void)
|
void _LCR_makeMapChunks(void)
|
||||||
{
|
{
|
||||||
LCR_log("making map chunks");
|
LCR_LOG1("making map chunks");
|
||||||
|
|
||||||
S3L_Index start = 0;
|
S3L_Index start = 0;
|
||||||
|
|
||||||
|
@ -607,7 +614,7 @@ void _LCR_makeMapChunks(void)
|
||||||
*/
|
*/
|
||||||
uint8_t _LCR_buildMapModel(void)
|
uint8_t _LCR_buildMapModel(void)
|
||||||
{
|
{
|
||||||
LCR_log("building map model");
|
LCR_LOG1("building map model");
|
||||||
|
|
||||||
uint8_t blockShapeBytes[LCR_MAP_BLOCK_SHAPE_MAX_BYTES];
|
uint8_t blockShapeBytes[LCR_MAP_BLOCK_SHAPE_MAX_BYTES];
|
||||||
uint8_t blockShapeByteCount;
|
uint8_t blockShapeByteCount;
|
||||||
|
@ -615,6 +622,13 @@ uint8_t _LCR_buildMapModel(void)
|
||||||
S3L_model3DInit(LCR_renderer.mapVerts,0,LCR_renderer.mapTris,0,
|
S3L_model3DInit(LCR_renderer.mapVerts,0,LCR_renderer.mapTris,0,
|
||||||
&LCR_renderer.mapModel);
|
&LCR_renderer.mapModel);
|
||||||
|
|
||||||
|
LCR_renderer.mapModel.transform.scale.x =
|
||||||
|
(_LCR_MAP_MODEL_SCALE * S3L_F) / 1024;
|
||||||
|
LCR_renderer.mapModel.transform.scale.y
|
||||||
|
= LCR_renderer.mapModel.transform.scale.x;
|
||||||
|
LCR_renderer.mapModel.transform.scale.z
|
||||||
|
= LCR_renderer.mapModel.transform.scale.x;
|
||||||
|
|
||||||
for (int j = 0; j < LCR_currentMap.blockCount; ++j)
|
for (int j = 0; j < LCR_currentMap.blockCount; ++j)
|
||||||
{
|
{
|
||||||
if ((j + 1) % LCR_SETTING_TRIANGLE_CULLING_PERIOD == 0)
|
if ((j + 1) % LCR_SETTING_TRIANGLE_CULLING_PERIOD == 0)
|
||||||
|
@ -714,7 +728,8 @@ uint8_t _LCR_buildMapModel(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_LCR_rendererAddMapTri(triIndices[0],triIndices[1],triIndices[2],triData);
|
_LCR_rendererAddMapTri(triIndices[0],triIndices[1],triIndices[2],
|
||||||
|
triData);
|
||||||
}
|
}
|
||||||
|
|
||||||
vi = 0;
|
vi = 0;
|
||||||
|
@ -726,14 +741,14 @@ uint8_t _LCR_buildMapModel(void)
|
||||||
|
|
||||||
_LCR_cullHiddenMapTris();
|
_LCR_cullHiddenMapTris();
|
||||||
|
|
||||||
LCR_log("map model built");
|
LCR_LOG1("map model built");
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _LCR_rendererComputeLOD(void)
|
void _LCR_rendererComputeLOD(void)
|
||||||
{
|
{
|
||||||
LCR_log("computing LOD");
|
LCR_LOG1("computing LOD");
|
||||||
|
|
||||||
for (int i = 0; i < LCR_RENDERER_LOD_BLOCKS; ++i)
|
for (int i = 0; i < LCR_RENDERER_LOD_BLOCKS; ++i)
|
||||||
LCR_renderer.gridOfLODs[i] = 0;
|
LCR_renderer.gridOfLODs[i] = 0;
|
||||||
|
@ -754,7 +769,7 @@ void _LCR_rendererComputeLOD(void)
|
||||||
|
|
||||||
uint8_t LCR_rendererInit(void)
|
uint8_t LCR_rendererInit(void)
|
||||||
{
|
{
|
||||||
LCR_log("initializing renderer");
|
LCR_LOG0("initializing renderer");
|
||||||
|
|
||||||
LCR_renderer.frame = 0;
|
LCR_renderer.frame = 0;
|
||||||
|
|
||||||
|
@ -821,6 +836,8 @@ LCR_renderer.ghostModel->transform.translation.x -= LCR_GAME_UNIT / 4;
|
||||||
LCR_renderer.wheelSteer = 0;
|
LCR_renderer.wheelSteer = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
LCR_LOG2("initializing 3D scene");
|
||||||
|
|
||||||
S3L_sceneInit(
|
S3L_sceneInit(
|
||||||
LCR_renderer.models,LCR_RENDERER_MODEL_COUNT,&LCR_renderer.scene);
|
LCR_renderer.models,LCR_RENDERER_MODEL_COUNT,&LCR_renderer.scene);
|
||||||
|
|
||||||
|
@ -851,6 +868,8 @@ void LCR_rendererGetCameraTransform(LCR_GameUnit position[3],
|
||||||
void LCR_rendererMoveCamera(LCR_GameUnit forwRightUpOffset[3],
|
void LCR_rendererMoveCamera(LCR_GameUnit forwRightUpOffset[3],
|
||||||
LCR_GameUnit yawPitchOffset[2])
|
LCR_GameUnit yawPitchOffset[2])
|
||||||
{
|
{
|
||||||
|
LCR_LOG2("moving camera");
|
||||||
|
|
||||||
S3L_Vec4 f, r, u;
|
S3L_Vec4 f, r, u;
|
||||||
|
|
||||||
S3L_rotationToDirections(LCR_renderer.scene.camera.transform.rotation,
|
S3L_rotationToDirections(LCR_renderer.scene.camera.transform.rotation,
|
||||||
|
@ -898,7 +917,7 @@ void LCR_rendererDrawRect(int x, int y, unsigned int w, unsigned int h,
|
||||||
|
|
||||||
if (x < 0)
|
if (x < 0)
|
||||||
{
|
{
|
||||||
if (-1 * x > ((int) w))
|
if (-1 * x >= ((int) w))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
w += x;
|
w += x;
|
||||||
|
@ -917,7 +936,7 @@ void LCR_rendererDrawRect(int x, int y, unsigned int w, unsigned int h,
|
||||||
y = 0;
|
y = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (y + h > LCR_EFFECTIVE_RESOLUTION_X)
|
if (y + h > LCR_EFFECTIVE_RESOLUTION_Y)
|
||||||
h = LCR_EFFECTIVE_RESOLUTION_Y - y;
|
h = LCR_EFFECTIVE_RESOLUTION_Y - y;
|
||||||
|
|
||||||
unsigned long index = y * LCR_EFFECTIVE_RESOLUTION_X + x;
|
unsigned long index = y * LCR_EFFECTIVE_RESOLUTION_X + x;
|
||||||
|
@ -950,6 +969,8 @@ void LCR_rendererDrawRect(int x, int y, unsigned int w, unsigned int h,
|
||||||
void _LCR_rendererDrawLODBlock(int blockX, int blockY, int blockZ, unsigned int size,
|
void _LCR_rendererDrawLODBlock(int blockX, int blockY, int blockZ, unsigned int size,
|
||||||
uint16_t color, uint8_t variability)
|
uint16_t color, uint8_t variability)
|
||||||
{
|
{
|
||||||
|
LCR_LOG2("drawing LOD block");
|
||||||
|
|
||||||
S3L_Vec4 p, r;
|
S3L_Vec4 p, r;
|
||||||
|
|
||||||
p.x = (blockX - LCR_MAP_SIZE_BLOCKS / 2) * LCR_RENDERER_UNIT
|
p.x = (blockX - LCR_MAP_SIZE_BLOCKS / 2) * LCR_RENDERER_UNIT
|
||||||
|
@ -994,6 +1015,8 @@ void _LCR_rendererDrawLODBlock(int blockX, int blockY, int blockZ, unsigned int
|
||||||
*/
|
*/
|
||||||
void LCR_rendererDrawSky(int sky, S3L_Unit offsetH, S3L_Unit offsetV)
|
void LCR_rendererDrawSky(int sky, S3L_Unit offsetH, S3L_Unit offsetV)
|
||||||
{
|
{
|
||||||
|
LCR_LOG2("drawing sky");
|
||||||
|
|
||||||
int anchorPoint[2], y;
|
int anchorPoint[2], y;
|
||||||
unsigned long pixelIndex;
|
unsigned long pixelIndex;
|
||||||
unsigned int topColor, bottomColor;
|
unsigned int topColor, bottomColor;
|
||||||
|
@ -1183,6 +1206,8 @@ S3L_Unit _LCR_rendererSmoothRot(S3L_Unit angleOld, S3L_Unit angleNew,
|
||||||
*/
|
*/
|
||||||
void _LCR_rendererLoadMapChunks(void)
|
void _LCR_rendererLoadMapChunks(void)
|
||||||
{
|
{
|
||||||
|
LCR_LOG2("loading map chunks");
|
||||||
|
|
||||||
int8_t camChunk[3], chunkOffsets[3];
|
int8_t camChunk[3], chunkOffsets[3];
|
||||||
S3L_Vec4 cp = LCR_renderer.scene.camera.transform.translation;
|
S3L_Vec4 cp = LCR_renderer.scene.camera.transform.translation;
|
||||||
S3L_Vec4 cf;
|
S3L_Vec4 cf;
|
||||||
|
@ -1223,6 +1248,8 @@ void _LCR_rendererLoadMapChunks(void)
|
||||||
*/
|
*/
|
||||||
void LCR_rendererDrawLOD(void)
|
void LCR_rendererDrawLOD(void)
|
||||||
{
|
{
|
||||||
|
LCR_LOG2("drawing LOD");
|
||||||
|
|
||||||
#if LCR_SETTING_LOD_DISTANCE < 64
|
#if LCR_SETTING_LOD_DISTANCE < 64
|
||||||
int variability = 0;
|
int variability = 0;
|
||||||
|
|
||||||
|
@ -1254,6 +1281,8 @@ void LCR_rendererDrawLOD(void)
|
||||||
|
|
||||||
void LCR_drawLevelFloor(void)
|
void LCR_drawLevelFloor(void)
|
||||||
{
|
{
|
||||||
|
LCR_LOG2("drawing floor");
|
||||||
|
|
||||||
#if LCR_SETTING_FLOOR_PARTICLE_SIZE != 0
|
#if LCR_SETTING_FLOOR_PARTICLE_SIZE != 0
|
||||||
#define _STEP ((LCR_MAP_SIZE_BLOCKS * LCR_RENDERER_UNIT) / LCR_SETTING_FLOOR_PARTICLE_RESOLUTION)
|
#define _STEP ((LCR_MAP_SIZE_BLOCKS * LCR_RENDERER_UNIT) / LCR_SETTING_FLOOR_PARTICLE_RESOLUTION)
|
||||||
|
|
||||||
|
@ -1289,6 +1318,8 @@ void LCR_drawLevelFloor(void)
|
||||||
#if LCR_ANIMATE_CAR
|
#if LCR_ANIMATE_CAR
|
||||||
void _LCR_rendererAnimateCar(void)
|
void _LCR_rendererAnimateCar(void)
|
||||||
{
|
{
|
||||||
|
LCR_LOG2("animating car");
|
||||||
|
|
||||||
for (int i = LCR_renderer.frame % LCR_SETTING_CAR_ANIMATION_SUBDIVIDE;
|
for (int i = LCR_renderer.frame % LCR_SETTING_CAR_ANIMATION_SUBDIVIDE;
|
||||||
i < LCR_CAR_VERTEX_COUNT; i += LCR_SETTING_CAR_ANIMATION_SUBDIVIDE)
|
i < LCR_CAR_VERTEX_COUNT; i += LCR_SETTING_CAR_ANIMATION_SUBDIVIDE)
|
||||||
{
|
{
|
||||||
|
@ -1338,6 +1369,8 @@ void _LCR_rendererAnimateCar(void)
|
||||||
|
|
||||||
void LCR_rendererCameraFollow(void)
|
void LCR_rendererCameraFollow(void)
|
||||||
{
|
{
|
||||||
|
LCR_LOG2("following camera");
|
||||||
|
|
||||||
S3L_Transform3D transPrev = LCR_renderer.scene.camera.transform;
|
S3L_Transform3D transPrev = LCR_renderer.scene.camera.transform;
|
||||||
|
|
||||||
LCR_renderer.scene.camera.transform.translation.y =
|
LCR_renderer.scene.camera.transform.translation.y =
|
||||||
|
@ -1414,6 +1447,8 @@ void LCR_rendererSetWheelState(LCR_GameUnit rotation, LCR_GameUnit steer)
|
||||||
|
|
||||||
void LCR_rendererDraw(void)
|
void LCR_rendererDraw(void)
|
||||||
{
|
{
|
||||||
|
LCR_LOG2("rendering frame (start)");
|
||||||
|
|
||||||
// first make sure rotations are in correct range:
|
// first make sure rotations are in correct range:
|
||||||
LCR_renderer.scene.camera.transform.rotation.y = S3L_wrap(
|
LCR_renderer.scene.camera.transform.rotation.y = S3L_wrap(
|
||||||
LCR_renderer.scene.camera.transform.rotation.y, S3L_F);
|
LCR_renderer.scene.camera.transform.rotation.y, S3L_F);
|
||||||
|
@ -1437,9 +1472,13 @@ void LCR_rendererDraw(void)
|
||||||
LCR_drawLevelFloor();
|
LCR_drawLevelFloor();
|
||||||
LCR_rendererDrawLOD();
|
LCR_rendererDrawLOD();
|
||||||
|
|
||||||
|
LCR_LOG2("gonna render 3D scene");
|
||||||
S3L_drawScene(LCR_renderer.scene);
|
S3L_drawScene(LCR_renderer.scene);
|
||||||
|
LCR_LOG2("rendering 3D scene done");
|
||||||
|
|
||||||
LCR_renderer.frame++;
|
LCR_renderer.frame++;
|
||||||
|
|
||||||
|
LCR_LOG2("rendering frame (end)");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // guard
|
#endif // guard
|
||||||
|
|
|
@ -131,4 +131,11 @@
|
||||||
#define LCR_SETTING_SMOOTH_ANIMATIONS 1
|
#define LCR_SETTING_SMOOTH_ANIMATIONS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef LCR_SETTING_LOG_LEVEL
|
||||||
|
/** How detailed the console logs should be. 0 turns off logging, 1 means
|
||||||
|
normal, 2 more detailed etc. Setting high log level may result in spam and
|
||||||
|
slower game, but is useful for debugging. */
|
||||||
|
#define LCR_SETTING_LOG_LEVEL 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // guard
|
#endif // guard
|
||||||
|
|
|
@ -252,6 +252,9 @@ typedef struct
|
||||||
energy. */
|
energy. */
|
||||||
#define TPE_BODY_FLAG_NO_BSPHERE 64 /**< Stops quick bounding sphere checks
|
#define TPE_BODY_FLAG_NO_BSPHERE 64 /**< Stops quick bounding sphere checks
|
||||||
against environment. */
|
against environment. */
|
||||||
|
#define TPE_BODY_FLAG_UNRESOLVED 128 /**< Set automatically for bodies whose
|
||||||
|
collision with environment failed
|
||||||
|
to be resolved. */
|
||||||
|
|
||||||
/** Function used for defining static environment, working similarly to an SDF
|
/** Function used for defining static environment, working similarly to an SDF
|
||||||
(signed distance function). The parameters are: 3D point P, max distance D.
|
(signed distance function). The parameters are: 3D point P, max distance D.
|
||||||
|
@ -539,7 +542,7 @@ TPE_Vec3 TPE_bodyGetCenterOfMass(const TPE_Body *body);
|
||||||
e.g. 16). */
|
e.g. 16). */
|
||||||
void TPE_worldDebugDraw(TPE_World *world, TPE_DebugDrawFunction drawFunc,
|
void TPE_worldDebugDraw(TPE_World *world, TPE_DebugDrawFunction drawFunc,
|
||||||
TPE_Vec3 camPos, TPE_Vec3 camRot, TPE_Vec3 camView, uint16_t envGridRes,
|
TPE_Vec3 camPos, TPE_Vec3 camRot, TPE_Vec3 camView, uint16_t envGridRes,
|
||||||
TPE_Unit envGridSize);
|
TPE_Unit envGridSize, TPE_Unit offset);
|
||||||
|
|
||||||
#define TPE_DEBUG_COLOR_CONNECTION 0
|
#define TPE_DEBUG_COLOR_CONNECTION 0
|
||||||
#define TPE_DEBUG_COLOR_JOINT 1
|
#define TPE_DEBUG_COLOR_JOINT 1
|
||||||
|
@ -592,7 +595,7 @@ TPE_Vec3 TPE_envLineSegment(TPE_Vec3 point, TPE_Vec3 a, TPE_Vec3 b);
|
||||||
TPE_Vec3 TPE_envHeightmap(TPE_Vec3 point, TPE_Vec3 center, TPE_Unit gridSize,
|
TPE_Vec3 TPE_envHeightmap(TPE_Vec3 point, TPE_Vec3 center, TPE_Unit gridSize,
|
||||||
TPE_Unit (*heightFunction)(int32_t x, int32_t y), TPE_Unit maxDist);
|
TPE_Unit (*heightFunction)(int32_t x, int32_t y), TPE_Unit maxDist);
|
||||||
|
|
||||||
/** Environment function for triagnular prism, e.g. for ramps. The sides array
|
/** Environment function for triangular prism, e.g. for ramps. The sides array
|
||||||
contains three 2D coordinates of points of the triangle in given plane with
|
contains three 2D coordinates of points of the triangle in given plane with
|
||||||
respect to the center. WARNING: the points must be specified in counter
|
respect to the center. WARNING: the points must be specified in counter
|
||||||
clowckwise direction! The direction var specified axis direction (0, 1 or
|
clowckwise direction! The direction var specified axis direction (0, 1 or
|
||||||
|
@ -637,8 +640,7 @@ static inline TPE_Unit TPE_nonZero(TPE_Unit x)
|
||||||
static inline TPE_Unit TPE_connectionTension(TPE_Unit length,
|
static inline TPE_Unit TPE_connectionTension(TPE_Unit length,
|
||||||
TPE_Unit desiredLength)
|
TPE_Unit desiredLength)
|
||||||
{
|
{
|
||||||
return (length * TPE_F) / desiredLength
|
return (length * TPE_F) / desiredLength - TPE_F;
|
||||||
- TPE_F;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TPE_Joint TPE_joint(TPE_Vec3 position, TPE_Unit size)
|
TPE_Joint TPE_joint(TPE_Vec3 position, TPE_Unit size)
|
||||||
|
@ -1913,6 +1915,8 @@ uint8_t TPE_bodyEnvironmentResolveCollision(TPE_Body *body,
|
||||||
TPE_Vec3 c;
|
TPE_Vec3 c;
|
||||||
TPE_Unit d;
|
TPE_Unit d;
|
||||||
|
|
||||||
|
body->flags &= ~TPE_BODY_FLAG_UNRESOLVED;
|
||||||
|
|
||||||
if (!(body->flags & TPE_BODY_FLAG_NO_BSPHERE))
|
if (!(body->flags & TPE_BODY_FLAG_NO_BSPHERE))
|
||||||
{
|
{
|
||||||
TPE_bodyGetFastBSphere(body,&c,&d);
|
TPE_bodyGetFastBSphere(body,&c,&d);
|
||||||
|
@ -1938,6 +1942,9 @@ uint8_t TPE_bodyEnvironmentResolveCollision(TPE_Body *body,
|
||||||
{
|
{
|
||||||
collision = 1;
|
collision = 1;
|
||||||
|
|
||||||
|
if (r == 2)
|
||||||
|
body->flags |= TPE_BODY_FLAG_UNRESOLVED;
|
||||||
|
|
||||||
if (body->flags & TPE_BODY_FLAG_NONROTATING)
|
if (body->flags & TPE_BODY_FLAG_NONROTATING)
|
||||||
_TPE_bodyNonrotatingJointCollided(body,i,previousPos,r == 1);
|
_TPE_bodyNonrotatingJointCollided(body,i,previousPos,r == 1);
|
||||||
}
|
}
|
||||||
|
@ -2079,7 +2086,7 @@ void _TPE_drawDebugPixel(
|
||||||
|
|
||||||
void TPE_worldDebugDraw(TPE_World *world, TPE_DebugDrawFunction drawFunc,
|
void TPE_worldDebugDraw(TPE_World *world, TPE_DebugDrawFunction drawFunc,
|
||||||
TPE_Vec3 camPos, TPE_Vec3 camRot, TPE_Vec3 camView, uint16_t envGridRes,
|
TPE_Vec3 camPos, TPE_Vec3 camRot, TPE_Vec3 camView, uint16_t envGridRes,
|
||||||
TPE_Unit envGridSize)
|
TPE_Unit envGridSize, TPE_Unit offset)
|
||||||
{
|
{
|
||||||
#define Z_LIMIT 250
|
#define Z_LIMIT 250
|
||||||
if (world->environmentFunction != 0)
|
if (world->environmentFunction != 0)
|
||||||
|
@ -2092,6 +2099,8 @@ void TPE_worldDebugDraw(TPE_World *world, TPE_DebugDrawFunction drawFunc,
|
||||||
|
|
||||||
TPE_Vec3 center;
|
TPE_Vec3 center;
|
||||||
|
|
||||||
|
offset %= envGridSize;
|
||||||
|
|
||||||
if (envGridRes != 0)
|
if (envGridRes != 0)
|
||||||
{
|
{
|
||||||
center = TPE_vec3(0,TPE_sin(camRot.x),TPE_cos(camRot.x));
|
center = TPE_vec3(0,TPE_sin(camRot.x),TPE_cos(camRot.x));
|
||||||
|
@ -2101,9 +2110,9 @@ void TPE_worldDebugDraw(TPE_World *world, TPE_DebugDrawFunction drawFunc,
|
||||||
center = TPE_vec3Times(center,gridHalfSize);
|
center = TPE_vec3Times(center,gridHalfSize);
|
||||||
center = TPE_vec3Plus(camPos,center);
|
center = TPE_vec3Plus(camPos,center);
|
||||||
|
|
||||||
center.x = (center.x / envGridSize) * envGridSize;
|
center.x = (center.x / envGridSize) * envGridSize + offset;
|
||||||
center.y = (center.y / envGridSize) * envGridSize;
|
center.y = (center.y / envGridSize) * envGridSize + offset;
|
||||||
center.z = (center.z / envGridSize) * envGridSize;
|
center.z = (center.z / envGridSize) * envGridSize + offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
testPoint.y = center.y - gridHalfSize;
|
testPoint.y = center.y - gridHalfSize;
|
||||||
|
|
Loading…
Reference in a new issue