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); } } };