diff options
| author | Nguyễn Gia Phong <cnx@loang.net> | 2023-11-18 21:40:15 +0900 |
|---|---|---|
| committer | Nguyễn Gia Phong <cnx@loang.net> | 2023-11-18 21:40:15 +0900 |
| commit | ae0810b2d4cdd31cd05f5746c6411da9d458eead (patch) | |
| tree | a827fbe10c12a4a4665b98144f32e767ba5a3553 /src/model.zig | |
| parent | 371906f5fb958691a8bfce85c28eb4dfaf63559c (diff) | |
| download | blackshades-ae0810b2d4cdd31cd05f5746c6411da9d458eead.tar.gz | |
Convert model geometry to Zig
Diffstat (limited to 'src/model.zig')
| -rw-r--r-- | src/model.zig | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/src/model.zig b/src/model.zig new file mode 100644 index 0000000..274176d --- /dev/null +++ b/src/model.zig @@ -0,0 +1,90 @@ +// 3D model +// Copyright (C) 2002 David Rosen +// Copyright (C) 2023 Nguyễn Gia Phong +// +// This file is part of Black Shades. +// +// Black Shades is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Black Shades is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Black Shades. If not, see <https://www.gnu.org/licenses/>. + +const XYZ = geom.XYZ; +const degToRad = std.math.degreesToRadians; +const floatMax = std.math.floatMax; +const geom = @import("geom.zig"); +const rotate2d = geom.rotate2d; +const segCrossSphere = geom.segCrossSphere; +const segCrossTrigon = geom.segCrossTrigon; +const sqr = geom.sqr; +const std = @import("std"); + +const max_trigons = 400; + +const Trigon = extern struct { + vertices: [3]u32, + r: f32, + g: f32, + b: f32, +}; + +pub const Model = extern struct { + vertices: [max_trigons * 3]XYZ, + vertices_len: u32, + normals: [max_trigons]XYZ, + trigons: [max_trigons]Trigon, + trigons_len: u32, + center: XYZ, + radius: f32, + vert_array: [max_trigons * 27]f32, +}; + +pub export fn segCrossModel(start: XYZ, end: XYZ, m: *const Model, + intersection: *XYZ) c_int { + if (!segCrossSphere(start, end, m.center, m.radius)) + return -1; + const p: @Vector(3, f32) = @bitCast(start); + var result: c_int = -1; + var shortest = floatMax(f32); + for (0..m.trigons_len) |j| { + var v: @Vector(3, f32) = undefined; + if (!segCrossTrigon(start, end, + &m.vertices[m.trigons[j].vertices[0]], + &m.vertices[m.trigons[j].vertices[1]], + &m.vertices[m.trigons[j].vertices[2]], + &m.normals[j], @ptrCast(&v))) + continue; + const distance = @reduce(.Add, sqr(v - p)); + if (distance < shortest or result == -1) { + shortest = distance; + result = @intCast(j); + intersection.* = @bitCast(v); + } + } + return result; +} + +pub export fn segCrossModelTrans(start: XYZ, end: XYZ, m: *const Model, + move: XYZ, rot: f32, + intersection: *XYZ) c_int { + const t: @Vector(3, f32) = @bitCast(move); + var p = @as(@Vector(3, f32), @bitCast(start)) - t; + rotate2d(&p[2], &p[0], degToRad(f32, -rot)); + var q = @as(@Vector(3, f32), @bitCast(end)) - t; + rotate2d(&q[2], &q[0], degToRad(f32, -rot)); + + defer { + rotate2d(&intersection.z, &intersection.x, degToRad(f32, rot)); + intersection.* = @bitCast(@as(@Vector(3, f32), + @bitCast(intersection.*)) + t); + } + return segCrossModel(@bitCast(p), @bitCast(q), m, intersection); +} |
