|
1 #include "compoundobject.h" |
|
2 #include "documentmanager.h" |
|
3 #include "invert.h" |
|
4 #include "polygoncache.h" |
|
5 |
|
6 ldraw::CompoundObject::CompoundObject |
|
7 ( |
|
8 const glm::mat4& transformation, |
|
9 const Color color |
|
10 ) : |
|
11 ColoredObject{color}, |
|
12 transformation{transformation} |
|
13 { |
|
14 } |
|
15 |
|
16 QVariant ldraw::CompoundObject::getProperty(Property property) const |
|
17 { |
|
18 switch (property) |
|
19 { |
|
20 case Property::Transformation: |
|
21 return QVariant::fromValue(this->transformation); |
|
22 case Property::IsInverted: |
|
23 return this->isInverted; |
|
24 default: |
|
25 return ColoredObject::getProperty(property); |
|
26 } |
|
27 } |
|
28 |
|
29 void ldraw::CompoundObject::setProperty(SetPropertyResult* result, const PropertyKeyValue& pair) |
|
30 { |
|
31 LDRAW_OBJECT_HANDLE_SET_PROPERTY(Transformation, {this->transformation = value;}); |
|
32 LDRAW_OBJECT_HANDLE_SET_PROPERTY(IsInverted, {this->isInverted = value;}); |
|
33 ldraw::ColoredObject::setProperty(result, pair); |
|
34 } |
|
35 |
|
36 glm::vec3 ldraw::CompoundObject::position() const |
|
37 { |
|
38 return this->transformation[3]; |
|
39 } |
|
40 |
|
41 void ldraw::CompoundObject::invert(GetPolygonsContext *context) |
|
42 { |
|
43 const std::optional<Axis> flatDimension = context ? this->flatDimension(context) : std::optional<Axis>{}; |
|
44 if (flatDimension.has_value()) |
|
45 { |
|
46 glm::mat4 matrix = glm::identity<glm::mat4>(); |
|
47 matrix[*flatDimension][*flatDimension] = -1.0f; |
|
48 this->transformation *= matrix; |
|
49 } |
|
50 else |
|
51 { |
|
52 this->isInverted = not this->isInverted; |
|
53 } |
|
54 } |
|
55 |
|
56 |
|
57 QDataStream& ldraw::CompoundObject::serialize(QDataStream &stream) const |
|
58 { |
|
59 return ColoredObject::serialize(stream) << this->transformation << this->isInverted; |
|
60 } |
|
61 |
|
62 QDataStream& ldraw::CompoundObject::deserialize(QDataStream &stream) |
|
63 { |
|
64 return ColoredObject::deserialize(stream) >> this->transformation >> this->isInverted; |
|
65 } |
|
66 |
|
67 /** |
|
68 * @brief Finds out in which dimension the object is flat in. In that dimension all vertices have a value of 0. |
|
69 * If the object is not flat, this does not return a value. |
|
70 * @param model Model to find out flatness of |
|
71 * @param documents Where to look for subfiles |
|
72 * @returns dimension the model is flat in, if such dimension exists, no value otherwise. |
|
73 */ |
|
74 std::optional<Axis> ldraw::CompoundObject::flatDimension(GetPolygonsContext *context) const |
|
75 { |
|
76 // The dimensions that this model is potentially flat in. |
|
77 QVector<Axis> dimensions = {X, Y, Z}; |
|
78 std::vector<gl::Polygon> polygons; |
|
79 this->getPolygons(polygons, context); |
|
80 for (const gl::Polygon& polygon : polygons) |
|
81 { |
|
82 for (unsigned int i = 0; i < polygon.numPolygonVertices(); i += 1) |
|
83 { |
|
84 const glm::vec3& v_i = polygon.vertices[i]; |
|
85 if (not qFuzzyCompare(v_i.x, 0.0f)) |
|
86 { |
|
87 dimensions.removeOne(X); |
|
88 } |
|
89 if (not qFuzzyCompare(v_i.y, 0.0f)) |
|
90 { |
|
91 dimensions.removeOne(Y); |
|
92 } |
|
93 if (not qFuzzyCompare(v_i.z, 0.0f)) |
|
94 { |
|
95 dimensions.removeOne(Z); |
|
96 } |
|
97 } |
|
98 // If there are no more dimensions left, we can exit the loop. |
|
99 if (dimensions.isEmpty()) |
|
100 { |
|
101 break; |
|
102 } |
|
103 } |
|
104 if (dimensions.size() == 1) |
|
105 { |
|
106 // The model is flat in one dimension, return that. |
|
107 // If the model is flat in two or three dimensions, it's not really a valid model. |
|
108 return dimensions[0]; |
|
109 } |
|
110 else |
|
111 { |
|
112 // The model is not flat. |
|
113 return {}; |
|
114 } |
|
115 } |