1 /* 2 Copyright (C) 2010-2014 Kristian Duske 3 4 This file is part of TrenchBroom. 5 6 TrenchBroom is free software: you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 TrenchBroom is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with TrenchBroom. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include "TexCoordSystem.h" 21 22 #include "Assets/Texture.h" 23 #include "Model/BrushFace.h" 24 25 namespace TrenchBroom { 26 namespace Model { ~TexCoordSystemSnapshot()27 TexCoordSystemSnapshot::~TexCoordSystemSnapshot() {} 28 restore()29 void TexCoordSystemSnapshot::restore() { 30 doRestore(); 31 } 32 ~TexCoordSystem()33 TexCoordSystem::~TexCoordSystem() {} 34 clone() const35 TexCoordSystem* TexCoordSystem::clone() const { 36 return doClone(); 37 } 38 takeSnapshot()39 TexCoordSystemSnapshot* TexCoordSystem::takeSnapshot() { 40 return doTakeSnapshot(); 41 } 42 xAxis() const43 Vec3 TexCoordSystem::xAxis() const { 44 return getXAxis(); 45 } 46 yAxis() const47 Vec3 TexCoordSystem::yAxis() const { 48 return getYAxis(); 49 } 50 resetTextureAxes(const Vec3 & normal)51 void TexCoordSystem::resetTextureAxes(const Vec3& normal) { 52 doResetTextureAxes(normal); 53 } 54 resetTextureAxesToParaxial(const Vec3 & normal,const float angle)55 void TexCoordSystem::resetTextureAxesToParaxial(const Vec3& normal, const float angle) { 56 doResetTextureAxesToParaxial(normal, angle); 57 } 58 resetTextureAxesToParallel(const Vec3 & normal,const float angle)59 void TexCoordSystem::resetTextureAxesToParallel(const Vec3& normal, const float angle) { 60 doResetTextureAxesToParaxial(normal, angle); 61 } 62 getTexCoords(const Vec3 & point,const BrushFaceAttributes & attribs) const63 Vec2f TexCoordSystem::getTexCoords(const Vec3& point, const BrushFaceAttributes& attribs) const { 64 return doGetTexCoords(point, attribs); 65 } 66 setRotation(const Vec3 & normal,const float oldAngle,const float newAngle)67 void TexCoordSystem::setRotation(const Vec3& normal, const float oldAngle, const float newAngle) { 68 doSetRotation(normal, oldAngle, newAngle); 69 } 70 transform(const Plane3 & oldBoundary,const Mat4x4 & transformation,BrushFaceAttributes & attribs,bool lockTexture,const Vec3 & invariant)71 void TexCoordSystem::transform(const Plane3& oldBoundary, const Mat4x4& transformation, BrushFaceAttributes& attribs, bool lockTexture, const Vec3& invariant) { 72 doTransform(oldBoundary, transformation, attribs, lockTexture, invariant); 73 } 74 updateNormal(const Vec3 & oldNormal,const Vec3 & newNormal,const BrushFaceAttributes & attribs)75 void TexCoordSystem::updateNormal(const Vec3& oldNormal, const Vec3& newNormal, const BrushFaceAttributes& attribs) { 76 if (oldNormal != newNormal) 77 doUpdateNormal(oldNormal, newNormal, attribs); 78 } 79 moveTexture(const Vec3 & normal,const Vec3 & up,const Vec3 & right,const Vec2f & offset,BrushFaceAttributes & attribs) const80 void TexCoordSystem::moveTexture(const Vec3& normal, const Vec3& up, const Vec3& right, const Vec2f& offset, BrushFaceAttributes& attribs) const { 81 82 /* 83 const Vec3 direction = crossed(up, right); 84 const Mat4x4 toPlane = Mat4x4::ZerZ * planeProjectionMatrix(0.0, direction); 85 const Vec3 upPlane = (toPlane * up).normalized(); 86 const Vec3 rightPlane = (toPlane * right).normalized(); 87 const Vec3 xPlane = (toPlane * xAxis()).normalized(); 88 const Vec3 yPlane = (toPlane * yAxis()).normalized(); 89 90 size_t hIndex, vIndex; 91 float hFactor, vFactor; 92 if (rightPlane.firstComponent() == xPlane.firstComponent()) { 93 hIndex = 0; 94 vIndex = 1; 95 if (rightPlane.dot(xPlane) > 0.0f) 96 hFactor = -1.0f; 97 else 98 hFactor = +1.0f; 99 if (upPlane.dot(yPlane) > 0.0f) 100 vFactor = -1.0f; 101 else 102 vFactor = +1.0f; 103 } else { 104 hIndex = 1; 105 vIndex = 0; 106 if (rightPlane.dot(yPlane) > 0.0f) 107 hFactor = +1.0f; 108 else 109 hFactor = -1.0f; 110 if (upPlane.dot(xPlane) > 0.0f) 111 vFactor = +1.0f; 112 else 113 vFactor = -1.0f; 114 } 115 116 Vec2f actualOffset; 117 actualOffset[hIndex] = hFactor * offset.x(); 118 actualOffset[vIndex] = vFactor * offset.y(); 119 */ 120 121 const Mat4x4 toPlane = planeProjectionMatrix(0.0, normal); 122 const Mat4x4 fromPlane = invertedMatrix(toPlane); 123 const Mat4x4 transform = fromPlane * Mat4x4::ZerZ * toPlane; 124 const Vec3 texX = (transform * getXAxis()).normalized(); 125 const Vec3 texY = (transform * getYAxis()).normalized(); 126 127 Vec3 vAxis, hAxis; 128 size_t xIndex = 0; 129 size_t yIndex = 0; 130 131 // we prefer to use the texture axis which is closer to the XY plane for horizontal movement 132 if (Math::lt(std::abs(texX.z()), std::abs(texY.z()))) { 133 hAxis = texX; 134 vAxis = texY; 135 xIndex = 0; 136 yIndex = 1; 137 } else if (Math::lt(std::abs(texY.z()), std::abs(texX.z()))) { 138 hAxis = texY; 139 vAxis = texX; 140 xIndex = 1; 141 yIndex = 0; 142 } else { 143 // both texture axes have the same absolute angle towards the XY plane, prefer the one that is closer 144 // to the right view axis for horizontal movement 145 146 if (Math::gt(std::abs(right.dot(texX)), std::abs(right.dot(texY)))) { 147 // the right view axis is closer to the X texture axis 148 hAxis = texX; 149 vAxis = texY; 150 xIndex = 0; 151 yIndex = 1; 152 } else if (Math::gt(std::abs(right.dot(texY)), std::abs(right.dot(texX)))) { 153 // the right view axis is closer to the Y texture axis 154 hAxis = texY; 155 vAxis = texX; 156 xIndex = 1; 157 yIndex = 0; 158 } else { 159 // the right axis is as close to the X texture axis as to the Y texture axis 160 // test the up axis 161 if (Math::gt(std::abs(up.dot(texY)), std::abs(up.dot(texX)))) { 162 // the up view axis is closer to the Y texture axis 163 hAxis = texX; 164 vAxis = texY; 165 xIndex = 0; 166 yIndex = 1; 167 } else if (Math::gt(std::abs(up.dot(texX)), std::abs(up.dot(texY)))) { 168 // the up view axis is closer to the X texture axis 169 hAxis = texY; 170 vAxis = texX; 171 xIndex = 1; 172 yIndex = 0; 173 } else { 174 // this is just bad, better to do nothing 175 return; 176 } 177 } 178 } 179 180 Vec2f actualOffset; 181 if (right.dot(hAxis) >= 0.0) 182 actualOffset[xIndex] = -offset.x(); 183 else 184 actualOffset[xIndex] = +offset.x(); 185 if (up.dot(vAxis) >= 0.0) 186 actualOffset[yIndex] = -offset.y(); 187 else 188 actualOffset[yIndex] = +offset.y(); 189 190 191 attribs.setOffset(attribs.offset() + actualOffset); 192 } 193 rotateTexture(const Vec3 & normal,const float angle,BrushFaceAttributes & attribs) const194 void TexCoordSystem::rotateTexture(const Vec3& normal, const float angle, BrushFaceAttributes& attribs) const { 195 const float actualAngle = isRotationInverted(normal) ? - angle : angle; 196 attribs.setRotation(attribs.rotation() + actualAngle); 197 } 198 shearTexture(const Vec3 & normal,const Vec2f & factors)199 void TexCoordSystem::shearTexture(const Vec3& normal, const Vec2f& factors) { 200 doShearTexture(normal, factors); 201 } 202 toMatrix(const Vec2f & o,const Vec2f & s) const203 Mat4x4 TexCoordSystem::toMatrix(const Vec2f& o, const Vec2f& s) const { 204 const Vec3 x = safeScaleAxis(getXAxis(), s.x()); 205 const Vec3 y = safeScaleAxis(getYAxis(), s.y()); 206 const Vec3 z = getZAxis(); 207 208 return Mat4x4(x[0], x[1], x[2], o[0], 209 y[0], y[1], y[2], o[1], 210 z[0], z[1], z[2], 0.0, 211 0.0, 0.0, 0.0, 1.0); 212 /* 213 const Vec3 xAxis(getXAxis() * scale.x()); 214 const Vec3 yAxis(getYAxis() * scale.y()); 215 const Vec3 zAxis(getZAxis()); 216 const Vec3 origin(xAxis * -offset.x() + yAxis * -offset.y()); 217 218 return coordinateSystemMatrix(xAxis, yAxis, zAxis, origin); 219 */ 220 } 221 fromMatrix(const Vec2f & offset,const Vec2f & scale) const222 Mat4x4 TexCoordSystem::fromMatrix(const Vec2f& offset, const Vec2f& scale) const { 223 return invertedMatrix(toMatrix(offset, scale)); 224 } 225 measureAngle(const float currentAngle,const Vec2f & center,const Vec2f & point) const226 float TexCoordSystem::measureAngle(const float currentAngle, const Vec2f& center, const Vec2f& point) const { 227 return doMeasureAngle(currentAngle, center, point); 228 } 229 computeTexCoords(const Vec3 & point,const Vec2f & scale) const230 Vec2f TexCoordSystem::computeTexCoords(const Vec3& point, const Vec2f& scale) const { 231 return Vec2f(point.dot(safeScaleAxis(getXAxis(), scale.x())), 232 point.dot(safeScaleAxis(getYAxis(), scale.y()))); 233 } 234 235 } 236 } 237