Rotation
This commit is contained in:
@@ -23,14 +23,16 @@
|
||||
|
||||
engine_t ENGINE;
|
||||
texture_t TEXTURE;
|
||||
#pragma pack(push, 1)
|
||||
color_t TEXTURE_COLORS[] = {
|
||||
COLOR_RED, COLOR_GREEN, COLOR_MAGENTA, COLOR_CYAN,
|
||||
COLOR_BLUE, COLOR_WHITE, COLOR_YELLOW, COLOR_BLACK,
|
||||
COLOR_CYAN, COLOR_MAGENTA, COLOR_GREEN, COLOR_RED,
|
||||
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) {
|
||||
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);
|
||||
|
||||
entityid_t ent1 = entityManagerAdd();
|
||||
componentid_t ent1Pos = entityAddComponent(ent1, COMPONENT_TYPE_POSITION);
|
||||
componentid_t ent1Mesh = entityAddComponent(ent1, COMPONENT_TYPE_MESH);
|
||||
componentid_t ent1Mat = entityAddComponent(ent1, COMPONENT_TYPE_MATERIAL);
|
||||
ent1 = entityManagerAdd();
|
||||
ent1Pos = entityAddComponent(ent1, COMPONENT_TYPE_POSITION);
|
||||
ent1Mesh = entityAddComponent(ent1, COMPONENT_TYPE_MESH);
|
||||
ent1Mat = entityAddComponent(ent1, COMPONENT_TYPE_MATERIAL);
|
||||
|
||||
textureInit(&TEXTURE, 4, 4, TEXTURE_FORMAT_RGBA, (texturedata_t){
|
||||
.rgbaColors = TEXTURE_COLORS
|
||||
@@ -80,8 +82,7 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) {
|
||||
));
|
||||
|
||||
shadermaterial_t *mat = entityMaterialGetShaderMaterial(ent1, ent1Mat);
|
||||
// mat->unlit.color = COLOR_WHITE;
|
||||
mat->unlit.color = COLOR_RED;
|
||||
mat->unlit.color = COLOR_WHITE;
|
||||
mat->unlit.texture = &TEXTURE;
|
||||
|
||||
// EOF
|
||||
@@ -99,6 +100,11 @@ errorret_t engineUpdate(void) {
|
||||
timeUpdate();
|
||||
inputUpdate();
|
||||
|
||||
vec3 rotation;
|
||||
entityPositionGetRotation(ent1, ent1Pos, rotation);
|
||||
rotation[1] += 0.01f;
|
||||
entityPositionSetRotation(ent1, ent1Pos, rotation);
|
||||
|
||||
uiUpdate();
|
||||
errorChain(sceneUpdate());
|
||||
errorChain(gameUpdate());
|
||||
|
||||
@@ -15,6 +15,9 @@ void entityPositionInit(
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -29,6 +32,7 @@ void entityPositionLookAt(
|
||||
entityId, componentId, COMPONENT_TYPE_POSITION
|
||||
);
|
||||
glm_lookat(eye, target, up, pos->transform);
|
||||
entityPositionDecompose(pos);
|
||||
}
|
||||
|
||||
void entityPositionGetTransform(
|
||||
@@ -40,4 +44,141 @@ void entityPositionGetTransform(
|
||||
entityId, componentId, COMPONENT_TYPE_POSITION
|
||||
);
|
||||
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 {
|
||||
mat4 transform;
|
||||
vec3 position;
|
||||
vec3 rotation;
|
||||
vec3 scale;
|
||||
} entityposition_t;
|
||||
|
||||
/**
|
||||
@@ -42,7 +45,7 @@ void entityPositionLookAt(
|
||||
|
||||
/**
|
||||
* Gets the transform matrix of the entity position component.
|
||||
*
|
||||
*
|
||||
* @param entityId The entity ID.
|
||||
* @param componentId The component ID.
|
||||
* @param dest The destination matrix to write the transform to.
|
||||
@@ -51,4 +54,97 @@ void entityPositionGetTransform(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
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