• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include <cmath>
19 #include <memory>
20 #include <vector>
21 
22 #include "AndroidOut.h"
23 #include "TextureAsset.h"
24 
25 union Vector3 {
26     struct {
27         float x, y, z;
28     };
29     float idx[3];
30     Vector3 operator*(float value) { return Vector3{{x * value, y * value, z * value}}; }
31     Vector3 operator/(float value) { return Vector3{{x / value, y / value, z / value}}; }
32     Vector3 operator+(Vector3 const &other) {
33         return Vector3{{x + other.x, y + other.y, z + other.z}};
34     }
35     Vector3 operator-(Vector3 const &other) {
36         return Vector3{{x - other.x, y - other.y, z - other.z}};
37     }
38 };
39 
40 union Vector2 {
41     struct {
42         float x, y;
43     };
44     struct {
45         float u, v;
46     };
47     float idx[2];
48 };
49 
50 struct Vertex {
VertexVertex51     constexpr Vertex(const Vector3 &inPosition, const Vector2 &inUV)
52           : position(inPosition), uv(inUV) {}
53 
54     Vector3 position;
55     Vector2 uv;
56 };
57 
58 typedef uint16_t Index;
59 
60 class Model {
61 public:
62     static std::shared_ptr<TextureAsset> texture;
63     // Default init only useful as a placeholder
Model()64     Model() {}
65 
Model(std::vector<Vertex> vertices,std::vector<Index> indices)66     inline Model(std::vector<Vertex> vertices, std::vector<Index> indices)
67           : currentVertices_(vertices),
68             startVertices_(std::move(vertices)),
69             indices_(std::move(indices)),
70             id_(0) {
71         findCenter();
72     }
73 
getVertexData()74     inline const Vertex *getVertexData() const { return currentVertices_.data(); }
75 
getIndexCount()76     inline size_t getIndexCount() const { return indices_.size(); }
77 
getIndexData()78     inline const Index *getIndexData() const { return indices_.data(); }
79 
getTexture()80     inline const TextureAsset &getTexture() const { return *texture; }
81 
getCenter()82     inline const Vector3 getCenter() { return center_; }
83 
dump()84     inline void dump() const {
85         aout << "Indices: " << std::endl;
86         for (auto &&ver : currentVertices_) {
87             aout << "Vertex: x: " << ver.position.x << " y: " << ver.position.y
88                  << " z: " << ver.position.z << std::endl;
89         }
90         aout << std::endl;
91         aout << "Center: x: " << center_.x << " y: " << center_.y << " z: " << center_.z
92              << std::endl;
93     }
94 
move(Vector3 offset)95     void move(Vector3 offset) {
96         for (int i = 0; i < startVertices_.size(); ++i) {
97             startVertices_[i].position = startVertices_[i].position + offset;
98             currentVertices_[i].position = currentVertices_[i].position + offset;
99         }
100         center_ = center_ + offset;
101     }
102 
addRotation(float angle)103     void addRotation(float angle) {
104         float rad = angle + rotationOffset_;
105         for (int i = 0; i < startVertices_.size(); ++i) {
106             Vector3 normalized = startVertices_[i].position - center_;
107             Vector3 out{{0, 0, 0}};
108             out.x = normalized.x * cos(rad) - normalized.y * sin(rad);
109             out.y = normalized.x * sin(rad) + normalized.y * cos(rad);
110             currentVertices_[i].position = out + center_;
111         }
112         rotationOffset_ = rad;
113     }
114 
setRotationOffset(float angle)115     void setRotationOffset(float angle) { rotationOffset_ = angle; }
116 
applyPhysics(float deltaTimeUnit,Model * models,int size,float width,float height)117     static void applyPhysics(float deltaTimeUnit, Model *models, int size, float width,
118                              float height) {
119         nBodySimulation(deltaTimeUnit, models, size, width, height);
120     }
121 
setMass(float m)122     void setMass(float m) { mass_ = m; }
123 
getId()124     int getId() const { return id_; }
setId(int id)125     void setId(int id) { id_ = id; }
126 
127 private:
findCenter()128     void findCenter() {
129         Vector3 center{{0, 0, 0}};
130         for (auto &&vertex : startVertices_) {
131             center = center + vertex.position;
132         }
133         center_ = center / static_cast<float>(startVertices_.size());
134     }
135 
nBodySimulation(float deltaTimeUnit,Model * models,int size,float width,float height)136     static void nBodySimulation(float deltaTimeUnit, Model *models, int size, float width,
137                                 float height) {
138         static const float G = 6.67e-10;
139         for (auto i = 0; i < size; i++) {
140             auto &model = models[i];
141             Vector3 acc = {{0, 0, 0}};
142             for (auto j = 0; j < size; j++) {
143                 if (i != j) {
144                     auto &other = models[j];
145                     auto dx = model.center_.x - other.center_.x;
146                     auto dy = model.center_.y - other.center_.y;
147                     auto dz = model.center_.z - other.center_.z;
148                     float distanceSq = dx * dx + dy * dy + dz * dz;
149                     Vector3 direction = {{dx, dy, dz}};
150                     float distance = std::sqrt(distanceSq);
151                     float force = (G * model.mass_ * other.mass_) / std::max(0.01f, distanceSq);
152                     acc = acc + (direction / std::max(0.01f, distance)) * (force / model.mass_);
153                 }
154             }
155             model.velocity_ = model.velocity_ + acc * deltaTimeUnit;
156             model.move(model.velocity_ * deltaTimeUnit);
157             if (model.center_.x <= -width / 2 || model.center_.x >= width / 2) {
158                 model.velocity_.x = model.center_.x <= -width / 2 ? abs(model.velocity_.x)
159                                                                   : -abs(model.velocity_.x);
160                 auto border = model.center_.x <= -width / 2 ? -width / 2 : width / 2;
161                 model.move({{border - model.center_.x, 0, 0}});
162             }
163             if (model.center_.y <= -height / 2 || model.center_.y >= height / 2) {
164                 model.velocity_.y = model.center_.y <= -height / 2 ? abs(model.velocity_.y)
165                                                                    : -abs(model.velocity_.y);
166                 auto border = model.center_.y <= -height / 2 ? -height / 2 : height / 2;
167                 model.move({{0, border - model.center_.y, 0}});
168             }
169         }
170     }
171 
172     Vector3 center_;
173     std::vector<Vertex> currentVertices_;
174     std::vector<Vertex> startVertices_;
175     std::vector<Index> indices_;
176     float rotationOffset_;
177     Vector3 velocity_;
178     float mass_ = 1.0f;
179     int id_;
180 };
181