diff --git a/cocos/3d/CCAnimate3D.cpp b/cocos/3d/CCAnimate3D.cpp index 0fc5d5b8a4..1242b38905 100644 --- a/cocos/3d/CCAnimate3D.cpp +++ b/cocos/3d/CCAnimate3D.cpp @@ -43,6 +43,7 @@ Animate3D* Animate3D::create(Animation3D* animation) animate->autorelease(); animate->setDuration(animation->getDuration()); + animate->setOriginInterval(animation->getDuration()); return animate; } @@ -58,6 +59,7 @@ Animate3D* Animate3D::create(Animation3D* animation, float fromTime, float durat animate->_start = fromTime / fullDuration; animate->_last = duration / fullDuration; animate->setDuration(duration); + animate->setOriginInterval(duration); return animate; } @@ -85,7 +87,7 @@ Animate3D* Animate3D::clone() const copy->_last = _last; copy->_playReverse = _playReverse; copy->setDuration(animate->getDuration()); - + copy->setOriginInterval(animate->getOriginInterval()); return copy; } @@ -160,7 +162,7 @@ void Animate3D::stop() //! called every frame with it's delta time. DON'T override unless you know what you are doing. void Animate3D::step(float dt) { - ActionInterval::step(dt * _absSpeed); + ActionInterval::step(dt); } void Animate3D::update(float t) @@ -238,6 +240,7 @@ void Animate3D::setSpeed(float speed) { _absSpeed = fabsf(speed); _playReverse = speed < 0; + _duration = _originInterval / _absSpeed; } void Animate3D::setWeight(float weight) @@ -246,6 +249,11 @@ void Animate3D::setWeight(float weight) _weight = fabsf(weight); } +void Animate3D::setOriginInterval(float interval) +{ + _originInterval = interval; +} + Animate3D::Animate3D() : _state(Animate3D::Animate3DState::Running) , _animation(nullptr) @@ -256,6 +264,7 @@ Animate3D::Animate3D() , _playReverse(false) , _accTransTime(0.0f) , _lastTime(0.0f) +, _originInterval(0.0f) { } diff --git a/cocos/3d/CCAnimate3D.h b/cocos/3d/CCAnimate3D.h index 1b75e9d3c3..fc0df412cc 100644 --- a/cocos/3d/CCAnimate3D.h +++ b/cocos/3d/CCAnimate3D.h @@ -85,6 +85,10 @@ public: float getWeight() const { return _weight; } void setWeight(float weight); + /**get & set origin interval*/ + void setOriginInterval(float interval); + float getOriginInterval() const {return _originInterval; } + /** animate transition time */ static float getTransitionTime() { return _transTime; } @@ -117,6 +121,7 @@ protected: static float _transTime; //transition time from one animate3d to another float _accTransTime; // acculate transition time float _lastTime; // last t (0 - 1) + float _originInterval;// save origin interval time std::unordered_map _boneCurves; //weak ref //sprite animates diff --git a/cocos/3d/CCRay.cpp b/cocos/3d/CCRay.cpp index 046901e8ef..bf41c23440 100755 --- a/cocos/3d/CCRay.cpp +++ b/cocos/3d/CCRay.cpp @@ -38,106 +38,167 @@ Ray::~Ray() { } -bool Ray::intersects(const AABB& aabb) const +bool Ray::intersects(const AABB& box, float* distance) const { - Vec3 ptOnPlane; - Vec3 min = aabb._min; - Vec3 max = aabb._max; - - const Vec3& origin = _origin; - const Vec3& dir = _direction; - + float lowt = 0.0f; float t; + bool hit = false; + Vec3 hitpoint; + const Vec3& min = box._min; + const Vec3& max = box._max; + const Vec3& rayorig = _origin; + const Vec3& raydir = _direction; - if (dir.x != 0.f) + // Check origin inside first + if (rayorig > min && rayorig < max) + return true; + + // Check each face in turn, only check closest 3 + // Min x + if (rayorig.x <= min.x && raydir.x > 0) { - if (dir.x > 0) - t = (min.x - origin.x) / dir.x; - else - t = (max.x - origin.x) / dir.x; - - if (t > 0.f) + t = (min.x - rayorig.x) / raydir.x; + if (t >= 0) { - ptOnPlane = origin + t * dir; - - if (min.y < ptOnPlane.y && ptOnPlane.y < max.y && min.z < ptOnPlane.z && ptOnPlane.z < max.z) + // Substitute t back into ray and check bounds and dist + hitpoint = rayorig + raydir * t; + if (hitpoint.y >= min.y && hitpoint.y <= max.y && + hitpoint.z >= min.z && hitpoint.z <= max.z && + (!hit || t < lowt)) { - return true; + hit = true; + lowt = t; } } } - - if (dir.y != 0.f) + // Max x + if (rayorig.x >= max.x && raydir.x < 0) { - if (dir.y > 0) - t = (min.y - origin.y) / dir.y; - else - t = (max.y - origin.y) / dir.y; - - if (t > 0.f) + t = (max.x - rayorig.x) / raydir.x; + if (t >= 0) { - ptOnPlane = origin + t * dir; - - if (min.z < ptOnPlane.z && ptOnPlane.z < max.z && min.x < ptOnPlane.x && ptOnPlane.x < max.x) + // Substitute t back into ray and check bounds and dist + hitpoint = rayorig + raydir * t; + if (hitpoint.y >= min.y && hitpoint.y <= max.y && + hitpoint.z >= min.z && hitpoint.z <= max.z && + (!hit || t < lowt)) { - return true; + hit = true; + lowt = t; } } } - - if (dir.z != 0.f) - { - if (dir.z > 0) - t = (min.z - origin.z) / dir.z; - else - t = (max.z - origin.z) / dir.z; - - if (t > 0.f) + // Min y + if (rayorig.y <= min.y && raydir.y > 0) + { + t = (min.y - rayorig.y) / raydir.y; + if (t >= 0) { - ptOnPlane = origin + t * dir; + // Substitute t back into ray and check bounds and dist + hitpoint = rayorig + raydir * t; + if (hitpoint.x >= min.x && hitpoint.x <= max.x && + hitpoint.z >= min.z && hitpoint.z <= max.z && + (!hit || t < lowt)) + { + hit = true; + lowt = t; + } + } + } + // Max y + if (rayorig.y >= max.y && raydir.y < 0) + { + t = (max.y - rayorig.y) / raydir.y; + if - if (min.x < ptOnPlane.x && ptOnPlane.x < max.x && min.y < ptOnPlane.y && ptOnPlane.y < max.y) + + (t >= 0) + { + // Substitute t back into ray and check bounds and dist + hitpoint = rayorig + raydir * t; + if (hitpoint.x >= min.x && hitpoint.x <= max.x && + hitpoint.z >= min.z && hitpoint.z <= max.z && + (!hit || t < lowt)) { - return true; + hit = true; + lowt = t; + } + } + } + // Min z + if (rayorig.z <= min.z && raydir.z > 0) + { + t = (min.z - rayorig.z) / raydir.z; + if (t >= 0) + { + // Substitute t back into ray and check bounds and dist + hitpoint = rayorig + raydir * t; + if (hitpoint.x >= min.x && hitpoint.x <= max.x && + hitpoint.y >= min.y && hitpoint.y <= max.y && + (!hit || t < lowt)) + { + hit = true; + lowt = t; + } + } + } + // Max z + if (rayorig.z >= max.z && raydir.z < 0) + { + t = (max.z - rayorig.z) / raydir.z; + if (t >= 0) + { + // Substitute t back into ray and check bounds and dist + hitpoint = rayorig + raydir * t; + if (hitpoint.x >= min.x && hitpoint.x <= max.x && + hitpoint.y >= min.y && hitpoint.y <= max.y && + (!hit || t < lowt)) + { + hit = true; + lowt = t; } } } - return false; + if (distance) + *distance = lowt; + + return hit; } -bool Ray::intersects(const OBB& obb) const +bool Ray::intersects(const OBB& obb, float* distance) const { AABB aabb; aabb._min = - obb._extents; aabb._max = obb._extents; - + Ray ray; ray._direction = _direction; ray._origin = _origin; - + Mat4 mat = Mat4::IDENTITY; mat.m[0] = obb._xAxis.x; mat.m[1] = obb._xAxis.y; mat.m[2] = obb._xAxis.z; - + mat.m[4] = obb._yAxis.x; mat.m[5] = obb._yAxis.y; mat.m[6] = obb._yAxis.z; - + mat.m[8] = obb._zAxis.x; mat.m[9] = obb._zAxis.y; mat.m[10] = obb._zAxis.z; - + mat.m[12] = obb._center.x; mat.m[13] = obb._center.y; mat.m[14] = obb._center.z; - + mat = mat.getInversed(); - + ray.transform(mat); - - return ray.intersects(aabb); + + return ray.intersects(aabb, distance); + } float Ray::dist(const Plane& plane) const diff --git a/cocos/3d/CCRay.h b/cocos/3d/CCRay.h index 150c734071..42e85dc675 100644 --- a/cocos/3d/CCRay.h +++ b/cocos/3d/CCRay.h @@ -59,14 +59,14 @@ public: ~Ray(); /** - * Check whether this ray intersects the specified bounding box. + * Check whether this ray intersects with the specified AABB. */ - bool intersects(const AABB& aabb) const; - + bool intersects(const AABB& aabb, float* distance = nullptr) const; + /** - * Check whether this ray intersects the specified obb. + * Check whether this ray intersects with the specified OBB. */ - bool intersects(const OBB& obb) const; + bool intersects(const OBB& obb, float* distance = nullptr) const; float dist(const Plane& plane) const; Vec3 intersects(const Plane& plane) const; diff --git a/cocos/math/Quaternion.h b/cocos/math/Quaternion.h index 414a9b0c48..c1188456ce 100644 --- a/cocos/math/Quaternion.h +++ b/cocos/math/Quaternion.h @@ -362,6 +362,13 @@ public: */ inline const Quaternion operator*(const Quaternion& q) const; + /** + * Calculates the quaternion product of this quaternion with the given vec3. + * @param v The vec3 to multiply. + * @return The vec3 product. + */ + inline Vec3 operator*(const Vec3& v) const; + /** * Multiplies this quaternion with the given quaternion. * diff --git a/cocos/math/Quaternion.inl b/cocos/math/Quaternion.inl index 22621d01ba..b848b7f6a7 100644 --- a/cocos/math/Quaternion.inl +++ b/cocos/math/Quaternion.inl @@ -35,4 +35,17 @@ inline Quaternion& Quaternion::operator*=(const Quaternion& q) return *this; } +inline Vec3 Quaternion::operator*(const Vec3& v) const +{ + Vec3 uv, uuv; + Vec3 qvec(x, y, z); + Vec3::cross(qvec, v, &uv); + Vec3::cross(qvec, uv, &uuv); + + uv *= (2.0f * w); + uuv *= 2.0f; + + return v + uv + uuv; +} + NS_CC_MATH_END diff --git a/cocos/math/Vec3.h b/cocos/math/Vec3.h index da567aa56c..4ca185c7b8 100644 --- a/cocos/math/Vec3.h +++ b/cocos/math/Vec3.h @@ -419,14 +419,25 @@ public: */ inline const Vec3 operator/(float s) const; - /** - * Determines if this vector is less than the given vector. - * - * @param v The vector to compare against. - * - * @return True if this vector is less than the given vector, false otherwise. + /** Returns true if the vector's scalar components are all greater + that the ones of the vector it is compared against. */ - inline bool operator<(const Vec3& v) const; + inline bool operator < (const Vec3& rhs) const + { + if (x < rhs.x && y < rhs.y && z < rhs.z) + return true; + return false; + } + + /** Returns true if the vector's scalar components are all smaller + that the ones of the vector it is compared against. + */ + inline bool operator >(const Vec3& rhs) const + { + if (x > rhs.x && y > rhs.y && z > rhs.z) + return true; + return false; + } /** * Determines if this vector is equal to the given vector. diff --git a/cocos/math/Vec3.inl b/cocos/math/Vec3.inl index 2bfbc74d8d..e99ee2a774 100644 --- a/cocos/math/Vec3.inl +++ b/cocos/math/Vec3.inl @@ -74,19 +74,6 @@ inline const Vec3 Vec3::operator/(const float s) const return Vec3(this->x / s, this->y / s, this->z / s); } -inline bool Vec3::operator<(const Vec3& v) const -{ - if (x == v.x) - { - if (y == v.y) - { - return z < v.z; - } - return y < v.y; - } - return x < v.x; -} - inline bool Vec3::operator==(const Vec3& v) const { return x==v.x && y==v.y && z==v.z; diff --git a/tests/cpp-tests/Classes/Camera3DTest/Camera3DTest.cpp b/tests/cpp-tests/Classes/Camera3DTest/Camera3DTest.cpp index 151ad99a31..69b503e3fc 100644 --- a/tests/cpp-tests/Classes/Camera3DTest/Camera3DTest.cpp +++ b/tests/cpp-tests/Classes/Camera3DTest/Camera3DTest.cpp @@ -1112,7 +1112,7 @@ void CameraArcBallDemo::onEnter() { _camera=Camera::createPerspective(60, (GLfloat)s.width/s.height, 1, 1000); _camera->setCameraFlag(CameraFlag::USER1); - _camera->setPosition3D(Vec3(0, 100, 50)); + _camera->setPosition3D(Vec3(0, 10, 50)); _camera->lookAt(Vec3(0, 0, 0), Vec3(0, 1, 0)); _camera->retain(); _layer3D->addChild(_camera); @@ -1236,7 +1236,7 @@ float CameraArcBallDemo::projectToSphere( float r, float x, float y ) void CameraArcBallDemo::updateCameraTransform() { Mat4 trans, rot, center; - Mat4::createTranslation(Vec3(0.0f, 0.0f, _distanceZ), &trans); + Mat4::createTranslation(Vec3(0.0f, 10.0f, _distanceZ), &trans); Mat4::createRotation(_rotationQuat, &rot); Mat4::createTranslation(_center, ¢er); Mat4 result = center * rot * trans;