Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
246 changes: 194 additions & 52 deletions src/gl/gl_renderer.c

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/gl_legacy/gl_legacy_renderer.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,8 @@ static void glEndView(MAYBE_UNUSED Renderer* renderer) {
}

// camera_apply: swap the active world->clip projection on the current target without touching its viewport.
static void glApplyProjection(Renderer* renderer, const Matrix4f* worldToClip) {
Matrix4f projection = *worldToClip;
static void glApplyProjection(Renderer* renderer, MAYBE_UNUSED const Matrix4f* ViewMatrix, MAYBE_UNUSED const Matrix4f* ProjectionMatrix) {
Matrix4f projection = *ProjectionMatrix; //fix it later
Matrix4f_flipClipY(&projection);
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(projection.m);
Expand Down
81 changes: 81 additions & 0 deletions src/matrix_math.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,87 @@ static inline Matrix4f* Matrix4f_multiply(Matrix4f* dest, const Matrix4f* a, con
return dest;
}

static inline Matrix4f* Matrix4f_LookAt(Matrix4f* dest, float x_from, float y_from, float z_from, float x_to, float y_to, float z_to, float x_up, float y_up, float z_up) {

double xFrom = x_from;
double yFrom = y_from;
double zFrom = z_from;

double xTo = x_to;
double yTo = y_to;
double zTo = z_to;

double xUp = x_up;
double yUp = y_up;
double zUp = z_up;
double magUp = sqrt(xUp * xUp + yUp * yUp + zUp * zUp);
xUp /= magUp;
yUp /= magUp;
zUp /= magUp;

double xLook = xTo - xFrom;
double yLook = yTo - yFrom;
double zLook = zTo - zFrom;
double magLook = sqrt(xLook * xLook + yLook * yLook + zLook * zLook);
xLook /= magLook;
yLook /= magLook;
zLook /= magLook;

// normalised cross product between Up and Look
double xRight = yUp * zLook - zUp * yLook;
double yRight = zUp * xLook - xUp * zLook;
double zRight = xUp * yLook - yUp * xLook;
double magRight = sqrt(xRight * xRight + yRight * yRight + zRight * zRight);
xRight /= magRight;
yRight /= magRight;
zRight /= magRight;

// normalised cross product between Look and Right
xUp = yLook * zRight - zLook * yRight;
yUp = zLook * xRight - xLook * zRight;
zUp = xLook * yRight - yLook * xRight;
magUp = sqrt(xUp * xUp + yUp * yUp + zUp * zUp);
xUp /= magUp;
yUp /= magUp;
zUp /= magUp;

double x, y, z;
x = xFrom * xRight + yFrom * yRight + zFrom * zRight;
y = xFrom * xUp + yFrom * yUp + zFrom * zUp;
z = xFrom * xLook + yFrom * yLook + zFrom * zLook;

dest->m[Matrix_getIndex(0, 0)] = xRight;
dest->m[Matrix_getIndex(1, 0)] = xUp;
dest->m[Matrix_getIndex(2, 0)] = xLook;

dest->m[Matrix_getIndex(0, 1)] = yRight;
dest->m[Matrix_getIndex(1, 1)] = yUp;
dest->m[Matrix_getIndex(2, 1)] = yLook;

dest->m[Matrix_getIndex(0, 2)] = zRight;
dest->m[Matrix_getIndex(1, 2)] = zUp;
dest->m[Matrix_getIndex(2, 2)] = zLook;

dest->m[Matrix_getIndex(0, 3)] = -x;
dest->m[Matrix_getIndex(1, 3)] = -y;
dest->m[Matrix_getIndex(2, 3)] = -z;

return dest;
}

static inline Matrix4f* Matrix4f_Orthographic(Matrix4f* dest, float width, float height, float zfar, float znear) {

memset(dest->m, 0, sizeof(dest->m));
dest->m[Matrix_getIndex(0,0)] = 2.0f / width;
dest->m[Matrix_getIndex(1,1)] = 2.0f / height;
dest->m[Matrix_getIndex(2,2)] = 1.0f / (zfar - znear);
dest->m[Matrix_getIndex(3,3)] = 1.0f;

dest->m[Matrix_getIndex(2,3)] = znear / (znear - zfar);

return dest;
}

// ===[ Orthographic Projection ]===

// Post-multiply orthographic projection onto dest: dest = dest * ortho(l, r, b, t, n, f)
Expand Down
3 changes: 2 additions & 1 deletion src/ps2/gs_renderer.c
Original file line number Diff line number Diff line change
Expand Up @@ -1157,8 +1157,9 @@ static void gsEndView(MAYBE_UNUSED Renderer* renderer) {
// No-op
}

static void gsApplyProjection(MAYBE_UNUSED Renderer* renderer, MAYBE_UNUSED const Matrix4f* worldToClip) {
static void gsApplyProjection(MAYBE_UNUSED Renderer* renderer, MAYBE_UNUSED const Matrix4f* ViewMatrix, MAYBE_UNUSED const Matrix4f* ProjectionMatrix) {
// No-op
//Um but I do feel like the PS2 should be capable of this though?
}

static void gsSetGuiProjection(Renderer* renderer, int32_t guiW, int32_t guiH, MAYBE_UNUSED int32_t portW, MAYBE_UNUSED int32_t portH, MAYBE_UNUSED bool renderingToUserSurface) {
Expand Down
9 changes: 7 additions & 2 deletions src/renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
#define MAX_VS_LIGHTS 8

#define MAX_TEXTURE_STAGES 8
//these 2 IDs are just IDs I simply made up, replace them with proper ones eventually oki?
#define GUI_CAMERA 4096
#define SURFACE_CAMERA 8192

// Sentinel returned by ensureApplicationSurface on platforms that don't back the application_surface with a real entry in the renderer's surface table.
//
Expand Down Expand Up @@ -72,7 +75,7 @@ typedef struct {
void (*endFrameEnd)(Renderer* renderer);
void (*beginView)(Renderer* renderer, int32_t viewX, int32_t viewY, int32_t viewW, int32_t viewH, int32_t portX, int32_t portY, int32_t portW, int32_t portH, float viewAngle);
void (*endView)(Renderer* renderer);
void (*applyProjection)(Renderer* renderer, const Matrix4f* worldToClip);
void (*applyProjection)(Renderer* renderer, const Matrix4f* ViewMatrix,const Matrix4f* ProjectionMatrix);
// GUI pass: coordinates are (0,0)..(guiW,guiH) mapped to the current view's port rect. Called after endView.
// targetSurfaceId is the surface the pass renders into, or RENDER_TARGET_HOST_FRAMEBUFFER.
void (*beginGUI)(Renderer* renderer, int32_t guiW, int32_t guiH, int32_t portX, int32_t portY, int32_t portW, int32_t portH, int32_t targetSurfaceId);
Expand Down Expand Up @@ -149,6 +152,7 @@ typedef struct {
void (*textureSetStage)(Renderer* renderer, int32_t slot, uint32_t texID);
bool (*shaderIsCompiled)(Renderer* renderer, int32_t shader);
bool (*shadersSupported)(void);
void (*setMatrix)(Renderer* renderer, int32_t MatrixType, Matrix4f Matrix);
} RendererVtable;

// ===[ Renderer Base Struct ]===
Expand All @@ -163,14 +167,15 @@ struct Renderer {
int32_t drawValign; // 0=top, 1=middle, 2=bottom
int32_t circlePrecision; // segments used by draw_circle/draw_ellipse, clamped to [4, 64] and rounded down to multiple of 4. Default 24.
//It's The Simplest Way I Found To Restore Previous Thingies For Rendering SORRY
Matrix4f previousViewMatrix;
Matrix4f previousViewMatrix; //when you go fix the Legacy OpenGL renderer, please remove this, as we don't need this anymore I hope
int32_t CPortX;
int32_t CPortY;
int32_t CPortW;
int32_t CPortH;
Runner* runner;
Matrix4f gmlMatrices[MATRICES_MAX];
int32_t currentShader;
int32_t CameraCurrent;
};

// ===[ Shared Helpers (platform-agnostic) ]===
Expand Down
79 changes: 76 additions & 3 deletions src/runner.c
Original file line number Diff line number Diff line change
Expand Up @@ -1137,11 +1137,16 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh
if (runner->drawBackgroundColor)
renderer->vtable->clearScreen(renderer, runner->currentRoom->backgroundColor, 1.0f);

Matrix4f proj;
Matrix4f_viewProjection(&proj, (float) camera->viewX, (float) camera->viewY, (float) camera->viewWidth, (float) camera->viewHeight, camera->viewAngle);
renderer->vtable->applyProjection(renderer, &proj);
Matrix4f ViewMatrix = camera->ViewMatrix;
Matrix4f ProjectionMatrix = camera->ProjectionMatrix;
runner->renderer->vtable->applyProjection(runner->renderer, &ViewMatrix, &ProjectionMatrix);


runner->viewCurrent = (int32_t) vi;
runner->renderer->CameraCurrent = runner->views[runner->viewCurrent].cameraId;
runner->renderer->vtable->applyProjection(runner->renderer, &ViewMatrix, &ProjectionMatrix);


Runner_draw(runner);

renderer->vtable->flush(renderer);
Expand All @@ -1162,6 +1167,7 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh
float viewAngle = camera->viewAngle;

runner->viewCurrent = (int32_t) vi;
runner->renderer->CameraCurrent = runner->views[runner->viewCurrent].cameraId;
renderer->vtable->beginView(renderer, viewX, viewY, viewW, viewH, portX, portY, portW, portH, viewAngle);

Runner_draw(runner);
Expand All @@ -1175,13 +1181,37 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh
}

if (!anyViewRendered) {
runner->viewCurrent = 0;
GMLCamera* camera = Runner_getCameraForView(runner, (int32_t) runner->viewCurrent);
runner->renderer->CameraCurrent = runner->views[runner->viewCurrent].cameraId;
// See GameMaker-HTML5's "DrawViews", in specific the !m_enableviews path
// When views aren't used, the room width/height is used
int32_t viewX, viewY, viewW, viewH;
expandViewAxis(0, (int32_t) runner->currentRoom->width, gameW, widescreenBaseW, &viewX, &viewW);
expandViewAxis(0, (int32_t) runner->currentRoom->height, gameH, widescreenBaseH, &viewY, &viewH);
applyFreeCamera(runner, &viewX, &viewY, &viewW, &viewH);
//whenever somebody feels like it, do make that free cam thingy work with this
//make default projection
Matrix4f ProjectionMatrix;
Matrix4f_Orthographic(&ProjectionMatrix, (float) runner->currentRoom->width, -((float) runner->currentRoom->height), 32000.0, 0.0);

Matrix4f ViewMatrix;
float x = (float) runner->currentRoom->width * 0.5f;
float y = (float) runner->currentRoom->height * 0.5f;
Matrix4f_identity(&ViewMatrix);
Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0);
if (camera != nullptr) {
camera->viewX = 0;
camera->viewY = 0;
camera->viewWidth = runner->currentRoom->width;
camera->viewHeight = runner->currentRoom->height;
camera->viewAngle = 0.0;
camera->ViewMatrix = ViewMatrix;
camera->ProjectionMatrix = ProjectionMatrix;
}

renderer->vtable->beginView(renderer, viewX, viewY, viewW, viewH, 0, 0, gameW, gameH, 0);

Runner_draw(runner);

if (debugShowCollisionMasks) DebugOverlay_drawCollisionMasks(runner);
Expand All @@ -1192,6 +1222,7 @@ void Runner_drawViews(Runner* runner, int32_t gameW, int32_t gameH, bool debugSh

// Reset view_current to 0 so non-Draw events (Step, Alarm, Create) see view_current = 0
runner->viewCurrent = 0;
runner->renderer->CameraCurrent = runner->views[runner->viewCurrent].cameraId;
}

// ===[ Instance Creation Helper ]===
Expand Down Expand Up @@ -1293,6 +1324,8 @@ GMLCamera* Runner_getCameraById(Runner* runner, int32_t id) {
if (0 > id) return nullptr;
else if (MAX_DEFAULT_ROOM_CAMERAS > id) camera = &runner->defaultCameras[id];
else if (MAX_CAMERAS > id) camera = &runner->userCameras[id - MAX_DEFAULT_ROOM_CAMERAS];
else if (id == SURFACE_CAMERA) camera = &runner->surfaceCamera;
else if (id == GUI_CAMERA) camera = &runner->guiCamera;
else return nullptr;
if (!camera->allocated) return nullptr;
return camera;
Expand All @@ -1316,6 +1349,23 @@ static void initDefaultCameraFromRoomView(GMLCamera* camera, RoomView* roomView)
camera->speedY = roomView->speedY;
camera->objectId = roomView->objectId;
camera->viewAngle = 0;
//make default projection
Matrix4f ProjectionMatrix;
Matrix4f_Orthographic(&ProjectionMatrix, (float) camera->viewWidth, -((float) camera->viewHeight), 32000.0, 0.0);

Matrix4f ViewMatrix;
float x = camera->viewX + camera->viewWidth * 0.5f;
float y = camera->viewY + camera->viewHeight * 0.5f;
Matrix4f_identity(&ViewMatrix);
Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0);
Matrix4f_translate(&ViewMatrix, x, y, 0.0f);
Matrix4f_rotateZ(&ViewMatrix, -camera->viewAngle * (float) M_PI / 180.0f);
Matrix4f_translate(&ViewMatrix, -x, -y, 0.0f);



camera->ProjectionMatrix = ProjectionMatrix;
camera->ViewMatrix = ViewMatrix;
}

// Copies the viewport (port) properties and enabled flag from parsed room data.
Expand Down Expand Up @@ -2289,6 +2339,28 @@ void Runner_destroyInstance(MAYBE_UNUSED Runner* runner, Instance* inst, bool ru
#endif
}

void UpdateCameraViewSimple(GMLCamera* camera) {

float x = camera->viewX + camera->viewWidth/2;
float y = camera->viewY + camera->viewHeight/2;
Matrix4f ViewMatrix;
Matrix4f_identity(&ViewMatrix);
Matrix4f_LookAt(&ViewMatrix, x, y, -16000.0, x, y, 16000.0, 0.0, 1.0, 0.0);
Matrix4f_translate(&ViewMatrix, x, y, 0.0f);
Matrix4f_rotateZ(&ViewMatrix, -camera->viewAngle * (float) M_PI / 180.0f);
Matrix4f_translate(&ViewMatrix, -x, -y, 0.0f);

Matrix4f ProjectionMatrix;
Matrix4f_Orthographic(&ProjectionMatrix, (float) camera->viewWidth, -((float) camera->viewHeight), 32000.0, 0.0);


camera->ViewMatrix = ViewMatrix;
camera->ProjectionMatrix = ProjectionMatrix;

}



RuntimeLayer* Runner_findRuntimeLayerByName(Runner* runner, char* name) {
size_t count = arrlenu(runner->runtimeLayers);
repeat(count, i) {
Expand Down Expand Up @@ -3200,6 +3272,7 @@ static void updateViews(Runner* runner) {
int32_t iy = (int32_t) GMLReal_floor(target->y);
camera->viewX = followAxis(camera->viewX, camera->viewWidth, ix, camera->borderX, camera->speedX, (int32_t) room->width);
camera->viewY = followAxis(camera->viewY, camera->viewHeight, iy, camera->borderY, camera->speedY, (int32_t) room->height);
UpdateCameraViewSimple(camera);
}
}
}
Expand Down
15 changes: 10 additions & 5 deletions src/runner.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,8 @@ typedef struct {

typedef struct {
bool allocated; // slot in use (default cameras: set when the room enables the view; user cameras: camera_create/destroy)
int32_t viewX;
int32_t viewY;
float viewX;
float viewY;
int32_t viewWidth;
int32_t viewHeight;
uint32_t borderX;
Expand All @@ -155,9 +155,8 @@ typedef struct {
int32_t speedY;
int32_t objectId; // follow target (object index), -1 = none
float viewAngle;
// Center derived from camera_set_view_mat; kept so set_view_mat / set_proj_mat (which arrive in either order) can both recompute the top-left viewX/viewY once the size from the proj matrix is known.
int32_t viewMatCenterX;
int32_t viewMatCenterY;
Matrix4f ViewMatrix;
Matrix4f ProjectionMatrix;
} GMLCamera;

typedef struct {
Expand Down Expand Up @@ -473,6 +472,8 @@ struct Runner {
RuntimeView views[MAX_VIEWS];
GMLCamera defaultCameras[MAX_DEFAULT_ROOM_CAMERAS];
GMLCamera userCameras[MAX_USER_CAMERAS];
GMLCamera surfaceCamera;
GMLCamera guiCamera;
RunnerGamepadState* gamepads;
RuntimeBackground backgrounds[8];
uint32_t backgroundColor; // runtime-mutable (BGR format)
Expand Down Expand Up @@ -672,6 +673,10 @@ void Runner_removeInstanceFromObjectLists(Runner* runner, Instance* inst);
// Reset every per-object list to length 0 without releasing the backing arrays.
void Runner_clearAllObjectLists(Runner* runner);

// Update the Camera with simple things!
void UpdateCameraViewSimple(GMLCamera* camera);


// Push a snapshot of instancesByObject[targetObjIndex] onto runner->instanceSnapshots. Returns the base offset where this snapshot begins.
// The length is arrlen(runner->instanceSnapshots) - base.
// Invalid indices or empty buckets push zero entries (base == current arena length).
Expand Down
Loading
Loading