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