Backlog/engine/graphics/src/render_objects.zig

317 lines
9.9 KiB
Zig

const std = @import("std");
const vk = @import("vulkan");
const resources = @import("resources");
const core = @import("core");
const VkConstants = @import("vk_constants.zig");
const graphics = @import("graphics.zig");
const meshes = @import("mesh.zig");
const NeonVkContext = @import("vk_renderer.zig").NeonVkContext;
const materials = @import("materials.zig");
const animationSystem = @import("animation/animationSystem.zig");
const Animator = animationSystem.Animator;
const Material = materials.Material;
const EulerAngles = core.EulerAngles;
const Mat = core.Mat;
const Vectorf = core.Vectorf;
const Quat = core.Quat;
const zm = core.zm;
const mul = zm.mul;
const Mesh = meshes.Mesh;
const mesh_pool = @import("vk_renderer/vk_mesh_pool.zig");
const IndexedMesh = mesh_pool.IndexedMesh;
// lol we need to rename this thing again, it should be called RenderMesh
pub const StaticMeshSet = core.SparseSet(StaticMesh);
pub const StaticMesh = struct {
const Self = @This();
mesh: ?IndexedMesh = null,
// texture: ?vk.DescriptorSet = null,
textureId: ?u32 = null,
transform: core.Mat = core.zm.translation(0, 0, 0),
visibility: bool = true,
// new position and rotator based api
position: Vectorf = .{},
rotation: Quat = .{ 0, 0, 0, 1 },
scale: Vectorf = .{ .x = 1, .y = 1, .z = 1 },
textureName: core.Name = core.NameInvalid,
meshName: core.Name = core.NameInvalid,
animated: bool = false, // todo remove
animator: ?*Animator = null,
flags: Flags0 = .{},
pub var BaseContainer: *StaticMeshSet = undefined;
pub const ComponentName = "StaticMesh";
pub const ScriptExports: []const []const u8 = &.{
"applyRelativeRotationX",
"applyRelativeRotationY",
"applyRelativeRotationZ",
"setMesh",
"setTextureByName",
};
pub const Flags0 = packed struct(u32) {
alwaysInFront: bool = false,
useAltFov: bool = false,
_pad: u30 = 0,
};
pub fn setMeshByName(self: *@This(), meshName: core.Name) void {
self.meshName = meshName;
}
// script function
pub fn setMesh(self: *@This(), meshName: []const u8) void {
const name = core.MakeName(meshName);
self.mesh = graphics.getIndexedMeshByName(core.MakeName(meshName));
self.meshName = name;
}
pub fn fromTransform(transform: core.Mat) Self {
var self = Self{
.mesh = null,
.transform = transform,
.position = undefined,
.rotation = undefined,
.scale = undefined,
};
self.updateScalars();
return self;
}
pub fn setTexture(self: *Self, textureName: []const u8) void {
var name = core.MakeName(textureName);
self.textureId = graphics.getContext().textureIds.get(name.handle());
self.textureName = name;
}
pub fn setTextureByName(self: *Self, _name: core.Name) void {
var name = _name;
self.textureId = graphics.getContext().textureIds.get(name.handle());
self.textureName = name;
}
pub fn updateTexture(self: *@This(), gc: *NeonVkContext) void {
self.textureId = gc.textureIds.get(self.textureName.handle());
}
pub fn applyTransform(self: *StaticMesh, transform: core.Mat) void {
self.transform = core.zm.mul(self.transform, transform);
self.updateScalars();
}
pub fn applyRelativeRotationX(self: *StaticMesh, angle: f32) void {
var imat = core.zm.identity();
imat[0][3] = -self.transform[0][3];
imat[1][3] = -self.transform[1][3];
imat[2][3] = -self.transform[2][3];
const rmat = core.zm.identity();
imat[0][3] = self.transform[0][3];
imat[1][3] = self.transform[1][3];
imat[2][3] = self.transform[2][3];
var newTransform = core.zm.mul(imat, self.transform);
newTransform = core.zm.mul(core.zm.rotationX(angle), newTransform);
newTransform = core.zm.mul(rmat, newTransform);
self.transform = newTransform;
}
pub fn applyRelativeRotationZ(self: *StaticMesh, angle: f32) void {
var imat = core.zm.identity();
imat[0][3] = -self.transform[0][3];
imat[1][3] = -self.transform[1][3];
imat[2][3] = -self.transform[2][3];
const rmat = core.zm.identity();
imat[0][3] = self.transform[0][3];
imat[1][3] = self.transform[1][3];
imat[2][3] = self.transform[2][3];
var newTransform = core.zm.mul(imat, self.transform);
newTransform = core.zm.mul(core.zm.rotationZ(angle), newTransform);
newTransform = core.zm.mul(rmat, newTransform);
self.transform = newTransform;
}
pub fn applyRelativeRotationY(self: *StaticMesh, angle: f32) void {
var imat = core.zm.identity();
imat[0][3] = -self.transform[0][3];
imat[1][3] = -self.transform[1][3];
imat[2][3] = -self.transform[2][3];
const rmat = core.zm.identity();
imat[0][3] = self.transform[0][3];
imat[1][3] = self.transform[1][3];
imat[2][3] = self.transform[2][3];
var newTransform = core.zm.mul(imat, self.transform);
newTransform = core.zm.mul(core.zm.rotationY(angle), newTransform);
newTransform = core.zm.mul(rmat, newTransform);
self.transform = newTransform;
}
pub fn updateScalars(self: *StaticMesh) void {
self.position = Vectorf.fromZm(mul(self.transform, Vectorf.new(0.0, 0.0, 0.0).toZm()));
self.rotation = zm.matToQuat(self.transform);
self.scale = core.matToScalef(self.transform);
}
pub fn applyScalars(self: *StaticMesh) void {
var newTransform = core.zm.mul(
core.zm.scalingV(self.scale.toZm()),
core.zm.matFromQuat(self.rotation),
);
newTransform = core.zm.mul(
newTransform,
core.zm.translationV(self.position.toZm()),
);
self.transform = newTransform;
}
pub fn initECS(self: *@This(), handle: core.ObjectHandle) void {
const entity = core.Entity.fromHandle(handle);
if (entity.get(core.Scene)) |scene| {
self.position = scene.getPosition();
self.rotation = scene.getRotation().quat;
self.scale = scene.getScaleV();
} else {
_ = entity.addComponent(core.Scene);
}
}
};
fn makePerspective(fov: f32, aspect: f32, near: f32, far: f32) Mat {
const proj = core.zm.perspectiveFovRh(
core.radians(fov),
aspect,
near,
far,
);
// proj[1][1] *= -1;
return proj;
}
// Camera coordinate system:
//
// from you as a user, staring at the screen:
//
// This is a right handed coordinate system
//
// forward = +Z (index finger)
// left = +X (middle finger)
// up = +Y (thumb)
const ecs = core.ecs;
pub const Camera = struct {
fov: f32 = 70.0,
altFov: f32 = 70.0,
aspect: f32 = 16.0 / 9.0,
near_clipping: f32 = 0.1,
far_clipping: f32 = 10000.0,
position: Vectorf = Vectorf{ .x = 0.0, .y = 0.0, .z = 0.0 },
rotation: Quat, // todo, remove, we only work with euler tracks now for camera.
// applied in that order,
yaw: f32 = 0,
pitch: f32 = 0,
roll: f32 = 0,
transform: core.Transform = zm.identity(),
worldTransform: Mat = zm.identity(),
projection: Mat = makePerspective(
core.radians(70.0), // angle
16.0 / 9.0,
0.1,
200000,
),
projectionAlt: Mat = makePerspective(
core.radians(70.0), // angle
16.0 / 9.0,
0.0001,
1000,
),
final: Mat = zm.identity(),
finalAlt: Mat = zm.identity(),
pub const EcsComponentDefinition = ecs.DefineComponent(@This(), .set); // set, map, multiset, maplist
pub fn init() Camera {
return .{
.rotation = zm.quatFromRollPitchYaw(0.0, 0.0, 0.0),
};
}
pub fn translate(self: *Camera, offset: core.Vectorf) void {
var off: core.Vectorf = offset;
off.y = offset.y;
off.x = offset.x;
off.z = offset.z;
self.*.position = self.position.add(off);
}
pub fn getRotation(self: *Camera) Quat {
return zm.quatFromMat(self.transform);
}
pub fn setRotationEuler(self: *@This(), x: f32, y: f32, z: f32) void {
self.rotation = core.zm.quatFromRollPitchYaw(x, y + core.radians(180.0), z);
}
pub fn updateCamera(self: *Camera) void {
self.projection = zm.perspectiveFovRh(core.radians(self.fov), 16.0 / 9.0, 0.1, 200000);
self.projection[1][1] *= -1;
self.projectionAlt = zm.perspectiveFovRh(core.radians(self.altFov), 16.0 / 9.0, 0.01, 200000);
self.projectionAlt[1][1] *= -1;
// self.projectionAlt = self.projection;
}
pub fn resolve(self: *Camera) void {
{
var base = core.zm.identity();
base = mul(core.zm.rotationY(-self.yaw), base);
base = mul(core.zm.rotationX(self.pitch), base);
base = mul(core.zm.rotationZ(self.roll), base);
const pr2 = core.scene.SceneObjectPosRot{
.position = self.position,
};
self.worldTransform = mul(base, pr2.toTransform());
}
// calculate viewProjections
{
var base = core.zm.rotationY(self.yaw + core.radians(180.0));
base = mul(base, core.zm.rotationX(self.pitch));
base = mul(base, core.zm.rotationZ(self.roll));
self.transform = base;
// self.transform = mul(
// base,
// mul(zm.matFromQuat(self.rotation), zm.rotationY(core.radians(180.0))),
// );
var position = self.position;
// position.x *= -1;
// position.z *= -1;
self.transform = mul(zm.translationV(position.fmul(-1).toZm()), self.transform);
self.final = mul(self.transform, self.projection);
self.finalAlt = mul(self.transform, self.projectionAlt);
}
}
};