s
This commit is contained in:
parent
714d9a8187
commit
5a116fa904
25 changed files with 3176 additions and 0 deletions
16
include/c3d/attribs.h
Normal file
16
include/c3d/attribs.h
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
#include "types.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 flags[2];
|
||||
u64 permutation;
|
||||
int attrCount;
|
||||
} C3D_AttrInfo;
|
||||
|
||||
void AttrInfo_Init(C3D_AttrInfo* info);
|
||||
int AttrInfo_AddLoader(C3D_AttrInfo* info, int regId, GPU_FORMATS format, int count);
|
||||
int AttrInfo_AddFixed(C3D_AttrInfo* info, int regId);
|
||||
|
||||
C3D_AttrInfo* C3D_GetAttrInfo(void);
|
||||
void C3D_SetAttrInfo(C3D_AttrInfo* info);
|
||||
46
include/c3d/base.h
Normal file
46
include/c3d/base.h
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
#pragma once
|
||||
#include "buffers.h"
|
||||
#include "maths.h"
|
||||
|
||||
#define C3D_DEFAULT_CMDBUF_SIZE 0x40000
|
||||
|
||||
enum
|
||||
{
|
||||
C3D_UNSIGNED_BYTE = 0,
|
||||
C3D_UNSIGNED_SHORT = 1,
|
||||
};
|
||||
|
||||
bool C3D_Init(size_t cmdBufSize);
|
||||
void C3D_Fini(void);
|
||||
|
||||
float C3D_GetCmdBufUsage(void);
|
||||
|
||||
void C3D_BindProgram(shaderProgram_s* program);
|
||||
|
||||
void C3D_SetViewport(u32 x, u32 y, u32 w, u32 h);
|
||||
void C3D_SetScissor(GPU_SCISSORMODE mode, u32 left, u32 top, u32 right, u32 bottom);
|
||||
|
||||
void C3D_DrawArrays(GPU_Primitive_t primitive, int first, int size);
|
||||
void C3D_DrawElements(GPU_Primitive_t primitive, int count, int type, const void* indices);
|
||||
|
||||
// Immediate-mode vertex submission
|
||||
void C3D_ImmDrawBegin(GPU_Primitive_t primitive);
|
||||
void C3D_ImmSendAttrib(float x, float y, float z, float w);
|
||||
void C3D_ImmDrawEnd(void);
|
||||
|
||||
static inline void C3D_ImmDrawRestartPrim(void)
|
||||
{
|
||||
GPUCMD_AddWrite(GPUREG_RESTART_PRIMITIVE, 1);
|
||||
}
|
||||
|
||||
// Fixed vertex attributes
|
||||
C3D_FVec* C3D_FixedAttribGetWritePtr(int id);
|
||||
|
||||
static inline void C3D_FixedAttribSet(int id, float x, float y, float z, float w)
|
||||
{
|
||||
C3D_FVec* ptr = C3D_FixedAttribGetWritePtr(id);
|
||||
ptr->x = x;
|
||||
ptr->y = y;
|
||||
ptr->z = z;
|
||||
ptr->w = w;
|
||||
}
|
||||
21
include/c3d/buffers.h
Normal file
21
include/c3d/buffers.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
#include "types.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 offset;
|
||||
u32 flags[2];
|
||||
} C3D_BufCfg;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 base_paddr;
|
||||
int bufCount;
|
||||
C3D_BufCfg buffers[12];
|
||||
} C3D_BufInfo;
|
||||
|
||||
void BufInfo_Init(C3D_BufInfo* info);
|
||||
int BufInfo_Add(C3D_BufInfo* info, const void* data, ptrdiff_t stride, int attribCount, u64 permutation);
|
||||
|
||||
C3D_BufInfo* C3D_GetBufInfo(void);
|
||||
void C3D_SetBufInfo(C3D_BufInfo* info);
|
||||
15
include/c3d/effect.h
Normal file
15
include/c3d/effect.h
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
#include "types.h"
|
||||
|
||||
void C3D_DepthMap(bool bIsZBuffer, float zScale, float zOffset);
|
||||
void C3D_CullFace(GPU_CULLMODE mode);
|
||||
void C3D_StencilTest(bool enable, GPU_TESTFUNC function, int ref, int inputMask, int writeMask);
|
||||
void C3D_StencilOp(GPU_STENCILOP sfail, GPU_STENCILOP dfail, GPU_STENCILOP pass);
|
||||
void C3D_BlendingColor(u32 color);
|
||||
void C3D_EarlyDepthTest(bool enable, GPU_EARLYDEPTHFUNC function, u32 ref);
|
||||
void C3D_DepthTest(bool enable, GPU_TESTFUNC function, GPU_WRITEMASK writemask);
|
||||
void C3D_AlphaTest(bool enable, GPU_TESTFUNC function, int ref);
|
||||
void C3D_AlphaBlend(GPU_BLENDEQUATION colorEq, GPU_BLENDEQUATION alphaEq, GPU_BLENDFACTOR srcClr, GPU_BLENDFACTOR dstClr, GPU_BLENDFACTOR srcAlpha, GPU_BLENDFACTOR dstAlpha);
|
||||
void C3D_ColorLogicOp(GPU_LOGICOP op);
|
||||
void C3D_FragOpMode(GPU_FRAGOPMODE mode);
|
||||
void C3D_FragOpShadow(float scale, float bias);
|
||||
39
include/c3d/fog.h
Normal file
39
include/c3d/fog.h
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#pragma once
|
||||
#include "types.h"
|
||||
#include <math.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 data[128];
|
||||
} C3D_FogLut;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 diff[8];
|
||||
u32 color[8];
|
||||
} C3D_GasLut;
|
||||
|
||||
static inline float FogLut_CalcZ(float depth, float near, float far)
|
||||
{
|
||||
return far*near/(depth*(far-near)+near);
|
||||
}
|
||||
|
||||
void FogLut_FromArray(C3D_FogLut* lut, const float data[256]);
|
||||
void FogLut_Exp(C3D_FogLut* lut, float density, float gradient, float near, float far);
|
||||
|
||||
void C3D_FogGasMode(GPU_FOGMODE fogMode, GPU_GASMODE gasMode, bool zFlip);
|
||||
void C3D_FogColor(u32 color);
|
||||
void C3D_FogLutBind(C3D_FogLut* lut);
|
||||
|
||||
void GasLut_FromArray(C3D_GasLut* lut, const u32 data[9]);
|
||||
|
||||
void C3D_GasBeginAcc(void);
|
||||
void C3D_GasDeltaZ(float value);
|
||||
|
||||
void C3D_GasAccMax(float value);
|
||||
void C3D_GasAttn(float value);
|
||||
void C3D_GasLightPlanar(float min, float max, float attn);
|
||||
void C3D_GasLightView(float min, float max, float attn);
|
||||
void C3D_GasLightDirection(float dotp);
|
||||
void C3D_GasLutInput(GPU_GASLUTINPUT input);
|
||||
void C3D_GasLutBind(C3D_GasLut* lut);
|
||||
69
include/c3d/framebuffer.h
Normal file
69
include/c3d/framebuffer.h
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
#pragma once
|
||||
#include "texture.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void* colorBuf;
|
||||
void* depthBuf;
|
||||
u16 width;
|
||||
u16 height;
|
||||
GPU_COLORBUF colorFmt;
|
||||
GPU_DEPTHBUF depthFmt;
|
||||
bool block32;
|
||||
u8 colorMask : 4;
|
||||
u8 depthMask : 4;
|
||||
} C3D_FrameBuf;
|
||||
|
||||
// Flags for C3D_FrameBufClear
|
||||
typedef enum
|
||||
{
|
||||
C3D_CLEAR_COLOR = BIT(0),
|
||||
C3D_CLEAR_DEPTH = BIT(1),
|
||||
C3D_CLEAR_ALL = C3D_CLEAR_COLOR | C3D_CLEAR_DEPTH,
|
||||
} C3D_ClearBits;
|
||||
|
||||
u32 C3D_CalcColorBufSize(u32 width, u32 height, GPU_COLORBUF fmt);
|
||||
u32 C3D_CalcDepthBufSize(u32 width, u32 height, GPU_DEPTHBUF fmt);
|
||||
|
||||
C3D_FrameBuf* C3D_GetFrameBuf(void);
|
||||
void C3D_SetFrameBuf(C3D_FrameBuf* fb);
|
||||
void C3D_FrameBufTex(C3D_FrameBuf* fb, C3D_Tex* tex, GPU_TEXFACE face, int level);
|
||||
void C3D_FrameBufClear(C3D_FrameBuf* fb, C3D_ClearBits clearBits, u32 clearColor, u32 clearDepth);
|
||||
void C3D_FrameBufTransfer(C3D_FrameBuf* fb, gfxScreen_t screen, gfx3dSide_t side, u32 transferFlags);
|
||||
|
||||
static inline void C3D_FrameBufAttrib(C3D_FrameBuf* fb, u16 width, u16 height, bool block32)
|
||||
{
|
||||
fb->width = width;
|
||||
fb->height = height;
|
||||
fb->block32 = block32;
|
||||
}
|
||||
|
||||
static inline void C3D_FrameBufColor(C3D_FrameBuf* fb, void* buf, GPU_COLORBUF fmt)
|
||||
{
|
||||
if (buf)
|
||||
{
|
||||
fb->colorBuf = buf;
|
||||
fb->colorFmt = fmt;
|
||||
fb->colorMask = 0xF;
|
||||
} else
|
||||
{
|
||||
fb->colorBuf = NULL;
|
||||
fb->colorFmt = GPU_RB_RGBA8;
|
||||
fb->colorMask = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void C3D_FrameBufDepth(C3D_FrameBuf* fb, void* buf, GPU_DEPTHBUF fmt)
|
||||
{
|
||||
if (buf)
|
||||
{
|
||||
fb->depthBuf = buf;
|
||||
fb->depthFmt = fmt;
|
||||
fb->depthMask = fmt == GPU_RB_DEPTH24_STENCIL8 ? 0x3 : 0x2;
|
||||
} else
|
||||
{
|
||||
fb->depthBuf = NULL;
|
||||
fb->depthFmt = GPU_RB_DEPTH24;
|
||||
fb->depthMask = 0;
|
||||
}
|
||||
}
|
||||
157
include/c3d/light.h
Normal file
157
include/c3d/light.h
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
#pragma once
|
||||
#include "lightlut.h"
|
||||
#include "maths.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Material
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float ambient[3];
|
||||
float diffuse[3];
|
||||
float specular0[3];
|
||||
float specular1[3];
|
||||
float emission[3];
|
||||
} C3D_Material;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Light environment
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Forward declarations
|
||||
typedef struct C3D_Light_t C3D_Light;
|
||||
typedef struct C3D_LightEnv_t C3D_LightEnv;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 abs, select, scale;
|
||||
} C3D_LightLutInputConf;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 ambient;
|
||||
u32 numLights;
|
||||
u32 config[2];
|
||||
C3D_LightLutInputConf lutInput;
|
||||
u32 permutation;
|
||||
} C3D_LightEnvConf;
|
||||
|
||||
enum
|
||||
{
|
||||
C3DF_LightEnv_Dirty = BIT(0),
|
||||
C3DF_LightEnv_MtlDirty = BIT(1),
|
||||
C3DF_LightEnv_LCDirty = BIT(2),
|
||||
|
||||
#define C3DF_LightEnv_IsCP(n) BIT(18+(n))
|
||||
#define C3DF_LightEnv_IsCP_Any (0xFF<<18)
|
||||
#define C3DF_LightEnv_LutDirty(n) BIT(26+(n))
|
||||
#define C3DF_LightEnv_LutDirtyAll (0x3F<<26)
|
||||
};
|
||||
|
||||
struct C3D_LightEnv_t
|
||||
{
|
||||
u32 flags;
|
||||
C3D_LightLut* luts[6];
|
||||
float ambient[3];
|
||||
C3D_Light* lights[8];
|
||||
C3D_LightEnvConf conf;
|
||||
C3D_Material material;
|
||||
};
|
||||
|
||||
void C3D_LightEnvInit(C3D_LightEnv* env);
|
||||
void C3D_LightEnvBind(C3D_LightEnv* env);
|
||||
|
||||
void C3D_LightEnvMaterial(C3D_LightEnv* env, const C3D_Material* mtl);
|
||||
void C3D_LightEnvAmbient(C3D_LightEnv* env, float r, float g, float b);
|
||||
void C3D_LightEnvLut(C3D_LightEnv* env, GPU_LIGHTLUTID lutId, GPU_LIGHTLUTINPUT input, bool negative, C3D_LightLut* lut);
|
||||
|
||||
enum
|
||||
{
|
||||
GPU_SHADOW_PRIMARY = BIT(16),
|
||||
GPU_SHADOW_SECONDARY = BIT(17),
|
||||
GPU_INVERT_SHADOW = BIT(18),
|
||||
GPU_SHADOW_ALPHA = BIT(19),
|
||||
};
|
||||
|
||||
void C3D_LightEnvFresnel(C3D_LightEnv* env, GPU_FRESNELSEL selector);
|
||||
void C3D_LightEnvBumpMode(C3D_LightEnv* env, GPU_BUMPMODE mode);
|
||||
void C3D_LightEnvBumpSel(C3D_LightEnv* env, int texUnit);
|
||||
|
||||
/**
|
||||
* @brief Configures whether to use the z component of the normal map.
|
||||
* @param[out] env Pointer to light environment structure.
|
||||
* @param[in] enable false if the z component is reconstructed from the xy components
|
||||
* of the normal map, true if the z component is taken from the normal map.
|
||||
*/
|
||||
void C3D_LightEnvBumpNormalZ(C3D_LightEnv *env, bool enable);
|
||||
void C3D_LightEnvShadowMode(C3D_LightEnv* env, u32 mode);
|
||||
void C3D_LightEnvShadowSel(C3D_LightEnv* env, int texUnit);
|
||||
void C3D_LightEnvClampHighlights(C3D_LightEnv* env, bool clamp);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Light
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 specular0, specular1, diffuse, ambient;
|
||||
} C3D_LightMatConf;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
C3D_LightMatConf material;
|
||||
u16 position[3]; u16 padding0;
|
||||
u16 spotDir[3]; u16 padding1;
|
||||
u32 padding2;
|
||||
u32 config;
|
||||
u32 distAttnBias, distAttnScale;
|
||||
} C3D_LightConf;
|
||||
|
||||
enum
|
||||
{
|
||||
C3DF_Light_Enabled = BIT(0),
|
||||
C3DF_Light_Dirty = BIT(1),
|
||||
C3DF_Light_MatDirty = BIT(2),
|
||||
//C3DF_Light_Shadow = BIT(3),
|
||||
//C3DF_Light_Spot = BIT(4),
|
||||
//C3DF_Light_DistAttn = BIT(5),
|
||||
|
||||
C3DF_Light_SPDirty = BIT(14),
|
||||
C3DF_Light_DADirty = BIT(15),
|
||||
};
|
||||
|
||||
struct C3D_Light_t
|
||||
{
|
||||
u16 flags, id;
|
||||
C3D_LightEnv* parent;
|
||||
C3D_LightLut *lut_SP, *lut_DA;
|
||||
float ambient[3];
|
||||
float diffuse[3];
|
||||
float specular0[3];
|
||||
float specular1[3];
|
||||
C3D_LightConf conf;
|
||||
};
|
||||
|
||||
int C3D_LightInit(C3D_Light* light, C3D_LightEnv* env);
|
||||
void C3D_LightEnable(C3D_Light* light, bool enable);
|
||||
void C3D_LightTwoSideDiffuse(C3D_Light* light, bool enable);
|
||||
void C3D_LightGeoFactor(C3D_Light* light, int id, bool enable);
|
||||
void C3D_LightAmbient(C3D_Light* light, float r, float g, float b);
|
||||
void C3D_LightDiffuse(C3D_Light* light, float r, float g, float b);
|
||||
void C3D_LightSpecular0(C3D_Light* light, float r, float g, float b);
|
||||
void C3D_LightSpecular1(C3D_Light* light, float r, float g, float b);
|
||||
void C3D_LightPosition(C3D_Light* light, C3D_FVec* pos);
|
||||
void C3D_LightShadowEnable(C3D_Light* light, bool enable);
|
||||
void C3D_LightSpotEnable(C3D_Light* light, bool enable);
|
||||
void C3D_LightSpotDir(C3D_Light* light, float x, float y, float z);
|
||||
void C3D_LightSpotLut(C3D_Light* light, C3D_LightLut* lut);
|
||||
void C3D_LightDistAttnEnable(C3D_Light* light, bool enable);
|
||||
void C3D_LightDistAttn(C3D_Light* light, C3D_LightLutDA* lut);
|
||||
|
||||
static inline void C3D_LightColor(C3D_Light* light, float r, float g, float b)
|
||||
{
|
||||
C3D_LightDiffuse(light, r, g, b);
|
||||
C3D_LightSpecular0(light, r, g, b);
|
||||
C3D_LightSpecular1(light, r, g, b);
|
||||
}
|
||||
35
include/c3d/lightlut.h
Normal file
35
include/c3d/lightlut.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
#pragma once
|
||||
#include "types.h"
|
||||
#include <math.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 data[256];
|
||||
} C3D_LightLut;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
C3D_LightLut lut;
|
||||
float bias, scale;
|
||||
} C3D_LightLutDA;
|
||||
|
||||
typedef float (* C3D_LightLutFunc)(float x, float param);
|
||||
typedef float (* C3D_LightLutFuncDA)(float dist, float arg0, float arg1);
|
||||
|
||||
static inline float quadratic_dist_attn(float dist, float linear, float quad)
|
||||
{
|
||||
return 1.0f / (1.0f + linear*dist + quad*dist*dist);
|
||||
}
|
||||
|
||||
static inline float spot_step(float angle, float cutoff)
|
||||
{
|
||||
return angle >= cutoff ? 1.0f : 0.0f;
|
||||
}
|
||||
|
||||
void LightLut_FromArray(C3D_LightLut* lut, float* data);
|
||||
void LightLut_FromFunc(C3D_LightLut* lut, C3D_LightLutFunc func, float param, bool negative);
|
||||
void LightLutDA_Create(C3D_LightLutDA* lut, C3D_LightLutFuncDA func, float from, float to, float arg0, float arg1);
|
||||
|
||||
#define LightLut_Phong(lut, shininess) LightLut_FromFunc((lut), powf, (shininess), false)
|
||||
#define LightLut_Spotlight(lut, angle) LightLut_FromFunc((lut), spot_step, cosf(angle), true)
|
||||
#define LightLutDA_Quadratic(lut, from, to, linear, quad) LightLutDA_Create((lut), quadratic_dist_attn, (from), (to), (linear), (quad))
|
||||
796
include/c3d/maths.h
Normal file
796
include/c3d/maths.h
Normal file
|
|
@ -0,0 +1,796 @@
|
|||
#pragma once
|
||||
#include "types.h"
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* @addtogroup math_support
|
||||
* @brief Implementations of matrix, vector, and quaternion operations.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* The one true circumference-to-radius ratio.
|
||||
* See http://tauday.com/tau-manifesto
|
||||
*/
|
||||
#define M_TAU (6.28318530717958647692528676655900576)
|
||||
|
||||
// Define the legacy circle constant as well
|
||||
#ifndef M_PI
|
||||
#define M_PI (M_TAU/2)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Convert an angle from revolutions to radians
|
||||
* @param[in] _angle Proportion of a full revolution
|
||||
* @return Angle in radians
|
||||
*/
|
||||
#define C3D_Angle(_angle) ((_angle)*M_TAU)
|
||||
|
||||
/**
|
||||
* @brief Convert an angle from degrees to radians
|
||||
* @param[in] _angle Angle in degrees
|
||||
* @return Angle in radians
|
||||
*/
|
||||
#define C3D_AngleFromDegrees(_angle) ((_angle)*M_TAU/360.0f)
|
||||
|
||||
#define C3D_AspectRatioTop (400.0f / 240.0f) ///< Aspect ratio for 3DS top screen
|
||||
#define C3D_AspectRatioBot (320.0f / 240.0f) ///< Aspect ratio for 3DS bottom screen
|
||||
|
||||
/**
|
||||
* @name Vector Math
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Create a new FVec4
|
||||
* @param[in] x X-component
|
||||
* @param[in] y Y-component
|
||||
* @param[in] z Z-component
|
||||
* @param[in] w W-component
|
||||
* @return New FVec4
|
||||
*/
|
||||
static inline C3D_FVec FVec4_New(float x, float y, float z, float w)
|
||||
{
|
||||
return (C3D_FVec){{ w, z, y, x }};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add two FVec4s
|
||||
* @param[in] lhs Augend
|
||||
* @param[in] rhs Addend
|
||||
* @return lhs+rhs (sum)
|
||||
*/
|
||||
static inline C3D_FVec FVec4_Add(C3D_FVec lhs, C3D_FVec rhs)
|
||||
{
|
||||
// component-wise addition
|
||||
return FVec4_New(lhs.x+rhs.x, lhs.y+rhs.y, lhs.z+rhs.z, lhs.w+rhs.w);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Subtract two FVec4s
|
||||
* @param[in] lhs Minuend
|
||||
* @param[in] rhs Subtrahend
|
||||
* @return lhs-rhs (difference)
|
||||
*/
|
||||
static inline C3D_FVec FVec4_Subtract(C3D_FVec lhs, C3D_FVec rhs)
|
||||
{
|
||||
// component-wise subtraction
|
||||
return FVec4_New(lhs.x-rhs.x, lhs.y-rhs.y, lhs.z-rhs.z, lhs.w-rhs.w);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Negate a FVec4
|
||||
* @note This is equivalent to `FVec4_Scale(v, -1)`
|
||||
* @param[in] v Vector to negate
|
||||
* @return -v
|
||||
*/
|
||||
static inline C3D_FVec FVec4_Negate(C3D_FVec v)
|
||||
{
|
||||
// component-wise negation
|
||||
return FVec4_New(-v.x, -v.y, -v.z, -v.w);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Scale a FVec4
|
||||
* @param[in] v Vector to scale
|
||||
* @param[in] s Scale factor
|
||||
* @return v*s
|
||||
*/
|
||||
static inline C3D_FVec FVec4_Scale(C3D_FVec v, float s)
|
||||
{
|
||||
// component-wise scaling
|
||||
return FVec4_New(v.x*s, v.y*s, v.z*s, v.w*s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Perspective divide
|
||||
* @param[in] v Vector to divide
|
||||
* @return v/v.w
|
||||
*/
|
||||
static inline C3D_FVec FVec4_PerspDivide(C3D_FVec v)
|
||||
{
|
||||
// divide by w
|
||||
return FVec4_New(v.x/v.w, v.y/v.w, v.z/v.w, 1.0f);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Dot product of two FVec4s
|
||||
* @param[in] lhs Left-side FVec4
|
||||
* @param[in] rhs Right-side FVec4
|
||||
* @return lhs∙rhs
|
||||
*/
|
||||
static inline float FVec4_Dot(C3D_FVec lhs, C3D_FVec rhs)
|
||||
{
|
||||
// A∙B = sum of component-wise products
|
||||
return lhs.x*rhs.x + lhs.y*rhs.y + lhs.z*rhs.z + lhs.w*rhs.w;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Magnitude of a FVec4
|
||||
* @param[in] v Vector
|
||||
* @return ‖v‖
|
||||
*/
|
||||
static inline float FVec4_Magnitude(C3D_FVec v)
|
||||
{
|
||||
// ‖v‖ = √(v∙v)
|
||||
return sqrtf(FVec4_Dot(v,v));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Normalize a FVec4
|
||||
* @param[in] v FVec4 to normalize
|
||||
* @return v/‖v‖
|
||||
*/
|
||||
static inline C3D_FVec FVec4_Normalize(C3D_FVec v)
|
||||
{
|
||||
// get vector magnitude
|
||||
float m = FVec4_Magnitude(v);
|
||||
|
||||
// scale by inverse magnitude to get a unit vector
|
||||
return FVec4_New(v.x/m, v.y/m, v.z/m, v.w/m);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a new FVec3
|
||||
* @param[in] x X-component
|
||||
* @param[in] y Y-component
|
||||
* @param[in] z Z-component
|
||||
* @return New FVec3
|
||||
*/
|
||||
static inline C3D_FVec FVec3_New(float x, float y, float z)
|
||||
{
|
||||
return FVec4_New(x, y, z, 0.0f);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Dot product of two FVec3s
|
||||
* @param[in] lhs Left-side FVec3
|
||||
* @param[in] rhs Right-side FVec3
|
||||
* @return lhs∙rhs
|
||||
*/
|
||||
static inline float FVec3_Dot(C3D_FVec lhs, C3D_FVec rhs)
|
||||
{
|
||||
// A∙B = sum of component-wise products
|
||||
return lhs.x*rhs.x + lhs.y*rhs.y + lhs.z*rhs.z;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Magnitude of a FVec3
|
||||
* @param[in] v Vector
|
||||
* @return ‖v‖
|
||||
*/
|
||||
static inline float FVec3_Magnitude(C3D_FVec v)
|
||||
{
|
||||
// ‖v‖ = √(v∙v)
|
||||
return sqrtf(FVec3_Dot(v,v));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Normalize a FVec3
|
||||
* @param[in] v FVec3 to normalize
|
||||
* @return v/‖v‖
|
||||
*/
|
||||
static inline C3D_FVec FVec3_Normalize(C3D_FVec v)
|
||||
{
|
||||
// get vector magnitude
|
||||
float m = FVec3_Magnitude(v);
|
||||
|
||||
// scale by inverse magnitude to get a unit vector
|
||||
return FVec3_New(v.x/m, v.y/m, v.z/m);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add two FVec3s
|
||||
* @param[in] lhs Augend
|
||||
* @param[in] rhs Addend
|
||||
* @return lhs+rhs (sum)
|
||||
*/
|
||||
static inline C3D_FVec FVec3_Add(C3D_FVec lhs, C3D_FVec rhs)
|
||||
{
|
||||
// component-wise addition
|
||||
return FVec3_New(lhs.x+rhs.x, lhs.y+rhs.y, lhs.z+rhs.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Subtract two FVec3s
|
||||
* @param[in] lhs Minuend
|
||||
* @param[in] rhs Subtrahend
|
||||
* @return lhs-rhs (difference)
|
||||
*/
|
||||
static inline C3D_FVec FVec3_Subtract(C3D_FVec lhs, C3D_FVec rhs)
|
||||
{
|
||||
// component-wise subtraction
|
||||
return FVec3_New(lhs.x-rhs.x, lhs.y-rhs.y, lhs.z-rhs.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Distance between two 3D points
|
||||
* @param[in] lhs Relative origin
|
||||
* @param[in] rhs Relative point of interest
|
||||
* @return ‖lhs-rhs‖
|
||||
*/
|
||||
static inline float FVec3_Distance(C3D_FVec lhs, C3D_FVec rhs)
|
||||
{
|
||||
// distance = ‖lhs-rhs‖
|
||||
return FVec3_Magnitude(FVec3_Subtract(lhs, rhs));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Scale a FVec3
|
||||
* @param[in] v Vector to scale
|
||||
* @param[in] s Scale factor
|
||||
* @return v*s
|
||||
*/
|
||||
static inline C3D_FVec FVec3_Scale(C3D_FVec v, float s)
|
||||
{
|
||||
// component-wise scaling
|
||||
return FVec3_New(v.x*s, v.y*s, v.z*s);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Negate a FVec3
|
||||
* @note This is equivalent to `FVec3_Scale(v, -1)`
|
||||
* @param[in] v Vector to negate
|
||||
* @return -v
|
||||
*/
|
||||
static inline C3D_FVec FVec3_Negate(C3D_FVec v)
|
||||
{
|
||||
// component-wise negation
|
||||
return FVec3_New(-v.x, -v.y, -v.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Cross product of two FVec3s
|
||||
* @note This returns a pseudo-vector which is perpendicular to the plane
|
||||
* spanned by the two input vectors.
|
||||
* @param[in] lhs Left-side FVec3
|
||||
* @param[in] rhs Right-side FVec3
|
||||
* @return lhs×rhs
|
||||
*/
|
||||
static inline C3D_FVec FVec3_Cross(C3D_FVec lhs, C3D_FVec rhs)
|
||||
{
|
||||
// A×B = (AyBz - AzBy, AzBx - AxBz, AxBy - AyBx)
|
||||
return FVec3_New(lhs.y*rhs.z - lhs.z*rhs.y, lhs.z*rhs.x - lhs.x*rhs.z, lhs.x*rhs.y - lhs.y*rhs.x);
|
||||
}
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Matrix Math
|
||||
* @note All matrices are 4x4 unless otherwise noted.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Zero matrix
|
||||
* @param[out] out Matrix to zero
|
||||
*/
|
||||
static inline void Mtx_Zeros(C3D_Mtx* out)
|
||||
{
|
||||
memset(out, 0, sizeof(*out));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy a matrix
|
||||
* @param[out] out Output matrix
|
||||
* @param[in] in Input matrix
|
||||
*/
|
||||
static inline void Mtx_Copy(C3D_Mtx* out, const C3D_Mtx* in)
|
||||
{
|
||||
*out = *in;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates a matrix with the diagonal using the given parameters.
|
||||
* @param[out] out Output matrix.
|
||||
* @param[in] x The X component.
|
||||
* @param[in] y The Y component.
|
||||
* @param[in] z The Z component.
|
||||
* @param[in] w The W component.
|
||||
*/
|
||||
static inline void Mtx_Diagonal(C3D_Mtx* out, float x, float y, float z, float w)
|
||||
{
|
||||
Mtx_Zeros(out);
|
||||
out->r[0].x = x;
|
||||
out->r[1].y = y;
|
||||
out->r[2].z = z;
|
||||
out->r[3].w = w;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Identity matrix
|
||||
* @param[out] out Matrix to fill
|
||||
*/
|
||||
static inline void Mtx_Identity(C3D_Mtx* out)
|
||||
{
|
||||
Mtx_Diagonal(out, 1.0f, 1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
|
||||
/**
|
||||
*@brief Transposes the matrix. Row => Column, and vice versa.
|
||||
*@param[in,out] out Output matrix.
|
||||
*/
|
||||
void Mtx_Transpose(C3D_Mtx* out);
|
||||
|
||||
/**
|
||||
* @brief Matrix addition
|
||||
* @param[out] out Output matrix.
|
||||
* @param[in] lhs Left matrix.
|
||||
* @param[in] rhs Right matrix.
|
||||
* @return lhs+rhs (sum)
|
||||
*/
|
||||
static inline void Mtx_Add(C3D_Mtx* out, const C3D_Mtx* lhs, const C3D_Mtx* rhs)
|
||||
{
|
||||
for (int i = 0; i < 16; i++)
|
||||
out->m[i] = lhs->m[i] + rhs->m[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Matrix subtraction
|
||||
* @param[out] out Output matrix.
|
||||
* @param[in] lhs Left matrix.
|
||||
* @param[in] rhs Right matrix.
|
||||
* @return lhs-rhs (difference)
|
||||
*/
|
||||
static inline void Mtx_Subtract(C3D_Mtx* out, const C3D_Mtx* lhs, const C3D_Mtx* rhs)
|
||||
{
|
||||
for (int i = 0; i < 16; i++)
|
||||
out->m[i] = lhs->m[i] - rhs->m[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Multiply two matrices
|
||||
* @param[out] out Output matrix
|
||||
* @param[in] a Multiplicand
|
||||
* @param[in] b Multiplier
|
||||
*/
|
||||
void Mtx_Multiply(C3D_Mtx* out, const C3D_Mtx* a, const C3D_Mtx* b);
|
||||
|
||||
/**
|
||||
* @brief Inverse a matrix
|
||||
* @param[in,out] out Matrix to inverse
|
||||
* @retval 0.0f Degenerate matrix (no inverse)
|
||||
* @return determinant
|
||||
*/
|
||||
float Mtx_Inverse(C3D_Mtx* out);
|
||||
|
||||
/**
|
||||
* @brief Multiply 3x3 matrix by a FVec3
|
||||
* @param[in] mtx Matrix
|
||||
* @param[in] v Vector
|
||||
* @return mtx*v (product)
|
||||
*/
|
||||
C3D_FVec Mtx_MultiplyFVec3(const C3D_Mtx* mtx, C3D_FVec v);
|
||||
|
||||
/**
|
||||
* @brief Multiply 4x4 matrix by a FVec4
|
||||
* @param[in] mtx Matrix
|
||||
* @param[in] v Vector
|
||||
* @return mtx*v (product)
|
||||
*/
|
||||
C3D_FVec Mtx_MultiplyFVec4(const C3D_Mtx* mtx, C3D_FVec v);
|
||||
|
||||
/**
|
||||
* @brief Multiply 4x3 matrix by a FVec3
|
||||
* @param[in] mtx Matrix
|
||||
* @param[in] v Vector
|
||||
* @return mtx*v (product)
|
||||
*/
|
||||
static inline C3D_FVec Mtx_MultiplyFVecH(const C3D_Mtx* mtx, C3D_FVec v)
|
||||
{
|
||||
v.w = 1.0f;
|
||||
|
||||
return Mtx_MultiplyFVec4(mtx, v);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get 4x4 matrix equivalent to Quaternion
|
||||
* @param[out] m Output matrix
|
||||
* @param[in] q Input Quaternion
|
||||
*/
|
||||
void Mtx_FromQuat(C3D_Mtx* m, C3D_FQuat q);
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name 3D Transformation Matrix Math
|
||||
* @note bRightSide is used to determine which side to perform the transformation.
|
||||
* With an input matrix A and a transformation matrix B, bRightSide being
|
||||
* true yields AB, while being false yield BA.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief 3D translation
|
||||
* @param[in,out] mtx Matrix to translate
|
||||
* @param[in] x X component to translate
|
||||
* @param[in] y Y component to translate
|
||||
* @param[in] z Z component to translate
|
||||
* @param[in] bRightSide Whether to transform from the right side
|
||||
*/
|
||||
void Mtx_Translate(C3D_Mtx* mtx, float x, float y, float z, bool bRightSide);
|
||||
|
||||
/**
|
||||
* @brief 3D Scale
|
||||
* @param[in,out] mtx Matrix to scale
|
||||
* @param[in] x X component to scale
|
||||
* @param[in] y Y component to scale
|
||||
* @param[in] z Z component to scale
|
||||
*/
|
||||
void Mtx_Scale(C3D_Mtx* mtx, float x, float y, float z);
|
||||
|
||||
/**
|
||||
* @brief 3D Rotation
|
||||
* @param[in,out] mtx Matrix to rotate
|
||||
* @param[in] axis Axis about which to rotate
|
||||
* @param[in] angle Radians to rotate
|
||||
* @param[in] bRightSide Whether to transform from the right side
|
||||
*/
|
||||
void Mtx_Rotate(C3D_Mtx* mtx, C3D_FVec axis, float angle, bool bRightSide);
|
||||
|
||||
/**
|
||||
* @brief 3D Rotation about the X axis
|
||||
* @param[in,out] mtx Matrix to rotate
|
||||
* @param[in] angle Radians to rotate
|
||||
* @param[in] bRightSide Whether to transform from the right side
|
||||
*/
|
||||
void Mtx_RotateX(C3D_Mtx* mtx, float angle, bool bRightSide);
|
||||
|
||||
/**
|
||||
* @brief 3D Rotation about the Y axis
|
||||
* @param[in,out] mtx Matrix to rotate
|
||||
* @param[in] angle Radians to rotate
|
||||
* @param[in] bRightSide Whether to transform from the right side
|
||||
*/
|
||||
void Mtx_RotateY(C3D_Mtx* mtx, float angle, bool bRightSide);
|
||||
|
||||
/**
|
||||
* @brief 3D Rotation about the Z axis
|
||||
* @param[in,out] mtx Matrix to rotate
|
||||
* @param[in] angle Radians to rotate
|
||||
* @param[in] bRightSide Whether to transform from the right side
|
||||
*/
|
||||
void Mtx_RotateZ(C3D_Mtx* mtx, float angle, bool bRightSide);
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name 3D Projection Matrix Math
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Orthogonal projection
|
||||
* @param[out] mtx Output matrix
|
||||
* @param[in] left Left clip plane (X=left)
|
||||
* @param[in] right Right clip plane (X=right)
|
||||
* @param[in] bottom Bottom clip plane (Y=bottom)
|
||||
* @param[in] top Top clip plane (Y=top)
|
||||
* @param[in] near Near clip plane (Z=near)
|
||||
* @param[in] far Far clip plane (Z=far)
|
||||
* @param[in] isLeftHanded Whether to build a LH projection
|
||||
* @sa Mtx_OrthoTilt
|
||||
*/
|
||||
void Mtx_Ortho(C3D_Mtx* mtx, float left, float right, float bottom, float top, float near, float far, bool isLeftHanded);
|
||||
|
||||
/**
|
||||
* @brief Perspective projection
|
||||
* @param[out] mtx Output matrix
|
||||
* @param[in] fovy Vertical field of view in radians
|
||||
* @param[in] aspect Aspect ration of projection plane (width/height)
|
||||
* @param[in] near Near clip plane (Z=near)
|
||||
* @param[in] far Far clip plane (Z=far)
|
||||
* @param[in] isLeftHanded Whether to build a LH projection
|
||||
* @sa Mtx_PerspTilt
|
||||
* @sa Mtx_PerspStereo
|
||||
* @sa Mtx_PerspStereoTilt
|
||||
*/
|
||||
void Mtx_Persp(C3D_Mtx* mtx, float fovy, float aspect, float near, float far, bool isLeftHanded);
|
||||
|
||||
/**
|
||||
* @brief Stereo perspective projection
|
||||
* @note Typically you will use iod to mean the distance between the eyes. Plug
|
||||
* in -iod for the left eye and iod for the right eye.
|
||||
* @note The focal length is defined by screen. If objects are further than this,
|
||||
* they will appear to be inside the screen. If objects are closer than this,
|
||||
* they will appear to pop out of the screen. Objects at this distance appear
|
||||
* to be at the screen.
|
||||
* @param[out] mtx Output matrix
|
||||
* @param[in] fovy Vertical field of view in radians
|
||||
* @param[in] aspect Aspect ration of projection plane (width/height)
|
||||
* @param[in] near Near clip plane (Z=near)
|
||||
* @param[in] far Far clip plane (Z=far)
|
||||
* @param[in] iod Interocular distance
|
||||
* @param[in] screen Focal length
|
||||
* @param[in] isLeftHanded Whether to build a LH projection
|
||||
* @sa Mtx_Persp
|
||||
* @sa Mtx_PerspTilt
|
||||
* @sa Mtx_PerspStereoTilt
|
||||
*/
|
||||
void Mtx_PerspStereo(C3D_Mtx* mtx, float fovy, float aspect, float near, float far, float iod, float screen, bool isLeftHanded);
|
||||
|
||||
/**
|
||||
* @brief Orthogonal projection, tilted to account for the 3DS screen rotation
|
||||
* @param[out] mtx Output matrix
|
||||
* @param[in] left Left clip plane (X=left)
|
||||
* @param[in] right Right clip plane (X=right)
|
||||
* @param[in] bottom Bottom clip plane (Y=bottom)
|
||||
* @param[in] top Top clip plane (Y=top)
|
||||
* @param[in] near Near clip plane (Z=near)
|
||||
* @param[in] far Far clip plane (Z=far)
|
||||
* @param[in] isLeftHanded Whether to build a LH projection
|
||||
* @sa Mtx_Ortho
|
||||
*/
|
||||
void Mtx_OrthoTilt(C3D_Mtx* mtx, float left, float right, float bottom, float top, float near, float far, bool isLeftHanded);
|
||||
|
||||
/**
|
||||
* @brief Perspective projection, tilted to account for the 3DS screen rotation
|
||||
* @param[out] mtx Output matrix
|
||||
* @param[in] fovy Vertical field of view in radians
|
||||
* @param[in] aspect Aspect ration of projection plane (width/height)
|
||||
* @param[in] near Near clip plane (Z=near)
|
||||
* @param[in] far Far clip plane (Z=far)
|
||||
* @param[in] isLeftHanded Whether to build a LH projection
|
||||
* @sa Mtx_Persp
|
||||
* @sa Mtx_PerspStereo
|
||||
* @sa Mtx_PerspStereoTilt
|
||||
*/
|
||||
void Mtx_PerspTilt(C3D_Mtx* mtx, float fovy, float aspect, float near, float far, bool isLeftHanded);
|
||||
|
||||
/**
|
||||
* @brief Stereo perspective projection, tilted to account for the 3DS screen rotation
|
||||
* @note See the notes for @ref Mtx_PerspStereo
|
||||
* @param[out] mtx Output matrix
|
||||
* @param[in] fovy Vertical field of view in radians
|
||||
* @param[in] aspect Aspect ration of projection plane (width/height)
|
||||
* @param[in] near Near clip plane (Z=near)
|
||||
* @param[in] far Far clip plane (Z=far)
|
||||
* @param[in] iod Interocular distance
|
||||
* @param[in] screen Focal length
|
||||
* @param[in] isLeftHanded Whether to build a LH projection
|
||||
* @sa Mtx_Persp
|
||||
* @sa Mtx_PerspTilt
|
||||
* @sa Mtx_PerspStereo
|
||||
*/
|
||||
void Mtx_PerspStereoTilt(C3D_Mtx* mtx, float fovy, float aspect, float near, float far, float iod, float screen, bool isLeftHanded);
|
||||
|
||||
/**
|
||||
* @brief Look-At matrix, based on DirectX implementation
|
||||
* @note See https://msdn.microsoft.com/en-us/library/windows/desktop/bb205342
|
||||
* @param[out] out Output matrix.
|
||||
* @param[in] cameraPosition Position of the intended camera in 3D space.
|
||||
* @param[in] cameraTarget Position of the intended target the camera is supposed to face in 3D space.
|
||||
* @param[in] cameraUpVector The vector that points straight up depending on the camera's "Up" direction.
|
||||
* @param[in] isLeftHanded Whether to build a LH projection
|
||||
*/
|
||||
void Mtx_LookAt(C3D_Mtx* out, C3D_FVec cameraPosition, C3D_FVec cameraTarget, C3D_FVec cameraUpVector, bool isLeftHanded);
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Quaternion Math
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Create a new Quaternion
|
||||
* @param[in] i I-component
|
||||
* @param[in] j J-component
|
||||
* @param[in] k K-component
|
||||
* @param[in] r Real component
|
||||
* @return New Quaternion
|
||||
*/
|
||||
#define Quat_New(i,j,k,r) FVec4_New(i,j,k,r)
|
||||
|
||||
/**
|
||||
* @brief Negate a Quaternion
|
||||
* @note This is equivalent to `Quat_Scale(v, -1)`
|
||||
* @param[in] q Quaternion to negate
|
||||
* @return -q
|
||||
*/
|
||||
#define Quat_Negate(q) FVec4_Negate(q)
|
||||
|
||||
/**
|
||||
* @brief Add two Quaternions
|
||||
* @param[in] lhs Augend
|
||||
* @param[in] rhs Addend
|
||||
* @return lhs+rhs (sum)
|
||||
*/
|
||||
#define Quat_Add(lhs,rhs) FVec4_Add(lhs,rhs)
|
||||
|
||||
/**
|
||||
* @brief Subtract two Quaternions
|
||||
* @param[in] lhs Minuend
|
||||
* @param[in] rhs Subtrahend
|
||||
* @return lhs-rhs (difference)
|
||||
*/
|
||||
#define Quat_Subtract(lhs,rhs) FVec4_Subtract(lhs,rhs)
|
||||
|
||||
/**
|
||||
* @brief Scale a Quaternion
|
||||
* @param[in] q Quaternion to scale
|
||||
* @param[in] s Scale factor
|
||||
* @return q*s
|
||||
*/
|
||||
#define Quat_Scale(q,s) FVec4_Scale(q,s)
|
||||
|
||||
/**
|
||||
* @brief Normalize a Quaternion
|
||||
* @param[in] q Quaternion to normalize
|
||||
* @return q/‖q‖
|
||||
*/
|
||||
#define Quat_Normalize(q) FVec4_Normalize(q)
|
||||
|
||||
/**
|
||||
* @brief Dot product of two Quaternions
|
||||
* @param[in] lhs Left-side Quaternion
|
||||
* @param[in] rhs Right-side Quaternion
|
||||
* @return lhs∙rhs
|
||||
*/
|
||||
#define Quat_Dot(lhs,rhs) FVec4_Dot(lhs,rhs)
|
||||
|
||||
/**
|
||||
* @brief Multiply two Quaternions
|
||||
* @param[in] lhs Multiplicand
|
||||
* @param[in] rhs Multiplier
|
||||
* @return lhs*rhs
|
||||
*/
|
||||
C3D_FQuat Quat_Multiply(C3D_FQuat lhs, C3D_FQuat rhs);
|
||||
|
||||
/**
|
||||
* @brief Raise Quaternion to a power
|
||||
* @note If p is 0, this returns the identity Quaternion.
|
||||
* If p is 1, this returns q.
|
||||
* @param[in] q Base Quaternion
|
||||
* @param[in] p Power
|
||||
* @return q<sup>p</sup>
|
||||
*/
|
||||
C3D_FQuat Quat_Pow(C3D_FQuat q, float p);
|
||||
|
||||
/**
|
||||
* @brief Cross product of Quaternion and FVec3
|
||||
* @param[in] q Base Quaternion
|
||||
* @param[in] v Vector to cross
|
||||
* @return q×v
|
||||
*/
|
||||
C3D_FVec Quat_CrossFVec3(C3D_FQuat q, C3D_FVec v);
|
||||
|
||||
/**
|
||||
* @brief 3D Rotation
|
||||
* @param[in] q Quaternion to rotate
|
||||
* @param[in] axis Axis about which to rotate
|
||||
* @param[in] r Radians to rotate
|
||||
* @param[in] bRightSide Whether to transform from the right side
|
||||
* @return Rotated Quaternion
|
||||
*/
|
||||
C3D_FQuat Quat_Rotate(C3D_FQuat q, C3D_FVec axis, float r, bool bRightSide);
|
||||
|
||||
/**
|
||||
* @brief 3D Rotation about the X axis
|
||||
* @param[in] q Quaternion to rotate
|
||||
* @param[in] r Radians to rotate
|
||||
* @param[in] bRightSide Whether to transform from the right side
|
||||
* @return Rotated Quaternion
|
||||
*/
|
||||
C3D_FQuat Quat_RotateX(C3D_FQuat q, float r, bool bRightSide);
|
||||
|
||||
/**
|
||||
* @brief 3D Rotation about the Y axis
|
||||
* @param[in] q Quaternion to rotate
|
||||
* @param[in] r Radians to rotate
|
||||
* @param[in] bRightSide Whether to transform from the right side
|
||||
* @return Rotated Quaternion
|
||||
*/
|
||||
C3D_FQuat Quat_RotateY(C3D_FQuat q, float r, bool bRightSide);
|
||||
|
||||
/**
|
||||
* @brief 3D Rotation about the Z axis
|
||||
* @param[in] q Quaternion to rotate
|
||||
* @param[in] r Radians to rotate
|
||||
* @param[in] bRightSide Whether to transform from the right side
|
||||
* @return Rotated Quaternion
|
||||
*/
|
||||
C3D_FQuat Quat_RotateZ(C3D_FQuat q, float r, bool bRightSide);
|
||||
|
||||
/**
|
||||
* @brief Get Quaternion equivalent to 4x4 matrix
|
||||
* @note If the matrix is orthogonal or special orthogonal, where determinant(matrix) = +1.0f, then the matrix can be converted.
|
||||
* @param[in] m Input Matrix
|
||||
* @return Generated Quaternion
|
||||
*/
|
||||
C3D_FQuat Quat_FromMtx(const C3D_Mtx* m);
|
||||
|
||||
/**
|
||||
* @brief Identity Quaternion
|
||||
* @return Identity Quaternion
|
||||
*/
|
||||
static inline C3D_FQuat Quat_Identity(void)
|
||||
{
|
||||
// r=1, i=j=k=0
|
||||
return Quat_New(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Quaternion conjugate
|
||||
* @param[in] q Quaternion of which to get conjugate
|
||||
* @return q*
|
||||
*/
|
||||
static inline C3D_FQuat Quat_Conjugate(C3D_FQuat q)
|
||||
{
|
||||
// q* = q.r - q.i - q.j - q.k
|
||||
return Quat_New(-q.i, -q.j, -q.k, q.r);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Quaternion inverse
|
||||
* @note This is equivalent to `Quat_Pow(v, -1)`
|
||||
* @param[in] q Quaternion of which to get inverse
|
||||
* @return q<sup>-1</sup>
|
||||
*/
|
||||
static inline C3D_FQuat Quat_Inverse(C3D_FQuat q)
|
||||
{
|
||||
// q^-1 = (q.r - q.i - q.j - q.k) / (q.r^2 + q.i^2 + q.j^2 + q.k^2)
|
||||
// = q* / (q∙q)
|
||||
C3D_FQuat c = Quat_Conjugate(q);
|
||||
float d = Quat_Dot(q, q);
|
||||
return Quat_New(c.i/d, c.j/d, c.k/d, c.r/d);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Cross product of FVec3 and Quaternion
|
||||
* @param[in] v Base FVec3
|
||||
* @param[in] q Quaternion to cross
|
||||
* @return v×q
|
||||
*/
|
||||
static inline C3D_FVec FVec3_CrossQuat(C3D_FVec v, C3D_FQuat q)
|
||||
{
|
||||
// v×q = (q^-1)×v
|
||||
return Quat_CrossFVec3(Quat_Inverse(q), v);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converting Pitch, Yaw, and Roll to Quaternion equivalent
|
||||
* @param[in] pitch The pitch angle in radians.
|
||||
* @param[in] yaw The yaw angle in radians.
|
||||
* @param[in] roll The roll angle in radians.
|
||||
* @param[in] bRightSide Whether to transform from the right side
|
||||
* @return C3D_FQuat The Quaternion equivalent with the pitch, yaw, and roll (in that order) orientations applied.
|
||||
*/
|
||||
C3D_FQuat Quat_FromPitchYawRoll(float pitch, float yaw, float roll, bool bRightSide);
|
||||
|
||||
/**
|
||||
* @brief Quaternion Look-At
|
||||
* @param[in] source C3D_FVec Starting position. Origin of rotation.
|
||||
* @param[in] target C3D_FVec Target position to orient towards.
|
||||
* @param[in] forwardVector C3D_FVec The Up vector.
|
||||
* @param[in] upVector C3D_FVec The Up vector.
|
||||
* @return Quaternion rotation.
|
||||
*/
|
||||
C3D_FQuat Quat_LookAt(C3D_FVec source, C3D_FVec target, C3D_FVec forwardVector, C3D_FVec upVector);
|
||||
|
||||
/**
|
||||
* @brief Quaternion, created from a given axis and angle in radians.
|
||||
* @param[in] axis C3D_FVec The axis to rotate around at.
|
||||
* @param[in] angle float The angle to rotate. Unit: Radians
|
||||
* @return Quaternion rotation based on the axis and angle. Axis doesn't have to be orthogonal.
|
||||
*/
|
||||
C3D_FQuat Quat_FromAxisAngle(C3D_FVec axis, float angle);
|
||||
/** @} */
|
||||
/** @} */
|
||||
24
include/c3d/mtxstack.h
Normal file
24
include/c3d/mtxstack.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
#include "maths.h"
|
||||
|
||||
#define C3D_MTXSTACK_SIZE 8
|
||||
|
||||
typedef struct
|
||||
{
|
||||
C3D_Mtx m[C3D_MTXSTACK_SIZE];
|
||||
int pos;
|
||||
u8 unifType, unifPos, unifLen;
|
||||
bool isDirty;
|
||||
} C3D_MtxStack;
|
||||
|
||||
static inline C3D_Mtx* MtxStack_Cur(C3D_MtxStack* stk)
|
||||
{
|
||||
stk->isDirty = true;
|
||||
return &stk->m[stk->pos];
|
||||
}
|
||||
|
||||
void MtxStack_Init(C3D_MtxStack* stk);
|
||||
void MtxStack_Bind(C3D_MtxStack* stk, GPU_SHADER_TYPE unifType, int unifPos, int unifLen);
|
||||
C3D_Mtx* MtxStack_Push(C3D_MtxStack* stk);
|
||||
C3D_Mtx* MtxStack_Pop(C3D_MtxStack* stk);
|
||||
void MtxStack_Update(C3D_MtxStack* stk);
|
||||
125
include/c3d/proctex.h
Normal file
125
include/c3d/proctex.h
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
#pragma once
|
||||
#include "types.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 color[256];
|
||||
u32 diff[256];
|
||||
} C3D_ProcTexColorLut;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
union
|
||||
{
|
||||
u32 proctex0;
|
||||
struct
|
||||
{
|
||||
u32 uClamp : 3;
|
||||
u32 vClamp : 3;
|
||||
u32 rgbFunc : 4;
|
||||
u32 alphaFunc : 4;
|
||||
bool alphaSeparate : 1;
|
||||
bool enableNoise : 1;
|
||||
u32 uShift : 2;
|
||||
u32 vShift : 2;
|
||||
u32 lodBiasLow : 8;
|
||||
};
|
||||
};
|
||||
union
|
||||
{
|
||||
u32 proctex1;
|
||||
struct
|
||||
{
|
||||
u16 uNoiseAmpl;
|
||||
u16 uNoisePhase;
|
||||
};
|
||||
};
|
||||
union
|
||||
{
|
||||
u32 proctex2;
|
||||
struct
|
||||
{
|
||||
u16 vNoiseAmpl;
|
||||
u16 vNoisePhase;
|
||||
};
|
||||
};
|
||||
union
|
||||
{
|
||||
u32 proctex3;
|
||||
struct
|
||||
{
|
||||
u16 uNoiseFreq;
|
||||
u16 vNoiseFreq;
|
||||
};
|
||||
};
|
||||
union
|
||||
{
|
||||
u32 proctex4;
|
||||
struct
|
||||
{
|
||||
u32 minFilter : 3;
|
||||
u32 unknown1 : 8;
|
||||
u32 width : 8;
|
||||
u32 lodBiasHigh : 8;
|
||||
};
|
||||
};
|
||||
union
|
||||
{
|
||||
u32 proctex5;
|
||||
struct
|
||||
{
|
||||
u32 offset : 8;
|
||||
u32 unknown2 : 24;
|
||||
};
|
||||
};
|
||||
} C3D_ProcTex;
|
||||
|
||||
enum
|
||||
{
|
||||
C3D_ProcTex_U = BIT(0),
|
||||
C3D_ProcTex_V = BIT(1),
|
||||
C3D_ProcTex_UV = C3D_ProcTex_U | C3D_ProcTex_V,
|
||||
};
|
||||
|
||||
void C3D_ProcTexInit(C3D_ProcTex* pt, int offset, int length);
|
||||
void C3D_ProcTexNoiseCoefs(C3D_ProcTex* pt, int mode, float amplitude, float frequency, float phase);
|
||||
void C3D_ProcTexLodBias(C3D_ProcTex* pt, float bias);
|
||||
void C3D_ProcTexBind(int texCoordId, C3D_ProcTex* pt);
|
||||
|
||||
// GPU_LUT_NOISE, GPU_LUT_RGBMAP, GPU_LUT_ALPHAMAP
|
||||
typedef u32 C3D_ProcTexLut[128];
|
||||
void C3D_ProcTexLutBind(GPU_PROCTEX_LUTID id, C3D_ProcTexLut* lut);
|
||||
void ProcTexLut_FromArray(C3D_ProcTexLut* lut, const float in[129]);
|
||||
|
||||
void C3D_ProcTexColorLutBind(C3D_ProcTexColorLut* lut);
|
||||
void ProcTexColorLut_Write(C3D_ProcTexColorLut* out, const u32* in, int offset, int length);
|
||||
|
||||
static inline void C3D_ProcTexClamp(C3D_ProcTex* pt, GPU_PROCTEX_CLAMP u, GPU_PROCTEX_CLAMP v)
|
||||
{
|
||||
pt->uClamp = u;
|
||||
pt->vClamp = v;
|
||||
}
|
||||
|
||||
static inline void C3D_ProcTexCombiner(C3D_ProcTex* pt, bool separate, GPU_PROCTEX_MAPFUNC rgb, GPU_PROCTEX_MAPFUNC alpha)
|
||||
{
|
||||
pt->alphaSeparate = separate;
|
||||
pt->rgbFunc = rgb;
|
||||
if (separate)
|
||||
pt->alphaFunc = alpha;
|
||||
}
|
||||
|
||||
static inline void C3D_ProcTexNoiseEnable(C3D_ProcTex* pt, bool enable)
|
||||
{
|
||||
pt->enableNoise = enable;
|
||||
}
|
||||
|
||||
static inline void C3D_ProcTexShift(C3D_ProcTex* pt, GPU_PROCTEX_SHIFT u, GPU_PROCTEX_SHIFT v)
|
||||
{
|
||||
pt->uShift = u;
|
||||
pt->vShift = v;
|
||||
}
|
||||
|
||||
static inline void C3D_ProcTexFilter(C3D_ProcTex* pt, GPU_PROCTEX_FILTER min)
|
||||
{
|
||||
pt->minFilter = min;
|
||||
}
|
||||
79
include/c3d/renderqueue.h
Normal file
79
include/c3d/renderqueue.h
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
#pragma once
|
||||
#include "framebuffer.h"
|
||||
|
||||
typedef struct C3D_RenderTarget_tag C3D_RenderTarget;
|
||||
|
||||
struct C3D_RenderTarget_tag
|
||||
{
|
||||
C3D_RenderTarget *next, *prev;
|
||||
C3D_FrameBuf frameBuf;
|
||||
|
||||
bool used;
|
||||
bool ownsColor, ownsDepth;
|
||||
|
||||
bool linked;
|
||||
gfxScreen_t screen;
|
||||
gfx3dSide_t side;
|
||||
u32 transferFlags;
|
||||
};
|
||||
|
||||
// Flags for C3D_FrameBegin
|
||||
enum
|
||||
{
|
||||
C3D_FRAME_SYNCDRAW = BIT(0), // Perform C3D_FrameSync before checking the GPU status
|
||||
C3D_FRAME_NONBLOCK = BIT(1), // Return false instead of waiting if the GPU is busy
|
||||
};
|
||||
|
||||
float C3D_FrameRate(float fps);
|
||||
void C3D_FrameSync(void);
|
||||
u32 C3D_FrameCounter(int id);
|
||||
|
||||
bool C3D_FrameBegin(u8 flags);
|
||||
bool C3D_FrameDrawOn(C3D_RenderTarget* target);
|
||||
void C3D_FrameSplit(u8 flags);
|
||||
void C3D_FrameEnd(u8 flags);
|
||||
|
||||
void C3D_FrameEndHook(void (* hook)(void*), void* param);
|
||||
|
||||
float C3D_GetDrawingTime(void);
|
||||
float C3D_GetProcessingTime(void);
|
||||
|
||||
#if defined(__GNUC__) && !defined(__cplusplus)
|
||||
typedef union __attribute__((__transparent_union__))
|
||||
{
|
||||
int __i;
|
||||
GPU_DEPTHBUF __e;
|
||||
} C3D_DEPTHTYPE;
|
||||
#else
|
||||
union C3D_DEPTHTYPE
|
||||
{
|
||||
private:
|
||||
int __i;
|
||||
GPU_DEPTHBUF __e;
|
||||
public:
|
||||
C3D_DEPTHTYPE(GPU_DEPTHBUF e) : __e(e) {}
|
||||
C3D_DEPTHTYPE(int i) : __i(-1) { (void)i; }
|
||||
};
|
||||
#endif
|
||||
|
||||
#define C3D_DEPTHTYPE_OK(_x) ((_x).__i >= 0)
|
||||
#define C3D_DEPTHTYPE_VAL(_x) ((_x).__e)
|
||||
|
||||
C3D_RenderTarget* C3D_RenderTargetCreate(int width, int height, GPU_COLORBUF colorFmt, C3D_DEPTHTYPE depthFmt);
|
||||
C3D_RenderTarget* C3D_RenderTargetCreateFromTex(C3D_Tex* tex, GPU_TEXFACE face, int level, C3D_DEPTHTYPE depthFmt);
|
||||
void C3D_RenderTargetDelete(C3D_RenderTarget* target);
|
||||
void C3D_RenderTargetSetOutput(C3D_RenderTarget* target, gfxScreen_t screen, gfx3dSide_t side, u32 transferFlags);
|
||||
|
||||
static inline void C3D_RenderTargetDetachOutput(C3D_RenderTarget* target)
|
||||
{
|
||||
C3D_RenderTargetSetOutput(NULL, target->screen, target->side, 0);
|
||||
}
|
||||
|
||||
static inline void C3D_RenderTargetClear(C3D_RenderTarget* target, C3D_ClearBits clearBits, u32 clearColor, u32 clearDepth)
|
||||
{
|
||||
C3D_FrameBufClear(&target->frameBuf, clearBits, clearColor, clearDepth);
|
||||
}
|
||||
|
||||
void C3D_SyncDisplayTransfer(u32* inadr, u32 indim, u32* outadr, u32 outdim, u32 flags);
|
||||
void C3D_SyncTextureCopy(u32* inadr, u32 indim, u32* outadr, u32 outdim, u32 size, u32 flags);
|
||||
void C3D_SyncMemoryFill(u32* buf0a, u32 buf0v, u32* buf0e, u16 control0, u32* buf1a, u32 buf1v, u32* buf1e, u16 control1);
|
||||
98
include/c3d/texenv.h
Normal file
98
include/c3d/texenv.h
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
#pragma once
|
||||
#include "types.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u16 srcRgb, srcAlpha;
|
||||
union
|
||||
{
|
||||
u32 opAll;
|
||||
struct { u32 opRgb:12, opAlpha:12; };
|
||||
};
|
||||
u16 funcRgb, funcAlpha;
|
||||
u32 color;
|
||||
u16 scaleRgb, scaleAlpha;
|
||||
} C3D_TexEnv;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
C3D_RGB = BIT(0),
|
||||
C3D_Alpha = BIT(1),
|
||||
C3D_Both = C3D_RGB | C3D_Alpha,
|
||||
} C3D_TexEnvMode;
|
||||
|
||||
C3D_TexEnv* C3D_GetTexEnv(int id);
|
||||
void C3D_SetTexEnv(int id, C3D_TexEnv* env);
|
||||
void C3D_DirtyTexEnv(C3D_TexEnv* env);
|
||||
|
||||
void C3D_TexEnvBufUpdate(int mode, int mask);
|
||||
void C3D_TexEnvBufColor(u32 color);
|
||||
|
||||
static inline void C3D_TexEnvInit(C3D_TexEnv* env)
|
||||
{
|
||||
env->srcRgb = GPU_TEVSOURCES(GPU_PREVIOUS, 0, 0);
|
||||
env->srcAlpha = env->srcRgb;
|
||||
env->opAll = 0;
|
||||
env->funcRgb = GPU_REPLACE;
|
||||
env->funcAlpha = env->funcRgb;
|
||||
env->color = 0xFFFFFFFF;
|
||||
env->scaleRgb = GPU_TEVSCALE_1;
|
||||
env->scaleAlpha = GPU_TEVSCALE_1;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define _C3D_DEFAULT(x) = x
|
||||
#else
|
||||
#define _C3D_DEFAULT(x)
|
||||
#endif
|
||||
|
||||
static inline void C3D_TexEnvSrc(C3D_TexEnv* env, C3D_TexEnvMode mode,
|
||||
GPU_TEVSRC s1,
|
||||
GPU_TEVSRC s2 _C3D_DEFAULT(GPU_PRIMARY_COLOR),
|
||||
GPU_TEVSRC s3 _C3D_DEFAULT(GPU_PRIMARY_COLOR))
|
||||
{
|
||||
int param = GPU_TEVSOURCES((int)s1, (int)s2, (int)s3);
|
||||
if ((int)mode & C3D_RGB)
|
||||
env->srcRgb = param;
|
||||
if ((int)mode & C3D_Alpha)
|
||||
env->srcAlpha = param;
|
||||
}
|
||||
|
||||
static inline void C3D_TexEnvOpRgb(C3D_TexEnv* env,
|
||||
GPU_TEVOP_RGB o1,
|
||||
GPU_TEVOP_RGB o2 _C3D_DEFAULT(GPU_TEVOP_RGB_SRC_COLOR),
|
||||
GPU_TEVOP_RGB o3 _C3D_DEFAULT(GPU_TEVOP_RGB_SRC_COLOR))
|
||||
{
|
||||
env->opRgb = GPU_TEVOPERANDS((int)o1, (int)o2, (int)o3);
|
||||
}
|
||||
|
||||
static inline void C3D_TexEnvOpAlpha(C3D_TexEnv* env,
|
||||
GPU_TEVOP_A o1,
|
||||
GPU_TEVOP_A o2 _C3D_DEFAULT(GPU_TEVOP_A_SRC_ALPHA),
|
||||
GPU_TEVOP_A o3 _C3D_DEFAULT(GPU_TEVOP_A_SRC_ALPHA))
|
||||
{
|
||||
env->opAlpha = GPU_TEVOPERANDS((int)o1, (int)o2, (int)o3);
|
||||
}
|
||||
|
||||
static inline void C3D_TexEnvFunc(C3D_TexEnv* env, C3D_TexEnvMode mode, GPU_COMBINEFUNC param)
|
||||
{
|
||||
if ((int)mode & C3D_RGB)
|
||||
env->funcRgb = param;
|
||||
if ((int)mode & C3D_Alpha)
|
||||
env->funcAlpha = param;
|
||||
}
|
||||
|
||||
static inline void C3D_TexEnvColor(C3D_TexEnv* env, u32 color)
|
||||
{
|
||||
env->color = color;
|
||||
}
|
||||
|
||||
static inline void C3D_TexEnvScale(C3D_TexEnv* env, int mode, GPU_TEVSCALE param)
|
||||
{
|
||||
if (mode & C3D_RGB)
|
||||
env->scaleRgb = param;
|
||||
if (mode & C3D_Alpha)
|
||||
env->scaleAlpha = param;
|
||||
}
|
||||
|
||||
#undef _C3D_DEFAULT
|
||||
183
include/c3d/texture.h
Normal file
183
include/c3d/texture.h
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
#pragma once
|
||||
#include "types.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void* data[6];
|
||||
} C3D_TexCube;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
union
|
||||
{
|
||||
void* data;
|
||||
C3D_TexCube* cube;
|
||||
};
|
||||
|
||||
GPU_TEXCOLOR fmt : 4;
|
||||
size_t size : 28;
|
||||
|
||||
union
|
||||
{
|
||||
u32 dim;
|
||||
struct
|
||||
{
|
||||
u16 height;
|
||||
u16 width;
|
||||
};
|
||||
};
|
||||
|
||||
u32 param;
|
||||
u32 border;
|
||||
union
|
||||
{
|
||||
u32 lodParam;
|
||||
struct
|
||||
{
|
||||
u16 lodBias;
|
||||
u8 maxLevel;
|
||||
u8 minLevel;
|
||||
};
|
||||
};
|
||||
} C3D_Tex;
|
||||
|
||||
typedef struct CTR_ALIGN(8)
|
||||
{
|
||||
u16 width;
|
||||
u16 height;
|
||||
u8 maxLevel : 4;
|
||||
GPU_TEXCOLOR format : 4;
|
||||
GPU_TEXTURE_MODE_PARAM type : 3;
|
||||
bool onVram : 1;
|
||||
} C3D_TexInitParams;
|
||||
|
||||
bool C3D_TexInitWithParams(C3D_Tex* tex, C3D_TexCube* cube, C3D_TexInitParams p);
|
||||
void C3D_TexLoadImage(C3D_Tex* tex, const void* data, GPU_TEXFACE face, int level);
|
||||
void C3D_TexGenerateMipmap(C3D_Tex* tex, GPU_TEXFACE face);
|
||||
void C3D_TexBind(int unitId, C3D_Tex* tex);
|
||||
void C3D_TexFlush(C3D_Tex* tex);
|
||||
void C3D_TexDelete(C3D_Tex* tex);
|
||||
|
||||
void C3D_TexShadowParams(bool perspective, float bias);
|
||||
|
||||
static inline int C3D_TexCalcMaxLevel(u32 width, u32 height)
|
||||
{
|
||||
return (31-__builtin_clz(width < height ? width : height)) - 3; // avoid sizes smaller than 8
|
||||
}
|
||||
|
||||
static inline u32 C3D_TexCalcLevelSize(u32 size, int level)
|
||||
{
|
||||
return size >> (2*level);
|
||||
}
|
||||
|
||||
static inline u32 C3D_TexCalcTotalSize(u32 size, int maxLevel)
|
||||
{
|
||||
/*
|
||||
S = s + sr + sr^2 + sr^3 + ... + sr^n
|
||||
Sr = sr + sr^2 + sr^3 + ... + sr^(n+1)
|
||||
S-Sr = s - sr^(n+1)
|
||||
S(1-r) = s(1 - r^(n+1))
|
||||
S = s (1 - r^(n+1)) / (1-r)
|
||||
|
||||
r = 1/4
|
||||
1-r = 3/4
|
||||
|
||||
S = 4s (1 - (1/4)^(n+1)) / 3
|
||||
S = 4s (1 - 1/4^(n+1)) / 3
|
||||
S = (4/3) (s - s/4^(n+1))
|
||||
S = (4/3) (s - s/(1<<(2n+2)))
|
||||
S = (4/3) (s - s>>(2n+2))
|
||||
*/
|
||||
return (size - C3D_TexCalcLevelSize(size,maxLevel+1)) * 4 / 3;
|
||||
}
|
||||
|
||||
static inline bool C3D_TexInit(C3D_Tex* tex, u16 width, u16 height, GPU_TEXCOLOR format)
|
||||
{
|
||||
return C3D_TexInitWithParams(tex, NULL,
|
||||
(C3D_TexInitParams){ width, height, 0, format, GPU_TEX_2D, false });
|
||||
}
|
||||
|
||||
static inline bool C3D_TexInitMipmap(C3D_Tex* tex, u16 width, u16 height, GPU_TEXCOLOR format)
|
||||
{
|
||||
return C3D_TexInitWithParams(tex, NULL,
|
||||
(C3D_TexInitParams){ width, height, (u8)C3D_TexCalcMaxLevel(width, height), format, GPU_TEX_2D, false });
|
||||
}
|
||||
|
||||
static inline bool C3D_TexInitCube(C3D_Tex* tex, C3D_TexCube* cube, u16 width, u16 height, GPU_TEXCOLOR format)
|
||||
{
|
||||
return C3D_TexInitWithParams(tex, cube,
|
||||
(C3D_TexInitParams){ width, height, 0, format, GPU_TEX_CUBE_MAP, false });
|
||||
}
|
||||
|
||||
static inline bool C3D_TexInitVRAM(C3D_Tex* tex, u16 width, u16 height, GPU_TEXCOLOR format)
|
||||
{
|
||||
return C3D_TexInitWithParams(tex, NULL,
|
||||
(C3D_TexInitParams){ width, height, 0, format, GPU_TEX_2D, true });
|
||||
}
|
||||
|
||||
static inline bool C3D_TexInitShadow(C3D_Tex* tex, u16 width, u16 height)
|
||||
{
|
||||
return C3D_TexInitWithParams(tex, NULL,
|
||||
(C3D_TexInitParams){ width, height, 0, GPU_RGBA8, GPU_TEX_SHADOW_2D, true });
|
||||
}
|
||||
|
||||
static inline bool C3D_TexInitShadowCube(C3D_Tex* tex, C3D_TexCube* cube, u16 width, u16 height)
|
||||
{
|
||||
return C3D_TexInitWithParams(tex, cube,
|
||||
(C3D_TexInitParams){ width, height, 0, GPU_RGBA8, GPU_TEX_SHADOW_CUBE, true });
|
||||
}
|
||||
|
||||
static inline GPU_TEXTURE_MODE_PARAM C3D_TexGetType(C3D_Tex* tex)
|
||||
{
|
||||
return (GPU_TEXTURE_MODE_PARAM)((tex->param>>28)&0x7);
|
||||
}
|
||||
|
||||
static inline void* C3D_TexGetImagePtr(C3D_Tex* tex, void* data, int level, u32* size)
|
||||
{
|
||||
if (size) *size = level >= 0 ? C3D_TexCalcLevelSize(tex->size, level) : C3D_TexCalcTotalSize(tex->size, tex->maxLevel);
|
||||
if (!level) return data;
|
||||
return (u8*)data + (level > 0 ? C3D_TexCalcTotalSize(tex->size, level-1) : 0);
|
||||
}
|
||||
|
||||
static inline void* C3D_Tex2DGetImagePtr(C3D_Tex* tex, int level, u32* size)
|
||||
{
|
||||
return C3D_TexGetImagePtr(tex, tex->data, level, size);
|
||||
}
|
||||
|
||||
static inline void* C3D_TexCubeGetImagePtr(C3D_Tex* tex, GPU_TEXFACE face, int level, u32* size)
|
||||
{
|
||||
return C3D_TexGetImagePtr(tex, tex->cube->data[face], level, size);
|
||||
}
|
||||
|
||||
static inline void C3D_TexUpload(C3D_Tex* tex, const void* data)
|
||||
{
|
||||
C3D_TexLoadImage(tex, data, GPU_TEXFACE_2D, 0);
|
||||
}
|
||||
|
||||
static inline void C3D_TexSetFilter(C3D_Tex* tex, GPU_TEXTURE_FILTER_PARAM magFilter, GPU_TEXTURE_FILTER_PARAM minFilter)
|
||||
{
|
||||
tex->param &= ~(GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR));
|
||||
tex->param |= GPU_TEXTURE_MAG_FILTER(magFilter) | GPU_TEXTURE_MIN_FILTER(minFilter);
|
||||
}
|
||||
|
||||
static inline void C3D_TexSetFilterMipmap(C3D_Tex* tex, GPU_TEXTURE_FILTER_PARAM filter)
|
||||
{
|
||||
tex->param &= ~GPU_TEXTURE_MIP_FILTER(GPU_LINEAR);
|
||||
tex->param |= GPU_TEXTURE_MIP_FILTER(filter);
|
||||
}
|
||||
|
||||
static inline void C3D_TexSetWrap(C3D_Tex* tex, GPU_TEXTURE_WRAP_PARAM wrapS, GPU_TEXTURE_WRAP_PARAM wrapT)
|
||||
{
|
||||
tex->param &= ~(GPU_TEXTURE_WRAP_S(3) | GPU_TEXTURE_WRAP_T(3));
|
||||
tex->param |= GPU_TEXTURE_WRAP_S(wrapS) | GPU_TEXTURE_WRAP_T(wrapT);
|
||||
}
|
||||
|
||||
static inline void C3D_TexSetLodBias(C3D_Tex* tex, float lodBias)
|
||||
{
|
||||
int iLodBias = (int)(lodBias*0x100);
|
||||
if (iLodBias > 0xFFF)
|
||||
iLodBias = 0xFFF;
|
||||
else if (iLodBias < -0x1000)
|
||||
iLodBias = -0x1000;
|
||||
tex->lodBias = iLodBias & 0x1FFF;
|
||||
}
|
||||
81
include/c3d/types.h
Normal file
81
include/c3d/types.h
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
#pragma once
|
||||
#if defined(__3DS__) || defined(_3DS)
|
||||
#include <3ds.h>
|
||||
#else
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
typedef uint8_t u8;
|
||||
typedef uint32_t u32;
|
||||
#endif
|
||||
|
||||
#ifndef CITRO3D_NO_DEPRECATION
|
||||
#define C3D_DEPRECATED __attribute__ ((deprecated))
|
||||
#else
|
||||
#define C3D_DEPRECATED
|
||||
#endif
|
||||
|
||||
typedef u32 C3D_IVec;
|
||||
|
||||
static inline C3D_IVec IVec_Pack(u8 x, u8 y, u8 z, u8 w)
|
||||
{
|
||||
return (u32)x | ((u32)y << 8) | ((u32)z << 16) | ((u32)w << 24);
|
||||
}
|
||||
|
||||
/**
|
||||
* @defgroup math_support Math Support Library
|
||||
* @brief Implementations of matrix, vector, and quaternion operations.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @struct C3D_FVec
|
||||
* @brief Float vector
|
||||
*
|
||||
* Matches PICA layout
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
/**
|
||||
* @brief Vector access
|
||||
*/
|
||||
struct
|
||||
{
|
||||
float w; ///< W-component
|
||||
float z; ///< Z-component
|
||||
float y; ///< Y-component
|
||||
float x; ///< X-component
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Quaternion access
|
||||
*/
|
||||
struct
|
||||
{
|
||||
float r; ///< Real component
|
||||
float k; ///< K-component
|
||||
float j; ///< J-component
|
||||
float i; ///< I-component
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Raw access
|
||||
*/
|
||||
float c[4];
|
||||
} C3D_FVec;
|
||||
|
||||
/**
|
||||
* @struct C3D_FQuat
|
||||
* @brief Float quaternion. See @ref C3D_FVec.
|
||||
*/
|
||||
typedef C3D_FVec C3D_FQuat;
|
||||
|
||||
/**
|
||||
* @struct C3D_Mtx
|
||||
* @brief Row-major 4x4 matrix
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
C3D_FVec r[4]; ///< Rows are vectors
|
||||
float m[4*4]; ///< Raw access
|
||||
} C3D_Mtx;
|
||||
/** @} */
|
||||
78
include/c3d/uniforms.h
Normal file
78
include/c3d/uniforms.h
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
#pragma once
|
||||
#include "maths.h"
|
||||
|
||||
#define C3D_FVUNIF_COUNT 96
|
||||
#define C3D_IVUNIF_COUNT 4
|
||||
|
||||
extern C3D_FVec C3D_FVUnif[2][C3D_FVUNIF_COUNT];
|
||||
extern C3D_IVec C3D_IVUnif[2][C3D_IVUNIF_COUNT];
|
||||
extern u16 C3D_BoolUnifs[2];
|
||||
|
||||
extern bool C3D_FVUnifDirty[2][C3D_FVUNIF_COUNT];
|
||||
extern bool C3D_IVUnifDirty[2][C3D_IVUNIF_COUNT];
|
||||
extern bool C3D_BoolUnifsDirty[2];
|
||||
|
||||
static inline C3D_FVec* C3D_FVUnifWritePtr(GPU_SHADER_TYPE type, int id, int size)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < size; i ++)
|
||||
C3D_FVUnifDirty[type][id+i] = true;
|
||||
return &C3D_FVUnif[type][id];
|
||||
}
|
||||
|
||||
static inline C3D_IVec* C3D_IVUnifWritePtr(GPU_SHADER_TYPE type, int id)
|
||||
{
|
||||
id -= 0x60;
|
||||
C3D_IVUnifDirty[type][id] = true;
|
||||
return &C3D_IVUnif[type][id];
|
||||
}
|
||||
|
||||
static inline void C3D_FVUnifMtxNx4(GPU_SHADER_TYPE type, int id, const C3D_Mtx* mtx, int num)
|
||||
{
|
||||
int i;
|
||||
C3D_FVec* ptr = C3D_FVUnifWritePtr(type, id, num);
|
||||
for (i = 0; i < num; i ++)
|
||||
ptr[i] = mtx->r[i]; // Struct copy.
|
||||
}
|
||||
|
||||
static inline void C3D_FVUnifMtx4x4(GPU_SHADER_TYPE type, int id, const C3D_Mtx* mtx)
|
||||
{
|
||||
C3D_FVUnifMtxNx4(type, id, mtx, 4);
|
||||
}
|
||||
|
||||
static inline void C3D_FVUnifMtx3x4(GPU_SHADER_TYPE type, int id, const C3D_Mtx* mtx)
|
||||
{
|
||||
C3D_FVUnifMtxNx4(type, id, mtx, 3);
|
||||
}
|
||||
|
||||
static inline void C3D_FVUnifMtx2x4(GPU_SHADER_TYPE type, int id, const C3D_Mtx* mtx)
|
||||
{
|
||||
C3D_FVUnifMtxNx4(type, id, mtx, 2);
|
||||
}
|
||||
|
||||
static inline void C3D_FVUnifSet(GPU_SHADER_TYPE type, int id, float x, float y, float z, float w)
|
||||
{
|
||||
C3D_FVec* ptr = C3D_FVUnifWritePtr(type, id, 1);
|
||||
ptr->x = x;
|
||||
ptr->y = y;
|
||||
ptr->z = z;
|
||||
ptr->w = w;
|
||||
}
|
||||
|
||||
static inline void C3D_IVUnifSet(GPU_SHADER_TYPE type, int id, int x, int y, int z, int w)
|
||||
{
|
||||
C3D_IVec* ptr = C3D_IVUnifWritePtr(type, id);
|
||||
*ptr = IVec_Pack(x, y, z, w);
|
||||
}
|
||||
|
||||
static inline void C3D_BoolUnifSet(GPU_SHADER_TYPE type, int id, bool value)
|
||||
{
|
||||
id -= 0x68;
|
||||
C3D_BoolUnifsDirty[type] = true;
|
||||
if (value)
|
||||
C3D_BoolUnifs[type] |= BIT(id);
|
||||
else
|
||||
C3D_BoolUnifs[type] &= ~BIT(id);
|
||||
}
|
||||
|
||||
void C3D_UpdateUniforms(GPU_SHADER_TYPE type);
|
||||
Loading…
Add table
Add a link
Reference in a new issue