void Camera::dolly(float _px, float _py, float _x, float _y) { float dx = _px - _x; float dy = _py - _y; ofxVec3f offset = convertToLocal(0, 0, -dx - dy); eye += offset; }
void Camera::track(float _px, float _py, float _x, float _y) { float dx = _px - _x; float dy = _py - _y; ofxVec3f offset = convertToLocal(dx, dy, 0); eye += offset; center += offset; }
Curve& Curve::add(const Curve& curve) { size_t offset = getVerticesCount(); for( auto& vertex : curve.m_vertices ) addVertex(convertToLocal(curve.convertToGlobal(vertex->getCoords()))); return *this; }
void Camera::tumble(float _px, float _py, float _x, float _y) { float tolerance = 0.01; if (fabs(_x - _px) < tolerance && fabs(_y - _py) < tolerance) return; // Not enough change to have an action. /* The arcball works by pretending that a ball encloses the 3D view. You roll this pretend ball with the mouse. For example, if you click on the center of the ball and move the mouse straight to the right, you roll the ball around its Y-axis. This produces a Y-axis rotation. You can click on the "edge" of the ball and roll it around in a circle to get a Z-axis rotation. The math behind the trackball is simple: start with a vector from the first mouse-click on the ball to the center of the 3D view. At the same time, set the radius of the ball to be the smaller dimension of the 3D view. As you drag the mouse around in the 3D view, a second vector is computed from the surface of the ball to the center. The axis of rotation is the cross product of these two vectors, and the angle of rotation is the angle between the two vectors. */ ofxVec3f arcBallStart = compArcBallVector(_px, _py); ofxVec3f arcBallEnd = compArcBallVector(_x, _y); // Convert from screen position to world position arcBallStart = convertToLocal(arcBallStart); arcBallEnd = convertToLocal(arcBallEnd); //------------------------------------------- // Figure the axis and angle of rotation between the start and end point. float cosAng, sinAng, angle; float ls, le; // Take the cross product of the two vectors. r = s X e ofxVec3f axis = arcBallStart.getCrossed(arcBallEnd); // Use atan for a better angle. If you use only cos or sin, you only get // half the possible angles, and you can end up with rotations that flip // around near the poles. // cos(a) = (s . e) / (||s|| ||e||) cosAng = arcBallStart.dot(arcBallEnd); // (s . e) ls = arcBallStart.length(); ls = 1.0 / ls; // 1 / ||s|| le = arcBallEnd.length(); le = 1.0 / le; // 1 / ||e|| cosAng = cosAng * ls * le; // sin(a) = ||(s X e)|| / (||s|| ||e||) sinAng = axis.length(); // ||(s X e)|| sinAng = sinAng * ls * le; angle = atan2f(sinAng, cosAng); // Normalize the rotation axis. axis.normalize(); //------------------------------------------- // Apply the rotation to the eye. ofxQuaternion rotation, point, rotated; ofxVec3f p = eye - center; // eye moved to rotate around 0, 0, 0. point.set(p.x, p.y, p.z, 0); rotation.makeRotate(angle, axis); rotated = (rotation*point)*rotation.conj(); eye = center + rotated.asVec3(); // Apply the rotation to the up vector. point.set(up.x, up.y, up.z, 0); rotated = (rotation*point)*rotation.conj(); up = rotated.asVec3(); }
ofxVec3f Camera::convertToLocal(ofxVec3f _v) { return convertToLocal(_v.x, _v.y, _v.z); }
bool View::containsPoint(SkPoint point, View * reference) { SkPoint p = convertToLocal(point, reference); return localRect().intersects(p.x(), p.y(), p.x() + 1, p.y() + 1); }
void Light::addTriangle(Point p1, Point p2, Uint32 begin, const std::vector<Segment>& segments) { if( p1 == p2 ) return; for( size_t k(begin); k < segments.size(); k++ ) { Segment s = convertToLocal(segments[k]); double a = Vector2d::angle(s.p1, s.p2); if( a == 0 ) continue; Point p0, w1, w2; if( a > 0 ) { w1 = s.p1; w2 = s.p2; } else { w1 = s.p2; w2 = s.p1; } if( Triangle::contains(p0, p1, p2, w1) ) { Point i; Line::intersects(p0, w1, p1, p2, i); addTriangle(p1, i, k + 1, segments); p1 = i; } if( Triangle::contains(p0, p1, p2, w2) ) { Point i; Line::intersects(p0, w2, p1, p2, i); addTriangle(i, p2, k + 1, segments); p2 = i; } Point i1, i2, i3; bool int1 = s.intersects(Segment(p0, p1), i1), int2 = s.intersects(Segment(p0, p2), i2), int3 = s.intersects(Segment(p1, p2), i3); if( (int1 && i1 == p0) || (int2 && i2 == p0) || (int3 && i3 == p0) ) continue; if( int1 && int2 ) { p1 = i1; p2 = i2; } else { if( int1 && int3 ) { addTriangle(i1, i3, begin, segments); p1 = i3; } if( int2 && int3 ) { addTriangle(i2, i3, begin, segments); p2 = i3; } } } m_colors.push_back({m_color.r, m_color.g, m_color.b, char(255*(m_radius - p2.length()) / m_radius)}); m_colors.push_back({m_color.r, m_color.g, m_color.b, char(255*(m_radius - p1.length()) / m_radius)}); addFace(getVertex(0), addVertex(p1), addVertex(p2)); }