ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

floorface.cpp

Go to the documentation of this file.
00001 /* ResidualVM - A 3D game interpreter
00002  *
00003  * ResidualVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the AUTHORS
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "engines/stark/resources/floorface.h"
00024 
00025 #include "engines/stark/debug.h"
00026 #include "engines/stark/formats/xrc.h"
00027 #include "engines/stark/resources/floor.h"
00028 
00029 namespace Stark {
00030 namespace Resources {
00031 
00032 FloorFace::FloorFace(Object *parent, byte subType, uint16 index, const Common::String &name) :
00033         Object(parent, subType, index, name),
00034         _distanceFromCamera(0),
00035         _unk2(0) {
00036     _type = TYPE;
00037 
00038     for (uint i = 0; i < ARRAYSIZE(_indices); i++) {
00039         _indices[i] = 0;
00040     }
00041 }
00042 
00043 FloorFace::~FloorFace() {
00044 }
00045 
00046 bool FloorFace::isPointInside(const Math::Vector3d &point) const {
00047     // Compute the barycentric coordinates of the point in the triangle
00048     float area = 1.0f / 2.0f
00049             * (-_vertices[1].y() * _vertices[2].x()
00050                     + _vertices[0].y() * (-_vertices[1].x() + _vertices[2].x())
00051                     + _vertices[0].x() * (_vertices[1].y() - _vertices[2].y())
00052                     + _vertices[1].x() * _vertices[2].y());
00053 
00054     float s = (_vertices[0].y() * _vertices[2].x() - _vertices[0].x() * _vertices[2].y()
00055             + (_vertices[2].y() - _vertices[0].y()) * point.x()
00056             + (_vertices[0].x() - _vertices[2].x()) * point.y())
00057                     / (2.0f * area);
00058 
00059     float t = (_vertices[0].x() * _vertices[1].y() - _vertices[0].y() * _vertices[1].x()
00060             + (_vertices[0].y() - _vertices[1].y()) * point.x()
00061             + (_vertices[1].x() - _vertices[0].x()) * point.y())
00062                     / (2.0f * area);
00063 
00064     // Check the coordinates are in the triangle
00065     return s > 0.0f && t > 0.0f && (1.0f - s - t) > 0.0f;
00066 }
00067 
00068 void FloorFace::computePointHeight(Math::Vector3d &point) const {
00069     // Compute the barycentric coordinates of the point in the triangle
00070     float area = 1.0f / 2.0f
00071             * (-_vertices[1].y() * _vertices[2].x()
00072                     + _vertices[0].y() * (-_vertices[1].x() + _vertices[2].x())
00073                     + _vertices[0].x() * (_vertices[1].y() - _vertices[2].y())
00074                     + _vertices[1].x() * _vertices[2].y());
00075 
00076     float s = (_vertices[0].y() * _vertices[2].x() - _vertices[0].x() * _vertices[2].y()
00077             + (_vertices[2].y() - _vertices[0].y()) * point.x()
00078             + (_vertices[0].x() - _vertices[2].x()) * point.y())
00079                     / (2.0f * area);
00080 
00081     float t = (_vertices[0].x() * _vertices[1].y() - _vertices[0].y() * _vertices[1].x()
00082             + (_vertices[0].y() - _vertices[1].y()) * point.x()
00083             + (_vertices[1].x() - _vertices[0].x()) * point.y())
00084                     / (2.0f * area);
00085 
00086     // Compute the Z coordinate of the point
00087     float pointZ = (1.0f - s - t) * _vertices[0].z() + s * _vertices[1].z() + t * _vertices[2].z();
00088 
00089     point.setValue(2, pointZ);
00090 }
00091 
00092 bool FloorFace::intersectRay(const Math::Ray &ray, Math::Vector3d &intersection) const {
00093     // Compute the triangle plane normal
00094     Math::Vector3d n = Math::Vector3d::crossProduct(_vertices[1] - _vertices[0],  _vertices[2] - _vertices[0]);
00095     if (n == Math::Vector3d()) {
00096         return false; // We don't handle degenerate triangles
00097     }
00098 
00099     // Point on triangle plane: dot(P - _vertices[0], n) = 0
00100     // Point on ray: P = origin + r * direction
00101     // Point on both => r = - dot(n, origin - _vertices[0]) / dot(n, direction)
00102 
00103     float num = -Math::Vector3d::dotProduct(n, ray.getOrigin() - _vertices[0]);
00104     float denom = Math::Vector3d::dotProduct(n, ray.getDirection());
00105 
00106     if (fabs(denom) < 0.00001) {
00107         // The ray is parallel to the plane
00108         return false;
00109     }
00110 
00111     float r = num / denom;
00112     if (r < 0.0) {
00113         // The ray goes away from the triangle
00114         return false;
00115     }
00116 
00117     // Compute the intersection point between the triangle plane and the ray
00118     intersection = ray.getOrigin() + r * ray.getDirection();
00119 
00120     // Check the intersection point is inside the triangle
00121     return isPointInside(intersection);
00122 }
00123 
00124 float FloorFace::distanceToRay(const Math::Ray &ray) const {
00125     Math::Vector3d center = getCenter();
00126     return Math::Vector3d::crossProduct(ray.getDirection(), center - ray.getOrigin()).getMagnitude();
00127 }
00128 
00129 float FloorFace::getDistanceFromCamera() const {
00130     return _distanceFromCamera;
00131 }
00132 
00133 int16 FloorFace::getVertexIndex(int32 index) const {
00134     assert(index < 3);
00135     return _indices[index];
00136 }
00137 
00138 void FloorFace::addEdge(FloorEdge *edge) {
00139     _edges.push_back(edge);
00140 }
00141 
00142 Common::Array<FloorEdge *> FloorFace::getEdges() const {
00143     return _edges;
00144 }
00145 
00146 FloorEdge *FloorFace::findNearestEdge(const Math::Vector3d &point) const {
00147     float minDistance = -1;
00148     FloorEdge *edge = nullptr;
00149 
00150     for (uint i = 0; i < _edges.size(); i++) {
00151         if (!_edges[i]->isEnabled()) {
00152             continue;
00153         }
00154 
00155         float distance = (point - _edges[i]->getPosition()).getSquareMagnitude();
00156 
00157 
00158         if (!edge || distance < minDistance) {
00159             minDistance = distance;
00160             edge = _edges[i];
00161         }
00162     }
00163 
00164     return edge;
00165 }
00166 
00167 Math::Vector3d FloorFace::getCenter() const {
00168     return (_vertices[0] + _vertices[1] + _vertices[2]) / 3.0;
00169 }
00170 
00171 bool FloorFace::hasVertices() const {
00172     return _indices[0] != 0 || _indices[1] != 0 || _indices[2] != 0;
00173 }
00174 
00175 void FloorFace::enable(bool e) {
00176     for (uint i = 0; i < _edges.size(); i++) {
00177         _edges[i]->enable(e);
00178     }
00179 }
00180 
00181 bool FloorFace::isEnabled() const {
00182     for (uint i = 0; i < _edges.size(); i++) {
00183         if (_edges[i]->isEnabled()) {
00184             return true;
00185         }
00186     }
00187 
00188     return false;
00189 }
00190 
00191 void FloorFace::readData(Formats::XRCReadStream *stream) {
00192     for (uint i = 0; i < ARRAYSIZE(_indices); i++) {
00193         _indices[i] = stream->readSint16LE();
00194     }
00195 
00196     _distanceFromCamera = stream->readFloatLE();
00197 
00198     for (uint i = 0; i < ARRAYSIZE(_indices); i++) {
00199         stream->readSint16LE(); // Skipped in the original
00200     }
00201 
00202     _unk2 = stream->readFloatLE();
00203 }
00204 
00205 void FloorFace::onAllLoaded() {
00206     Object::onAllLoaded();
00207     Floor *floor = Object::cast<Floor>(_parent);
00208 
00209     for (uint i = 0; i < ARRAYSIZE(_indices); i++) {
00210         _vertices[i] = floor->getVertex(_indices[i]);
00211     }
00212 }
00213 
00214 void FloorFace::printData() {
00215     debug("indices: %d %d %d, distanceFromCamera %f, unk2 %f", _indices[0], _indices[1], _indices[2], _distanceFromCamera, _unk2);
00216 }
00217 
00218 } // End of namespace Resources
00219 } // End of namespace Stark


Generated on Sat May 18 2019 05:01:02 for ResidualVM by doxygen 1.7.1
curved edge   curved edge