Changeset 425 for cafu/trunk

Show
Ignore:
Timestamp:
11/19/11 18:04:23 (6 months ago)
Author:
Carsten
Message:

Rearranged the methods of AnimPoseT into a more intuitive order. No other changes.

Location:
cafu/trunk/Libs/Models
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • cafu/trunk/Libs/Models/AnimPose.cpp

    r422 r425  
    4545{ 
    4646    delete m_DlodPose; 
    47 } 
    48  
    49  
    50 void AnimPoseT::SetSequNr(int SequNr) 
    51 { 
    52     if (m_SequNr==SequNr) return; 
    53  
    54     m_SequNr=SequNr; 
    55     NormalizeInput(); 
    56  
    57     m_NeedsRecache=true; 
    58  
    59     // Recursively update the chain of dlod poses. 
    60     if (m_DlodPose) m_DlodPose->SetSequNr(SequNr); 
    61 } 
    62  
    63  
    64 void AnimPoseT::SetFrameNr(float FrameNr) 
    65 { 
    66     if (m_FrameNr==FrameNr) return; 
    67  
    68     m_FrameNr=FrameNr; 
    69     NormalizeInput(); 
    70  
    71     m_NeedsRecache=true; 
    72  
    73     // Recursively update the chain of dlod poses. 
    74     if (m_DlodPose) m_DlodPose->SetFrameNr(FrameNr); 
    75 } 
    76  
    77  
    78 void AnimPoseT::SetSuperPose(const AnimPoseT* SuperPose) 
    79 { 
    80     if (m_SuperPose==SuperPose) return; 
    81  
    82     m_SuperPose=SuperPose; 
    83  
    84     m_NeedsRecache=true; 
    85  
    86     // Recursively update the chain of dlod poses. 
    87     if (m_DlodPose) m_DlodPose->SetSuperPose(SuperPose); 
    88 } 
    89  
    90  
    91 void AnimPoseT::Advance(float Time, bool ForceLoop) 
    92 { 
    93     // TODO: Beachte korrekte Wrap-Regeln für mit loopen und ohne. 
    94     // TODO: Sollte in NormalizeInput() die m_FrameNr gegen das jeweilige Maximum begrenzt werden? 
    95     // TODO: Loops (next vs. ForceLoop) richtig behandeln 
    96     const ArrayT<CafuModelT::AnimT>& Anims=m_Model.GetAnims(); 
    97  
    98     if (m_SequNr<0 || m_SequNr>=int(Anims.Size())) { SetFrameNr(0.0f); return; } 
    99     if (Anims[m_SequNr].Frames.Size()<=1) { SetFrameNr(0.0f); return; } 
    100  
    101     const float NumFrames=float(Anims[m_SequNr].Frames.Size()); 
    102  
    103     float FrameNr=m_FrameNr + Time*Anims[m_SequNr].FPS; 
    104  
    105     if (ForceLoop) 
    106     { 
    107         // Wrap the sequence (it's a looping (repeating) sequence, like idle, walk, ...). 
    108         FrameNr=fmod(FrameNr, NumFrames); 
    109         if (FrameNr<0.0f) FrameNr+=NumFrames; 
    110     } 
    111     else 
    112     { 
    113         // Clamp the sequence (it's a play-once (non-repeating) sequence, like dying). 
    114         // On clamping, stop the sequence 1/100th sec before the end of the last frame. 
    115         if (FrameNr>=NumFrames-1.0f) FrameNr=NumFrames-1.0f-0.01f; 
    116         if (FrameNr<0.0f) FrameNr=0.0f; 
    117     } 
    118  
    119     SetFrameNr(FrameNr); 
    120  
    121     // Recursively update the chain of dlod poses. 
    122     if (m_DlodPose) m_DlodPose->Advance(Time, ForceLoop); 
    123 } 
    124  
    125  
    126 void AnimPoseT::Draw(int SkinNr, float LodDist) const 
    127 { 
    128     if (m_Model.GetDlodModel() && LodDist >= m_Model.GetDlodDist()) 
    129     { 
    130         m_DlodPose->Draw(SkinNr, LodDist); 
    131         return; 
    132     } 
    133  
    134     Recache(); 
    135  
    136     // Do an early check whether the light and the sequence BBs intersect. 
    137     switch (MatSys::Renderer->GetCurrentRenderAction()) 
    138     { 
    139         case MatSys::RendererI::AMBIENT: 
    140             break; 
    141  
    142         case MatSys::RendererI::LIGHTING: 
    143         case MatSys::RendererI::STENCILSHADOW: 
    144         { 
    145             const float                LightRadius=MatSys::Renderer->GetCurrentLightSourceRadius(); 
    146             const Vector3T<float>      LightBox(LightRadius, LightRadius, LightRadius); 
    147             const Vector3T<float>      LightPosOLD(MatSys::Renderer->GetCurrentLightSourcePosition()); 
    148             const BoundingBox3T<float> LightBB(LightPosOLD+LightBox, LightPosOLD-LightBox); 
    149  
    150             if (!LightBB.Intersects(m_BoundingBox)) return; 
    151             break; 
    152         } 
    153     } 
    154  
    155     switch (MatSys::Renderer->GetCurrentRenderAction()) 
    156     { 
    157         case MatSys::RendererI::AMBIENT: 
    158         { 
    159             for (unsigned long MeshNr=0; MeshNr<m_Draw_Meshes.Size(); MeshNr++) 
    160             { 
    161                 MatSys::Renderer->SetCurrentMaterial(m_Model.GetRenderMaterial(MeshNr, SkinNr)); 
    162                 MatSys::Renderer->RenderMesh(m_Draw_Meshes[MeshNr]); 
    163             } 
    164             break; 
    165         } 
    166  
    167         case MatSys::RendererI::LIGHTING: 
    168         { 
    169             for (unsigned long MeshNr=0; MeshNr<m_Draw_Meshes.Size(); MeshNr++) 
    170             { 
    171                 MatSys::Renderer->SetCurrentMaterial(m_Model.GetRenderMaterial(MeshNr, SkinNr)); 
    172                 MatSys::Renderer->RenderMesh(m_Draw_Meshes[MeshNr]); 
    173             } 
    174             break; 
    175         } 
    176  
    177         case MatSys::RendererI::STENCILSHADOW: 
    178         { 
    179             typedef CafuModelT::MeshT MeshT; 
    180  
    181             const ArrayT<MeshT>& Meshes=m_Model.GetMeshes(); 
    182             const Vector3fT      LightPos(MatSys::Renderer->GetCurrentLightSourcePosition()); 
    183  
    184             for (unsigned long MeshNr=0; MeshNr<Meshes.Size(); MeshNr++) 
    185             { 
    186                 const MeshT&     Mesh    =Meshes[MeshNr]; 
    187                 const MeshInfoT& MeshInfo=m_MeshInfos[MeshNr]; 
    188                 const MaterialT* MeshMat =m_Model.GetMaterial(MeshNr, SkinNr); 
    189  
    190                 if (MeshMat==NULL || MeshMat->NoShadows) continue; 
    191  
    192                 static ArrayT<bool> TriangleIsFrontFacing; 
    193                 if (TriangleIsFrontFacing.Size()<Mesh.Triangles.Size()) 
    194                     TriangleIsFrontFacing.PushBackEmpty(Mesh.Triangles.Size()-TriangleIsFrontFacing.Size()); 
    195  
    196                 for (unsigned long TriNr=0; TriNr<Mesh.Triangles.Size(); TriNr++) 
    197                 { 
    198                     const MeshT::TriangleT&     Tri    =Mesh.Triangles[TriNr]; 
    199                     const MeshInfoT::TriangleT& TriInfo=MeshInfo.Triangles[TriNr]; 
    200  
    201                     const float Dot=(LightPos-MeshInfo.Vertices[Tri.VertexIdx[0]].Pos).dot(TriInfo.Normal); 
    202  
    203                     TriangleIsFrontFacing[TriNr]=Dot>0; 
    204                 } 
    205  
    206  
    207                 // Note that we have to cull the following polygons wrt. the *VIEWER* (not the light source)! 
    208                 static MatSys::MeshT MeshSilhouette(MatSys::MeshT::Quads);  // The default winding order is "CW". 
    209                 MeshSilhouette.Vertices.Overwrite(); 
    210  
    211                 for (unsigned long TriNr=0; TriNr<Mesh.Triangles.Size(); TriNr++) 
    212                 { 
    213                     if (!TriangleIsFrontFacing[TriNr]) continue; 
    214  
    215                     // This triangle is front-facing wrt. the light source. 
    216                     const MeshT::TriangleT& Tri=Mesh.Triangles[TriNr]; 
    217  
    218                     for (unsigned long EdgeNr=0; EdgeNr<3; EdgeNr++) 
    219                     { 
    220                         // If an edge has no (-1) or more than one (-2) neighbours, make it a silhouette edge. 
    221                         const bool IsSilhouetteEdge=(Tri.NeighbIdx[EdgeNr]<0) ? true : !TriangleIsFrontFacing[Tri.NeighbIdx[EdgeNr]]; 
    222  
    223                         if (IsSilhouetteEdge) 
    224                         { 
    225                             // The neighbour at edge 'EdgeNr' is back-facing (or non-existant), so we have found a possible silhouette edge. 
    226                             const unsigned long v1=EdgeNr; 
    227                             const unsigned long v2=(EdgeNr+1) % 3; 
    228                             const Vector3fT     LA=MeshInfo.Vertices[Tri.VertexIdx[v1]].Pos-LightPos; 
    229                             const Vector3fT     LB=MeshInfo.Vertices[Tri.VertexIdx[v2]].Pos-LightPos; 
    230  
    231                             MeshSilhouette.Vertices.PushBackEmpty(4); 
    232  
    233                             const unsigned long MeshSize=MeshSilhouette.Vertices.Size(); 
    234  
    235                             MeshSilhouette.Vertices[MeshSize-4].SetOrigin(MeshInfo.Vertices[Tri.VertexIdx[v2]].Pos); 
    236                             MeshSilhouette.Vertices[MeshSize-3].SetOrigin(MeshInfo.Vertices[Tri.VertexIdx[v1]].Pos); 
    237                             MeshSilhouette.Vertices[MeshSize-2].SetOrigin(LA, 0.0); 
    238                             MeshSilhouette.Vertices[MeshSize-1].SetOrigin(LB, 0.0); 
    239                         } 
    240                     } 
    241                 } 
    242  
    243                 MatSys::Renderer->RenderMesh(MeshSilhouette); 
    244  
    245  
    246                 static MatSys::MeshT MeshCaps(MatSys::MeshT::Triangles);    // The default winding order is "CW". 
    247                 MeshCaps.Vertices.Overwrite(); 
    248  
    249                 for (unsigned long TriNr=0; TriNr<Mesh.Triangles.Size(); TriNr++) 
    250                 { 
    251                     if (!TriangleIsFrontFacing[TriNr]) continue; 
    252  
    253                     // This triangle is front-facing wrt. the light source. 
    254                     const CafuModelT::MeshT::TriangleT& Tri=Mesh.Triangles[TriNr]; 
    255  
    256                     MeshCaps.Vertices.PushBackEmpty(6); 
    257  
    258                     const unsigned long MeshSize=MeshCaps.Vertices.Size(); 
    259  
    260                     // Render the occluder (front-facing wrt. the light source). 
    261                     const Vector3fT& A=MeshInfo.Vertices[Tri.VertexIdx[0]].Pos; 
    262                     const Vector3fT& B=MeshInfo.Vertices[Tri.VertexIdx[1]].Pos; 
    263                     const Vector3fT& C=MeshInfo.Vertices[Tri.VertexIdx[2]].Pos; 
    264  
    265                     MeshCaps.Vertices[MeshSize-6].SetOrigin(A); 
    266                     MeshCaps.Vertices[MeshSize-5].SetOrigin(B); 
    267                     MeshCaps.Vertices[MeshSize-4].SetOrigin(C); 
    268  
    269                     // Render the occluder (back-facing wrt. the light source). 
    270                     const Vector3fT LA=A-LightPos; 
    271                     const Vector3fT LB=B-LightPos; 
    272                     const Vector3fT LC=C-LightPos; 
    273  
    274                     MeshCaps.Vertices[MeshSize-3].SetOrigin(LC, 0.0); 
    275                     MeshCaps.Vertices[MeshSize-2].SetOrigin(LB, 0.0); 
    276                     MeshCaps.Vertices[MeshSize-1].SetOrigin(LA, 0.0); 
    277                 } 
    278  
    279                 MatSys::Renderer->RenderMesh(MeshCaps); 
    280             } 
    281  
    282             break; 
    283         } 
    284     } 
    285 } 
    286  
    287  
    288 bool AnimPoseT::TraceRay(int SkinNr, const Vector3fT& RayOrigin, const Vector3fT& RayDir, ModelT::TraceResultT& Result) const 
    289 { 
    290     // if (m_Model.GetDlodModel() && LodDist >= m_Model.GetDlodDist()) 
    291     // { 
    292     //     return m_DlodPose->TraceRay(SkinNr, RayOrigin, RayDir, Result); 
    293     // } 
    294  
    295     Recache(); 
    296  
    297     // If we miss the bounding-box, then we miss all the triangles as well. 
    298     float Fraction=0.0f; 
    299     if (!GetBB().TraceRay(RayOrigin, RayDir, Fraction)) return false; 
    300  
    301     typedef CafuModelT::MeshT MeshT; 
    302  
    303     const ArrayT<MeshT>& Meshes=m_Model.GetMeshes(); 
    304  
    305     for (unsigned long MeshNr=0; MeshNr<Meshes.Size(); MeshNr++) 
    306     { 
    307         const MeshT&     Mesh    =Meshes[MeshNr]; 
    308         const MeshInfoT& MeshInfo=m_MeshInfos[MeshNr]; 
    309         const MaterialT* MeshMat =m_Model.GetMaterial(MeshNr, SkinNr); 
    310  
    311         // If the ClipFlags don't match the ClipMask, this polygon doesn't interfere with the trace. 
    312         if (!MeshMat) continue; 
    313         // if ((MeshMat->ClipFlags & ClipMask)==0) continue; 
    314  
    315         for (unsigned long TriNr=0; TriNr<Mesh.Triangles.Size(); TriNr++) 
    316         { 
    317             // This code is a modification of the code in CollisionModelStaticT::PolygonT::TraceRay(), 
    318             // see there for details and additional information. 
    319             using namespace cf::math; 
    320             const MeshT::TriangleT&     Tri    =Mesh.Triangles[TriNr]; 
    321             const MeshInfoT::TriangleT& TriInfo=MeshInfo.Triangles[TriNr]; 
    322  
    323             const Vector3fT& A=MeshInfo.Vertices[Tri.VertexIdx[0]].Pos; 
    324             const Vector3fT& B=MeshInfo.Vertices[Tri.VertexIdx[1]].Pos; 
    325             const Vector3fT& C=MeshInfo.Vertices[Tri.VertexIdx[2]].Pos; 
    326  
    327             const PlueckerfT R=PlueckerfT::CreateFromRay(RayOrigin, RayDir); 
    328  
    329             // We use Pluecker coordinates for the orientation tests. 
    330             // Note that Christer Ericson has shown in his blog at http://realtimecollisiondetection.net/blog/?p=13 
    331             // that scalar triple products (Spatprodukte) are equivalent and could be used as well.  ;-) 
    332             if (!MeshMat->TwoSided) 
    333             { 
    334                 if (R*PlueckerfT::CreateFromLine(A, B) >= 0) continue; 
    335                 if (R*PlueckerfT::CreateFromLine(B, C) >= 0) continue; 
    336                 if (R*PlueckerfT::CreateFromLine(C, A) >= 0) continue; 
    337             } 
    338             else 
    339             { 
    340                 int Count=0; 
    341  
    342                 // Should not change Count if result == 0... 
    343                 Count+=(R*PlueckerfT::CreateFromLine(A, B) >= 0) ? -1 : 1; 
    344                 Count+=(R*PlueckerfT::CreateFromLine(B, C) >= 0) ? -1 : 1; 
    345                 Count+=(R*PlueckerfT::CreateFromLine(C, A) >= 0) ? -1 : 1; 
    346  
    347                 if (Count!=-3 && Count!=3) continue; 
    348             } 
    349  
    350             // The "aperture" test passed, now compute the fraction at which RayDir intersects the triangle plane. 
    351             const float Nenner=dot(TriInfo.Normal, RayDir); 
    352  
    353             if (Nenner==0) continue;                            // If Nenner==0, then RayDir is parallel to the triangle plane (no intersection). 
    354             assert(MeshMat->TwoSided || Nenner<0);              // If the material is single sided, then Nenner<0, a consequence of the Pluecker tests above. 
    355  
    356             const float Dist=dot(TriInfo.Normal, RayOrigin-A);  // The distance of RayOrigin to the triangle plane. 
    357             const float F   =-(Dist-0.03125f)/Nenner; 
    358  
    359             // The intersection is only valid in the positive direction of RayDir. 
    360             if (F<0) continue; 
    361  
    362             // Hit the triangle! 
    363             Result.Fraction=F; 
    364             Result.Normal  =(Nenner<0) ? TriInfo.Normal : -TriInfo.Normal;  // Handle two-sided materials properly. 
    365             Result.Material=MeshMat; 
    366             Result.MeshNr  =MeshNr; 
    367             Result.TriNr   =TriNr; 
    368             return true; 
    369         } 
    370     } 
    371  
    372     return false; 
    373 } 
    374  
    375  
    376 unsigned int AnimPoseT::FindClosestVertex(unsigned int MeshNr, unsigned int TriNr, const Vector3fT& P) const 
    377 { 
    378     unsigned int BestVertexNr=0; 
    379     float        BestDist    =0.0f; 
    380  
    381     Recache(); 
    382  
    383     for (unsigned int i=0; i<3; i++) 
    384     { 
    385         const unsigned int VertexNr=m_Model.GetMeshes()[MeshNr].Triangles[TriNr].VertexIdx[i]; 
    386         const Vector3fT&   DrawPos =m_MeshInfos[MeshNr].Vertices[VertexNr].Pos; 
    387         const float        Dist    =length(DrawPos-P); 
    388  
    389         if (i==0 || Dist<BestDist) 
    390         { 
    391             BestDist    =Dist; 
    392             BestVertexNr=VertexNr; 
    393         } 
    394     } 
    395  
    396     return BestVertexNr; 
    397 } 
    398  
    399  
    400 const ArrayT<MatrixT>& AnimPoseT::GetJointMatrices() const 
    401 { 
    402     Recache(); 
    403  
    404     return m_JointMatrices; 
    405 } 
    406  
    407  
    408 const MatrixT* AnimPoseT::GetJointMatrix(const std::string& JointName) const 
    409 { 
    410     Recache(); 
    411  
    412     for (unsigned int JointNr=0; JointNr<m_Model.GetJoints().Size(); JointNr++) 
    413         if (m_Model.GetJoints()[JointNr].Name == JointName) 
    414             return &m_JointMatrices[JointNr]; 
    415  
    416     return NULL; 
    417 } 
    418  
    419  
    420 const ArrayT<AnimPoseT::MeshInfoT>& AnimPoseT::GetMeshInfos() const 
    421 { 
    422     Recache(); 
    423  
    424     return m_MeshInfos; 
    425 } 
    426  
    427  
    428 const ArrayT<MatSys::MeshT>& AnimPoseT::GetDrawMeshes() const 
    429 { 
    430     Recache(); 
    431  
    432     return m_Draw_Meshes; 
    433 } 
    434  
    435  
    436 const BoundingBox3fT& AnimPoseT::GetBB() const 
    437 { 
    438     Recache(); 
    439  
    440     return m_BoundingBox; 
    441 } 
    442  
    443  
    444 void AnimPoseT::NormalizeInput() 
    445 { 
    446     const ArrayT<CafuModelT::AnimT>& Anims=m_Model.GetAnims(); 
    447  
    448     // m_SequNr==-1 means "use the bind pose from the model file only (no anim)". 
    449     if (m_SequNr < -1) m_SequNr = -1; 
    450     if (m_SequNr >= int(Anims.Size())) m_SequNr = -1; 
    451     if (m_SequNr != -1 && (Anims[m_SequNr].FPS<0.0 || Anims[m_SequNr].Frames.Size()==0)) m_SequNr = -1; 
    452     if (m_SequNr == -1) m_FrameNr = 0.0f; 
    45347} 
    45448 
     
    859453    m_NeedsRecache=false; 
    860454} 
     455 
     456 
     457void AnimPoseT::NormalizeInput() 
     458{ 
     459    const ArrayT<CafuModelT::AnimT>& Anims=m_Model.GetAnims(); 
     460 
     461    // m_SequNr==-1 means "use the bind pose from the model file only (no anim)". 
     462    if (m_SequNr < -1) m_SequNr = -1; 
     463    if (m_SequNr >= int(Anims.Size())) m_SequNr = -1; 
     464    if (m_SequNr != -1 && (Anims[m_SequNr].FPS<0.0 || Anims[m_SequNr].Frames.Size()==0)) m_SequNr = -1; 
     465    if (m_SequNr == -1) m_FrameNr = 0.0f; 
     466} 
     467 
     468 
     469void AnimPoseT::SetSequNr(int SequNr) 
     470{ 
     471    if (m_SequNr==SequNr) return; 
     472 
     473    m_SequNr=SequNr; 
     474    NormalizeInput(); 
     475 
     476    m_NeedsRecache=true; 
     477 
     478    // Recursively update the chain of dlod poses. 
     479    if (m_DlodPose) m_DlodPose->SetSequNr(SequNr); 
     480} 
     481 
     482 
     483void AnimPoseT::SetFrameNr(float FrameNr) 
     484{ 
     485    if (m_FrameNr==FrameNr) return; 
     486 
     487    m_FrameNr=FrameNr; 
     488    NormalizeInput(); 
     489 
     490    m_NeedsRecache=true; 
     491 
     492    // Recursively update the chain of dlod poses. 
     493    if (m_DlodPose) m_DlodPose->SetFrameNr(FrameNr); 
     494} 
     495 
     496 
     497void AnimPoseT::SetSuperPose(const AnimPoseT* SuperPose) 
     498{ 
     499    if (m_SuperPose==SuperPose) return; 
     500 
     501    m_SuperPose=SuperPose; 
     502 
     503    m_NeedsRecache=true; 
     504 
     505    // Recursively update the chain of dlod poses. 
     506    if (m_DlodPose) m_DlodPose->SetSuperPose(SuperPose); 
     507} 
     508 
     509 
     510void AnimPoseT::Advance(float Time, bool ForceLoop) 
     511{ 
     512    // TODO: Beachte korrekte Wrap-Regeln für mit loopen und ohne. 
     513    // TODO: Sollte in NormalizeInput() die m_FrameNr gegen das jeweilige Maximum begrenzt werden? 
     514    // TODO: Loops (next vs. ForceLoop) richtig behandeln 
     515    const ArrayT<CafuModelT::AnimT>& Anims=m_Model.GetAnims(); 
     516 
     517    if (m_SequNr<0 || m_SequNr>=int(Anims.Size())) { SetFrameNr(0.0f); return; } 
     518    if (Anims[m_SequNr].Frames.Size()<=1) { SetFrameNr(0.0f); return; } 
     519 
     520    const float NumFrames=float(Anims[m_SequNr].Frames.Size()); 
     521 
     522    float FrameNr=m_FrameNr + Time*Anims[m_SequNr].FPS; 
     523 
     524    if (ForceLoop) 
     525    { 
     526        // Wrap the sequence (it's a looping (repeating) sequence, like idle, walk, ...). 
     527        FrameNr=fmod(FrameNr, NumFrames); 
     528        if (FrameNr<0.0f) FrameNr+=NumFrames; 
     529    } 
     530    else 
     531    { 
     532        // Clamp the sequence (it's a play-once (non-repeating) sequence, like dying). 
     533        // On clamping, stop the sequence 1/100th sec before the end of the last frame. 
     534        if (FrameNr>=NumFrames-1.0f) FrameNr=NumFrames-1.0f-0.01f; 
     535        if (FrameNr<0.0f) FrameNr=0.0f; 
     536    } 
     537 
     538    SetFrameNr(FrameNr); 
     539 
     540    // Recursively update the chain of dlod poses. 
     541    if (m_DlodPose) m_DlodPose->Advance(Time, ForceLoop); 
     542} 
     543 
     544 
     545void AnimPoseT::Draw(int SkinNr, float LodDist) const 
     546{ 
     547    if (m_Model.GetDlodModel() && LodDist >= m_Model.GetDlodDist()) 
     548    { 
     549        m_DlodPose->Draw(SkinNr, LodDist); 
     550        return; 
     551    } 
     552 
     553    Recache(); 
     554 
     555    // Do an early check whether the light and the sequence BBs intersect. 
     556    switch (MatSys::Renderer->GetCurrentRenderAction()) 
     557    { 
     558        case MatSys::RendererI::AMBIENT: 
     559            break; 
     560 
     561        case MatSys::RendererI::LIGHTING: 
     562        case MatSys::RendererI::STENCILSHADOW: 
     563        { 
     564            const float                LightRadius=MatSys::Renderer->GetCurrentLightSourceRadius(); 
     565            const Vector3T<float>      LightBox(LightRadius, LightRadius, LightRadius); 
     566            const Vector3T<float>      LightPosOLD(MatSys::Renderer->GetCurrentLightSourcePosition()); 
     567            const BoundingBox3T<float> LightBB(LightPosOLD+LightBox, LightPosOLD-LightBox); 
     568 
     569            if (!LightBB.Intersects(m_BoundingBox)) return; 
     570            break; 
     571        } 
     572    } 
     573 
     574    switch (MatSys::Renderer->GetCurrentRenderAction()) 
     575    { 
     576        case MatSys::RendererI::AMBIENT: 
     577        { 
     578            for (unsigned long MeshNr=0; MeshNr<m_Draw_Meshes.Size(); MeshNr++) 
     579            { 
     580                MatSys::Renderer->SetCurrentMaterial(m_Model.GetRenderMaterial(MeshNr, SkinNr)); 
     581                MatSys::Renderer->RenderMesh(m_Draw_Meshes[MeshNr]); 
     582            } 
     583            break; 
     584        } 
     585 
     586        case MatSys::RendererI::LIGHTING: 
     587        { 
     588            for (unsigned long MeshNr=0; MeshNr<m_Draw_Meshes.Size(); MeshNr++) 
     589            { 
     590                MatSys::Renderer->SetCurrentMaterial(m_Model.GetRenderMaterial(MeshNr, SkinNr)); 
     591                MatSys::Renderer->RenderMesh(m_Draw_Meshes[MeshNr]); 
     592            } 
     593            break; 
     594        } 
     595 
     596        case MatSys::RendererI::STENCILSHADOW: 
     597        { 
     598            typedef CafuModelT::MeshT MeshT; 
     599 
     600            const ArrayT<MeshT>& Meshes=m_Model.GetMeshes(); 
     601            const Vector3fT      LightPos(MatSys::Renderer->GetCurrentLightSourcePosition()); 
     602 
     603            for (unsigned long MeshNr=0; MeshNr<Meshes.Size(); MeshNr++) 
     604            { 
     605                const MeshT&     Mesh    =Meshes[MeshNr]; 
     606                const MeshInfoT& MeshInfo=m_MeshInfos[MeshNr]; 
     607                const MaterialT* MeshMat =m_Model.GetMaterial(MeshNr, SkinNr); 
     608 
     609                if (MeshMat==NULL || MeshMat->NoShadows) continue; 
     610 
     611                static ArrayT<bool> TriangleIsFrontFacing; 
     612                if (TriangleIsFrontFacing.Size()<Mesh.Triangles.Size()) 
     613                    TriangleIsFrontFacing.PushBackEmpty(Mesh.Triangles.Size()-TriangleIsFrontFacing.Size()); 
     614 
     615                for (unsigned long TriNr=0; TriNr<Mesh.Triangles.Size(); TriNr++) 
     616                { 
     617                    const MeshT::TriangleT&     Tri    =Mesh.Triangles[TriNr]; 
     618                    const MeshInfoT::TriangleT& TriInfo=MeshInfo.Triangles[TriNr]; 
     619 
     620                    const float Dot=(LightPos-MeshInfo.Vertices[Tri.VertexIdx[0]].Pos).dot(TriInfo.Normal); 
     621 
     622                    TriangleIsFrontFacing[TriNr]=Dot>0; 
     623                } 
     624 
     625 
     626                // Note that we have to cull the following polygons wrt. the *VIEWER* (not the light source)! 
     627                static MatSys::MeshT MeshSilhouette(MatSys::MeshT::Quads);  // The default winding order is "CW". 
     628                MeshSilhouette.Vertices.Overwrite(); 
     629 
     630                for (unsigned long TriNr=0; TriNr<Mesh.Triangles.Size(); TriNr++) 
     631                { 
     632                    if (!TriangleIsFrontFacing[TriNr]) continue; 
     633 
     634                    // This triangle is front-facing wrt. the light source. 
     635                    const MeshT::TriangleT& Tri=Mesh.Triangles[TriNr]; 
     636 
     637                    for (unsigned long EdgeNr=0; EdgeNr<3; EdgeNr++) 
     638                    { 
     639                        // If an edge has no (-1) or more than one (-2) neighbours, make it a silhouette edge. 
     640                        const bool IsSilhouetteEdge=(Tri.NeighbIdx[EdgeNr]<0) ? true : !TriangleIsFrontFacing[Tri.NeighbIdx[EdgeNr]]; 
     641 
     642                        if (IsSilhouetteEdge) 
     643                        { 
     644                            // The neighbour at edge 'EdgeNr' is back-facing (or non-existant), so we have found a possible silhouette edge. 
     645                            const unsigned long v1=EdgeNr; 
     646                            const unsigned long v2=(EdgeNr+1) % 3; 
     647                            const Vector3fT     LA=MeshInfo.Vertices[Tri.VertexIdx[v1]].Pos-LightPos; 
     648                            const Vector3fT     LB=MeshInfo.Vertices[Tri.VertexIdx[v2]].Pos-LightPos; 
     649 
     650                            MeshSilhouette.Vertices.PushBackEmpty(4); 
     651 
     652                            const unsigned long MeshSize=MeshSilhouette.Vertices.Size(); 
     653 
     654                            MeshSilhouette.Vertices[MeshSize-4].SetOrigin(MeshInfo.Vertices[Tri.VertexIdx[v2]].Pos); 
     655                            MeshSilhouette.Vertices[MeshSize-3].SetOrigin(MeshInfo.Vertices[Tri.VertexIdx[v1]].Pos); 
     656                            MeshSilhouette.Vertices[MeshSize-2].SetOrigin(LA, 0.0); 
     657                            MeshSilhouette.Vertices[MeshSize-1].SetOrigin(LB, 0.0); 
     658                        } 
     659                    } 
     660                } 
     661 
     662                MatSys::Renderer->RenderMesh(MeshSilhouette); 
     663 
     664 
     665                static MatSys::MeshT MeshCaps(MatSys::MeshT::Triangles);    // The default winding order is "CW". 
     666                MeshCaps.Vertices.Overwrite(); 
     667 
     668                for (unsigned long TriNr=0; TriNr<Mesh.Triangles.Size(); TriNr++) 
     669                { 
     670                    if (!TriangleIsFrontFacing[TriNr]) continue; 
     671 
     672                    // This triangle is front-facing wrt. the light source. 
     673                    const CafuModelT::MeshT::TriangleT& Tri=Mesh.Triangles[TriNr]; 
     674 
     675                    MeshCaps.Vertices.PushBackEmpty(6); 
     676 
     677                    const unsigned long MeshSize=MeshCaps.Vertices.Size(); 
     678 
     679                    // Render the occluder (front-facing wrt. the light source). 
     680                    const Vector3fT& A=MeshInfo.Vertices[Tri.VertexIdx[0]].Pos; 
     681                    const Vector3fT& B=MeshInfo.Vertices[Tri.VertexIdx[1]].Pos; 
     682                    const Vector3fT& C=MeshInfo.Vertices[Tri.VertexIdx[2]].Pos; 
     683 
     684                    MeshCaps.Vertices[MeshSize-6].SetOrigin(A); 
     685                    MeshCaps.Vertices[MeshSize-5].SetOrigin(B); 
     686                    MeshCaps.Vertices[MeshSize-4].SetOrigin(C); 
     687 
     688                    // Render the occluder (back-facing wrt. the light source). 
     689                    const Vector3fT LA=A-LightPos; 
     690                    const Vector3fT LB=B-LightPos; 
     691                    const Vector3fT LC=C-LightPos; 
     692 
     693                    MeshCaps.Vertices[MeshSize-3].SetOrigin(LC, 0.0); 
     694                    MeshCaps.Vertices[MeshSize-2].SetOrigin(LB, 0.0); 
     695                    MeshCaps.Vertices[MeshSize-1].SetOrigin(LA, 0.0); 
     696                } 
     697 
     698                MatSys::Renderer->RenderMesh(MeshCaps); 
     699            } 
     700 
     701            break; 
     702        } 
     703    } 
     704} 
     705 
     706 
     707bool AnimPoseT::TraceRay(int SkinNr, const Vector3fT& RayOrigin, const Vector3fT& RayDir, ModelT::TraceResultT& Result) const 
     708{ 
     709    // if (m_Model.GetDlodModel() && LodDist >= m_Model.GetDlodDist()) 
     710    // { 
     711    //     return m_DlodPose->TraceRay(SkinNr, RayOrigin, RayDir, Result); 
     712    // } 
     713 
     714    Recache(); 
     715 
     716    // If we miss the bounding-box, then we miss all the triangles as well. 
     717    float Fraction=0.0f; 
     718    if (!GetBB().TraceRay(RayOrigin, RayDir, Fraction)) return false; 
     719 
     720    typedef CafuModelT::MeshT MeshT; 
     721 
     722    const ArrayT<MeshT>& Meshes=m_Model.GetMeshes(); 
     723 
     724    for (unsigned long MeshNr=0; MeshNr<Meshes.Size(); MeshNr++) 
     725    { 
     726        const MeshT&     Mesh    =Meshes[MeshNr]; 
     727        const MeshInfoT& MeshInfo=m_MeshInfos[MeshNr]; 
     728        const MaterialT* MeshMat =m_Model.GetMaterial(MeshNr, SkinNr); 
     729 
     730        // If the ClipFlags don't match the ClipMask, this polygon doesn't interfere with the trace. 
     731        if (!MeshMat) continue; 
     732        // if ((MeshMat->ClipFlags & ClipMask)==0) continue; 
     733 
     734        for (unsigned long TriNr=0; TriNr<Mesh.Triangles.Size(); TriNr++) 
     735        { 
     736            // This code is a modification of the code in CollisionModelStaticT::PolygonT::TraceRay(), 
     737            // see there for details and additional information. 
     738            using namespace cf::math; 
     739            const MeshT::TriangleT&     Tri    =Mesh.Triangles[TriNr]; 
     740            const MeshInfoT::TriangleT& TriInfo=MeshInfo.Triangles[TriNr]; 
     741 
     742            const Vector3fT& A=MeshInfo.Vertices[Tri.VertexIdx[0]].Pos; 
     743            const Vector3fT& B=MeshInfo.Vertices[Tri.VertexIdx[1]].Pos; 
     744            const Vector3fT& C=MeshInfo.Vertices[Tri.VertexIdx[2]].Pos; 
     745 
     746            const PlueckerfT R=PlueckerfT::CreateFromRay(RayOrigin, RayDir); 
     747 
     748            // We use Pluecker coordinates for the orientation tests. 
     749            // Note that Christer Ericson has shown in his blog at http://realtimecollisiondetection.net/blog/?p=13 
     750            // that scalar triple products (Spatprodukte) are equivalent and could be used as well.  ;-) 
     751            if (!MeshMat->TwoSided) 
     752            { 
     753                if (R*PlueckerfT::CreateFromLine(A, B) >= 0) continue; 
     754                if (R*PlueckerfT::CreateFromLine(B, C) >= 0) continue; 
     755                if (R*PlueckerfT::CreateFromLine(C, A) >= 0) continue; 
     756            } 
     757            else 
     758            { 
     759                int Count=0; 
     760 
     761                // Should not change Count if result == 0... 
     762                Count+=(R*PlueckerfT::CreateFromLine(A, B) >= 0) ? -1 : 1; 
     763                Count+=(R*PlueckerfT::CreateFromLine(B, C) >= 0) ? -1 : 1; 
     764                Count+=(R*PlueckerfT::CreateFromLine(C, A) >= 0) ? -1 : 1; 
     765 
     766                if (Count!=-3 && Count!=3) continue; 
     767            } 
     768 
     769            // The "aperture" test passed, now compute the fraction at which RayDir intersects the triangle plane. 
     770            const float Nenner=dot(TriInfo.Normal, RayDir); 
     771 
     772            if (Nenner==0) continue;                            // If Nenner==0, then RayDir is parallel to the triangle plane (no intersection). 
     773            assert(MeshMat->TwoSided || Nenner<0);              // If the material is single sided, then Nenner<0, a consequence of the Pluecker tests above. 
     774 
     775            const float Dist=dot(TriInfo.Normal, RayOrigin-A);  // The distance of RayOrigin to the triangle plane. 
     776            const float F   =-(Dist-0.03125f)/Nenner; 
     777 
     778            // The intersection is only valid in the positive direction of RayDir. 
     779            if (F<0) continue; 
     780 
     781            // Hit the triangle! 
     782            Result.Fraction=F; 
     783            Result.Normal  =(Nenner<0) ? TriInfo.Normal : -TriInfo.Normal;  // Handle two-sided materials properly. 
     784            Result.Material=MeshMat; 
     785            Result.MeshNr  =MeshNr; 
     786            Result.TriNr   =TriNr; 
     787            return true; 
     788        } 
     789    } 
     790 
     791    return false; 
     792} 
     793 
     794 
     795unsigned int AnimPoseT::FindClosestVertex(unsigned int MeshNr, unsigned int TriNr, const Vector3fT& P) const 
     796{ 
     797    unsigned int BestVertexNr=0; 
     798    float        BestDist    =0.0f; 
     799 
     800    Recache(); 
     801 
     802    for (unsigned int i=0; i<3; i++) 
     803    { 
     804        const unsigned int VertexNr=m_Model.GetMeshes()[MeshNr].Triangles[TriNr].VertexIdx[i]; 
     805        const Vector3fT&   DrawPos =m_MeshInfos[MeshNr].Vertices[VertexNr].Pos; 
     806        const float        Dist    =length(DrawPos-P); 
     807 
     808        if (i==0 || Dist<BestDist) 
     809        { 
     810            BestDist    =Dist; 
     811            BestVertexNr=VertexNr; 
     812        } 
     813    } 
     814 
     815    return BestVertexNr; 
     816} 
     817 
     818 
     819const ArrayT<MatrixT>& AnimPoseT::GetJointMatrices() const 
     820{ 
     821    Recache(); 
     822 
     823    return m_JointMatrices; 
     824} 
     825 
     826 
     827const MatrixT* AnimPoseT::GetJointMatrix(const std::string& JointName) const 
     828{ 
     829    Recache(); 
     830 
     831    for (unsigned int JointNr=0; JointNr<m_Model.GetJoints().Size(); JointNr++) 
     832        if (m_Model.GetJoints()[JointNr].Name == JointName) 
     833            return &m_JointMatrices[JointNr]; 
     834 
     835    return NULL; 
     836} 
     837 
     838 
     839const ArrayT<AnimPoseT::MeshInfoT>& AnimPoseT::GetMeshInfos() const 
     840{ 
     841    Recache(); 
     842 
     843    return m_MeshInfos; 
     844} 
     845 
     846 
     847const ArrayT<MatSys::MeshT>& AnimPoseT::GetDrawMeshes() const 
     848{ 
     849    Recache(); 
     850 
     851    return m_Draw_Meshes; 
     852} 
     853 
     854 
     855const BoundingBox3fT& AnimPoseT::GetBB() const 
     856{ 
     857    Recache(); 
     858 
     859    return m_BoundingBox; 
     860} 
  • cafu/trunk/Libs/Models/AnimPose.hpp

    r422 r425  
    147147    void operator = (const AnimPoseT&);             ///< Use of the Assignment Operator is not allowed. 
    148148 
    149     void NormalizeInput(); 
    150149    void SyncDimensions() const; 
    151150    void UpdateData() const; 
    152151    void Recache() const; 
     152    void NormalizeInput(); 
    153153 
    154154    const CafuModelT&             m_Model;          ///< The related model that this is a pose for.