Line data Source code
1 : /*
2 : * Copyright (C) 2025 aeml
3 : *
4 : * This program is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 3 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * This program is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 : */
17 :
18 : #include "simlab/WorldHasher.hpp"
19 :
20 : #include "ecs/World.hpp"
21 :
22 : #include <algorithm>
23 : #include <cstring>
24 :
25 : namespace simlab
26 : {
27 :
28 2827178 : void WorldHasher::HashBytes(std::uint64_t& h, const void* data, std::size_t len) const noexcept
29 : {
30 2827178 : const unsigned char* bytes = static_cast<const unsigned char*>(data);
31 14135890 : for (std::size_t i = 0; i < len; ++i)
32 : {
33 11308712 : h ^= static_cast<std::uint64_t>(bytes[i]);
34 11308712 : h *= kPrime;
35 : }
36 2827178 : }
37 :
38 20 : std::uint64_t WorldHasher::HashBodies(const std::vector<physics::TransformComponent>& transforms,
39 : const std::vector<physics::RigidBodyComponent>& bodies) const noexcept
40 : {
41 20 : std::uint64_t h = kOffset;
42 20 : const std::size_t count = std::min(transforms.size(), bodies.size());
43 60 : for (std::size_t i = 0; i < count; ++i)
44 : {
45 40 : const auto& t = transforms[i];
46 40 : const auto& b = bodies[i];
47 40 : HashBytes(h, &t.x, sizeof(t.x));
48 40 : HashBytes(h, &t.y, sizeof(t.y));
49 40 : HashBytes(h, &t.rotation, sizeof(t.rotation));
50 40 : HashBytes(h, &b.vx, sizeof(b.vx));
51 40 : HashBytes(h, &b.vy, sizeof(b.vy));
52 40 : HashBytes(h, &b.angularVelocity, sizeof(b.angularVelocity));
53 40 : HashBytes(h, &b.mass, sizeof(b.mass));
54 40 : HashBytes(h, &b.invMass, sizeof(b.invMass));
55 40 : HashBytes(h, &b.inertia, sizeof(b.inertia));
56 40 : HashBytes(h, &b.invInertia, sizeof(b.invInertia));
57 40 : HashBytes(h, &b.restitution, sizeof(b.restitution));
58 40 : HashBytes(h, &b.friction, sizeof(b.friction));
59 : }
60 20 : return h;
61 : }
62 :
63 3 : std::uint64_t WorldHasher::HashAABBs(const std::vector<physics::AABBComponent>& aabbs) const noexcept
64 : {
65 3 : std::uint64_t h = kOffset;
66 9 : for (const auto& box : aabbs)
67 : {
68 6 : HashBytes(h, &box.minX, sizeof(box.minX));
69 6 : HashBytes(h, &box.minY, sizeof(box.minY));
70 6 : HashBytes(h, &box.maxX, sizeof(box.maxX));
71 6 : HashBytes(h, &box.maxY, sizeof(box.maxY));
72 : }
73 3 : return h;
74 : }
75 :
76 1465 : std::uint64_t WorldHasher::HashWorld(const ecs::World& world) const noexcept
77 : {
78 1465 : std::uint64_t h = kOffset;
79 :
80 1465 : if (const auto* transforms = world.GetStorage<physics::TransformComponent>())
81 : {
82 1465 : const auto& entities = transforms->GetEntities();
83 1465 : const auto& data = transforms->GetData();
84 117270 : for (std::size_t i = 0; i < data.size(); ++i)
85 : {
86 115805 : HashBytes(h, &entities[i], sizeof(entities[i]));
87 115805 : HashBytes(h, &data[i].x, sizeof(data[i].x));
88 115805 : HashBytes(h, &data[i].y, sizeof(data[i].y));
89 115805 : HashBytes(h, &data[i].rotation, sizeof(data[i].rotation));
90 : }
91 : }
92 :
93 1465 : if (const auto* bodies = world.GetStorage<physics::RigidBodyComponent>())
94 : {
95 1465 : const auto& entities = bodies->GetEntities();
96 1465 : const auto& data = bodies->GetData();
97 117270 : for (std::size_t i = 0; i < data.size(); ++i)
98 : {
99 115805 : const auto& body = data[i];
100 115805 : HashBytes(h, &entities[i], sizeof(entities[i]));
101 115805 : HashBytes(h, &body.vx, sizeof(body.vx));
102 115805 : HashBytes(h, &body.vy, sizeof(body.vy));
103 115805 : HashBytes(h, &body.lastX, sizeof(body.lastX));
104 115805 : HashBytes(h, &body.lastY, sizeof(body.lastY));
105 115805 : HashBytes(h, &body.lastAngle, sizeof(body.lastAngle));
106 115805 : HashBytes(h, &body.mass, sizeof(body.mass));
107 115805 : HashBytes(h, &body.invMass, sizeof(body.invMass));
108 115805 : HashBytes(h, &body.inertia, sizeof(body.inertia));
109 115805 : HashBytes(h, &body.invInertia, sizeof(body.invInertia));
110 115805 : HashBytes(h, &body.restitution, sizeof(body.restitution));
111 115805 : HashBytes(h, &body.friction, sizeof(body.friction));
112 115805 : HashBytes(h, &body.angularVelocity, sizeof(body.angularVelocity));
113 115805 : HashBytes(h, &body.torque, sizeof(body.torque));
114 115805 : HashBytes(h, &body.angularFriction, sizeof(body.angularFriction));
115 115805 : HashBytes(h, &body.angularDrag, sizeof(body.angularDrag));
116 : }
117 : }
118 :
119 1465 : if (const auto* aabbs = world.GetStorage<physics::AABBComponent>())
120 : {
121 1084 : const auto& entities = aabbs->GetEntities();
122 1084 : const auto& data = aabbs->GetData();
123 26026 : for (std::size_t i = 0; i < data.size(); ++i)
124 : {
125 24942 : HashBytes(h, &entities[i], sizeof(entities[i]));
126 24942 : HashBytes(h, &data[i].minX, sizeof(data[i].minX));
127 24942 : HashBytes(h, &data[i].minY, sizeof(data[i].minY));
128 24942 : HashBytes(h, &data[i].maxX, sizeof(data[i].maxX));
129 24942 : HashBytes(h, &data[i].maxY, sizeof(data[i].maxY));
130 : }
131 : }
132 :
133 1465 : if (const auto* circles = world.GetStorage<physics::CircleColliderComponent>())
134 : {
135 1463 : const auto& entities = circles->GetEntities();
136 1463 : const auto& data = circles->GetData();
137 91604 : for (std::size_t i = 0; i < data.size(); ++i)
138 : {
139 90141 : HashBytes(h, &entities[i], sizeof(entities[i]));
140 90141 : HashBytes(h, &data[i].radius, sizeof(data[i].radius));
141 90141 : HashBytes(h, &data[i].offsetX, sizeof(data[i].offsetX));
142 90141 : HashBytes(h, &data[i].offsetY, sizeof(data[i].offsetY));
143 : }
144 : }
145 :
146 1465 : if (const auto* joints = world.GetStorage<physics::DistanceJointComponent>())
147 : {
148 722 : const auto& entities = joints->GetEntities();
149 722 : const auto& data = joints->GetData();
150 5782 : for (std::size_t i = 0; i < data.size(); ++i)
151 : {
152 5060 : HashBytes(h, &entities[i], sizeof(entities[i]));
153 5060 : HashBytes(h, &data[i].entityA, sizeof(data[i].entityA));
154 5060 : HashBytes(h, &data[i].entityB, sizeof(data[i].entityB));
155 5060 : HashBytes(h, &data[i].targetDistance, sizeof(data[i].targetDistance));
156 5060 : HashBytes(h, &data[i].compliance, sizeof(data[i].compliance));
157 : }
158 : }
159 :
160 1465 : return h;
161 : }
162 : }
|