HRESULT CVector3DClassFactory::CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, void** ppvObj) { CVector3D* pObj; HRESULT hr; *ppvObj = NULL; hr = E_OUTOFMEMORY; // Агрегация не поддерживается!!! if(NULL != pUnkOuter) return CLASS_E_NOAGGREGATION; pObj = new CVector3D(); if(NULL == pObj) return hr; hr = pObj->QueryInterface(riid, ppvObj); if (FAILED(hr)) delete pObj; else { g_cObj++; } return hr; }
// called after all nodes added. This function calculates the node velocities void RNSpline::BuildSpline() { if (NodeCount == 2) { Node[0].Velocity = GetStartVelocity(0); Node[NodeCount-1].Velocity = GetEndVelocity(NodeCount-1); return; } else if (NodeCount < 2) return; for (int i = 1; i < NodeCount-1; ++i) { CVector3D Next = Node[i+1].Position - Node[i].Position; CVector3D Previous = Node[i-1].Position - Node[i].Position; Next.Normalize(); Previous.Normalize(); // split the angle (figure 4) Node[i].Velocity = Next - Previous; Node[i].Velocity.Normalize(); } // calculate start and end velocities Node[0].Velocity = GetStartVelocity(0); Node[NodeCount-1].Velocity = GetEndVelocity(NodeCount-1); }
//! perpendicular connecting line between two lines bool CMathGeom3D:: LineBetweenLines(const CLine3D &line1, const CLine3D &line2, CLine3D &linei) { const CVector3D &v1 = line1.vector(); const CVector3D &v2 = line2.vector(); const CVector3D vd(line2.start(), line1.start()); double v22 = v2.dotProduct(v2); if (fabs(v22) < CMathGen::EPSILON_E6) return false; double v11 = v1.dotProduct(v1); double v21 = v2.dotProduct(v1); double d = v11*v22 - v21*v21; if (fabs(d) < CMathGen::EPSILON_E6) return false; double vd1 = vd.dotProduct(v1); double vd2 = vd.dotProduct(v2); double mu1 = (vd2*v21 - vd1*v22)/d; double mu2 = (vd2 + mu1*v21)/v22; linei = CLine3D(line1.point(mu1), line2.point(mu2)); return true; }
void TerrainOverlay::RenderTileOutline(const CColor& colour, int line_width, bool draw_hidden, ssize_t i, ssize_t j) { if (draw_hidden) { glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); } else { glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); } glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); if (line_width != 1) glLineWidth((float)line_width); CVector3D pos; glBegin(GL_QUADS); glColor4fv(colour.FloatArray()); m_Terrain->CalcPosition(i, j, pos); glVertex3fv(pos.GetFloatArray()); m_Terrain->CalcPosition(i+1, j, pos); glVertex3fv(pos.GetFloatArray()); m_Terrain->CalcPosition(i+1, j+1, pos); glVertex3fv(pos.GetFloatArray()); m_Terrain->CalcPosition(i, j+1, pos); glVertex3fv(pos.GetFloatArray()); glEnd(); if (line_width != 1) glLineWidth(1.0f); }
void CMatrix::RotateVector(const CVector3D *a, const CVector3D *b, const CVector3D *axis) { CVector3D c; if (axis == NULL) { c.CrossProduct(a, b); } else { c = *axis; } float fCos = a->DotProduct(b) / (a->Length() * b->Length()); float fSin = sqrtf(1 - (fCos * fCos)); float nCos = 1.0f - fCos; m[0][0] = ((c.x*c.x) * nCos) + fCos; m[1][0] = ((c.y*c.x) * nCos) - (c.z * fSin); m[2][0] = ((c.z*c.x) * nCos) + (c.y * fSin); m[3][0] = 0; m[0][1] = ((c.x*c.y) * nCos) + (c.z * fSin); m[1][1] = ((c.y*c.y) * nCos) + fCos; m[2][1] = ((c.z*c.y) * nCos) - (c.x * fSin); m[3][1] = 0; m[0][2] = ((c.x*c.z) * nCos) - (c.y * fSin); m[1][2] = ((c.y*c.z) * nCos) + (c.x * fSin); m[2][2] = ((c.z*c.z) * nCos) + fCos; m[3][2] = 0; m[0][3] = 0; m[1][3] = 0; m[2][3] = 0; m[3][3] = 1; }
bool CCollision::CollisionOBBShpere(const COBB &A,const CVector3D ¢er , float radius){ CVector3D V = center-A.m_center; CVector3D VL; for(int i=0;i<3;i++) { VL.v[i] = abs(CVector3D::Dot(A.m_axis[i],V)) - A.m_length[i]; if(VL.v[i]<0) VL.v[i]=0; } return (VL.Length()<radius); }
void CCamera::LookAlong(CVector3D camera, CVector3D orientation, CVector3D up) { orientation.Normalize(); up.Normalize(); CVector3D s = orientation.Cross(up); m_Orientation._11 = -s.X; m_Orientation._12 = up.X; m_Orientation._13 = orientation.X; m_Orientation._14 = camera.X; m_Orientation._21 = -s.Y; m_Orientation._22 = up.Y; m_Orientation._23 = orientation.Y; m_Orientation._24 = camera.Y; m_Orientation._31 = -s.Z; m_Orientation._32 = up.Z; m_Orientation._33 = orientation.Z; m_Orientation._34 = camera.Z; m_Orientation._41 = 0.0f; m_Orientation._42 = 0.0f; m_Orientation._43 = 0.0f; m_Orientation._44 = 1.0f; }
CVector3D CThinLens::Ray_Direction(CPoint2D _sp, CPoint2D _lp) const { CVector3D direction; CPoint2D p; p.x = _sp.x * m_f / m_d; p.y = _sp.y * m_f / m_d; direction = (p.x - _lp.x) * m_u + (p.y - _lp.y) * m_v - m_f * m_w; direction.Normalize(); return direction; }
//---------------------------------------------------------------------------------------- CVector3D CParallelProjectionGeometry2D::getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex /* = 0 */) { CVector3D vOutput; float32 fProjectionAngle = getProjectionAngle(_iProjectionIndex); vOutput.setX(cosf(fProjectionAngle)); vOutput.setY(sinf(fProjectionAngle)); vOutput.setZ(0.0f); return vOutput; }
CQuaternion::CQuaternion(const CEulerRotation & oRot) { CLog("math","CQuaternion::Constructor (CEulerRotation)",LL_OBJECT); CEulerType::EEulerAxis NextAngle[] = {CEulerType::EU_Y_AXIS, CEulerType::EU_Z_AXIS, CEulerType::EU_X_AXIS, CEulerType::EU_Y_AXIS}; CVector3D oEulerAngles = oRot.Angles(); CEulerType oType = oRot.Type(); int iFirstAxis = oType.InnerAxis(); int iSecondAxis = NextAngle[iFirstAxis + (oType.OddParity() ? 1 : 0)]; int iThirdAxis = NextAngle[iFirstAxis + 1 - (oType.OddParity() ? 1 : 0)]; if (oType.RotatingFrame()) { double dTemp = oEulerAngles.X(); oEulerAngles.X() = oEulerAngles.Z(); oEulerAngles.Z() = dTemp; } if (oType.OddParity()) { oEulerAngles.Y() = -oEulerAngles.Y(); } double dHF = oEulerAngles.X() * 0.5; double dHS = oEulerAngles.Y() * 0.5; double dHT = oEulerAngles.Z() * 0.5; double dCHF = cos(dHF); double dCHS = cos(dHS); double dCHT = cos(dHT); double dSHF = sin(dHF); double dSHS = sin(dHS); double dSHT = sin(dHT); double dCHFxCHT = dCHF * dCHT; double dCHFxSHT = dCHF * dSHT; double dSHFxCHT = dSHF * dCHT; double dSHFxSHT = dSHF * dSHT; double a[3]; if (oType.Repetition()) { a[iFirstAxis] = dCHS * (dCHFxSHT + dSHFxCHT); a[iSecondAxis] = dSHS * (dCHFxCHT + dSHFxSHT); a[iThirdAxis] = dSHS * (dCHFxSHT - dSHFxCHT); m_dScalar = dCHS * (dCHFxCHT - dSHFxSHT); } else { a[iFirstAxis] = dCHS * dSHFxCHT - dSHS * dCHFxSHT; a[iSecondAxis] = dCHS * dSHFxSHT + dSHS * dCHFxCHT; a[iThirdAxis] = dCHS * dCHFxSHT - dSHS * dSHFxCHT; m_dScalar = dCHS * dCHFxCHT + dSHS * dSHFxSHT; } if (oType.OddParity()) { a[iSecondAxis] = -a[iSecondAxis]; } m_oVector.FromDouble(a[0], a[1], a[2]); Normalise(); return; } //CQuaternion(const CEulerRotation & oRot)
float CMatrix3D::GetYRotation() const { // Project the X axis vector onto the XZ plane CVector3D axis = -GetLeft(); axis.Y = 0; // Normalise projected vector float len = axis.Length(); if (len < 0.0001f) return 0.f; axis *= 1.0f/len; // Negate the return angle to match the SetYRotation convention return -atan2(axis.Z, axis.X);
void CalcNormal(CPoint3D v[3], CVector3D &out) { CVector3D v1,v2; //static const int x = 0; //static const int y = 1; //static const int z = 2; // Calculate two vectors from the three points //v1.dx = v[0].x - v[1].x; //v1.dy = v[0].y - v[1].y; //v1.dz = v[0].z - v[1].z; v1=v[0]-v[1]; //v2.dx = v[1].x - v[2].x; //v2.dy = v[1].y - v[2].y; //v2.dz = v[1].z - v[2].z; v2=v[1]-v[2]; // Take the cross product of the two vectors to get // the normal vector which will be stored in out //out.dx = v1.dy*v2.dz - v1.dz*v2.dy; //out.dy = v1.dz*v2.dx - v1.dx*v2.dz; //out.dz= v1.dx*v2.dy - v1.dy*v2.dx; out = v1*v2; // Normalize the vector (shorten length to one) out.Normalize(); }
void CGameView::ResetCameraAngleZoom() { CCamera targetCam = m->ViewCamera; SetupCameraMatrixNonSmooth(m, &targetCam.m_Orientation); // Compute the zoom adjustment to get us back to the default CVector3D forwards = targetCam.m_Orientation.GetIn(); CVector3D pivot = GetSmoothPivot(targetCam); CVector3D delta = pivot - targetCam.m_Orientation.GetTranslation(); float dist = delta.Dot(forwards); m->Zoom.AddSmoothly(m->ViewZoomDefault - dist); // Reset orientations to default m->RotateX.SetValueSmoothly(DEGTORAD(m->ViewRotateXDefault)); m->RotateY.SetValueSmoothly(DEGTORAD(m->ViewRotateYDefault)); }
void TerrainOverlay::RenderTile(const CColor& colour, bool draw_hidden, ssize_t i, ssize_t j) { // TODO: if this is unpleasantly slow, make it much more efficient // (e.g. buffering data and making a single draw call? or at least // far fewer calls than it makes now) if (draw_hidden) { glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); } else { glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); } #if CONFIG2_GLES #warning TODO: implement TerrainOverlay::RenderTile for GLES #else glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); CVector3D pos; glBegin(GL_TRIANGLES); glColor4fv(colour.FloatArray()); if (m_Terrain->GetTriangulationDir(i, j)) { m_Terrain->CalcPosition(i, j, pos); glVertex3fv(pos.GetFloatArray()); m_Terrain->CalcPosition(i+1, j, pos); glVertex3fv(pos.GetFloatArray()); m_Terrain->CalcPosition(i, j+1, pos); glVertex3fv(pos.GetFloatArray()); m_Terrain->CalcPosition(i+1, j, pos); glVertex3fv(pos.GetFloatArray()); m_Terrain->CalcPosition(i+1, j+1, pos); glVertex3fv(pos.GetFloatArray()); m_Terrain->CalcPosition(i, j+1, pos); glVertex3fv(pos.GetFloatArray()); } else { m_Terrain->CalcPosition(i, j, pos); glVertex3fv(pos.GetFloatArray()); m_Terrain->CalcPosition(i+1, j, pos); glVertex3fv(pos.GetFloatArray()); m_Terrain->CalcPosition(i+1, j+1, pos); glVertex3fv(pos.GetFloatArray()); m_Terrain->CalcPosition(i+1, j+1, pos); glVertex3fv(pos.GetFloatArray()); m_Terrain->CalcPosition(i, j+1, pos); glVertex3fv(pos.GetFloatArray()); m_Terrain->CalcPosition(i, j, pos); glVertex3fv(pos.GetFloatArray()); } glEnd(); #endif }
void CSoundBase::SetDirection(const CVector3D& direction) { if ( m_ALSource ) { CScopeLock lock(m_ItemMutex); alSourcefv(m_ALSource, AL_DIRECTION, direction.GetFloatArray()); AL_CHECK; } }
void CSoundBase::SetLocation (const CVector3D& position) { if ( m_ALSource != 0 ) { CScopeLock lock(m_ItemMutex); alSourcefv(m_ALSource,AL_POSITION, position.GetFloatArray()); AL_CHECK; } }
CVector3D CModelDef::SkinNormal(const SModelVertex& vtx, const CMatrix3D newPoseMatrices[]) { // To be correct, the normal vectors apparently need to be multiplied by the // inverse of the transpose. Unfortunately inverses are slow. // If a matrix is orthogonal, M * M^T = I and so the inverse of the transpose // is the original matrix. But that's not entirely relevant here, because // the bone matrices include translation components and so they're not // orthogonal. // But that's okay because we have // M = T * R // and want to find // n' = (M^T^-1) * n // = (T * R)^T^-1 * n // = (R^T * T^T)^-1 * n // = (T^T^-1 * R^T^-1) * n // R is indeed orthogonal so R^T^-1 = R. T isn't orthogonal at all. // But n is only a 3-vector, and from the forms of T and R (which have // lots of zeroes) I can convince myself that replacing T with T^T^-1 has no // effect on anything but the fourth component of M^T^-1 - and the fourth // component is discarded since it has no effect on n', and so we can happily // use n' = M*n. // // (This isn't very good as a proof, but it's better than assuming M is // orthogonal when it's clearly not.) CVector3D result (0, 0, 0); for (int i = 0; i < SVertexBlend::SIZE && vtx.m_Blend.m_Bone[i] != 0xff; ++i) { result += newPoseMatrices[vtx.m_Blend.m_Bone[i]].Rotate(vtx.m_Norm) * vtx.m_Blend.m_Weight[i]; } // If there was more than one influence, the result is probably not going // to be of unit length (since it's a weighted sum of several independent // unit vectors), so we need to normalise it. // (It's fairly common to only have one influence, so it seems sensible to // optimise that case a bit.) if (vtx.m_Blend.m_Bone[1] != 0xff) // if more than one influence result.Normalize(); return result; }
void CBoundingBoxAligned::Transform(const CMatrix3D& transform, CBoundingBoxOriented& result) const { // The idea is this: compute the corners of this bounding box, transform them according to the specified matrix, // then derive the box center, orientation vectors, and half-sizes. // TODO: this implementation can be further optimized; see Philip's comments on http://trac.wildfiregames.com/ticket/914 const CVector3D& pMin = m_Data[0]; const CVector3D& pMax = m_Data[1]; // Find the corners of these bounds. We only need some of the corners to derive the information we need, so let's // not actually compute all of them. The corners are numbered starting from the minimum position (m_Data[0]), going // counter-clockwise in the bottom plane, and then in the same order for the top plane (starting from the corner // that's directly above the minimum position). Hence, corner0 is pMin and corner6 is pMax, so we don't need to // custom-create those. CVector3D corner0; // corner0 is pMin, no need to copy it CVector3D corner1(pMax.X, pMin.Y, pMin.Z); CVector3D corner3(pMin.X, pMin.Y, pMax.Z); CVector3D corner4(pMin.X, pMax.Y, pMin.Z); CVector3D corner6; // corner6 is pMax, no need to copy it // transform corners to world space corner0 = transform.Transform(pMin); // = corner0 corner1 = transform.Transform(corner1); corner3 = transform.Transform(corner3); corner4 = transform.Transform(corner4); corner6 = transform.Transform(pMax); // = corner6 // Compute orientation vectors, half-size vector, and box center. We can get the orientation vectors by just taking // the directional vectors from a specific corner point (corner0) to the other corners, once in each direction. The // half-sizes are similarly computed by taking the distances of those sides and dividing them by 2. Finally, the // center is simply the middle between the transformed pMin and pMax corners. const CVector3D sideU(corner1 - corner0); const CVector3D sideV(corner4 - corner0); const CVector3D sideW(corner3 - corner0); result.m_Basis[0] = sideU.Normalized(); result.m_Basis[1] = sideV.Normalized(); result.m_Basis[2] = sideW.Normalized(); result.m_HalfSizes = CVector3D( sideU.Length()/2.f, sideV.Length()/2.f, sideW.Length()/2.f ); result.m_Center = (corner0 + corner6) * 0.5f; }
//! intersection of line and plane bool CMathGeom3D:: LinePlaneIntersect(const CVector3D &vector1, const CVector3D &vector2, const CVector3D &normal, double normalc, CVector3D &ipoint, double &iparam) { CVector3D direction = vector2 - vector1; double d1 = direction.dotProduct(normal); if (fabs(d1) < CMathGen::EPSILON_E6) return false; double d2 = vector1.dotProduct(normal); iparam = (normalc - d2)/d1; ipoint = vector1 + direction*iparam; return true; }
void CClassifyGrid::GetNeighbor( PointData & point, int dis, CClassifyChunk * chunk, int x, int y ) { m_vecPointData.clear(); double distance = m_dbGridLength * dis; double distance2 = distance * distance; for ( int xx = x - dis; xx <= x + dis; xx++ ) for ( int yy = y - dis; yy <= y + dis; yy++ ) { int i = xx; int j = yy; CClassifyChunk * data_chunk = chunk; while ( i < 0 && data_chunk != NULL ) { i += m_nUnitNumber[ 0 ]; data_chunk = InBound( data_chunk->m_iX - 1, data_chunk->m_iY ) ? m_vecPointer[ Index( data_chunk->m_iX - 1, data_chunk->m_iY ) ] : NULL; } while ( i > m_nUnitNumber[ 0 ] - 1 && data_chunk != NULL ) { i -= m_nUnitNumber[ 0 ]; data_chunk = InBound( data_chunk->m_iX + 1, data_chunk->m_iY ) ? m_vecPointer[ Index( data_chunk->m_iX + 1, data_chunk->m_iY ) ] : NULL; } while ( j < 0 && data_chunk != NULL ) { j += m_nUnitNumber[ 1 ]; data_chunk = InBound( data_chunk->m_iX, data_chunk->m_iY - 1 ) ? m_vecPointer[ Index( data_chunk->m_iX, data_chunk->m_iY - 1 ) ] : NULL; } while ( j > m_nUnitNumber[ 1 ] - 1 && data_chunk != NULL ) { j -= m_nUnitNumber[ 1 ]; data_chunk = InBound( data_chunk->m_iX, data_chunk->m_iY + 1 ) ? m_vecPointer[ Index( data_chunk->m_iX, data_chunk->m_iY + 1 ) ] : NULL; } if ( data_chunk != NULL ) { PointDataVector & cell_vector = data_chunk->m_vecGridIndex[ data_chunk->Index( i, j ) ]; for ( int k = 0; k < ( int )cell_vector.size(); k++ ) { CVector3D diff = point.v - ( cell_vector[ k ] )->v; if ( diff.length2() < distance2 ) { m_vecPointData.push_back( cell_vector[ k ] ); } } } } }
// if the point is on the left of the triangle, then it is in the triangle BOOL CPoint3D::IsInTheTriangle(CPoint3D p1, CPoint3D p2, CPoint3D p3) const { CVector3D normal = (p2-p1)*(p3-p2); normal.Normalize(); if ( this->IsAtTheLeftOf(p1, p2, normal)==0 || this->IsAtTheLeftOf(p2, p3, normal)==0 || this->IsAtTheLeftOf(p3, p1, normal)==0) { return 0; //one the triangle's side } else { if ( this->IsAtTheLeftOf(p1, p2, normal)==1 && this->IsAtTheLeftOf(p2, p3, normal)==1 && this->IsAtTheLeftOf(p3, p1, normal)==1 ) { return 1; //in the triangle } else return -1; //out the triangle } }
//rotate the camera angleInc radians around a unit vector void CGraphicsCamera::Rotate( CVector3D axis, double angleInc ) { CQuaternion quat( angleInc, axis.normalize() ); double m[4][4] = {0.}; quat.QuatToMat( m ); CVector3D v1( m_pos, m_focalPt ); //multiply our view vector by the rotation matrix v1 = v1*m; //update our position m_pos = CPoint3D( v1.x + m_focalPt.x, v1.y + m_focalPt.y, v1.z + m_focalPt.z ); //update our camera's up vector m_up = m_up*m; }
Noise3D::Noise3D(int f, int v) : freq(f), vfreq(v) { grads = new CVector3D**[freq]; for(int i=0; i<freq; i++) { grads[i] = new CVector3D*[freq]; for(int j=0; j<freq; j++) { grads[i][j] = new CVector3D[vfreq]; for(int k=0; k<vfreq; k++) { CVector3D vec; do { vec = CVector3D(2*randFloat()-1, 2*randFloat()-1, 2*randFloat()-1); } while(vec.LengthSquared() > 1 || vec.LengthSquared() < 0.1); vec.Normalize(); grads[i][j][k] = CVector3D(vec.X, vec.Y, vec.Z); } } } }
//modified by wangxin CMatrix3D CMatrix3D::CreateRotateMatrix( double da, CVector3D bv ) { bv.Normalize(); CMatrix3D matrix; matrix.a[0] = bv.dx*bv.dx*(1-cos(da))+cos(da); matrix.a[5] = bv.dy*bv.dy*(1-cos(da))+cos(da); matrix.a[10] = bv.dz*bv.dz*(1-cos(da))+cos(da); matrix.a[1] = bv.dx*bv.dy*(1-cos(da))+bv.dz*sin(da); matrix.a[4] = bv.dx*bv.dy*(1-cos(da))-bv.dz*sin(da); matrix.a[2] = bv.dx*bv.dz*(1-cos(da))-bv.dy*sin(da); matrix.a[8] = bv.dx*bv.dz*(1-cos(da))+bv.dy*sin(da); matrix.a[6] = bv.dy*bv.dz*(1-cos(da))+bv.dx*sin(da); matrix.a[9] = bv.dy*bv.dz*(1-cos(da))-bv.dx*sin(da); matrix.a[3] = matrix.a[7] = matrix.a[11] = matrix.a[12] = matrix.a[13] = matrix.a[14] = 0; matrix.a[15] = 1; return matrix; }
/////////////////////////////////////////////////////////////////////////////// // CalcNormal: calculate the world space normal of the vertex at (i,j) void CTerrain::CalcNormal(ssize_t i, ssize_t j, CVector3D& normal) const { CVector3D left, right, up, down; // Calculate normals of the four half-tile triangles surrounding this vertex: // get position of vertex where normal is being evaluated CVector3D basepos; CalcPosition(i, j, basepos); if (i > 0) { CalcPosition(i-1, j, left); left -= basepos; left.Normalize(); } if (i < m_MapSize-1) { CalcPosition(i+1, j, right); right -= basepos; right.Normalize(); } if (j > 0) { CalcPosition(i, j-1, up); up -= basepos; up.Normalize(); } if (j < m_MapSize-1) { CalcPosition(i, j+1, down); down -= basepos; down.Normalize(); } CVector3D n0 = up.Cross(left); CVector3D n1 = left.Cross(down); CVector3D n2 = down.Cross(right); CVector3D n3 = right.Cross(up); // Compute the mean of the normals normal = n0 + n1 + n2 + n3; float nlen=normal.Length(); if (nlen>0.00001f) normal*=1.0f/nlen; }
//! intersection of line and plane bool CMathGeom3D:: LinePlaneIntersect(const CPoint3D &point, const CVector3D &direction, const CNPlane3D &normal, CPoint3D &ipoint, double &iparam) { double d1 = direction.dotProduct(normal.getDirection()); if (fabs(d1) < CMathGen::EPSILON_E6) return false; CVector3D vector1(point); double d2 = vector1.dotProduct(normal.getDirection()); iparam = (normal.getScalar() - d2)/d1; ipoint = point + direction*iparam; return true; }
bool CGraphicsCamera::MouseMove( const CPoint& delta ) { float dx = float( delta.x ); float dy = float( delta.y ); CVector3D v1( m_pos, m_focalPt ); CVector3D right = v1.normalize().cross( m_up ); CVector3D up = m_up; right *= dx; up *= dy; m_pos = m_pos + up.asPoint3D() + right.asPoint3D(); m_focalPt = m_focalPt + up.asPoint3D() + right.asPoint3D(); return true; }
void CCamera::BuildCameraRay(int px, int py, CVector3D& origin, CVector3D& dir) const { CVector3D cPts[4]; GetCameraPlanePoints(m_FarPlane, cPts); // transform to world space CVector3D wPts[4]; for (int i = 0; i < 4; i++) wPts[i] = m_Orientation.Transform(cPts[i]); // get world space position of mouse point float dx = (float)px / (float)g_Renderer.GetWidth(); float dz = 1 - (float)py / (float)g_Renderer.GetHeight(); CVector3D vdx = wPts[1] - wPts[0]; CVector3D vdz = wPts[3] - wPts[0]; CVector3D pt = wPts[0] + (vdx * dx) + (vdz * dz); // copy origin origin = m_Orientation.GetTranslation(); // build direction dir = pt - origin; dir.Normalize(); }
////////////////////////////////////////////////////////////////////////////// // SetupFrame: camera and light direction for this frame void ShadowMap::SetupFrame(const CCamera& camera, const CVector3D& lightdir) { if (!m->Texture) m->CreateTexture(); CVector3D z = lightdir; CVector3D y; CVector3D x = camera.m_Orientation.GetIn(); CVector3D eyepos = camera.m_Orientation.GetTranslation(); z.Normalize(); x -= z * z.Dot(x); if (x.Length() < 0.001) { // this is invoked if the camera and light directions almost coincide // assumption: light direction has a significant Z component x = CVector3D(1.0, 0.0, 0.0); x -= z * z.Dot(x); } x.Normalize(); y = z.Cross(x); // X axis perpendicular to light direction, flowing along with view direction m->LightTransform._11 = x.X; m->LightTransform._12 = x.Y; m->LightTransform._13 = x.Z; // Y axis perpendicular to light and view direction m->LightTransform._21 = y.X; m->LightTransform._22 = y.Y; m->LightTransform._23 = y.Z; // Z axis is in direction of light m->LightTransform._31 = z.X; m->LightTransform._32 = z.Y; m->LightTransform._33 = z.Z; // eye is at the origin of the coordinate system m->LightTransform._14 = -x.Dot(eyepos); m->LightTransform._24 = -y.Dot(eyepos); m->LightTransform._34 = -z.Dot(eyepos); m->LightTransform._41 = 0.0; m->LightTransform._42 = 0.0; m->LightTransform._43 = 0.0; m->LightTransform._44 = 1.0; m->LightTransform.GetInverse(m->InvLightTransform); m->ShadowBound.SetEmpty(); // m->LightspaceCamera = camera; m->LightspaceCamera.m_Orientation = m->LightTransform * camera.m_Orientation; m->LightspaceCamera.UpdateFrustum(); }
CVector3D CGraphicsCamera::GetRightVector() { CVector3D forward = GetForwardVector(); return forward.cross( m_up ).normalize(); }