// P - source point, A - direction // C - sphere center, R - radius bool IntersectRayToSphere( const LVector3& P, const LVector3& A, const LVector3& C, float R ) { float t = -( P.Dot( A ) - A.Dot( C ) ) / A.Dot( A ); LVector3 v = P + A * t - C; return ( v.Dot( v ) <= R * R ); }
bool IntersectRayToBox( const LVector3& P, const LVector3& A, const LVector3& Pos, LVector3* V, const LVector3& Size, LVector3& isect ) { float Sign[] = { -1, -1, -1, +1, +1, +1 }; // distance to source point; float _dist = -1.0f; bool Intersection = false; // check six faces for ( int i = 0 ; i < 6 ; i++ ) { LVector3 Pt = Sign[i] * V[i % 3] * Size[i % 3] * 0.5f; LVector3 N = Pt.GetNormalized(); Pt = P + Pt; float D = N.Dot( Pt ); LVector3 LocalISect; if ( IntersectRayToPlane( P, A, N, D, LocalISect ) ) { // plane vectors LVector3 V1 = V[( i+1 )%3]; LVector3 V2 = V[( i+2 )%3]; float szX = Size[( i+1 )%3]; float szY = Size[( i+2 )%3]; // project to plane float x = ( LocalISect - Pt ).Dot( V1 ); float y = ( LocalISect - Pt ).Dot( V2 ); // check if the point is inside the rectangle if ( x > -szX / 2 && x < szX / 2 && y > -szY / 2 && y < szY / 2 ) { Intersection = true; // it is, compare its distance to P - to select the closest one float _newDist = ( isect - P ).Length(); if ( _dist < 0.0f || _newDist < _dist ) { isect = LocalISect; _dist = _newDist; } } } } return Intersection; }
bool IntersectRayToPlane( const LVector3& P, const LVector3& A, const LVector3& N, float D, LVector3& isect ) { float denom = A.Dot( N ); if ( fabs( denom ) < 0.0001f ) { return false; } float t = -( D + P.Dot( N ) ) / denom; isect = P + A * t; return true; }
void clGraph::From2DGrid( const LVector3& Center, const LVector3& V1, const LVector3& V2, float SizeX, float SizeY, int Nx, int Ny, int Conn ) { ClearGraph(); LVector3 N = V1.Cross( V2 ); // common orientation for all nodes LQuaternion Orientation; Orientation.FromAxisAngle( N, 0.0f ); float CellX = SizeX / Nx; float CellY = SizeY / Ny; FOriented = false; FLocalOrientations.resize( Nx * Ny ); FVertices.resize( Nx * Ny ); for ( int i = 0 ; i < Nx ; i++ ) { for ( int j = 0 ; j < Ny ; j++ ) { int ThisNode = NodeForPair( i, j, Nx, Ny ); FLocalOrientations[ThisNode] = Orientation; FVertices[ThisNode] = Center + V1 * static_cast<float>( i - Nx / 2 ) * CellX + V2 * static_cast<float>( j - Ny / 2 ) * CellY; // add 4-connected edges int West = NodeForPair( i - 1, j, Nx, Ny ); int East = NodeForPair( i + 1, j, Nx, Ny ); int North = NodeForPair( i, j - 1, Nx, Ny ); int South = NodeForPair( i, j - 1, Nx, Ny ); if ( West > -1 ) { FEdge0.push_back( ThisNode ); FEdge1.push_back( West ); } if ( East > -1 ) { FEdge0.push_back( ThisNode ); FEdge1.push_back( East ); } if ( North > -1 ) { FEdge0.push_back( ThisNode ); FEdge1.push_back( North ); } if ( South > -1 ) { FEdge0.push_back( ThisNode ); FEdge1.push_back( South ); } if ( Conn > 4 ) { int NW = NodeForPair( i - 1, j - 1, Nx, Ny ); int NE = NodeForPair( i + 1, j - 1, Nx, Ny ); int SW = NodeForPair( i - 1, j + 1, Nx, Ny ); int SE = NodeForPair( i + 1, j + 1, Nx, Ny ); if ( NW > -1 ) { FEdge0.push_back( ThisNode ); FEdge1.push_back( NW ); } if ( NE > -1 ) { FEdge0.push_back( ThisNode ); FEdge1.push_back( NE ); } if ( SW > -1 ) { FEdge0.push_back( ThisNode ); FEdge1.push_back( SW ); } if ( SE > -1 ) { FEdge0.push_back( ThisNode ); FEdge1.push_back( SE ); } } } } }
void clAudioSource_OpenAL::SetVelocity( const LVector3& Velocity ) { #if L_AUDIO_USE_OPENAL alSourcef( FSourceID, AL_REFERENCE_DISTANCE, 1.0 ); alSourcefv( FSourceID, AL_VELOCITY, Velocity.ToFloatPtr() ); #endif }
void clAudioSource_OpenAL::SetPosition( const LVector3& Position ) { #if L_AUDIO_USE_OPENAL alSourcef( FSourceID, AL_REFERENCE_DISTANCE, 1.0 ); alSourcefv( FSourceID, AL_POSITION, Position.ToFloatPtr() ); #endif }
//---------------------------------------------------------------------- // //---------------------------------------------------------------------- void CylinderMouseMoveCameraOperator::_doMouseMoveM( lnFloat dx, lnFloat dy ) { LVector3 pos = getTargetCamera()->getPosition(); LVector3 look_at = getTargetCamera()->getLookAt(); lnFloat s = 0.00175f * ( pos - look_at ).GetLength(); LVector3 view; LMatrix mat = LMatrix::Inverse(getTargetCamera()->getViewMatrix()); mat.M[3][0] = mat.M[3][1] = mat.M[3][2] = 0.0f; view.X = -dx * s; view.Y = dy * s; view.Z = 0.f; view.TransformCoord( mat ); getTargetCamera()->setPosition( pos + view ); getTargetCamera()->setLookAt( look_at + view ); }
bool IntersectRayToTriangle( const LVector3& P, const LVector3& A, const LVector3& V1, const LVector3& V2, const LVector3& V3, LVector3& isect ) { LVector3 N = ( V3 - V2 ).Cross( V2 - V1 ); if ( !IntersectRayToPlane( P, A, N , -N.Dot( V1 ), isect ) ) { return false; } // try cross products LVector3 l1 = V1 - isect; LVector3 l2 = V2 - isect; LVector3 l3 = V3 - isect; float lam1 = ( l1 ).Cross( l2 ).Dot( N ); float lam2 = ( l2 ).Cross( l3 ).Dot( N ); float lam3 = ( l3 ).Cross( l1 ).Dot( N ); // unnormalized barycentric coordinates must be of the same sign (the sign depends on N's direction and does not matter) return ( ( lam1 < 0 && lam2 < 0 && lam3 < 0 ) || ( lam1 > 0 && lam2 > 0 && lam3 > 0 ) ); }
void LFrustum::CalcFrustumInBasis( const LVector3& Pos, const LVector3& To, const LVector3& Up, float fw, float fh, float nw, float nh ) { LVector3 Z = Pos - To; Z.Normalize(); LVector3 X = Up.Cross( Z ); X.Normalize(); LVector3 Y = Z.Cross( X ); LVector3 nc = Pos - Z * FNearClipPlane; LVector3 fc = Pos - Z * FFarClipPlane; FCornerPoints[FRUSTUM_ntl] = nc + Y * nh - X * nw; FCornerPoints[FRUSTUM_ntr] = nc + Y * nh + X * nw; FCornerPoints[FRUSTUM_nbl] = nc - Y * nh - X * nw; FCornerPoints[FRUSTUM_nbr] = nc - Y * nh + X * nw; FCornerPoints[FRUSTUM_ftl] = fc + Y * fh - X * fw; FCornerPoints[FRUSTUM_ftr] = fc + Y * fh + X * fw; FCornerPoints[FRUSTUM_fbl] = fc - Y * fh - X * fw; FCornerPoints[FRUSTUM_fbr] = fc - Y * fh + X * fw; for ( int i = PLANE_LEFT ; i < PLANE_FAR + 1 ; i++ ) { LVector3 P1 = FCornerPoints[ static_cast<int>( FrustumPlanePoints[i].X ) ]; LVector3 P2 = FCornerPoints[ static_cast<int>( FrustumPlanePoints[i].Y ) ]; LVector3 P3 = FCornerPoints[ static_cast<int>( FrustumPlanePoints[i].Z ) ]; TODO( "store planes as LPlane, not as Vector4 !" ) // FPlanes[i].From3Points(P1, P2, P3); } }
int CharacterScriptInterface:: SummonEnemy(lua_State *l_) { Weapon::CreateData wdata; wdata.Data.WeaponType = static_cast<WeaponType>(::rand() % (WEAPON_NORMAL_MAX_NUM - 1) + 1); wdata.Data.UseCount = gWeaponBaseData[wdata.Data.WeaponType].UseCount; LVector3 v ; v.set(900,1000,0); v.x += ::rand() % 300 - 150; v.y += 180; wdata.Position = v; Weapon::create( &wdata ); Enemy* mEnemy1 = Enemy::createRandom(); mEnemy1->setPosition(LVector3(700,1000,1)); mEnemy1->setDefPosition(LVector3(700,1000,1)); mEnemy1->setScore(1); Enemy* mEnemy = Enemy::createRandom(); mEnemy->setPosition(LVector3(1200,1000,1)); mEnemy->setDefPosition(LVector3(1200,1000,1)); mEnemy->setScore(1); return 0; }
// old Pascal source ... bool ClosestPointsOnLines( const LVector3& Pt1, const LVector3& Dir1, const LVector3& Pt2, const LVector3& Dir2, float& t1, float& t2 ) { float C0, C1; float a11, a12, a21, a22; float det1, detA, detB; C0 = ( Pt2 - Pt1 ).Dot( Dir1 ); C1 = ( Pt2 - Pt1 ).Dot( Dir2 ); a11 = +Dir1.Dot( Dir1 ); a12 = -Dir1.Dot( Dir2 ); a21 = -a12; a22 = -Dir2.Dot( Dir2 ); det1 = a11 * a22 - a21 * a12; FIXME( "perform approximate IsZero() check" ) if ( det1 != 0.0f ) { detA = C0 * a22 - C1 * a12; detB = a11 * C1 - a21 * C0; t1 = detA / det1; t2 = detB / det1; return true; } // no single point , but we just give a required pair t1 = C0 / a11; t2 = 0; return false; }
void LFrustum::CreateFrustum( const LMatrix4& Projection, const LMatrix4& ModelView ) { LMatrix4 ProjModelView = ModelView * Projection; for ( int i = 0; i != 4; ++i ) { FPlanes[0][i] = ProjModelView[i][3] + ProjModelView[i][0]; // left FPlanes[1][i] = ProjModelView[i][3] - ProjModelView[i][0]; // right FPlanes[2][i] = ProjModelView[i][3] - ProjModelView[i][1]; // top FPlanes[3][i] = ProjModelView[i][3] + ProjModelView[i][1]; // bottom FPlanes[4][i] = ProjModelView[i][3] + ProjModelView[i][2]; // near FPlanes[5][i] = ProjModelView[i][3] - ProjModelView[i][2]; // far } for ( int i = 0; i != 6; ++i ) { LVector3 Vec = FPlanes[i].ToVector3(); float Len = Vec.Length(); if ( Len > Linderdaum::Math::EPSILON ) { FPlanes[i] /= Len; } } }
// build the basis of complementary 2-dimensional space void BuildComplementaryBasis( const LVector3& N, LVector3& V1, LVector3& V2 ) { V1 = N.Cross( vec3( 1, 0, 0 ) ); if ( V1.SqrLength() <= Linderdaum::Math::EPSILON ) { V1 = N.Cross( vec3( 0, 1, 0 ) ); if ( V1.SqrLength() <= Linderdaum::Math::EPSILON ) { V1 = N.Cross( vec3( 0, 0, 1 ) ); } } V2 = N.Cross( V1 ); V1.Normalize(); V2.Normalize(); }
void clVAMender::CalculateTBN( clVertexAttribs* CurrentVA, int ForSubMaterial ) { if ( !FTextureFaces.size() ) { return; } // split vertices //LVector3* Tangents = CurrentVA->GetTangents(); //LVector3* Binormals = CurrentVA->GetBinormals(); bool CalcNormals = FNormals.empty(); int Idx = 0; for ( size_t i = 0; i != FFaces.size(); ++i ) { if ( FFacesSubMaterial[i] != ForSubMaterial ) { continue; } int VertexIndex1 = static_cast<int>( FFaces[Idx][0] ); int VertexIndex2 = static_cast<int>( FFaces[Idx][1] ); int VertexIndex3 = static_cast<int>( FFaces[Idx][2] ); int OutputVertexIndex1 = Idx * 3 + 0; int OutputVertexIndex2 = Idx * 3 + 1; int OutputVertexIndex3 = Idx * 3 + 2; int CurrentFaceSG = FFacesSmoothingGroup[ Idx ]; LVector3 p1 = FVertices[VertexIndex1]; LVector3 p2 = FVertices[VertexIndex2]; LVector3 p3 = FVertices[VertexIndex3]; int TextureIndex1 = static_cast<int>( FTextureFaces[Idx][0] ); int TextureIndex2 = static_cast<int>( FTextureFaces[Idx][1] ); int TextureIndex3 = static_cast<int>( FTextureFaces[Idx][2] ); float u1 = FTextureVertices[TextureIndex1].X; float v1 = FTextureVertices[TextureIndex1].Y; float u2 = FTextureVertices[TextureIndex2].X; float v2 = FTextureVertices[TextureIndex2].Y; float u3 = FTextureVertices[TextureIndex3].X; float v3 = FTextureVertices[TextureIndex3].Y; float Tdenom = ( u2 - u1 ) * ( v3 - v1 ) - ( v2 - v1 ) * ( u3 - u1 ); float Bdenom = ( v2 - v1 ) * ( u3 - u1 ) - ( u2 - u1 ) * ( v3 - v1 ); LVector3 LocalBinormal = ( ( u3 - u1 ) * ( p2 - p1 ) - ( u2 - u1 ) * ( p3 - p1 ) ) / Bdenom; LVector3 LocalTangent = ( ( v3 - v1 ) * ( p2 - p1 ) - ( v2 - v1 ) * ( p3 - p1 ) ) / Tdenom; if ( CalcNormals ) { // LVector3* Normals = CurrentVA->GetNormals(); LVector3 LocalNormal = ( p3 - p1 ).Cross( p2 - p1 ); // LVector3 LocalNormal = LocalTangent.Cross(LocalBinormal); LocalNormal.Normalize(); int Index; Index = FSplitVertexToSGVertex_VIndex[ OutputVertexIndex1 ]; FSGN[ CurrentFaceSG ][ Index ] += LocalNormal; Index = FSplitVertexToSGVertex_VIndex[ OutputVertexIndex2 ]; FSGN[ CurrentFaceSG ][ Index ] += LocalNormal; Index = FSplitVertexToSGVertex_VIndex[ OutputVertexIndex3 ]; FSGN[ CurrentFaceSG ][ Index ] += LocalNormal; // Normals[OutputVertexIndex1] = LocalNormal; // Normals[OutputVertexIndex2] = LocalNormal; // Normals[OutputVertexIndex3] = LocalNormal; } Idx++; } LVector3* Normals = CurrentVA->FNormals.GetPtr(); for ( size_t j = 0 ; j != CurrentVA->FVertices.size(); j++ ) { if ( CalcNormals ) { int SG = FSplitVertexToSGVertex_SGNum[ j ]; int Index = FSplitVertexToSGVertex_VIndex[ j ]; Normals[j] = FSGN[ SG ][ Index ]; Normals[j].Normalize(); // Env->Logger->Log( L_DEBUG, "Dumping normal: Vertex: " +LStr::ToStr(j) + "(SG:"+LStr::ToStr(SG)+" Idx:"+LStr::ToStr(Index)+") Normal: " + Vec3ToString( Normals[j], ',' ) ); } } }
void clAudioSubSystem_OpenAL::SetListenerVelocity( const LVector3& Velocity ) { #if L_AUDIO_USE_OPENAL alListenerfv( AL_VELOCITY, Velocity.ToFloatPtr() ); #endif }
// (Re)generate representing geometry (beads and sticks) for the graph/curve clGeom* clGraph::CreateGraphGeometry( float BeadRadius, float TubeRadius, float EdgeArrowSize, bool UseCubes, clMaterial* BeadMaterial, clMaterial* StickMaterial, clMaterial* EdgeArrowMaterial ) { clMesh* Mesh = Env->Resources->CreateMesh(); int VtxMaterialID = Mesh->AddMaterial( BeadMaterial->GetMaterialDesc() ); // 1. points(vertices) are spheres for ( size_t i = 0 ; i < FVertices.size() ; i++ ) { // int VtxGeomID = static_cast<int>(i); clVertexAttribs* VtxVA; LVector3 BoxMin( -BeadRadius, -BeadRadius, -BeadRadius ); LVector3 BoxMax( +BeadRadius, +BeadRadius, +BeadRadius ); // name it for picking LString VtxName = LString( "Vertex " ) + LStr::ToStr( i ); if ( UseCubes ) { FIXME( "hack, resources should also create a VA ? Or it is a geomserv ?" ) // clGeomServ::CreateAxisAlignedBox(BoxMin, BoxMax, false); VtxVA = Env->Resources->CreateBox( BoxMin, BoxMax )->GetCurrentMesh()->GetRigid( 0 ); } else { // it does not work... // VtxVA = Env->Resources->CreateSphere(); VtxVA = Env->Resources->CreateBox( BoxMin, BoxMax )->GetCurrentMesh()->GetRigid( 0 ); } LVector3 VtxPos = FVertices[i]; LMatrix4 VtxTransform = LMatrix4::GetTranslateMatrix( VtxPos ); if ( UseCubes ) { LQuaternion VtxOrientation = FLocalOrientations[i]; // orient the cube at point, if needed VtxTransform = ComposeTransformation( VtxPos, LMatrix4( VtxOrientation.ToMatrix3() ) ); // add rotation from LocalOrientation } Mesh->AddVertexAttribs( VtxName, VtxVA, VtxTransform, -1, VtxMaterialID ); } // 2. render arrows for oriented edges int ArrowMaterialID = -1; if ( FOriented && EdgeArrowMaterial ) { ArrowMaterialID = Mesh->AddMaterial( EdgeArrowMaterial->GetMaterialDesc() ); } // map< pair<int,int> > ProcessedEdges; int EdgeMaterialID = Mesh->AddMaterial( StickMaterial->GetMaterialDesc() ); // 3. render lines from point to point ("tubes"), avoiding duplicate generation for non-oriented edges for ( size_t i = 0; i < FEdge0.size() ; i++ ) { int v1 = FEdge0[i]; int v2 = FEdge1[i]; LVector3 v1pos = FVertices[v1]; LVector3 v2pos = FVertices[v2]; LVector3 Dir = ( v2pos - v1pos ); LVector3 DirN = Dir.GetNormalized(); LVector3 EndPointDir = -Dir.Length() * DirN * ( EdgeArrowSize ); LVector3 Offset = DirN * EdgeArrowSize; clVertexAttribs* EdgeVA = clGeomServ::CreateTube( 10, v1pos + Offset, Dir - Offset, TubeRadius, false ); // name the edge for picking LString EdgeName = LString( "Edge " ) + LStr::ToStr( v1 ) + LString( " " ) + LStr::ToStr( v2 ); LMatrix4 EdgeTransform = LMatrix4::Identity(); Mesh->AddVertexAttribs( EdgeName, EdgeVA, EdgeTransform, -1, EdgeMaterialID ); FIXME( "avoid duplicates, use processed edges list" ) // add arrow, if required if ( FOriented ) { clVertexAttribs* ArrowVA = clGeomServ::CreateTube( 10, v2pos - Offset, -EndPointDir, TubeRadius * 2.0f , true ); LString ArrowName = LString( "Arrow_" ) + EdgeName; LMatrix4 ArrowTransform = LMatrix4::Identity(); Mesh->AddVertexAttribs( ArrowName, ArrowVA, ArrowTransform, -1, ArrowMaterialID ); } } clGeom* Geom = Env->Resources->CreateGeom(); Geom->SetMesh( Mesh ); return Geom; }
//---------------------------------------------------------------------- // //---------------------------------------------------------------------- void CylinderMouseMoveCameraOperator::_doMouseMoveR( lnFloat dx, lnFloat dy, lnFloat width, lnFloat height ) { LVector3 view; LVector3 vup = getTargetCamera()->getUpDirection(); LVector3 pos = getTargetCamera()->getPosition(); LVector3 look_at = getTargetCamera()->getLookAt(); vup.Normalize(); // 注視点中心回転 if ( 1 ) { view = pos - look_at; } // 視点中心回転 else { view = look_at - pos; } LMatrix m; lnFloat d; if ( dx != 0 ) { d = LMath::PI * dx / width; // Y 軸周りの回転を逆にする場合 (右手系) if ( 0 ) // CAMTYPE_REV_ROT_Y { d = -d; } // vup を軸にする場合 //if ( m_type & CAMTYPE_AROUND_UP ) // D3DXMatrixRotationAxis( &m, &vup, D3DXToRadian(d) ); //else // D3DXMatrixRotationY( &m, D3DXToRadian(d) ); m.RotationY( d ); view.TransformCoord( m ); } if ( dy != 0 ) { // 球タイプ if ( 1 ) { LVector3 vaxis = LVector3::Cross(vup, view); vaxis.Normalize(); d = -( LMath::PI * dy / height ); m = LMatrix::RotationAxis(vaxis, d ); view.TransformCoord( m ); //D3DXVec3Cross( &vaxis, &vup, &view ); //D3DXVec3Normalize( &vaxis, &vaxis ); //d = (float)180.0 * (float)dy / (float)prc->bottom; //D3DXMatrixRotationAxis( &m, &vaxis, D3DXToRadian(d) ); //D3DXVec3TransformNormal( &view, &view, &m ); } else { //if( m_type & CAMTYPE_AROUND_UP ) // view += ( vup * (float)dy ); //else // view.y += (float)dy; } } // 注視点中心回転 if ( 1 ) { LVector3 old = pos; pos = look_at + view; // 上または下にドラッグし続けた場合、中天を通り過ぎたところで // XZ上の反対側の象限にカメラが移動して画面がちらちらするのを防ぐ処理 if ( ( ( old.X < 0 && pos.X > 0 ) || ( old.X > 0 && pos.X < 0 ) ) && ( ( old.Z < 0 && pos.Z > 0 ) || ( old.Z > 0 && pos.Z < 0 ) ) ) { pos = old; } } // 視点中心回転 else { pos += view; } getTargetCamera()->setPosition( pos ); }
void clAudioSubSystem_OpenAL::SetListenerPosition( const LVector3& Position ) { #if L_AUDIO_USE_OPENAL alListenerfv( AL_POSITION, Position.ToFloatPtr() ); #endif }