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 "TextureAsset.h"
23 
24 union Vector3 {
25     struct {
26         float x, y, z;
27     };
28     float idx[3];
29     Vector3 operator*(float value) { return Vector3{{x * value, y * value, z * value}}; }
30     Vector3 operator/(float value) { return Vector3{{x / value, y / value, z / value}}; }
31     Vector3 operator+(Vector3 const &other) {
32         return Vector3{{x + other.x, y + other.y, z + other.z}};
33     }
34     Vector3 operator-(Vector3 const &other) {
35         return Vector3{{x - other.x, y - other.y, z - other.z}};
36     }
37 };
38 
39 union Vector2 {
40     struct {
41         float x, y;
42     };
43     struct {
44         float u, v;
45     };
46     float idx[2];
47 };
48 
49 struct Vertex {
VertexVertex50     constexpr Vertex(const Vector3 &inPosition, const Vector2 &inUV)
51           : position(inPosition), uv(inUV) {}
52 
53     Vector3 position;
54     Vector2 uv;
55 };
56 
57 typedef uint16_t Index;
58 
59 class Model {
60 public:
Model(std::vector<Vertex> vertices,std::vector<Index> indices,std::shared_ptr<TextureAsset> spTexture)61     inline Model(std::vector<Vertex> vertices, std::vector<Index> indices,
62                  std::shared_ptr<TextureAsset> spTexture)
63           : currentVertices_(vertices),
64             startVertices_(std::move(vertices)),
65             indices_(std::move(indices)),
66             spTexture_(std::move(spTexture)) {
67         findCenter();
68     }
69 
getVertexData()70     inline const Vertex *getVertexData() const { return currentVertices_.data(); }
71 
getIndexCount()72     inline size_t getIndexCount() const { return indices_.size(); }
73 
getIndexData()74     inline const Index *getIndexData() const { return indices_.data(); }
75 
getTexture()76     inline const TextureAsset &getTexture() const { return *spTexture_; }
77 
getCenter()78     inline const Vector3 getCenter() { return center_; }
79 
move(Vector3 offset)80     void move(Vector3 offset) {
81         for (int i = 0; i < startVertices_.size(); ++i) {
82             startVertices_[i].position = startVertices_[i].position + offset;
83             currentVertices_[i].position = currentVertices_[i].position + offset;
84         }
85         center_ = center_ + offset;
86     }
87 
setRotation(float angle)88     void setRotation(float angle) {
89         float rad = angle + rotationOffset_;
90         for (int i = 0; i < startVertices_.size(); ++i) {
91             Vector3 normalized = startVertices_[i].position - center_;
92             Vector3 out{{0, 0, 0}};
93             out.x = normalized.x * cos(rad) - normalized.y * sin(rad);
94             out.y = normalized.x * sin(rad) + normalized.y * cos(rad);
95             currentVertices_[i].position = out + center_;
96         }
97     }
98 
setRotationOffset(float angle)99     void setRotationOffset(float angle) { rotationOffset_ = angle; }
100 
101 private:
findCenter()102     void findCenter() {
103         Vector3 center{{0, 0, 0}};
104         for (auto &&vertex : startVertices_) {
105             center = center + vertex.position;
106         }
107         center_ = center / static_cast<float>(startVertices_.size());
108     }
109 
110     Vector3 center_;
111     std::vector<Vertex> currentVertices_;
112     std::vector<Vertex> startVertices_;
113     std::vector<Index> indices_;
114     std::shared_ptr<TextureAsset> spTexture_;
115     float rotationOffset_;
116 };
117