Rotation
This commit is contained in:
@@ -23,14 +23,16 @@
|
|||||||
|
|
||||||
engine_t ENGINE;
|
engine_t ENGINE;
|
||||||
texture_t TEXTURE;
|
texture_t TEXTURE;
|
||||||
#pragma pack(push, 1)
|
|
||||||
color_t TEXTURE_COLORS[] = {
|
color_t TEXTURE_COLORS[] = {
|
||||||
COLOR_RED, COLOR_GREEN, COLOR_MAGENTA, COLOR_CYAN,
|
COLOR_RED, COLOR_GREEN, COLOR_MAGENTA, COLOR_CYAN,
|
||||||
COLOR_BLUE, COLOR_WHITE, COLOR_YELLOW, COLOR_BLACK,
|
COLOR_BLUE, COLOR_WHITE, COLOR_YELLOW, COLOR_BLACK,
|
||||||
COLOR_CYAN, COLOR_MAGENTA, COLOR_GREEN, COLOR_RED,
|
COLOR_CYAN, COLOR_MAGENTA, COLOR_GREEN, COLOR_RED,
|
||||||
COLOR_WHITE, COLOR_BLUE, COLOR_BLACK, COLOR_YELLOW
|
COLOR_WHITE, COLOR_BLUE, COLOR_BLACK, COLOR_YELLOW
|
||||||
};
|
};
|
||||||
#pragma pack(pop)
|
entityid_t ent1;
|
||||||
|
componentid_t ent1Pos;
|
||||||
|
componentid_t ent1Mesh;
|
||||||
|
componentid_t ent1Mat;
|
||||||
|
|
||||||
errorret_t engineInit(const int32_t argc, const char_t **argv) {
|
errorret_t engineInit(const int32_t argc, const char_t **argv) {
|
||||||
memoryZero(&ENGINE, sizeof(engine_t));
|
memoryZero(&ENGINE, sizeof(engine_t));
|
||||||
@@ -62,10 +64,10 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) {
|
|||||||
);
|
);
|
||||||
componentid_t camCam = entityAddComponent(cam, COMPONENT_TYPE_CAMERA);
|
componentid_t camCam = entityAddComponent(cam, COMPONENT_TYPE_CAMERA);
|
||||||
|
|
||||||
entityid_t ent1 = entityManagerAdd();
|
ent1 = entityManagerAdd();
|
||||||
componentid_t ent1Pos = entityAddComponent(ent1, COMPONENT_TYPE_POSITION);
|
ent1Pos = entityAddComponent(ent1, COMPONENT_TYPE_POSITION);
|
||||||
componentid_t ent1Mesh = entityAddComponent(ent1, COMPONENT_TYPE_MESH);
|
ent1Mesh = entityAddComponent(ent1, COMPONENT_TYPE_MESH);
|
||||||
componentid_t ent1Mat = entityAddComponent(ent1, COMPONENT_TYPE_MATERIAL);
|
ent1Mat = entityAddComponent(ent1, COMPONENT_TYPE_MATERIAL);
|
||||||
|
|
||||||
textureInit(&TEXTURE, 4, 4, TEXTURE_FORMAT_RGBA, (texturedata_t){
|
textureInit(&TEXTURE, 4, 4, TEXTURE_FORMAT_RGBA, (texturedata_t){
|
||||||
.rgbaColors = TEXTURE_COLORS
|
.rgbaColors = TEXTURE_COLORS
|
||||||
@@ -80,8 +82,7 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) {
|
|||||||
));
|
));
|
||||||
|
|
||||||
shadermaterial_t *mat = entityMaterialGetShaderMaterial(ent1, ent1Mat);
|
shadermaterial_t *mat = entityMaterialGetShaderMaterial(ent1, ent1Mat);
|
||||||
// mat->unlit.color = COLOR_WHITE;
|
mat->unlit.color = COLOR_WHITE;
|
||||||
mat->unlit.color = COLOR_RED;
|
|
||||||
mat->unlit.texture = &TEXTURE;
|
mat->unlit.texture = &TEXTURE;
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
@@ -99,6 +100,11 @@ errorret_t engineUpdate(void) {
|
|||||||
timeUpdate();
|
timeUpdate();
|
||||||
inputUpdate();
|
inputUpdate();
|
||||||
|
|
||||||
|
vec3 rotation;
|
||||||
|
entityPositionGetRotation(ent1, ent1Pos, rotation);
|
||||||
|
rotation[1] += 0.01f;
|
||||||
|
entityPositionSetRotation(ent1, ent1Pos, rotation);
|
||||||
|
|
||||||
uiUpdate();
|
uiUpdate();
|
||||||
errorChain(sceneUpdate());
|
errorChain(sceneUpdate());
|
||||||
errorChain(gameUpdate());
|
errorChain(gameUpdate());
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ void entityPositionInit(
|
|||||||
entityId, componentId, COMPONENT_TYPE_POSITION
|
entityId, componentId, COMPONENT_TYPE_POSITION
|
||||||
);
|
);
|
||||||
|
|
||||||
|
glm_vec3_zero(pos->position);
|
||||||
|
glm_vec3_zero(pos->rotation);
|
||||||
|
glm_vec3_one(pos->scale);
|
||||||
glm_mat4_identity(pos->transform);
|
glm_mat4_identity(pos->transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,6 +32,7 @@ void entityPositionLookAt(
|
|||||||
entityId, componentId, COMPONENT_TYPE_POSITION
|
entityId, componentId, COMPONENT_TYPE_POSITION
|
||||||
);
|
);
|
||||||
glm_lookat(eye, target, up, pos->transform);
|
glm_lookat(eye, target, up, pos->transform);
|
||||||
|
entityPositionDecompose(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void entityPositionGetTransform(
|
void entityPositionGetTransform(
|
||||||
@@ -41,3 +45,140 @@ void entityPositionGetTransform(
|
|||||||
);
|
);
|
||||||
glm_mat4_copy(pos->transform, dest);
|
glm_mat4_copy(pos->transform, dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void entityPositionGetPosition(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId,
|
||||||
|
vec3 dest
|
||||||
|
) {
|
||||||
|
entityposition_t *pos = componentGetData(
|
||||||
|
entityId, componentId, COMPONENT_TYPE_POSITION
|
||||||
|
);
|
||||||
|
glm_vec3_copy(pos->position, dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
void entityPositionSetPosition(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId,
|
||||||
|
vec3 position
|
||||||
|
) {
|
||||||
|
entityposition_t *pos = componentGetData(
|
||||||
|
entityId, componentId, COMPONENT_TYPE_POSITION
|
||||||
|
);
|
||||||
|
glm_vec3_copy(position, pos->position);
|
||||||
|
entityPositionRebuild(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void entityPositionGetRotation(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId,
|
||||||
|
vec3 dest
|
||||||
|
) {
|
||||||
|
entityposition_t *pos = componentGetData(
|
||||||
|
entityId, componentId, COMPONENT_TYPE_POSITION
|
||||||
|
);
|
||||||
|
glm_vec3_copy(pos->rotation, dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
void entityPositionSetRotation(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId,
|
||||||
|
vec3 rotation
|
||||||
|
) {
|
||||||
|
entityposition_t *pos = componentGetData(
|
||||||
|
entityId, componentId, COMPONENT_TYPE_POSITION
|
||||||
|
);
|
||||||
|
glm_vec3_copy(rotation, pos->rotation);
|
||||||
|
entityPositionRebuild(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void entityPositionGetScale(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId,
|
||||||
|
vec3 dest
|
||||||
|
) {
|
||||||
|
entityposition_t *pos = componentGetData(
|
||||||
|
entityId, componentId, COMPONENT_TYPE_POSITION
|
||||||
|
);
|
||||||
|
glm_vec3_copy(pos->scale, dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
void entityPositionSetScale(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId,
|
||||||
|
vec3 scale
|
||||||
|
) {
|
||||||
|
entityposition_t *pos = componentGetData(
|
||||||
|
entityId, componentId, COMPONENT_TYPE_POSITION
|
||||||
|
);
|
||||||
|
glm_vec3_copy(scale, pos->scale);
|
||||||
|
entityPositionRebuild(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
void entityPositionRebuild(entityposition_t *pos) {
|
||||||
|
glm_mat4_identity(pos->transform);
|
||||||
|
glm_translate(pos->transform, pos->position);
|
||||||
|
glm_rotate_x(pos->transform, pos->rotation[0], pos->transform);
|
||||||
|
glm_rotate_y(pos->transform, pos->rotation[1], pos->transform);
|
||||||
|
glm_rotate_z(pos->transform, pos->rotation[2], pos->transform);
|
||||||
|
glm_scale(pos->transform, pos->scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
void entityPositionDecompose(entityposition_t *pos) {
|
||||||
|
// Translation: column 3
|
||||||
|
pos->position[0] = pos->transform[3][0];
|
||||||
|
pos->position[1] = pos->transform[3][1];
|
||||||
|
pos->position[2] = pos->transform[3][2];
|
||||||
|
|
||||||
|
// Scale: length of each basis column (xyz only)
|
||||||
|
pos->scale[0] = sqrtf(
|
||||||
|
pos->transform[0][0] * pos->transform[0][0] +
|
||||||
|
pos->transform[0][1] * pos->transform[0][1] +
|
||||||
|
pos->transform[0][2] * pos->transform[0][2]
|
||||||
|
);
|
||||||
|
pos->scale[1] = sqrtf(
|
||||||
|
pos->transform[1][0] * pos->transform[1][0] +
|
||||||
|
pos->transform[1][1] * pos->transform[1][1] +
|
||||||
|
pos->transform[1][2] * pos->transform[1][2]
|
||||||
|
);
|
||||||
|
pos->scale[2] = sqrtf(
|
||||||
|
pos->transform[2][0] * pos->transform[2][0] +
|
||||||
|
pos->transform[2][1] * pos->transform[2][1] +
|
||||||
|
pos->transform[2][2] * pos->transform[2][2]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Normalize columns to isolate the rotation matrix
|
||||||
|
float invS0 = pos->scale[0] > 0.0f ? 1.0f / pos->scale[0] : 0.0f;
|
||||||
|
float invS1 = pos->scale[1] > 0.0f ? 1.0f / pos->scale[1] : 0.0f;
|
||||||
|
float invS2 = pos->scale[2] > 0.0f ? 1.0f / pos->scale[2] : 0.0f;
|
||||||
|
|
||||||
|
mat4 r;
|
||||||
|
glm_mat4_identity(r);
|
||||||
|
r[0][0] = pos->transform[0][0] * invS0;
|
||||||
|
r[0][1] = pos->transform[0][1] * invS0;
|
||||||
|
r[0][2] = pos->transform[0][2] * invS0;
|
||||||
|
r[1][0] = pos->transform[1][0] * invS1;
|
||||||
|
r[1][1] = pos->transform[1][1] * invS1;
|
||||||
|
r[1][2] = pos->transform[1][2] * invS1;
|
||||||
|
r[2][0] = pos->transform[2][0] * invS2;
|
||||||
|
r[2][1] = pos->transform[2][1] * invS2;
|
||||||
|
r[2][2] = pos->transform[2][2] * invS2;
|
||||||
|
|
||||||
|
// Extract XYZ euler angles (R = Rx * Ry * Rz, column-major)
|
||||||
|
// r[2][0] = sin(Y), r[2][1] = -sin(X)*cos(Y), r[2][2] = cos(X)*cos(Y)
|
||||||
|
// r[0][0] = cos(Y)*cos(Z), r[1][0] = -cos(Y)*sin(Z)
|
||||||
|
float sinBeta = glm_clamp(r[2][0], -1.0f, 1.0f);
|
||||||
|
pos->rotation[1] = asinf(sinBeta);
|
||||||
|
float cosBeta = cosf(pos->rotation[1]);
|
||||||
|
|
||||||
|
if (fabsf(cosBeta) > 1e-6f) {
|
||||||
|
pos->rotation[0] = atan2f(-r[2][1], r[2][2]);
|
||||||
|
pos->rotation[2] = atan2f(-r[1][0], r[0][0]);
|
||||||
|
} else {
|
||||||
|
// Gimbal lock: pin Z to 0, recover X from the remaining degree of freedom
|
||||||
|
pos->rotation[2] = 0.0f;
|
||||||
|
pos->rotation[0] = (sinBeta > 0.0f)
|
||||||
|
? atan2f(r[0][1], r[1][1])
|
||||||
|
: -atan2f(r[0][1], r[1][1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,9 @@
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
mat4 transform;
|
mat4 transform;
|
||||||
|
vec3 position;
|
||||||
|
vec3 rotation;
|
||||||
|
vec3 scale;
|
||||||
} entityposition_t;
|
} entityposition_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,3 +55,96 @@ void entityPositionGetTransform(
|
|||||||
const componentid_t componentId,
|
const componentid_t componentId,
|
||||||
mat4 dest
|
mat4 dest
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the cached position of the entity.
|
||||||
|
*
|
||||||
|
* @param entityId The entity ID.
|
||||||
|
* @param componentId The component ID.
|
||||||
|
* @param dest The destination vec3 to write the position to.
|
||||||
|
*/
|
||||||
|
void entityPositionGetPosition(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId,
|
||||||
|
vec3 dest
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the position of the entity and rebuilds the transform matrix.
|
||||||
|
*
|
||||||
|
* @param entityId The entity ID.
|
||||||
|
* @param componentId The component ID.
|
||||||
|
* @param position The new position.
|
||||||
|
*/
|
||||||
|
void entityPositionSetPosition(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId,
|
||||||
|
vec3 position
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the cached euler rotation (XYZ, radians) of the entity.
|
||||||
|
*
|
||||||
|
* @param entityId The entity ID.
|
||||||
|
* @param componentId The component ID.
|
||||||
|
* @param dest The destination vec3 to write the rotation to.
|
||||||
|
*/
|
||||||
|
void entityPositionGetRotation(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId,
|
||||||
|
vec3 dest
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the euler rotation (XYZ, radians) of the entity and rebuilds the
|
||||||
|
* transform matrix.
|
||||||
|
*
|
||||||
|
* @param entityId The entity ID.
|
||||||
|
* @param componentId The component ID.
|
||||||
|
* @param rotation The new euler rotation in radians.
|
||||||
|
*/
|
||||||
|
void entityPositionSetRotation(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId,
|
||||||
|
vec3 rotation
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the cached scale of the entity.
|
||||||
|
*
|
||||||
|
* @param entityId The entity ID.
|
||||||
|
* @param componentId The component ID.
|
||||||
|
* @param dest The destination vec3 to write the scale to.
|
||||||
|
*/
|
||||||
|
void entityPositionGetScale(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId,
|
||||||
|
vec3 dest
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the scale of the entity and rebuilds the transform matrix.
|
||||||
|
*
|
||||||
|
* @param entityId The entity ID.
|
||||||
|
* @param componentId The component ID.
|
||||||
|
* @param scale The new scale.
|
||||||
|
*/
|
||||||
|
void entityPositionSetScale(
|
||||||
|
const entityid_t entityId,
|
||||||
|
const componentid_t componentId,
|
||||||
|
vec3 scale
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal function to rebuild the transform matrix of the entity position
|
||||||
|
* component based on the current position, rotation, and scale.
|
||||||
|
*/
|
||||||
|
void entityPositionRebuild(entityposition_t *pos);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decomposes the transform matrix back into the position, rotation (XYZ euler,
|
||||||
|
* radians), and scale cache fields. Call after any direct matrix modification.
|
||||||
|
*
|
||||||
|
* @param pos Pointer to the entity position component data.
|
||||||
|
*/
|
||||||
|
void entityPositionDecompose(entityposition_t *pos);
|
||||||
Reference in New Issue
Block a user