new starfield (not working for now)

This commit is contained in:
Sonic Dreamcaster 2024-10-15 13:30:42 -03:00
parent da211828e2
commit b925cabee9
3 changed files with 282 additions and 56 deletions

View File

@ -100,11 +100,46 @@ f32 sGroundPositions360z[4] = {
-6000.0f,
};
// Declare global variables for screen dimensions
float gCurrentScreenWidth = 320.0f * 3; // Default width
float gCurrentScreenHeight = 240.0f * 3; // Default height
// Custom floating-point modulo function (replaces fmodf)
float FloatMod(float a, float b) {
float result = a - ((int) (a / b)) * b;
if (result < 0.0f) {
result += b;
}
return result;
}
// Define a single 1x1 star as two triangles
static Vtx starVerts[4] = {
// Format: VTX(x, y, z, s, t, r, g, b, a)
VTX(0, 0, 0, 0, 0, 255, 255, 255, 255), // Bottom-left
VTX(0, 1, 0, 0, 0, 255, 255, 255, 255), // Top-left
VTX(1, 0, 0, 0, 0, 255, 255, 255, 255), // Bottom-right
VTX(1, 1, 0, 0, 0, 255, 255, 255, 255), // Top-right
};
// Display list to render the two triangles forming the star quad
static Gfx starDL[] = {
gsSPVertex(starVerts, ARRAY_COUNT(starVerts), 0),
gsSP2Triangles(0, 1, 2, 0, 1, 2, 3, 0),
gsSPEndDisplayList(),
};
// Display list to render the two triangles forming the partial star quad
static Gfx starDLPartial[] = {
gsSPVertex(starVerts, ARRAY_COUNT(starVerts), 0),
gsSP2Triangles(0, 1, 2, 0, 1, 2, 3, 0),
gsSPEndDisplayList(),
};
// @port: Starfield drawn with triangles, re-engineered by @Tharo & @TheBoy181
void Background_DrawStarfield(void) {
f32 by;
f32 bx;
s16 vy;
s16 vx;
s32 i;
s32 starCount;
f32 zCos;
@ -114,24 +149,52 @@ void Background_DrawStarfield(void) {
f32* xStar;
f32* yStar;
u32* color;
float currentScreenWidth;
float currentScreenHeight;
float starfieldWidth;
float starfieldHeight;
float vx;
float vy;
const float STAR_MARGIN = 10.0f; // Margin to hide seam stars
// Set projection to orthographic before drawing stars
Lib_InitOrtho(&gMasterDisp);
// Setup render state for stars
static Gfx starSetupDL[] = {
gsSPTexture(0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF), // Disable texturing
gsSPClearGeometryMode(G_ZBUFFER | G_SHADE | G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR | G_CULL_BACK |
G_SHADING_SMOOTH),
gsDPPipeSync(),
gsDPSetCombineMode(G_CC_PRIMITIVE, G_CC_PRIMITIVE), // Use primitive color
gsDPSetOtherMode(G_AD_NOTPATTERN | G_CD_MAGICSQ | G_CK_NONE | G_TC_FILT | G_TF_BILERP | G_TT_NONE | G_TL_TILE |
G_TD_CLAMP | G_TP_PERSP | G_CYC_1CYCLE | G_PM_NPRIMITIVE,
G_AC_NONE | G_ZS_PIXEL | G_RM_OPA_SURF | G_RM_OPA_SURF2),
gsSPEndDisplayList(),
};
gSPDisplayList(gMasterDisp++, starSetupDL);
// Get current screen dimensions
currentScreenWidth = gCurrentScreenWidth;
currentScreenHeight = gCurrentScreenHeight;
starfieldWidth = 1.0f * currentScreenWidth;
starfieldHeight = 1.0f * currentScreenHeight;
gDPPipeSync(gMasterDisp++);
gDPSetCycleType(gMasterDisp++, G_CYC_FILL);
gDPSetCombineMode(gMasterDisp++, G_CC_SHADE, G_CC_SHADE);
gDPSetRenderMode(gMasterDisp++, G_RM_OPA_SURF, G_RM_OPA_SURF2);
starCount = gStarCount;
if (starCount != 0) {
if (gStarfieldX >= 1.5f * SCREEN_WIDTH) {
gStarfieldX -= 1.5f * SCREEN_WIDTH;
// Wrapping logic for starfield positions
if (gStarfieldX >= starfieldWidth) {
gStarfieldX -= starfieldWidth;
}
if (gStarfieldY >= 1.5f * SCREEN_HEIGHT) {
gStarfieldY -= 1.5f * SCREEN_HEIGHT;
if (gStarfieldY >= starfieldHeight) {
gStarfieldY -= starfieldHeight;
}
if (gStarfieldX < 0.0f) {
gStarfieldX += 1.5f * SCREEN_WIDTH;
gStarfieldX += starfieldWidth;
}
if (gStarfieldY < 0.0f) {
gStarfieldY += 1.5f * SCREEN_HEIGHT;
gStarfieldY += starfieldHeight;
}
xField = gStarfieldX;
yField = gStarfieldY;
@ -143,35 +206,86 @@ void Background_DrawStarfield(void) {
if (gGameState != GSTATE_PLAY) {
starCount = 1000;
}
starCount = starCount * 3; // Adjust multiplier as needed
zCos = __cosf(gStarfieldRoll);
zSin = __sinf(gStarfieldRoll);
for (i = 0; i < starCount; i++, yStar++, xStar++, color++) {
// Adjust star positions with field offsets
bx = *xStar + xField;
by = *yStar + yField;
if (bx >= 1.25f * SCREEN_WIDTH) {
bx -= 1.5f * SCREEN_WIDTH;
}
bx -= SCREEN_WIDTH / 2.0f;
if (by >= 1.25f * SCREEN_HEIGHT) {
by -= 1.5f * SCREEN_HEIGHT;
// Wrapping logic for individual stars along X-axis
if (bx >= starfieldWidth) {
bx -= starfieldWidth;
}
if (bx < 0.0f) {
bx += starfieldWidth;
}
by -= SCREEN_HEIGHT / 2.0f;
vx = (zCos * bx) + (zSin * by) + SCREEN_WIDTH / 2.0f;
vy = (-zSin * bx) + (zCos * by) + SCREEN_HEIGHT / 2.0f;
if ((vx >= 0) && (vx < SCREEN_WIDTH) && (vy > 0) && (vy < SCREEN_HEIGHT)) {
gDPPipeSync(gMasterDisp++);
gDPSetFillColor(gMasterDisp++, *color);
gDPFillRectangle(gMasterDisp++, vx, vy, vx, vy);
// Wrapping logic for individual stars along Y-axis
if (by >= starfieldHeight) {
by -= starfieldHeight;
}
if (by < 0.0f) {
by += starfieldHeight;
}
// Center the positions
bx -= starfieldWidth / 2.0f;
by -= starfieldHeight / 2.0f;
// Apply rotation
vx = (zCos * bx) + (zSin * by) + currentScreenWidth / 2.0f;
vy = (-zSin * bx) + (zCos * by) + currentScreenHeight / 2.0f;
// Check if the star is within the visible screen area with margin
if ((vx >= STAR_MARGIN) && (vx < currentScreenWidth - STAR_MARGIN) && (vy >= STAR_MARGIN) &&
(vy < currentScreenHeight - STAR_MARGIN)) {
// @recomp Tag the transform.
// gEXMatrixGroupDecomposed(gMasterDisp++, TAG_STARFIELD + i, G_EX_PUSH, G_MTX_MODELVIEW,
// G_EX_COMPONENT_AUTO, G_EX_COMPONENT_AUTO, G_EX_COMPONENT_AUTO,
// G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP,
// G_EX_COMPONENT_INTERPOLATE, G_EX_ORDER_AUTO, G_EX_EDIT_ALLOW);
// Translate to (vx, vy) in ortho coordinates
Matrix_Push(&gGfxMatrix);
Matrix_Translate(gGfxMatrix, vx - (currentScreenWidth / 2.0f), -(vy - (currentScreenHeight / 2.0f)),
0.0f, MTXF_NEW);
Matrix_SetGfxMtx(&gMasterDisp);
Matrix_Pop(&gGfxMatrix);
// Convert color from fill color (assuming RGB5A1) to RGBA8
u8 r = ((*color >> 11) & 0x1F);
r = (r << 3) | (r >> 2); // Convert 5-bit to 8-bit
u8 g = ((*color >> 6) & 0x1F);
g = (g << 3) | (g >> 2); // Convert 5-bit to 8-bit
u8 b = ((*color >> 1) & 0x1F);
b = (b << 3) | (b >> 2); // Convert 5-bit to 8-bit
u8 a = 255; // Fully opaque
gDPSetPrimColor(gMasterDisp++, 0, 0, r, g, b, a);
// Draw the star using the predefined display list
gSPDisplayList(gMasterDisp++, starDL);
// Pop the transform id
// gEXPopMatrixGroup(gMasterDisp++, G_MTX_MODELVIEW);
}
}
}
// Restore original perspective after drawing stars
Lib_InitPerspective(&gMasterDisp);
// Finalize rendering state
gDPPipeSync(gMasterDisp++);
gDPSetColorDither(gMasterDisp++, G_CD_MAGICSQ);
}
void Background_DrawPartialStarfield(s32 yMin, s32 yMax) {
void Background_DrawPartialStarfield(s32 yMin, s32 yMax) { // Stars that are in the Epilogue
f32 by;
f32 bx;
s16 vy;
@ -185,22 +299,30 @@ void Background_DrawPartialStarfield(s32 yMin, s32 yMax) {
f32* sp60;
f32* sp5C;
u32* sp58;
// Get current screen dimensions
float currentScreenWidth = gCurrentScreenWidth;
float currentScreenHeight = gCurrentScreenHeight;
float starfieldWidth = 1.0f * currentScreenWidth;
float starfieldHeight = 1.0f * currentScreenHeight;
// Graphics pipeline setup
gDPPipeSync(gMasterDisp++);
gDPSetCycleType(gMasterDisp++, G_CYC_FILL);
gDPSetCombineMode(gMasterDisp++, G_CC_SHADE, G_CC_SHADE);
gDPSetRenderMode(gMasterDisp++, G_RM_OPA_SURF, G_RM_OPA_SURF2);
if (gStarfieldX >= 1.5f * SCREEN_WIDTH) {
gStarfieldX -= 1.5f * SCREEN_WIDTH;
if (gStarfieldX >= 1.5f * currentScreenWidth) {
gStarfieldX -= 1.5f * currentScreenWidth;
}
if (gStarfieldY >= 1.5f * SCREEN_HEIGHT) {
gStarfieldY -= 1.5f * SCREEN_HEIGHT;
if (gStarfieldY >= 1.5f * currentScreenHeight) {
gStarfieldY -= 1.5f * currentScreenHeight;
}
if (gStarfieldX < 0.0f) {
gStarfieldX += 1.5f * SCREEN_WIDTH;
gStarfieldX += 1.5f * currentScreenWidth;
}
if (gStarfieldY < 0.0f) {
gStarfieldY += 1.5f * SCREEN_HEIGHT;
gStarfieldY += 1.5f * currentScreenHeight;
}
spf68 = gStarfieldX;
@ -216,21 +338,50 @@ void Background_DrawPartialStarfield(s32 yMin, s32 yMax) {
for (i = 0; i < var_s2; i++, sp5C++, sp60++, sp58++) {
bx = *sp60 + spf68;
by = *sp5C + spf64;
if (bx >= SCREEN_WIDTH * 1.25f) {
bx -= 1.5f * SCREEN_WIDTH;
if (bx >= starfieldWidth * 1.25f) {
bx -= 1.5f * starfieldWidth;
}
bx -= SCREEN_WIDTH / 2.0f;
if (by >= SCREEN_HEIGHT * 1.25f) {
by -= 1.5f * SCREEN_HEIGHT;
bx -= starfieldWidth / 2.0f;
if (by >= starfieldHeight * 1.25f) {
by -= 1.5f * starfieldHeight;
}
by -= SCREEN_HEIGHT / 2.0f;
by -= starfieldHeight / 2.0f;
vx = (cos * bx) + (sin * by) + SCREEN_WIDTH / 2.0f;
vy = (-sin * bx) + (cos * by) + SCREEN_HEIGHT / 2.0f;
if ((vx >= 0) && (vx < SCREEN_WIDTH) && (yMin < vy) && (vy < yMax)) {
gDPPipeSync(gMasterDisp++);
gDPSetFillColor(gMasterDisp++, *sp58);
gDPFillRectangle(gMasterDisp++, vx, vy, vx, vy);
// Apply rotation
vx = (cos * bx) + (sin * by) + currentScreenWidth / 2.0f;
vy = (-sin * bx) + (cos * by) + currentScreenHeight / 2.0f;
// Check if the star is within the visible screen area
if ((vx >= 0) && (vx < currentScreenWidth) && (yMin < vy) && (vy < yMax)) {
// Tag the transform. Assuming TAG_STARFIELD is a defined base tag value
// @recomp Tag the transform.
// gEXMatrixGroupDecomposed(gMasterDisp++, TAG_STARFIELD + i, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_COMPONENT_AUTO,
// G_EX_COMPONENT_AUTO, G_EX_COMPONENT_AUTO, G_EX_COMPONENT_INTERPOLATE,
// G_EX_COMPONENT_INTERPOLATE, G_EX_COMPONENT_SKIP, G_EX_COMPONENT_INTERPOLATE,
// G_EX_ORDER_AUTO, G_EX_EDIT_ALLOW);
// Translate to (vx, vy) in ortho coordinates
Matrix_Push(&gGfxMatrix);
Matrix_Translate(gGfxMatrix, vx - (currentScreenWidth / 2.0f), -(vy - (currentScreenHeight / 2.0f)), 0.0f,
MTXF_NEW);
Matrix_SetGfxMtx(&gMasterDisp);
Matrix_Pop(&gGfxMatrix);
// Convert color from fill color (assuming RGB5A1) to RGBA8
u8 r = ((*sp58 >> 11) & 0x1F);
r = (r << 3) | (r >> 2); // Convert 5-bit to 8-bit
u8 g = ((*sp58 >> 6) & 0x1F);
g = (g << 3) | (g >> 2); // Convert 5-bit to 8-bit
u8 b = ((*sp58 >> 1) & 0x1F);
b = (b << 3) | (b >> 2); // Convert 5-bit to 8-bit
u8 a = 255; // Fully opaque
gDPSetPrimColor(gMasterDisp++, 0, 0, r, g, b, a);
// Draw the star using the predefined display list
gSPDisplayList(gMasterDisp++, starDLPartial);
// Pop the transform id
// gEXPopMatrixGroup(gMasterDisp++, G_MTX_MODELVIEW);
}
}
gDPPipeSync(gMasterDisp++);

View File

@ -22,6 +22,9 @@
#include "assets/ast_area_6.h"
#include "assets/ast_zoness.h"
extern float gCurrentScreenWidth;
extern float gCurrentScreenHeight;
UNK_TYPE D_800D2F50 = 0; // unused
s32 sOverheadCam = 0;
f32 sOverheadCamDist = 0.0f;
@ -559,7 +562,7 @@ void Play_InitEnvironment(void) {
D_ctx_80178544 = 40;
gFovY = 45.0f;
}
/*
void Play_GenerateStarfield(void) {
u32 i;
@ -574,34 +577,92 @@ void Play_GenerateStarfield(void) {
gStarFillColors[i] = FILL_COLOR(gStarColors[i % ARRAY_COUNT(gStarColors)]);
}
}
*/
void Play_GenerateStarfield(void) {
u32 i;
float currentScreenWidth = gCurrentScreenWidth;
float currentScreenHeight = gCurrentScreenHeight;
float starfieldWidth = 1.0f * currentScreenWidth;
float starfieldHeight = 1.0f * currentScreenHeight;
MEM_ARRAY_ALLOCATE(gStarOffsetsX, 3000);
MEM_ARRAY_ALLOCATE(gStarOffsetsY, 3000);
MEM_ARRAY_ALLOCATE(gStarFillColors, 3000);
Rand_SetSeed(1, 29000, 9876);
for (i = 0; i < 3000; i++) {
gStarOffsetsX[i] = RAND_FLOAT_SEEDED(starfieldWidth);
gStarOffsetsY[i] = RAND_FLOAT_SEEDED(starfieldHeight);
gStarFillColors[i] = FILL_COLOR(gStarColors[i % ARRAY_COUNT(gStarColors)]);
}
}
void Play_SetupStarfield(void) {
// Get current screen dimensions
float currentScreenWidth = gCurrentScreenWidth;
float currentScreenHeight = gCurrentScreenHeight;
float baseAspectRatio = 4.0f / 3.0f; // Original aspect ratio
float baseScreenWidth = gCurrentScreenHeight * baseAspectRatio;
float baseArea = baseScreenWidth * gCurrentScreenHeight;
float currentArea = currentScreenWidth * currentScreenHeight;
float areaRatio = currentArea / baseArea;
Play_GenerateStarfield();
gGroundHeight = -25000.0f;
gStarCount = 600;
// Base star count adjusted for screen area
gStarCount = (s32) (600 * areaRatio);
if (gStarCount > 1000) {
gStarCount = 1000; // Cap the star count to 1000
}
// Adjust star count based on the current level
if (gCurrentLevel == LEVEL_AREA_6) {
gStarCount = 300;
gStarCount = (s32) (300 * areaRatio);
if (gStarCount > 1000) {
gStarCount = 1000;
}
}
if (gCurrentLevel == LEVEL_UNK_15) {
gStarCount = 400;
gStarCount = (s32) (400 * areaRatio);
if (gStarCount > 1000) {
gStarCount = 1000;
}
}
if (gGameState != GSTATE_PLAY) {
gStarCount = 800;
gStarCount = (s32) (800 * areaRatio);
if (gStarCount > 1000) {
gStarCount = 1000;
}
}
if (gCurrentLevel == LEVEL_FORTUNA) {
gStarCount = 500;
gStarCount = (s32) (500 * areaRatio);
if (gStarCount > 1000) {
gStarCount = 1000;
}
}
if (gVersusMode) {
gStarCount = 0;
gStarCount = 0; // No stars in versus mode
}
if (gCurrentLevel == LEVEL_BOLSE) {
gStarCount = 300;
gStarCount = (s32) (300 * areaRatio);
if (gStarCount > 1000) {
gStarCount = 1000;
}
gGroundHeight = -0.0f;
}
if (gCurrentLevel == LEVEL_TRAINING) {
gStarCount = 800;
gStarCount = (s32) (800 * areaRatio);
if (gStarCount > 1000) {
gStarCount = 1000;
}
gGroundHeight = -0.0f;
}
// Initialize starfield position with dynamic screen dimensions
gStarfieldX = currentScreenWidth;
gStarfieldY = currentScreenHeight;
}
void Player_PlaySfx(f32* sfxSrc, u32 sfxId, s32 mode) {
@ -6370,27 +6431,39 @@ void Camera_SetStarfieldPos(f32 xEye, f32 yEye, f32 zEye, f32 xAt, f32 yAt, f32
f32 tempf;
f32 sp20;
// Get current screen dimensions
float currentScreenWidth = gCurrentScreenWidth;
float currentScreenHeight = gCurrentScreenHeight;
float starfieldWidth = 1.0f * currentScreenWidth;
float starfieldHeight = 1.0f * currentScreenHeight;
yaw = -Math_Atan2F(xEye - xAt, zEye - zAt);
tempf = sqrtf(SQ(zEye - zAt) + SQ(xEye - xAt));
pitch = -Math_Atan2F(yEye - yAt, tempf);
// Adjust yaw to stay within the range [-π/2, π/2]
if (yaw >= M_PI / 2) {
yaw -= M_PI;
}
if (yaw <= -M_PI / 2) {
yaw += M_PI;
}
tempf = 0.0f;
if (gCurrentLevel == LEVEL_UNK_15) {
tempf = gPlayer[0].cam.eye.y * 0.03f;
}
// Calculate new starfield positions
sp30 = (-pitch * (-8.0f / 3.0f * M_RTOD) * 2.0f) + 3000.0f + gStarfieldScrollY + tempf;
sp34 = (yaw * (-8.0f / 3.0f * M_RTOD) * 2.0f) + 3000.0f + gStarfieldScrollX;
sp20 = gStarfieldX;
gStarfieldX = Math_ModF(sp34, SCREEN_WIDTH * 1.5f);
gStarfieldY = Math_ModF(sp30, SCREEN_HEIGHT * 1.5f);
// Wrap the starfield positions within the starfield dimensions
gStarfieldX = FloatMod(sp34, starfieldWidth);
gStarfieldY = FloatMod(sp30, starfieldHeight);
// Special case handling for specific game state and level
if ((gGameState == GSTATE_PLAY) && (gPlayer[0].state_1C8 == PLAYERSTATE_1C8_LEVEL_INTRO) &&
(gCurrentLevel == LEVEL_METEO)) {
if (fabsf(gStarfieldX - sp20) < 50.0f) {

View File

@ -1,6 +1,8 @@
#include "sys.h"
s32 sMemoryBuffer[0x8800];
// s32 sMemoryBuffer[0x8800];
// @ port: Increase memory buffer size.
s32 sMemoryBuffer[1000000];
s32* sMemoryPtr;
void Memory_FreeAll(void) {