void MT_Transform::invert(const MT_Transform& t) { m_basis = t.m_type & SCALING ? t.m_basis.inverse() : t.m_basis.transposed(); m_origin.setValue(-MT_dot(m_basis[0], t.m_origin), -MT_dot(m_basis[1], t.m_origin), -MT_dot(m_basis[2], t.m_origin)); m_type = t.m_type; }
void set(RAS_MeshSlot *ms, RAS_MaterialBucket *bucket, const MT_Vector3& pnorm) { // would be good to use the actual bounding box center instead MT_Point3 pos(ms->m_OpenGLMatrix[12], ms->m_OpenGLMatrix[13], ms->m_OpenGLMatrix[14]); m_z = MT_dot(pnorm, pos); m_ms = ms; m_bucket = bucket; }
void RAS_BucketManager::sortedmeshslot::set(RAS_MeshSlot *ms, RAS_MaterialBucket *bucket, const MT_Vector3& pnorm) { // would be good to use the actual bounding box center instead float *matrix = ms->m_meshUser->GetMatrix(); const MT_Vector3 pos(matrix[12], matrix[13], matrix[14]); m_z = MT_dot(pnorm, pos); m_ms = ms; m_bucket = bucket; }
/* pnorm is the normal from the plane equation that the distance from is * used to sort again. */ void get(const RAS_TexVert *vertexarray, const unsigned short *indexarray, int offset, int nvert, const MT_Vector3& pnorm) { MT_Vector3 center(0, 0, 0); int i; for (i=0; i<nvert; i++) { m_index[i] = indexarray[offset+i]; center += vertexarray[m_index[i]].getXYZ(); } /* note we don't divide center by the number of vertices, since all * polygons have the same number of vertices, and that we leave out * the 4-th component of the plane equation since it is constant. */ m_z = MT_dot(pnorm, center); }
static int sweepCircleCircle(const MT_Vector3& pos0, const MT_Scalar r0, const MT_Vector2& v, const MT_Vector3& pos1, const MT_Scalar r1, float& tmin, float& tmax) { static const float EPS = 0.0001f; MT_Vector2 c0(pos0.x(), pos0.y()); MT_Vector2 c1(pos1.x(), pos1.y()); MT_Vector2 s = c1 - c0; MT_Scalar r = r0+r1; float c = s.length2() - r*r; float a = v.length2(); if (a < EPS) return 0; // not moving // Overlap, calc time to exit. float b = MT_dot(v,s); float d = b*b - a*c; if (d < 0.0f) return 0; // no intersection. tmin = (b - sqrtf(d)) / a; tmax = (b + sqrtf(d)) / a; return 1; }
static int sweepCircleSegment(const MT_Vector3& pos0, const MT_Scalar r0, const MT_Vector2& v, const MT_Vector3& pa, const MT_Vector3& pb, const MT_Scalar sr, float& tmin, float &tmax) { // equation parameters MT_Vector2 c0(pos0.x(), pos0.y()); MT_Vector2 sa(pa.x(), pa.y()); MT_Vector2 sb(pb.x(), pb.y()); MT_Vector2 L = sb-sa; MT_Vector2 H = c0-sa; MT_Scalar radius = r0+sr; float l2 = L.length2(); float r2 = radius * radius; float dl = perp(v, L); float hl = perp(H, L); float a = dl * dl; float b = 2.0f * hl * dl; float c = hl * hl - (r2 * l2); float d = (b*b) - (4.0f * a * c); // infinite line missed by infinite ray. if (d < 0.0f) return 0; d = sqrtf(d); tmin = (-b - d) / (2.0f * a); tmax = (-b + d) / (2.0f * a); // line missed by ray range. /* if (tmax < 0.0f || tmin > 1.0f) return 0;*/ // find what part of the ray was collided. MT_Vector2 Pedge; Pedge = c0+v*tmin; H = Pedge - sa; float e0 = MT_dot(H, L) / l2; Pedge = c0 + v*tmax; H = Pedge - sa; float e1 = MT_dot(H, L) / l2; if (e0 < 0.0f || e1 < 0.0f) { float ctmin, ctmax; if (sweepCircleCircle(pos0, r0, v, pa, sr, ctmin, ctmax)) { if (e0 < 0.0f && ctmin > tmin) tmin = ctmin; if (e1 < 0.0f && ctmax < tmax) tmax = ctmax; } else { return 0; } } if (e0 > 1.0f || e1 > 1.0f) { float ctmin, ctmax; if (sweepCircleCircle(pos0, r0, v, pb, sr, ctmin, ctmax)) { if (e0 > 1.0f && ctmin > tmin) tmin = ctmin; if (e1 > 1.0f && ctmax < tmax) tmax = ctmax; } else { return 0; } } return 1; }