dsma-library/examples/blend_animations/source/main.c
2024-06-02 13:12:02 +01:00

251 lines
6.8 KiB
C

// SPDX-License-Identifier: CC0-1.0
//
// SPDX-FileContributor: Antonio Niño Díaz, 2022-2024
#include <stdio.h>
#include <nds.h>
#include "dsma/dsma.h"
// Animated models
#include "robot_dsm_bin.h"
// Animations
#include "robot_walk_dsa_bin.h"
#include "robot_wave_dsa_bin.h"
// Textures
#include "texture128_bin.h"
// Static models
#include "ball_bin.h"
void setup_video(void)
{
videoSetMode(MODE_0_3D);
vramSetBankA(VRAM_A_TEXTURE);
consoleDemoInit();
glInit();
glEnable(GL_ANTIALIAS);
glEnable(GL_TEXTURE_2D);
// Setup the rear plane
glClearColor(2, 2, 2, 31); // BG must be opaque for AA to work
glClearPolyID(63); // BG must have a unique polygon ID for AA to work
glClearDepth(0x7FFF);
glViewport(0, 0, 255, 191);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(70, 256.0 / 192.0, 0.1, 40);
glLight(0, RGB15(0, 31, 0), 0, floattov10(0.8), floattov10(-0.2));
glLight(1, RGB15(31, 0, 0), 0, floattov10(-0.8), floattov10(-0.2));
glLight(2, RGB15(31, 31, 0), floattov10(0.7), 0, floattov10(-0.7));
glLight(3, RGB15(0, 0, 31), floattov10(-0.7), 0, floattov10(-0.7));
glMaterialf(GL_AMBIENT, RGB15(0, 0, 0));
glMaterialf(GL_DIFFUSE, RGB15(31, 31, 31));
glMaterialf(GL_SPECULAR, BIT(15) | RGB15(0, 0, 0));
glMaterialf(GL_EMISSION, RGB15(0, 0, 0));
glMaterialShinyness();
glMatrixMode(GL_MODELVIEW);
//glMatrixMode(GL_POSITION); // This rotates lights with the model
}
int main(void)
{
float rotateY = 45.0;
float rotateZ = 0.0;
setup_video();
int textureID;
glGenTextures(1, &textureID);
glBindTexture(0, textureID);
if (glTexImage2D(0, 0, GL_RGBA, 128, 128, 0, TEXGEN_TEXCOORD, texture128_bin) == 0)
{
printf("Failed to load texture");
while (1)
swiWaitForVBlank();
}
const void *dsm_file = robot_dsm_bin;
const void *dsa_file_1 = robot_wave_dsa_bin;
const void *dsa_file_2 = robot_walk_dsa_bin;
int32_t frame_1 = inttof32(8);
int32_t frame_2 = 0;
printf("\x1b[0;0HAnimation 1: X/Y");
printf("\x1b[1;0HAnimation 2: L/R");
printf("\x1b[2;0HBlend factor: A/B");
printf("\x1b[3;0HRotate model: Direction pad");
printf("\x1b[4;0HExit demo: START");
printf("\x1b[7;0HFor example, while holding R to\n"
"make the model walk, hold A or\n"
"B to switch between the two\n"
"animations.");
const uint32_t num_frames_1 = DSMA_GetNumFrames(dsa_file_1);
const uint32_t num_frames_2 = DSMA_GetNumFrames(dsa_file_2);
uint32_t blend = floattof32(0.5);
while(1)
{
printf("\x1b[13;0HCurrent frame 1: %.2f ", f32tofloat(frame_1));
printf("\x1b[14;0HCurrent frame 2: %.2f ", f32tofloat(frame_2));
printf("\x1b[15;0HBlend factor: %.2f ", f32tofloat(blend));
glLoadIdentity();
gluLookAt(8.0, 3.0, 0.0, // camera possition
0.0, 3.0, 0.0, // look at
0.0, 1.0, 0.0); // up
glPushMatrix();
{
glRotateY(rotateY);
glRotateZ(rotateZ);
glBindTexture(0, textureID);
glPolyFmt(POLY_ALPHA(31) | POLY_CULL_BACK | POLY_FORMAT_LIGHT0 |
POLY_FORMAT_LIGHT1 | POLY_FORMAT_LIGHT2 | POLY_FORMAT_LIGHT3);
cpuStartTiming(0);
DSMA_DrawModelBlendAnimation(dsm_file,
dsa_file_1, frame_1,
dsa_file_2, frame_2,
blend);
uint32_t end_time = cpuEndTiming();
const float us_per_frame = 1000000.0 / 60.0;
printf("\x1b[19;0HTime Ticks us CPU%%");
printf("\x1b[20;0HTotal: %6lu %4lu %.3f%% ",
end_time, timerTicks2usec(end_time),
100.0 * timerTicks2usec(end_time) / us_per_frame);
// Wait for geometry engine operations to end
while (GFX_STATUS & BIT(27));
printf("\x1b[23;0HPolys: %4d Vertices: %4d",
GFX_POLYGON_RAM_USAGE, GFX_VERTEX_RAM_USAGE);
// Draw axes of coordinates of the model
glPolyFmt(POLY_ALPHA(31) | POLY_CULL_NONE);
glBindTexture(0, 0);
glColor3f(1, 0, 0);
glVertex3f(0, 0.2, 0);
glVertex3f(0., -0.2, 0);
glVertex3f(5, 0, 0);
glVertex3f(0, 0, 0.2);
glVertex3f(0., 0, -0.2);
glVertex3f(5, 0, 0);
glColor3f(0, 1, 0);
glVertex3f(0, 0, 0.2);
glVertex3f(0, 0, -0.2);
glVertex3f(0, 5, 0);
glVertex3f(0.2, 0, 0);
glVertex3f(-0.2, 0, 0);
glVertex3f(0, 5, 0);
glColor3f(0, 0, 1);
glVertex3f(0.2, 0, 0);
glVertex3f(-0.2, 0, 0);
glVertex3f(0, 0, 5);
glVertex3f(0, 0.2, 0);
glVertex3f(0, -0.2, 0);
glVertex3f(0, 0, 5);
}
glPopMatrix(1);
// Draw a ball to use as reference for the lights
glPushMatrix();
{
glPolyFmt(POLY_ALPHA(31) | POLY_CULL_BACK | POLY_FORMAT_LIGHT0 |
POLY_FORMAT_LIGHT1 | POLY_FORMAT_LIGHT2 | POLY_FORMAT_LIGHT3);
glTranslatef(0, 3, 5);
glCallList(ball_bin);
}
glPopMatrix(1);
scanKeys();
u16 keys_held = keysHeld();
if (keys_held & KEY_UP)
rotateZ += 3;
if (keys_held & KEY_DOWN)
rotateZ -= 3;
if (keys_held & KEY_LEFT)
rotateY -= 3;
if (keys_held & KEY_RIGHT)
rotateY += 3;
if (keys_held & KEY_A)
{
blend += 1 << 7;
if (blend > inttof32(1))
blend = inttof32(1);
}
if (keys_held & KEY_B)
{
if (blend <= 1 << 7)
blend = 0;
else
blend -= 1 << 7;
}
if (keys_held & KEY_X)
{
frame_1 += 1 << 9;
if (frame_1 >= (num_frames_1 << 12))
frame_1 -= num_frames_1 << 12;
}
if (keys_held & KEY_Y)
{
frame_1 -= 1 << 9;
if (frame_1 < 0)
frame_1 += num_frames_1 << 12;
}
if (keys_held & KEY_R)
{
frame_2 += 1 << 9;
if (frame_2 >= (num_frames_2 << 12))
frame_2 -= num_frames_2 << 12;
}
if (keys_held & KEY_L)
{
frame_2 -= 1 << 9;
if (frame_2 < 0)
frame_2 += num_frames_2 << 12;
}
glFlush(0);
swiWaitForVBlank();
if (keys_held & KEY_START)
break;
}
return 0;
}