void vHavokShapeFactory::GetHktDependencies(VResourceSnapshot &snapshot, VisBaseEntity_cl *pEntity)
{
  VASSERT(pEntity != NULL);

  // Get wrapped rigid body
  vHavokRigidBody *pWrappedRigidBody = pEntity->Components().GetComponentOfType<vHavokRigidBody>();
  if (pWrappedRigidBody == NULL)
    return;

  // Get shape
  vHavokPhysicsModule *pModule = vHavokPhysicsModule::GetInstance();
  VASSERT(pModule != NULL);
  pModule->MarkForRead();
  const hkpRigidBody *pRigidBody = pWrappedRigidBody->GetHkRigidBody();
  if (pRigidBody == NULL)
  {
    pModule->UnmarkForRead();
    return;
  }
  const hkpShape *pShape = pRigidBody->getCollidable()->getShape();
  pModule->UnmarkForRead();
  
  // Only convex/ mesh rigid bodies have a cached HKT file
  const hkClass* loadedClassType = hkVtableClassRegistry::getInstance().getClassFromVirtualInstance(pShape);
  if (loadedClassType!=&hkvConvexVerticesShapeClass && loadedClassType!=&hkvBvCompressedMeshShapeClass)
    return;

  // Get mesh
  VDynamicMesh *pMesh = pEntity->GetMesh();
  if (pMesh == NULL)
    return;

  // Get scale
  hkvVec3 vScale = pEntity->GetScaling();
  bool shrinkToFit = pWrappedRigidBody->Havok_TightFit;

  // Get HKT file dependency for convex/ mesh rigid body
  if (loadedClassType == &hkvConvexVerticesShapeClass) 
  {
    VStaticString<FS_MAX_PATH> szCachedShapeName(pMesh->GetFilename());
    vHavokCachedShape::GetConvexShapePath(szCachedShapeName, vScale, shrinkToFit);
    IVFileInStream *pIn = Vision::File.Open(szCachedShapeName);
    if (pIn)
    {
      snapshot.AddFileDependency(pMesh, szCachedShapeName, pIn->GetSize() );
      pIn->Close();
    }
  }
  else if(loadedClassType == &hkvBvCompressedMeshShapeClass) 
  {
    VStaticString<FS_MAX_PATH> szCachedShapeName(pMesh->GetFilename());
    vHavokCachedShape::GetMeshShapePath(szCachedShapeName, vScale, VisStaticMeshInstance_cl::VIS_COLLISION_BEHAVIOR_CUSTOM, (VisWeldingType_e)pWrappedRigidBody->Havok_WeldingType);
    IVFileInStream *pIn = Vision::File.Open(szCachedShapeName);
    if (pIn)
    {
      snapshot.AddFileDependency(pMesh, szCachedShapeName, pIn->GetSize() );
      pIn->Close();
    }
  }
}
// ----------------------------------------------------------------------------
void vHavokChainAnimation::CommonInit()
{
  CommonDeinit();

  if (!m_pOwner || !m_pOwner->IsOfType(V_RUNTIME_CLASS(VisBaseEntity_cl)))
    return;

  Vision::Callbacks.OnUpdateSceneFinished += this;

  m_pOwnerEntity = static_cast<VisBaseEntity_cl*>(m_pOwner);
  VisAnimConfig_cl *pAnimConfig = m_pOwnerEntity->GetAnimConfig();

  // If there is no AnimConfig, but we can get a skeleton, create the AnimConfig.
  if (!pAnimConfig)
  {
    VDynamicMesh *pMesh = m_pOwnerEntity->GetMesh();
    VisSkeleton_cl *pSkeleton = pMesh ? pMesh->GetSkeleton() : NULL;
    if (pSkeleton)
    {
      VisAnimFinalSkeletalResult_cl* pFinalSkeletalResult;
      pAnimConfig = VisAnimConfig_cl::CreateSkeletalConfig(pMesh, &pFinalSkeletalResult);
      m_pOwnerEntity->SetAnimConfig(pAnimConfig);
    }
  }
}
bool VAnimationComponent::AddAnimationSequence(const char * szAnimSequence)
{
  if (szAnimSequence == NULL || GetOwner() == NULL) return false;

  VDynamicMesh * pMesh = ((VisBaseEntity_cl *)m_pOwner)->GetMesh();
  if(pMesh==NULL)
  {
    hkvLog::Warning("AddAnimationSequence: No mesh present!");
    return false;
  }

  VASSERT_MSG(pMesh->GetSequenceSetCollection()!=NULL, "No animation sequence set present!");

  VisAnimSequenceSet_cl *pSet = Vision::Animations.GetSequenceSetManager()->LoadAnimSequenceSet(szAnimSequence);

  if(pSet==NULL)
  {
    hkvLog::Warning("AddAnimationSequence: Could not load '%s' animation sequence.", szAnimSequence);
    return false;
  }

  pMesh->GetSequenceSetCollection()->Add(pSet);

  return true;
}
void VAnimationEventEffectTrigger::MessageFunction( int iID, INT_PTR iParamA, INT_PTR iParamB )
{  
  IVTransitionEventTrigger::MessageFunction(iID, iParamA, iParamB);

#ifdef WIN32
  if (iID == VIS_MSG_EDITOR_GETSTANDARDVALUES)
  {
    // Get bone names
    const char *szKey = (const char *)iParamA;
    if (!strcmp(szKey,"Bone"))
    {
      // Check for model and skeleton
      VisBaseEntity_cl* pEntity = (VisBaseEntity_cl *)m_pOwner;
      if (pEntity == NULL)
        return;
      VDynamicMesh* pMesh = pEntity->GetMesh();
      if (pMesh == NULL)
        return;
      VisSkeleton_cl *pSkeleton = pMesh->GetSkeleton();
      if (pSkeleton == NULL)
        return;

      // Fill list with bone names (first entry is empty)
      VStrList *pDestList = (VStrList*) iParamB;
      pDestList->AddString(" ");
      for (int i = 0; i < pSkeleton->GetBoneCount(); i++)
        pDestList->AddString(pSkeleton->GetBone(i)->m_sBoneName.AsChar());
    }
  }
#endif
}
void vHavokBehaviorComponent::UpdateAnimationAndBoneIndexList()
{
	// Set up the animation config
	VDynamicMesh* mesh = m_entityOwner->GetMesh();
	if( mesh != HK_NULL && mesh->GetSkeleton() != HK_NULL )
	{
		// create an anim config, if one is not present
		VisAnimConfig_cl* pConfig = m_entityOwner->GetAnimConfig();
		if ( pConfig == HK_NULL )
		{
			pConfig = VisAnimConfig_cl::CreateSkeletalConfig(mesh);
			m_entityOwner->SetAnimConfig( pConfig );
		}

		pConfig->SetFlags(pConfig->GetFlags() | MULTITHREADED_ANIMATION);

		// Create mapping
		VisSkeleton_cl* visionSkeleton = mesh->GetSkeleton();
		const hkaSkeleton* havokSkeleton = m_character->getSetup()->m_animationSkeleton;

		for( int i = 0; i < havokSkeleton->m_bones.getSize(); i++ )
		{
			const VHashString &boneName = havokSkeleton->m_bones[i].m_name.cString();
			int visionBoneIndex = visionSkeleton->GetBoneIndexByName( boneName );
			m_boneIndexList.pushBack( visionBoneIndex );
		}
	}
}
void SimpleSkeletalAnimatedObject_cl::LookAt()
{
  // start a single animation
  StartSingleAnimation(true);

  // start a simple skeletal animation
  bool bLooped = true;
  int iFlags = VSKELANIMCTRL_DEFAULTS;
  if (bLooped)
    iFlags |= VANIMCTRL_LOOP;
  m_spSingleAnimControl = VisAnimConfig_cl::StartSkeletalAnimation(this, "Run", iFlags);


  // find the head bone index
  VDynamicMesh *pMesh = GetMesh();
  m_iHeadBoneIndex = pMesh->GetSkeleton()->GetBoneIndexByName("skeleton1:Head");

  // create a rotation matrix that defines the actual orientation of the head. This is model specific and can
  // only be found out by trial and error (typically 0, 90 or 180 deg). In our case the head is rotated by 180 degrees; Without this additional
  // orientation that model would follow the target with the backside of the head.
  m_RelativeHeadOrientation.setFromEulerAngles (90, 0, 270);

  // create an entity that rotates around the model
  m_pLookAtTarget = Vision::Game.CreateEntity("VisBaseEntity_cl", hkvVec3::ZeroVector(), "Models/MagicBall.model");
  m_fLookAtRotationPhase = 0.f;
}
bool VAnimationEventEffectTrigger::CommonInit()
{
  // Initialize base component
  if (!IVTransitionEventTrigger::CommonInit())
    return false;
  
  // Get owner entity
  VisBaseEntity_cl *pEntity = (VisBaseEntity_cl *)m_pOwner;
  if (pEntity == NULL)
    return false;

  // Fill the event trigger info
  if (m_iEventTriggerInfoCount <= 0)
  {
    VEventEffectTriggerInfo_t* info = NULL;
    if(m_pActiveTriggerInfo == NULL) //make sure it does not get created more than once
    {
      // Create new list with only one entry and set properties
      info = new VEventEffectTriggerInfo_t();
    }
    else
    {
      info = (VEventEffectTriggerInfo_t*)m_pActiveTriggerInfo;
    }

    info->m_vPositionOffset = PositionOffset;
    info->m_vOrientationOffset= OrientationOffset;


    // Get effect file
    info->m_spEffectFile = VisParticleGroupManager_cl::GlobalManager().LoadFromFile(EffectFilename);
    if (info->m_spEffectFile == NULL || !GetEventTriggerInfoBaseData(info))
    {
      V_SAFE_DELETE(info);
      m_pActiveTriggerInfo = NULL;
      return false;
    }

    // Get Bone Index if specified
    if (!AttachToBone.IsEmpty())
    {
      VDynamicMesh* pMesh = pEntity->GetMesh();
      if (pMesh == NULL)
        return false;
      VisSkeleton_cl *pSkeleton = pMesh->GetSkeleton();
      if (pSkeleton == NULL)
        return false;

      info->m_iAttachToBone = pSkeleton->GetBoneIndexByName(AttachToBone);
    }

    // Set it as the active event trigger info
    m_pActiveTriggerInfo = info;
  }

  return true;
}
void MergedModelFactory_cl::PreviewModel()
{
  DeleteModels();

  m_pPreviewModelEntities = new VisBaseEntity_cl*[BARBARIAN_MAX];
  m_pPreviewModelEntities[BARBARIAN_BODY] = Vision::Game.CreateEntity("VisBaseEntity_cl", hkvVec3(0.f, 0.f, 0.f), "Barbarian_Body.model");
  m_pPreviewModelEntities[BARBARIAN_ARM] = Vision::Game.CreateEntity("VisBaseEntity_cl", hkvVec3(0.f, 0.f, 0.f), "Barbarian_Arm.model");
  m_pPreviewModelEntities[BARBARIAN_SHOULDER] = Vision::Game.CreateEntity("VisBaseEntity_cl", hkvVec3(0.f, 0.f, 0.f), "Barbarian_Shoulder.model");
  m_pPreviewModelEntities[BARBARIAN_LEGS] = Vision::Game.CreateEntity("VisBaseEntity_cl", hkvVec3(0.f, 0.f, 0.f), "Barbarian_Legs.model");
  m_pPreviewModelEntities[BARBARIAN_KNEE] = Vision::Game.CreateEntity("VisBaseEntity_cl", hkvVec3(0.f, 0.f, 0.f), "Barbarian_Knee.model");
  m_pPreviewModelEntities[BARBARIAN_ACCESSOIRE] = Vision::Game.CreateEntity("VisBaseEntity_cl", hkvVec3(0.f, 0.f, 0.f), "Barbarian_Accessoire.model");
  m_pPreviewModelEntities[BARBARIAN_BELT] = Vision::Game.CreateEntity("VisBaseEntity_cl", hkvVec3(0.f, 0.f, 0.f), "Barbarian_Belt.model");
  m_pPreviewModelEntities[BARBARIAN_CLOTH] = Vision::Game.CreateEntity("VisBaseEntity_cl", hkvVec3(0.f, 0.f, 0.f), "Barbarian_Cloth.model");
  m_pPreviewModelEntities[BARBARIAN_BEARD] = Vision::Game.CreateEntity("VisBaseEntity_cl", hkvVec3(0.f, 0.f, 0.f), "Barbarian_Beard.model");
  m_pPreviewModelEntities[BARBARIAN_AXE] = Vision::Game.CreateEntity("VisBaseEntity_cl", hkvVec3(0.f, 0.f, 0.f), "Barbarian_Axe.model");
  m_pPreviewModelEntities[BARBARIAN_SWORD] = Vision::Game.CreateEntity("VisBaseEntity_cl", hkvVec3(0.f, 0.f, 0.f), "Barbarian_Sword.model");

  // Setup animation system
  VDynamicMesh* pBodyMesh = m_pPreviewModelEntities[BARBARIAN_BODY]->GetMesh();
  VisSkeletalAnimSequence_cl* pSequence = static_cast<VisSkeletalAnimSequence_cl*>(pBodyMesh->GetSequence("Idle", VIS_MODELANIM_SKELETAL));

  // Create shared skeletal anim control to animate all models in sync
  VisSkeletalAnimControl_cl* pSkeletalAnimControl = 
    VisSkeletalAnimControl_cl::Create(pBodyMesh->GetSkeleton(), pSequence, VSKELANIMCTRL_DEFAULTS | VANIMCTRL_LOOP);

  for (int i = 0; i < BARBARIAN_MAX; i++)
  {
    // Create anim config per entity
    VisAnimFinalSkeletalResult_cl* pFinalSkeletalResult = NULL;
    VisAnimConfig_cl* pConfig = VisAnimConfig_cl::CreateSkeletalConfig(m_pPreviewModelEntities[i]->GetMesh(), &pFinalSkeletalResult);
    pConfig->SetFlags(pConfig->GetFlags() | APPLY_MOTION_DELTA);

    // Anim config uses shared skeletal anim control as input
    pFinalSkeletalResult->SetSkeletalAnimInput(pSkeletalAnimControl);

    m_pPreviewModelEntities[i]->SetAnimConfig(pConfig);
    m_pPreviewModelEntities[i]->SetPosition(m_vPos);
    m_pPreviewModelEntities[i]->SetOrientation(m_vOri);
#ifndef _VISION_PSP2
    m_pPreviewModelEntities[i]->SetCastShadows(TRUE);
#endif
  }

  m_pCameraEntity->AttachToParent(m_pPreviewModelEntities[BARBARIAN_BODY]);
  m_pPlayerCamera->ResetOldPosition();
  m_pPlayerCamera->Follow = true;
  m_pPlayerCamera->Zoom = false;
  m_pPlayerCamera->InitialYaw = -90.f;

  
  UpdatePreview();
}
// **************************************************
//            OVERRIDDEN ENTITY FUNCTIONS
// **************************************************
void TransitionBarbarian_cl::InitFunction()
{
  if (!HasMesh())
    return;

  SetCastShadows(TRUE);
  
  // Setup all animation sequences
	SetupAnimations();
  if (!m_bModelValid)
    return;

  if( !m_pPhys)
  {
    m_pPhys = new vHavokCharacterController();
    m_pPhys->Initialize();

    hkvAlignedBBox bbox;
    VDynamicMesh *pMesh = GetMesh();
    pMesh->GetCollisionBoundingBox(bbox);

    float r = bbox.getSizeX() * 0.5f;
    m_pPhys->Capsule_Radius = r;
    m_pPhys->Character_Top.set(0,0,bbox.m_vMax.z - r);
    m_pPhys->Character_Bottom.set(0,0,bbox.m_vMin.z + r);

    m_pPhys->Max_Slope = 75.0f;
    AddComponent(m_pPhys);
    //	pPhys->SetDebugRendering(TRUE);
  }
 
  // Get Model
  VDynamicMesh* pModel = GetMesh();
	VASSERT(pModel);

  // Transition table to use
  VTransitionTable *pTable = VTransitionManager::GlobalManager().LoadTransitionTable(pModel,"Barbarian.vTransition");
  VASSERT(pTable && pTable->IsLoaded());

	// Setup the state machine component and pass the filename of the transition file
  // in which the transitions between the various animation states are defined.
	m_pStateMachine = new VTransitionStateMachine();
  m_pStateMachine->Init(this, pTable);
	AddComponent(m_pStateMachine);

	// Set initial state
	m_pStateMachine->SetState(m_pSkeletalSequenceList[ANIMID_IDLE]);
}
// **************************************************
//            SETUP ANIMATIONS
// **************************************************
void TransitionBarbarian_cl::SetupAnimations()
{
  m_bModelValid = false;
  VDynamicMesh *pModel = GetMesh();
  VVERIFY_OR_RET(pModel);

  m_pSkeletalSequenceList[ANIMID_IDLE] = (VisSkeletalAnimSequence_cl*)pModel->GetSequence("Idle", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_pSkeletalSequenceList[ANIMID_IDLE]);

  m_pSkeletalSequenceList[ANIMID_WALK] = (VisSkeletalAnimSequence_cl*)pModel->GetSequence("Walk", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_pSkeletalSequenceList[ANIMID_WALK]);

  m_pSkeletalSequenceList[ANIMID_RUN] = (VisSkeletalAnimSequence_cl*)pModel->GetSequence("Run", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_pSkeletalSequenceList[ANIMID_RUN]);

  m_bModelValid = true;
}
void SimpleSkeletalAnimatedObject_cl::ForwardKinematics()
{
  // Apply forward kinematics to the head "Neck" bone, using a bone modifier node. The bone modifier
  // gets a skeletal animation as input, modifies the translation of the neck bone and generates the
  // combined result. The animation tree looks as follows:
  //
  // - FinalSkeletalResult
  //    - BoneModifierNode (modifies the neck bone)
  //      - SkeletalAnimControl (Walk Animation)
  //
  // The translation of the neck bone is set on the bone modifier node.
  //

  // Create a new AnimConfig instance
  VDynamicMesh *pMesh = GetMesh();
  VisAnimFinalSkeletalResult_cl* pFinalSkeletalResult;
  VisAnimConfig_cl* pConfig = VisAnimConfig_cl::CreateSkeletalConfig(pMesh, &pFinalSkeletalResult);

  // Get skeletal animation sequence.
  VisSkeletalAnimSequence_cl* pAnimSequenceWalk = 
    static_cast<VisSkeletalAnimSequence_cl*>(pMesh->GetSequence("Walk", VIS_MODELANIM_SKELETAL));
  if (pAnimSequenceWalk == NULL)
    return;

  // Create the animation control to play the walk animation (via a helper function).
  VSmartPtr<VisSkeletalAnimControl_cl> spWalkAnimControl = VisSkeletalAnimControl_cl::Create(
    pMesh->GetSkeleton(), pAnimSequenceWalk, VANIMCTRL_LOOP|VSKELANIMCTRL_DEFAULTS, 1.0f, true);

  // Create the bone modifier node that translates the head bone. Set the animation control instance
  // as the input for this node.
  m_spBoneModifierNode = new VisAnimBoneModifierNode_cl(pMesh->GetSkeleton());
  m_spBoneModifierNode->SetModifierInput(spWalkAnimControl);
  hkvQuat customBoneRotation;

  // set the neck bone translation on the bone modifier node
  m_iNeckBoneIndex = pMesh->GetSkeleton()->GetBoneIndexByName("skeleton1:Neck");
  customBoneRotation.setFromEulerAngles (0, -45, 0);
  m_spBoneModifierNode->SetCustomBoneRotation(m_iNeckBoneIndex, customBoneRotation, VIS_MODIFY_BONE);

  // finally set the bone modifier as the root animation node
  pFinalSkeletalResult->SetSkeletalAnimInput(m_spBoneModifierNode);
  SetAnimConfig(pConfig);

  // The bone modifier node is now part of the animation tree. You can at any time update the translation
  // on the bone modifier. The animation system will take care of generating the proper final result.
}
void SimpleSkeletalAnimatedObject_cl::LayerTwoAnimations()
{
  // Layer two animations (using a LayerMixer node). We use this to fade-in an upper body animation 
  // on top of a full body animation. The mixer gets the two animation controls as input and generates
  // the layered result. The animation tree looks as follows:
  //
  // - FinalSkeletalResult
  //    - LayerMixerNode
  //       - SkeletalAnimControl (WalkDagger Animation; influences full body)
  //       - SkeletalAnimControl (RunDagger Animation: influences upper body only)
  //
  // The weight of the layered upper body animation is set on the mixer instance.
  //

  // Create a new AnimConfig instance
  VDynamicMesh *pMesh = GetMesh();
  VisSkeleton_cl *pSkeleton = pMesh->GetSkeleton();
  VisAnimFinalSkeletalResult_cl* pFinalSkeletalResult;
  VisAnimConfig_cl* pConfig = VisAnimConfig_cl::CreateSkeletalConfig(pMesh, &pFinalSkeletalResult);

  // get skeletal animation sequence
  VisSkeletalAnimSequence_cl* pAnimSequenceWalkDagger = static_cast<VisSkeletalAnimSequence_cl*>(
    pMesh->GetSequence("Walk_Dagger", VIS_MODELANIM_SKELETAL));
  VisSkeletalAnimSequence_cl* pAnimSequenceDrawDagger = static_cast<VisSkeletalAnimSequence_cl*>(
    pMesh->GetSequence("Draw_Dagger", VIS_MODELANIM_SKELETAL));

  if (pAnimSequenceWalkDagger == NULL || pAnimSequenceDrawDagger == NULL)
    return;

  // Create the two animation controls: WalkDagger: full body animation; DrawDagger: upper body animation.
  // Use a helper function to create the animation controls.
  VSmartPtr<VisSkeletalAnimControl_cl> spWalkDaggerAnimControl = VisSkeletalAnimControl_cl::Create(
    pMesh->GetSkeleton(), pAnimSequenceWalkDagger, VANIMCTRL_LOOP|VSKELANIMCTRL_DEFAULTS, 1.0f, true);
  VSmartPtr<VisSkeletalAnimControl_cl> spDrawDaggerAnimControl = VisSkeletalAnimControl_cl::Create(
    pMesh->GetSkeleton(), pAnimSequenceDrawDagger, VSKELANIMCTRL_DEFAULTS, 1.0f, true);

  // create the layer node which layers the two animations
  m_spLayerMixerNode = new VisAnimLayerMixerNode_cl(pMesh->GetSkeleton());
  m_spLayerMixerNode->AddMixerInput(spWalkDaggerAnimControl, 1.0f);
  int iMixerInputDrawDagger = m_spLayerMixerNode->AddMixerInput(spDrawDaggerAnimControl, 0.0f);
  
  // set a per bone weighting list for the DrawDagger (upper body) slot in the mixer. It shall overlay the
  // upper body of the character and thus only influence the upper body bones.
  int iBoneCount = pSkeleton->GetBoneCount();
  VASSERT(iBoneCount < 256);

  float fPerBoneWeightingList[256];
  memset(fPerBoneWeightingList, 0, sizeof(float)*iBoneCount);

  pSkeleton->SetBoneWeightRecursive(1.f, pSkeleton->GetBoneIndexByName("skeleton1:Spine"), fPerBoneWeightingList);
  m_spLayerMixerNode->ApplyPerBoneWeightingMask(iMixerInputDrawDagger, iBoneCount, fPerBoneWeightingList);

  // finally set the mixer as the root animation node
  pFinalSkeletalResult->SetSkeletalAnimInput(m_spLayerMixerNode);
  SetAnimConfig(pConfig);

  // fade-in the upper body animation
  //m_spLayerMixerNode->EaseIn(iMixerInputDrawDagger, 0.4f, true);
}
VisMeshBuffer_cl *VRendererNodeHelper::GetSphereMeshBuffer()
{
  if (m_spSphereMeshBuffer != NULL)
    return m_spSphereMeshBuffer;

  VDynamicMesh *pMesh = Vision::Game.LoadDynamicMesh("\\Models\\MagicBall.model", true, false);
  VASSERT(pMesh!=NULL);

  m_spSphereMeshBuffer = new VisMeshBuffer_cl();
  m_spSphereMeshBuffer->SetPrimitiveType(VisMeshBuffer_cl::MB_PRIMTYPE_INDEXED_TRILIST);
#ifdef HK_DEBUG
  m_spSphereMeshBuffer->SetFilename("<DeferredShadingSphereMesh>");
#endif

  VisMBVertexDescriptor_t descr;
  descr.Reset();
  descr.m_iPosOfs = 0 | VERTEXDESC_FORMAT_FLOAT3;
  descr.m_iStride = sizeof(float)*3;

  // get model properties
  int iVertexCount = pMesh->GetNumOfVertices();
  int iIndexCount = pMesh->GetNumOfTriangles() * 3;

  // copy vertex buffer, normalize vertex positions
  m_spSphereMeshBuffer->AllocateVertices(descr, iVertexCount); 
  float *pDestVerts = (float *)m_spSphereMeshBuffer->LockVertices(VIS_LOCKFLAG_DISCARDABLE);
  pMesh->CopyMeshVertices(pDestVerts, descr, 0, iVertexCount);
  for (int i=0; i<iVertexCount*3; i+=3)
  {
    hkvVec3 vPos(pDestVerts[i], pDestVerts[i+1], pDestVerts[i+2]);
    vPos.normalizeIfNotZero();
    memcpy(&pDestVerts[i], vPos.data, 3*sizeof(float));
  }
  m_spSphereMeshBuffer->UnLockVertices();

  // copy index buffer
  m_spSphereMeshBuffer->AllocateIndexList(iIndexCount);
  unsigned short *pDestIndices = (unsigned short *)m_spSphereMeshBuffer->LockIndices(VIS_LOCKFLAG_DISCARDABLE);
  pMesh->CopyMeshIndices(pDestIndices, (VisSurface_cl *)NULL);
  m_spSphereMeshBuffer->UnLockIndices();

  return m_spSphereMeshBuffer;
}
// **************************************************
//            SETUP ANIMATIONS
// **************************************************
void TransitionCharacter_cl::SetupAnimations()
{
  m_bModelValid = false;
  VDynamicMesh *pMesh = GetMesh();
  VVERIFY_OR_RET(pMesh);

  // idle animations
  m_spSkeletalSequenceList[ANIMID_IDLE] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Idle", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_IDLE]);

  // run animations
  m_spSkeletalSequenceList[ANIMID_RUN] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Run", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_RUN]);

  // walk animations
  m_spSkeletalSequenceList[ANIMID_WALK] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Walk", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_WALK]);

  // turn animations
  m_spSkeletalSequenceList[ANIMID_TURN] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Turn", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_TURN]);

  // walk backwards animation
  m_spSkeletalSequenceList[ANIMID_WALKBACKWARDS] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Run_BWD", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_WALKBACKWARDS]);

  m_bModelValid = true;
}
Example #15
0
bool VisClothDeformer_cl::UpdateDeformerResult(VisVertexAnimResult_cl* pVertexAnimResult)
{
  VISION_PROFILE_FUNCTION(VIS_PROFILE_ANIMSYS_RESULT_VERTEX_ANIM);
   
  if(m_spMesh == NULL)
    return false;

  //// fill vertexanimresult with the mesh data
  // destination buffer
  float *pDestVertexPosition;
  const int  iDestVertexPositionStride = pVertexAnimResult->GetDestVertexPosition(pDestVertexPosition);
  float *pDestVertexNormal;
  const int  iDestVertexNormalStride = pVertexAnimResult->GetDestVertexNormal(pDestVertexNormal);

  int iVertexCount = m_spMesh->GetVertexCount();
  VDynamicMesh *pMesh = pVertexAnimResult->GetMesh();
  VASSERT(pMesh->GetNumOfVertices() == m_spMesh->GetVertexCount());
  VisObjectVertexDelta_t *pVertexDelta = m_spMesh->GetVertexDeltaList();

  // copy mesh vertices into vertexanim result
  hkvVec3 tempNormal(hkvNoInitialization);
  hkvVec3 vTranslate;
  if (m_pParentObject)
    vTranslate = m_pParentObject->GetPosition();

  for(int i=0; i<iVertexCount; i++, pVertexDelta++, ADVANCE_VERTEXPOINTERS)
  {
    pDestVertexPosition[0] = pVertexDelta->delta[0] - vTranslate.x;
    pDestVertexPosition[1] = pVertexDelta->delta[1] - vTranslate.y;
    pDestVertexPosition[2] = pVertexDelta->delta[2] - vTranslate.z;
    tempNormal.set(pVertexDelta->normal[0], pVertexDelta->normal[1], pVertexDelta->normal[2]);
    tempNormal.normalizeIfNotZero();
    pDestVertexNormal[0] = tempNormal.x;
    pDestVertexNormal[1] = tempNormal.y;
    pDestVertexNormal[2] = tempNormal.z;
  }

  return true;
}
// Render shaders on entities
void VPostProcessTranslucencies::DrawEntitiesShaders(const VisEntityCollection_cl &EntityCollection, VPassType_e ePassType)
{
  VisDrawCallInfo_t SurfaceShaderList[RLP_MAX_ENTITY_SURFACESHADERS];
  unsigned int iNumEntities = EntityCollection.GetNumEntries();
  unsigned int i;

  Vision::RenderLoopHelper.BeginEntityRendering();

  for (i=0; i<iNumEntities; i++)
  {
    VisBaseEntity_cl *pEntity = EntityCollection.GetEntry(i);
    // Foreground entities will be handled separately
    if (pEntity->IsObjectAlwaysInForegroundEnabled()) continue;
    if ( pEntity->HasShadersForPass(ePassType) )
    {
      // Get a list of the corresponding pass type surface shaders
      VisShaderSet_cl *pShaderSet = pEntity->GetActiveShaderSet();
      if (pShaderSet == NULL) continue;
      int iNumSurfaceShaders = pShaderSet->GetShaderAssignmentList(SurfaceShaderList, ePassType, RLP_MAX_ENTITY_SURFACESHADERS);
      VASSERT(iNumSurfaceShaders < RLP_MAX_ENTITY_SURFACESHADERS);
      if (iNumSurfaceShaders == 0) continue;

      VDynamicMesh *pMesh = pEntity->GetMesh();

      // If the model has lit surfaces, and if the shaders makes use of the lighting information, we need to set up
      // the global lights.
      if (pMesh != NULL && pMesh->HasLitSurfaces() && (pShaderSet->GetCombinedTrackingMask()&(VSHADER_TRACKING_LIGHTGRID_PS|VSHADER_TRACKING_LIGHTGRID_GS|VSHADER_TRACKING_LIGHTGRID_VS)) )
      {
        Vision::RenderLoopHelper.TrackLightGridInfo(pEntity);
      }
      // Render the entity with the surface shader list
      Vision::RenderLoopHelper.RenderEntityWithSurfaceShaderList(pEntity, iNumSurfaceShaders, SurfaceShaderList);
    } 
  }

  Vision::RenderLoopHelper.EndEntityRendering();

} 
void SimpleSkeletalAnimatedObject_cl::BlendTwoAnimations()
{
  // Blend two animations using a NormalizeMixer node. The mixer gets the two animations as input
  // and generates the blended result. The animation tree looks as follows:
  //
  // - FinalSkeletalResult
  //    - NormalizeMixerNode
  //       - SkeletalAnimControl (Walk Animation)
  //       - SkeletalAnimControl (Run Animation)
  //
  // The weights of the two animations are set on the mixer instance.
  //

  // create a new AnimConfig instance
  VDynamicMesh *pMesh = GetMesh();
  VisAnimFinalSkeletalResult_cl* pFinalSkeletalResult;
  VisAnimConfig_cl* pConfig = VisAnimConfig_cl::CreateSkeletalConfig(pMesh, &pFinalSkeletalResult);

  // get skeletal animation sequence
  VisSkeletalAnimSequence_cl* pAnimSequenceWalk = static_cast<VisSkeletalAnimSequence_cl*>(
    pMesh->GetSequence("Walk", VIS_MODELANIM_SKELETAL));
  VisSkeletalAnimSequence_cl* pAnimSequenceRun = static_cast<VisSkeletalAnimSequence_cl*>(
    pMesh->GetSequence("Run", VIS_MODELANIM_SKELETAL));

  if(pAnimSequenceWalk == NULL || pAnimSequenceRun == NULL)
    return;

  // create two animation controls: walk and run (use a helper function for creating them)
  VSmartPtr<VisSkeletalAnimControl_cl> spWalkAnimControl = VisSkeletalAnimControl_cl::Create(
    pMesh->GetSkeleton(), pAnimSequenceWalk, VANIMCTRL_LOOP|VSKELANIMCTRL_DEFAULTS, 1.0f, true);
  VSmartPtr<VisSkeletalAnimControl_cl> spRunAnimControl = VisSkeletalAnimControl_cl::Create(
    pMesh->GetSkeleton(), pAnimSequenceRun, VANIMCTRL_LOOP|VSKELANIMCTRL_DEFAULTS, 1.0f, true);

  // create the mixer node that blends the two animations
  // (set initial weight to show walk animation only)
  m_spNormalizeMixerNode = new VisAnimNormalizeMixerNode_cl(pMesh->GetSkeleton());
  m_iMixerInputWalk = m_spNormalizeMixerNode->AddMixerInput(spWalkAnimControl, 1.0f);
  m_iMixerInputRun = m_spNormalizeMixerNode->AddMixerInput(spRunAnimControl, 0.0f);

  // finally set the mixer as the root animation node
  pFinalSkeletalResult->SetSkeletalAnimInput(m_spNormalizeMixerNode);
  SetAnimConfig(pConfig);

  // blend from walk to run
  SetBlendWalkToRun(true);
}
// Renders foreground entities (i.e. entities which have been flagged as "always in foreground")
void VPostProcessTranslucencies::DrawTransparentForegroundEntities(const VisEntityCollection_cl &EntityCollection)
{
  unsigned int iNumEntities = EntityCollection.GetNumEntries(); // this collection only contains foreground objects
  if (iNumEntities==0 || m_spForegroundFillPassTechnique==NULL)
    return;

  INSERT_PERF_MARKER_SCOPE("VisionRenderLoop_cl::DrawForegroundEntities");

  unsigned int i;
  const hkvMat4* pLastProj = NULL;

  Vision::RenderLoopHelper.BeginEntityRendering();
  const int iPassCount = m_spForegroundFillPassTechnique->GetShaderCount();
  for (int iPass=0;iPass<=iPassCount;iPass++) // +1 passes, where the last one is the actual material pass
  {
    for (i=0; i<iNumEntities; i++)
    {
      VisBaseEntity_cl *pEntity = EntityCollection.GetEntry(i);

      // Render only Entities that are flagged as "always in foreground"
      VASSERT_MSG(pEntity->IsObjectAlwaysInForegroundEnabled(), "Only entities with this flag should be passed to this function");

      if (pEntity->HasShadersForPass(VPT_TransparentPass))
      {
        VDynamicMesh *pMesh = pEntity->GetMesh();
        VisShaderSet_cl *pShaderSet = pEntity->GetActiveShaderSet();

        VASSERT(pMesh && pShaderSet);

        const hkvMat4* pThisProj = pEntity->GetCustomProjectionMatrixForForegroundObject();

        if (pThisProj != pLastProj)
        {
          VisRenderStates_cl::SetCurrentProjectionMatrix(pThisProj);
          pLastProj = pThisProj;
        }

        if (iPass<iPassCount) // depth fill pass
        {
          VCompiledShaderPass *pPass = m_spForegroundFillPassTechnique->GetShader(iPass);
          Vision::RenderLoopHelper.RenderEntityWithShaders(pEntity, 1, &pPass);
        }
        else // material pass
        {
          const VisDrawCallInfo_t *pAssignment;

          int iNumSurfaceShaders = pShaderSet->GetShaderAssignmentList(&pAssignment);

          // If the shaders make use of the lighting information, we need to track the light grid
          if (pMesh != NULL && pMesh->HasLitSurfaces() && 
            (pShaderSet->GetCombinedTrackingMask() & (VSHADER_TRACKING_LIGHTGRID_PS|VSHADER_TRACKING_LIGHTGRID_GS|VSHADER_TRACKING_LIGHTGRID_VS)) )
          {
            Vision::RenderLoopHelper.TrackLightGridInfo(pEntity);
          }

          // Render the entity with the surface shader list
          Vision::RenderLoopHelper.RenderEntityWithSurfaceShaderList(pEntity, iNumSurfaceShaders, pAssignment);
        }
      }
    }
  }

  Vision::RenderLoopHelper.EndEntityRendering();

  // reset to context projection matrix
  if (pLastProj)
  {
    VisRenderStates_cl::SetCurrentProjectionMatrix(NULL);
  }
}
void AnimatedWarrior_cl::InitFunction()
{
  SetCastShadows(TRUE);
  
  SetupAnimations();
  if (!m_bModelValid)
    return;

	m_pCharacterController = new vHavokCharacterController();
	m_pCharacterController->Initialize();

	hkvAlignedBBox bbox;
	GetMesh()->GetCollisionBoundingBox(bbox);

  float r = bbox.getSizeX() * 0.5f;
	m_pCharacterController->Capsule_Radius = r;
	m_pCharacterController->Character_Top.set(0,0,bbox.m_vMax.z - r);
  m_pCharacterController->Character_Bottom.set(0,0,bbox.m_vMin.z + r);

 	m_pCharacterController->Max_Slope = 75.0f;

  if (!m_bEnabled)
    m_pCharacterController->SetEnabled(FALSE);

	AddComponent(m_pCharacterController);

  //// setup animation system
  // create config
  VDynamicMesh* pMesh = GetMesh();
  VASSERT(pMesh);
  VisSkeleton_cl* pSkeleton = pMesh->GetSkeleton();
  VASSERT(pSkeleton);

  // create mixer structure, we keep pointers on the mixers to add and remove inputs
  m_spLayerMixer = new VisAnimLayerMixerNode_cl(pSkeleton);

  m_pNormalizeMixer = new VisAnimNormalizeMixerNode_cl(pSkeleton);
  m_spLayerMixer->AddMixerInput(m_pNormalizeMixer, 1.f);

  //// create per bone weighting list for upper body
  int iBoneCount = pSkeleton->GetBoneCount();
  float* fPerBoneWeightingList = new float[iBoneCount];
  memset(fPerBoneWeightingList, 0, sizeof(float)*iBoneCount);

  // set all bone weights above the spine to 1
  pSkeleton->SetBoneWeightRecursive(1.f, pSkeleton->GetBoneIndexByName("skeleton1:Spine"), fPerBoneWeightingList);

  int iMixerInputIndex = -1;

  for(int i=0; i<UPPERBODY_CONTROLCOUNT; i++)
  {
    m_spUpperBodyControls[i] = new VisSkeletalAnimControl_cl(pSkeleton, VSKELANIMCTRL_DEFAULTS);
    m_spUpperBodyControls[i]->AddEventListener(this); // we want to receive all events from sequence and control
    iMixerInputIndex = m_spLayerMixer->AddMixerInput(m_spUpperBodyControls[i], 0.f);
    m_spLayerMixer->ApplyPerBoneWeightingMask(iMixerInputIndex, iBoneCount, fPerBoneWeightingList);
  }
  
  V_SAFE_DELETE_ARRAY(fPerBoneWeightingList);

  // set the start animation
  BlendOverFullBodyAnimation(0.f, ANIMID_IDLE, 1.f, 0.f);
 
  SetFullBodyState(m_pFullBodyIdleState[FBSTATETYPE_NORMAL]);
  SetUpperBodyState(m_pUpperBodyIdleState);

  // initialize variables for upperbody fadein/fadeout
  m_eUpperBodyFadeState = FADESTATE_NONE;

  // setup neck bone for head rotation
  m_iHeadBoneIndex = pSkeleton->GetBoneIndexByName("skeleton1:Neck");
  m_fHeadRotationAngles[0] = 0.f; m_fHeadRotationAngles[1] = 0.f; m_fHeadRotationAngles[2] = 0.f;
  m_bHeadInMovement = false;

  // setup the torch
  hkvVec3 vDummyOrigin;
  m_pTorch = (AttachedTorch_cl *) Vision::Game.CreateEntity( "AttachedTorch_cl", vDummyOrigin );
  
  HideTorch();

  // attach the torch to the bone
  //hkvVec3 localTranslation(-11.f, -4.5f, 25.f);
  hkvVec3 localTranslation(-11.f, 5.5f, 0.f);
  float euler[3] = {90, 0, 185};
  hkvQuat localRotation;
  localRotation.setFromEulerAngles (euler[2], euler[1], euler[0]); // pass as roll, pitch, yaw
  m_pTorch->Attach(this, "skeleton1:RightHand", localRotation, localTranslation);

  SetEnabled(true);
}
BOOL VLineFollowerComponent::StartAnimation(const char *szAnimName)
{
  VisBaseEntity_cl* pOwner = (VisBaseEntity_cl *)GetOwner();
  if (!pOwner)
    return false;

  m_bPlayingAnim = false;

  // Check for animation sequences
  VDynamicMesh *pMesh = pOwner->GetMesh();
  if (!pMesh || !pMesh->GetSequenceSetCollection() || !pMesh->GetSequenceSetCollection()->GetSequenceSetCount())
    return false;

  VisAnimFinalSkeletalResult_cl* pFinalSkeletalResult = NULL;
  VisVertexAnimDeformer_cl* pVertexAnimDeformer = NULL;

  // Get the sequence(s) for vertex and skeletal animation
  VisSkeletalAnimSequence_cl* pAnimSequenceSkeletal = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence(szAnimName, VIS_MODELANIM_SKELETAL);
  VisVertexAnimSequence_cl* pAnimSequenceVertex = (VisVertexAnimSequence_cl*)pMesh->GetSequence(szAnimName, VIS_MODELANIM_VERTEX);

  // If no sequence with the given name is present
  if ((!pAnimSequenceSkeletal) && (!pAnimSequenceVertex))
  {
    VisAnimSequenceSet_cl * pSequenceSet =  pMesh->GetSequenceSetCollection()->GetSequenceSet(0);
    // Find the first skeletal or vertex animation and use it
    for (int i=0; i< pSequenceSet->GetSequenceCount(); ++i)
    {
      VisAnimSequence_cl* pTempAnimSequence = pSequenceSet->GetSequence(i);
      if (pTempAnimSequence->GetType() == VIS_MODELANIM_SKELETAL)
      {
        // If it is a skeletal animation, create a config for it
        VisAnimConfig_cl* pConfig = VisAnimConfig_cl::CreateSkeletalConfig(pMesh, &pFinalSkeletalResult);
        VisSkeletalAnimControl_cl* pSkeletalAnimControl = VisSkeletalAnimControl_cl::Create(pMesh->GetSkeleton(), (VisSkeletalAnimSequence_cl*)pTempAnimSequence, VANIMCTRL_LOOP|VSKELANIMCTRL_DEFAULTS, 1.0f, true);
        pFinalSkeletalResult->SetSkeletalAnimInput(pSkeletalAnimControl);
        pOwner->SetAnimConfig(pConfig);
        m_bPlayingAnim = true;
        return true;
      }
      else if (pTempAnimSequence->GetType() == VIS_MODELANIM_VERTEX)
      {
        // If it is a vertex animation, create a config for it
        VisAnimConfig_cl* pConfig = VisAnimConfig_cl::CreateVertexConfig(pMesh, &pVertexAnimDeformer);
        VisVertexAnimControl_cl* pVertexAnimControl = VisVertexAnimControl_cl::Create((VisVertexAnimSequence_cl*)pTempAnimSequence, VANIMCTRL_LOOP|VSKELANIMCTRL_DEFAULTS, 1.0f, true);
        pVertexAnimDeformer->AddVertexAnimControl(pVertexAnimControl, 1.0f);
        pOwner->SetAnimConfig(pConfig);
        m_bPlayingAnim = true;
        return true;
      }
    }
    // If neither a skeletal nor a vertex animation has been found, report failure
    return false;
  }

  // If both a vertex and a skeletal animation with the given name has been found
  // create a combined config for skeletal and vertex animation.
  VisAnimConfig_cl* pConfig = NULL;
  if ((pAnimSequenceSkeletal) && (pAnimSequenceVertex))
    pConfig = VisAnimConfig_cl::CreateSkeletalVertexConfig(pMesh, &pFinalSkeletalResult, &pVertexAnimDeformer);

  // If it is just a skeletal animation, create a config for it
  if (pAnimSequenceSkeletal)
  {    
    if (!pConfig)
      pConfig = VisAnimConfig_cl::CreateSkeletalConfig(pMesh, &pFinalSkeletalResult);

    // If a skeletal animation has been found create a control for it
    VisSkeletalAnimControl_cl* pSkeletalAnimControl = VisSkeletalAnimControl_cl::Create(pMesh->GetSkeleton(), pAnimSequenceSkeletal, VANIMCTRL_LOOP|VSKELANIMCTRL_DEFAULTS, 1.0f, true);
    // And set it as the input for the final skeletal result
    pFinalSkeletalResult->SetSkeletalAnimInput(pSkeletalAnimControl);
  }

  // If it is just a vertex animation, create a config for it
  if (pAnimSequenceVertex)
  {
    if (!pConfig)
      pConfig = VisAnimConfig_cl::CreateVertexConfig(pMesh, &pVertexAnimDeformer);

    // If a vertex animation has been found create a control for it
    VisVertexAnimControl_cl* pVertexAnimControl = VisVertexAnimControl_cl::Create(pAnimSequenceVertex, VANIMCTRL_LOOP|VSKELANIMCTRL_DEFAULTS, 1.0f, true);
    // And set add it to the vertex anim deformer
    pVertexAnimDeformer->AddVertexAnimControl(pVertexAnimControl, 1.0f);
  }

  // Set the current config
  pOwner->SetAnimConfig(pConfig);

  // Make sure we get the motion delta from the animation
  pOwner->GetAnimConfig()->SetFlags(pOwner->GetAnimConfig()->GetFlags() | APPLY_MOTION_DELTA | MULTITHREADED_ANIMATION);

  // And report success
  m_bPlayingAnim = true;
  return true;
}
Example #21
0
VBool SaveGame(int iNum)
{
  if ( (iNum < 1) || (iNum > 4) )
  {
    // we just allow 4 save games
    return FALSE;
  }

  int i;
  char pszSaveFileName[FS_MAX_PATH];

  sprintf(pszSaveFileName,SAVEGAME_NAME, iNum);
  IVFileOutStream* pOut = Vision::File.Create(pszSaveFileName);
  // creating the file didn't work!
  if (!pOut)
  {
    return FALSE;
  }

  VArchive ar( pszSaveFileName, pOut, Vision::GetTypeManager() );

  // serialize global game data
  ar << ARCHIVE_START_TAG; 		      // magic number
  int iSavingVersion = Vision::GetArchiveVersion();
  ar << iSavingVersion;             // archive class version
  ar << g_iCurrentMap;              // current map number
  ar << Vision::GetTimer()->GetTime();		// current time

  // count entities
  SerializeBaseEntity_cl *pSerEnt = NULL;
  VisBaseEntity_cl *pEnt = NULL;
  int iFullCtr = 0;
  int iReCreateCtr = 0;
  int iNumOfAllEntities = VisBaseEntity_cl::ElementManagerGetSize();
  for (i = 0; i < iNumOfAllEntities; i++)
  {
    pEnt = VisBaseEntity_cl::ElementManagerGet(i);
    if ( pEnt )
    {
      if ( pEnt->IsOfType(SerializeBaseEntity_cl::GetClassTypeId()) )
      {
        pSerEnt = static_cast<SerializeBaseEntity_cl*>(pEnt);
        if ( pSerEnt->GetSerializeType() == SERIALIZE_FULL )
          iFullCtr++;
        else
          iReCreateCtr++;
      }
    }
  }

  // serialize number of entities
  ar << iReCreateCtr;
  ar << iFullCtr;

  hkvVec3 vTemp;

  // do ReCreate serialization of entities
  for (i = 0; i < iNumOfAllEntities; i++)
  {
    pEnt = VisBaseEntity_cl::ElementManagerGet(i);
    if ( pEnt )
    {
      if ( pEnt->IsOfType(SerializeBaseEntity_cl::GetClassTypeId()) )
      {
        pSerEnt = (SerializeBaseEntity_cl *) pEnt;
        if ( pSerEnt->GetSerializeType() == SERIALIZE_RECREATE )
        {
          char pszEntityParams[4000];
          GetEntityParameters( pSerEnt, pszEntityParams );
          VDynamicMesh* pMesh = pSerEnt->GetMesh();
          ar << pSerEnt->GetClassFullName() << pSerEnt->GetEntityKey();
          vTemp = pSerEnt->GetPosition();
          vTemp.SerializeAsVisVector (ar);
          vTemp = pSerEnt->GetOrientation();
          vTemp.SerializeAsVisVector (ar);
          const char *szFilename = pMesh ? pMesh->GetFilename() : NULL;
          ar << szFilename << pszEntityParams;
        }
      }
    }
  }

  // do full serialization of entities
  for (i = 0; i < iNumOfAllEntities; i++)
  {
    pEnt = VisBaseEntity_cl::ElementManagerGet(i);
    if ( pEnt )
    {
      if ( pEnt->IsOfType(SerializeBaseEntity_cl::GetClassTypeId()) )
      {
        pSerEnt = (SerializeBaseEntity_cl *) pEnt;
        if ( pSerEnt->GetSerializeType() == SERIALIZE_FULL )
        {
          ar << pSerEnt;
        }
      }
    }
  }

  // store end tag - useful to verify a valid archive
  ar << ARCHIVE_END_TAG;

  ar.Close();
  pOut->Close();

  g_SaveSlot[iNum-1].SaveScreenShotPreview();

  return TRUE;
}
void VLineFollowerComponent::InitPhysics(float fPathPos)
{
  VisBaseEntity_cl* pOwner = (VisBaseEntity_cl *)GetOwner();
  if (!pOwner)
    return;

  hkvVec3 vPos;
  hkvVec3 vDir;
  hkvAlignedBBox bbox;

  m_fCurrentPathPos = fPathPos;
  if(m_pFollowPath)
    m_pFollowPath->EvalPoint(fPathPos, vPos, &vDir);
  else
    vPos = pOwner->GetPosition();

  // to determine correct height on the ground, perform a ray-cast:
  if (Vision::GetApplication()->GetPhysicsModule()!=NULL && Model_CapsuleHeight>0)
  {
    hkvVec3 vRayStart(vPos.x,vPos.y,vPos.z+Model_CapsuleHeight);
    hkvVec3 vRayEnd(vPos.x,vPos.y,vPos.z-Model_CapsuleHeight);
    VisPhysicsHit_t hitPoint;
    if (Vision::GetApplication()->GetPhysicsModule()->Raycast(vRayStart, vRayEnd, hitPoint)) // hit?
    {
      vPos.z = hitPoint.vImpactPoint.z + 5.f*Vision::World.GetGlobalUnitScaling(); // add some margin
    }
  }

  VDynamicMesh *pMesh = pOwner->GetMesh();
  if (pMesh)
  {
    pMesh->GetCollisionBoundingBox(bbox);
    vPos.z -= bbox.m_vMin.z;

    // Use model size if not set
    if (Model_CapsuleRadius<=0.f) Model_CapsuleRadius = hkvMath::Min( bbox.getSizeX(), bbox.getSizeY() )/2.f;
    if (Model_CapsuleHeight<=0.f) Model_CapsuleHeight = bbox.getSizeZ();
  } else
  { 
    // No model - set some sane values if not set
    if (Model_CapsuleRadius<=0.f) Model_CapsuleRadius = 40.f;
    if (Model_CapsuleHeight<=0.f) Model_CapsuleHeight = 90.f;
  }

  // Create the physics object 
  pOwner->SetPosition(vPos);
  if (!m_pPhys)
  {
    m_pPhys = new vHavokCharacterController();
    m_pPhys->Capsule_Radius = Model_CapsuleRadius;
    float h = Model_CapsuleHeight * 0.5f;
    float fPivot = Model_GroundOffset;
    m_pPhys->Character_Top.set(0, 0, h - fPivot);
    m_pPhys->Character_Bottom.set(0, 0, -h - fPivot);
    pOwner->AddComponent(m_pPhys);
  }

  // Update position
  m_pPhys->SetPosition(vPos);

  // Enable debug rendering
  m_pPhys->SetDebugRendering(Debug_RenderMesh);
  m_pPhys->SetDebugColor(V_RGBA_RED);
}
void VMobileForwardRenderLoop::RenderLitGeometry(VisLightSource_cl *pLight, IVShadowMapComponent *pShadowMapComponent, bool bBasePass, bool bUsesLightClippingVolume, bool bEntities, bool bStaticGeometry)
{
  if (!pLight)
    return;

  // Some local variables for storing surfaces, shaders, surface shaders, and the like.
  VCompiledTechnique *pTechnique = NULL;
  VisDrawCallInfo_t SurfaceShaderList[RLP_MAX_ENTITY_SURFACESHADERS];

  VisRenderContext_cl *pContext = VisRenderContext_cl::GetCurrentContext();
  const hkvVec3 &vCamPos = pContext->GetCamera()->GetPosition();
 
  const float fFade = pLight->GetFadeWeight(vCamPos);

  VisStaticGeometryInstanceCollection_cl *pLitGeoInstanceCollection = NULL;
  VisEntityCollection_cl *pLitEntityCollection = NULL;

  if (bBasePass || pLight != m_pBasePassLight)
  {
    if (bStaticGeometry)
    {
      pLitGeoInstanceCollection = &s_LitGeoInstanceCollection;
      pLitGeoInstanceCollection->Clear();
    }
    if (bEntities)
    {
      pLitEntityCollection = &s_LitEntityCollection;
      pLitEntityCollection->Clear();
    }

    Vision::RenderLoopHelper.GetVisibleGeometryInLightsourceRange(pLitGeoInstanceCollection, pLitEntityCollection, NULL, *pLight);
  }
  else
  {
    if (bStaticGeometry)
      pLitGeoInstanceCollection = &m_AdditiveLitGeoInstanceCollection;
    if (bEntities)
      pLitEntityCollection = &m_AdditiveLitEntityCollection;
  }

#ifdef SUPPORTS_SHADOW_MAPS
  VShadowMapGenSpotDir *pShadowMapGenDir = NULL;
  if (pShadowMapComponent)
  {
    VShadowMapGenerator *pShadowMapGen = pShadowMapComponent->GetShadowMapGenerator();
    if (pShadowMapGen->GetProjectionType()==SHADOW_PROJECTION_ORTHOGRAPHIC)
      pShadowMapGenDir = static_cast<VShadowMapGenSpotDir*>(pShadowMapGen);
  }
#endif

  // Set the stencil render state for reading light clipping volume information
  if(bUsesLightClippingVolume)
  {
    const VLightClippingVolumeComponent* pLightClippingComponent = pLight->Components().GetComponentOfBaseType<VLightClippingVolumeComponent>();
    VASSERT(pLightClippingComponent != NULL && V_ARRAY_SIZE(m_lightClippingStencilStatesRead)==2);
    VisRenderStates_cl::SetDepthStencilState(m_lightClippingStencilStatesRead[pLightClippingComponent->GetClipHandedness()]);
  }
  else
    VisRenderStates_cl::SetDepthStencilState(m_dynLightDefaultState);

  // For all illuminated entities: Render a dynamic lighting pass now.
  if (pLight->GetLightInfluenceBitMaskEntity() != 0  && bEntities)
  {
    int iNumLitEntities = pLitEntityCollection->GetNumEntries();

    Vision::RenderLoopHelper.BeginEntityRendering();

    for (int j=0; j<iNumLitEntities; j++)
    {
      VisBaseEntity_cl *pEntity = pLitEntityCollection->GetEntry(j);

      if (!(pEntity->GetLightInfluenceBitMask() & pLight->GetLightInfluenceBitMaskEntity()))
        continue;

      VDynamicMesh *pMesh = pEntity->GetMesh();
      VisSurface_cl **ppSurfaces = pEntity->GetSurfaceArray();

      // Get list of all the surfaces in the model
      int iNumSubmeshes = pMesh->GetSubmeshCount();
      int iNumSurfaceShaders = 0;

      // For all the surfaces...
      for (int k=0; k<iNumSubmeshes; k++)
      {
        VDynamicSubmesh *pSubmesh = pMesh->GetSubmesh(k);
        VisSurface_cl *pSurface = ppSurfaces[pSubmesh->m_iMaterialIndex];

        // Full-bright surfaces can't be rendered in the compound base pass, since such surfaces are not illuminated. Since tagging
        // of already rendered geometry happens per entity instance, in case an entity contains full-bright surfaces, all surfaces 
        // of this entity have to be rendered in the normal rendering pipeline.
        const VisLightingMethod_e eLightingMethod = pSurface->GetLightingMode();
        if (bBasePass)
        {
          // Since entities can contain several surfaces with different lighting methods (full-bright, dynamic only, etc.), entities 
          // with full-bright surfaces have to be also added to the additive lit entity collection, in order to ensure rendering of 
          // dynamic only surfaces.
          if (eLightingMethod==VIS_LIGHTING_FULLBRIGHT)
          {
            iNumSurfaceShaders = 0;
            m_AdditiveLitEntityCollection.AppendEntry(pEntity);
            break; 
          }
        }
        else
        {
          if (eLightingMethod == VIS_LIGHTING_FULLBRIGHT)
            continue;
        }

        // If not all surfaces have a primary opaque pass type in the base pass, then render corresponding entity 
        // in the additive lighting pass.
        if (bBasePass && pSurface->GetResolvedPassType()!=VPT_PrimaryOpaquePass)
        {
          iNumSurfaceShaders = 0;
          m_AdditiveLitEntityCollection.AppendEntry(pEntity);
          break; 
        }

        // Check whether entity is in current shadow volume for orthographic shadows. In that case the entity is rendered
        // without shadows since it is not in the relevant shadow volume.
        IVShadowMapComponent *pTmpShadowMapComponent = pShadowMapComponent;
#ifdef SUPPORTS_SHADOW_MAPS
        if (pShadowMapGenDir)
        {
          if (!pShadowMapGenDir->IsEntityInsideOrthoShadowVolume(pEntity))
            pTmpShadowMapComponent = NULL;
        }
#endif

        pTechnique = GetLightShader(pLight, bBasePass, pSurface, fFade, pTmpShadowMapComponent);
        if (!pTechnique || !pTechnique->GetShaderCount()) // do not light this surface
        {
          // If base-pass lighting technique could not be retrieved, render lit entity in the additive pass.
          if (bBasePass && pLight->IsDynamic())
            m_AdditiveLitEntityCollection.AppendEntry(pEntity);
          iNumSurfaceShaders = 0;
          break; 
        }

        // Generate a list of surface shader from the combined surface/shader information
        VisDrawCallInfo_t &info(SurfaceShaderList[iNumSurfaceShaders++]);
        info.Set(pSubmesh, pSurface, pTechnique->m_Shaders.GetAt(0));
      }

      // Finally, render the entity with a surface shader list.
      if (iNumSurfaceShaders>0)
      {
        Vision::RenderLoopHelper.RenderEntityWithSurfaceShaderList(pEntity, iNumSurfaceShaders, SurfaceShaderList);
        if (bBasePass)
          pEntity->Tag();
      }
    }

    Vision::RenderLoopHelper.EndEntityRendering();
  }

  // For all illuminated world primitives: Render a dynamic lighting pass now.
  if (pLight->GetLightInfluenceBitMaskWorld() != 0 && bStaticGeometry)
  {
    VisSurface_cl *pSurface;
    VisSurface_cl *pLastSurface = NULL;
    VCompiledTechnique *pLastTechnique = NULL;

    // We start collecting illuminated mesh instances. Whenever a relevant property changes, we set the
    // shader information, render all collected world instances, and start collecting from scratch.
    int iNumLitGeoInstances = pLitGeoInstanceCollection->GetNumEntries();
    pLastSurface = NULL;
    s_RenderGeoInstanceCollection.Clear();
    pLastTechnique = NULL;

    for (int j=0; j<iNumLitGeoInstances; j++)
    {
      VisStaticGeometryInstance_cl *pGI = pLitGeoInstanceCollection->GetEntry(j);

      pSurface = pGI->GetSurface();
      VASSERT(pSurface);
      if (pSurface->IsFullbright()) 
        continue; 

      // If surface does not have a primary opaque pass type in the base pass, then render corresponding static
      // mesh instance in the additive lighting pass.
      if (bBasePass && pSurface->GetResolvedPassType()!=VPT_PrimaryOpaquePass)
      {
        m_AdditiveLitGeoInstanceCollection.AppendEntry(pGI);
        continue;
      }

      // Check whether mesh is in current shadow volume for orthographic shadows. In that case the mesh is rendered
      // without shadows since it is not in the relevant shadow volume.
      IVShadowMapComponent *pTmpShadowMapComponent = pShadowMapComponent;
#ifdef SUPPORTS_SHADOW_MAPS
      if (pShadowMapGenDir)
      {
        if (!pShadowMapGenDir->IsMeshInsideOrthoShadowVolume(pGI))
          pTmpShadowMapComponent = NULL;
      }
#endif

      if (pLastSurface!=pSurface)
      { 
        pTechnique = GetLightShader(pLight, bBasePass, pSurface, fFade, pTmpShadowMapComponent);          
        pLastSurface = pSurface;
      }
      if (pTechnique == NULL || !pTechnique->GetShaderCount())
      {
        // If base-pass lighting technique could not be retrieved, render lit mesh in the additive pass.
        if (bBasePass && pLight->IsDynamic())
          m_AdditiveLitGeoInstanceCollection.AppendEntry(pGI);
        continue; 
      }

      // If the state information is different from the previous one, we have to render the world primitives we
      // have collected so far
      if (pLastTechnique!=pTechnique)
      {
        if (s_RenderGeoInstanceCollection.GetNumEntries()!=0)
        {
          VASSERT(pLastTechnique != NULL);
          Vision::RenderLoopHelper.RenderStaticGeometryWithShader(s_RenderGeoInstanceCollection, *pLastTechnique->m_Shaders.GetAt(0));
          if (bBasePass)
            s_RenderGeoInstanceCollection.TagEntries();
          s_RenderGeoInstanceCollection.Clear();      
        }
        // Update the stored state information
        pLastTechnique = pTechnique;
      }
      // Naturally, we have to append the primitive to our collection (otherwise it won't be collected =) ).
      s_RenderGeoInstanceCollection.AppendEntry(pGI);
    }

    // If there's still something left in the collection, render it as well.
    if (s_RenderGeoInstanceCollection.GetNumEntries()!=0)
    {
      if (pLastTechnique && pLastTechnique->GetShaderCount()>0)
      {
        Vision::RenderLoopHelper.RenderStaticGeometryWithShader(s_RenderGeoInstanceCollection, *pLastTechnique->m_Shaders.GetAt(0));
        if (bBasePass)
          s_RenderGeoInstanceCollection.TagEntries();
      } 
      s_RenderGeoInstanceCollection.Clear();
    }
  }

  // Restore default render state
  VisRenderStates_cl::SetDepthStencilState(*VisRenderStates_cl::GetDepthStencilDefaultState());
}
Example #24
0
// TODO: This doesn't handle opaque fullbright surfaces correctly yet, and translucent fullbright surfaces are simply ignored.
void MirrorRenderLoop_cl::OnDoRenderLoop(void *pUserData)
{
  INSERT_PERF_MARKER_SCOPE("MirrorRenderLoop_cl::OnDoRenderLoop");

#if defined (WIN32) || defined (_VISION_XENON) || defined (_VISION_PS3) || defined(_VISION_PSP2) || defined(_VISION_WIIU)
  if (Vision::Editor.GetIgnoreAdvancedEffects())
  {
    // force a black reflection because it won't work with orthographic views
    Vision::RenderLoopHelper.ClearScreen(VisRenderLoopHelper_cl::VCTF_All, V_RGBA_BLACK);
    return;
  }
#endif

  VisRenderContext_cl *pContext = Vision::Contexts.GetCurrentContext();

  const int iRenderFlags = pContext->GetRenderFlags();

  const float fFarClipDist = m_pMirror->GetActualFarClipDistance();

  const VFogParameters &fog = Vision::World.GetFogParameters();
  VColorRef clearColor = (fog.depthMode != VFogParameters::Off) ? fog.iDepthColor : Vision::Renderer.GetDefaultClearColor();
  Vision::RenderLoopHelper.ClearScreen(VisRenderLoopHelper_cl::VCTF_All, clearColor);

  // set the oblique clipping plane...
  pContext->SetCustomProjectionMatrix (m_pMirror->GetObliqueClippingProjection().getPointer ());

  const VisStaticGeometryInstanceCollection_cl *pVisibleGeoInstancesPrimaryOpaquePass;
  const VisStaticGeometryInstanceCollection_cl *pVisibleGeoInstancesSecondaryOpaquePass;
  const VisStaticGeometryInstanceCollection_cl *pVisibleGeoInstancesTransparentPass;
  const VisEntityCollection_cl *pVisEntities;


  // === Visibility Determination ===

  IVisVisibilityCollector_cl *pVisColl = VisRenderContext_cl::GetCurrentContext()->GetVisibilityCollector();
  if (pVisColl == NULL)
    return;
  const VisVisibilityObjectCollection_cl *pVisObjectCollection = pVisColl->GetVisibleVisObjects();

  hkvAlignedBBox box;
  int iVoCount = m_pMirror->GetVisibilityObjectCount();
  int iFrustumCount = 0;
  bool bUseCommonFrustum = false;

  // === Determine Scissor Rect ===
  hkvVec2 vMinScreenSpace, vMaxScreenSpace;
  const hkvAlignedBBox &worldSpaceBox = m_pMirror->GetBoundingBox();

  hkvVec3 vCorners[8];
  worldSpaceBox.getCorners (vCorners);

  VRectanglef scissorRect;
  bool bUseScissorRect = true;
  for (int i=0; i<8; i++)
  {
    float x2d, y2d;
    BOOL bInFrontOfCamera = pContext->Project2D(vCorners[i], x2d, y2d);
    if (bInFrontOfCamera)
    {
      scissorRect.Add(hkvVec2(x2d, y2d));
    }
    else
    {
      bUseScissorRect = false;
      break;
    }
  }

  if (bUseScissorRect)
    Vision::RenderLoopHelper.SetScissorRect(&scissorRect);

  for (int iVo = 0; iVo < iVoCount; iVo++)
  {
    VisVisibilityObject_cl *pVisObj = m_pMirror->GetVisibilityObject(iVo);
    if (pVisObj != NULL && pVisObj->WasVisibleInAnyLastFrame())
    {
      if (iFrustumCount <= MAX_SEPARATE_FRUSTA)
      {
        const hkvAlignedBBox &voBox = pVisObj->GetWorldSpaceBoundingBox();
        box.expandToInclude(voBox);
        if (m_Frustum[iFrustumCount].Set(pContext->GetCamera()->GetPosition(), voBox, true, fFarClipDist))
        {
          iFrustumCount++;
        }
        else
        {
          bUseCommonFrustum = true;
        }
      }
      else
      {
        const hkvAlignedBBox &voBox = pVisObj->GetWorldSpaceBoundingBox();
        box.expandToInclude(voBox);
        bUseCommonFrustum = true;
      }
    }
  }

  if (bUseCommonFrustum)
  {
    iFrustumCount = 1;
    if (!m_Frustum[0].Set(pContext->GetCamera()->GetPosition(), box, true, fFarClipDist))
      iFrustumCount = 0;
  }

  if (iFrustumCount>0)
  {
    for (int i=0; i<iFrustumCount; i++)
    {
      m_visiblePrimaryOpaquePassGeoInstances.Clear();
      m_visibleSecondaryOpaquePassGeoInstances.Clear();
      m_visibleTransparentOpaquePassGeoInstances.Clear();
      m_visEntities.Clear();
      pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_PrimaryOpaquePass)->DetermineEntriesTouchingFrustum(m_Frustum[i], m_visiblePrimaryOpaquePassGeoInstances);
      pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_SecondaryOpaquePass)->DetermineEntriesTouchingFrustum(m_Frustum[i], m_visibleSecondaryOpaquePassGeoInstances);
      pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_TransparentPass)->DetermineEntriesTouchingFrustum(m_Frustum[i], m_visibleTransparentOpaquePassGeoInstances);
      pVisColl->GetVisibleEntities()->DetermineEntriesTouchingFrustum(m_Frustum[i], m_visEntities);
      if (iFrustumCount == 1)
        break;
      m_visiblePrimaryOpaquePassGeoInstances.TagEntries();
      m_visibleSecondaryOpaquePassGeoInstances.TagEntries();
      m_visibleTransparentOpaquePassGeoInstances.TagEntries();
      m_visEntities.TagEntries();
    }
    if (iFrustumCount > 1)
    {
      m_visiblePrimaryOpaquePassGeoInstances.Clear();
      m_visibleSecondaryOpaquePassGeoInstances.Clear();
      m_visibleTransparentOpaquePassGeoInstances.Clear();
      m_visEntities.Clear();
      pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_PrimaryOpaquePass)->GetTaggedEntries(m_visiblePrimaryOpaquePassGeoInstances);
      pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_SecondaryOpaquePass)->GetTaggedEntries(m_visibleSecondaryOpaquePassGeoInstances);
      pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_TransparentPass)->GetTaggedEntries(m_visibleTransparentOpaquePassGeoInstances);
      pVisColl->GetVisibleEntities()->GetTaggedEntries(m_visEntities);
    }
    pVisibleGeoInstancesPrimaryOpaquePass = &m_visiblePrimaryOpaquePassGeoInstances;
    pVisibleGeoInstancesSecondaryOpaquePass = &m_visibleSecondaryOpaquePassGeoInstances;
    pVisibleGeoInstancesTransparentPass = &m_visibleTransparentOpaquePassGeoInstances;
    pVisEntities = &m_visEntities;
  }
  else
  {
    pVisibleGeoInstancesPrimaryOpaquePass = pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_PrimaryOpaquePass);
    pVisibleGeoInstancesSecondaryOpaquePass = pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_SecondaryOpaquePass);
    pVisibleGeoInstancesTransparentPass = pVisColl->GetVisibleStaticGeometryInstancesForPass(VPT_TransparentPass);
    pVisEntities = pVisColl->GetVisibleEntities();
  }

  // === End Visibility Determination ===

  if (m_pMirror->GetExecuteRenderHooks())
  {
    VisRenderHookDataObject_cl data(&Vision::Callbacks.OnRenderHook,VRH_PRE_PRIMARY_OPAQUE_PASS_GEOMETRY);
    Vision::Callbacks.OnRenderHook.TriggerCallbacks(&data);
  }

  // Render opaque static geometry
  VASSERT(m_spDefaultLightMapping->m_Shaders.Count()==1);

  TRIGGER_MIRROR_HOOK(VRH_PRE_PRIMARY_OPAQUE_PASS_GEOMETRY)
  VisMirror_cl::VReflectionShaderSets_e shaderMode = m_pMirror->m_eReflectionShaderMode;
  DrawStaticGeometry(*pVisibleGeoInstancesPrimaryOpaquePass, VPT_PrimaryOpaquePass);
  DrawStaticGeometry(*pVisibleGeoInstancesSecondaryOpaquePass, VPT_SecondaryOpaquePass);

  // Render entities
  const VisEntityCollection_cl *pEntities = pVisEntities;
  int iCount = pEntities->GetNumEntries();
  VASSERT(m_spDefaultLightGrid->m_Shaders.Count()==1);
  //VCompiledShaderPass *pLightgridShader = m_spDefaultLightGrid->m_Shaders.GetAt(0);
  int i;
  //bool bUseSimpleShader = shaderMode==VisMirror_cl::AlwaysSimple;

  Vision::RenderLoopHelper.BeginEntityRendering();

  for (i=0;i<iCount;i++)
  { 
    VisBaseEntity_cl *pEnt = pEntities->GetEntry(i);

//    Vision::RenderLoopHelper.TrackLightGridInfo(pEnt);  // important: need to be done in RenderEntityWithSurfaceShaderList

    //if (bUseSimpleShader)
    //{
    //  Vision::RenderLoopHelper.RenderEntityWithShaders(pEnt,1,&pLightgridShader);
    //}
    //else
    {
      VisDrawCallInfo_t surfaceShaderList[RLP_MAX_ENTITY_SURFACES];
      VDynamicMesh *pMesh = pEnt->GetMesh();
      VisSurface_cl **ppSurfaces = pEnt->GetSurfaceArray();
      int iNumSubmeshes = pMesh->GetSubmeshCount();
      for (int j=0; j<iNumSubmeshes; j++)
      {
        VisDrawCallInfo_t &info(surfaceShaderList[j]);
        VBaseSubmesh* pSubmesh = pMesh->GetSubmesh(j);
        VisSurface_cl* pSurface = ppSurfaces[pSubmesh->m_iMaterialIndex];
        info.Set(pSubmesh, pSurface, GetMirrorShader (pSurface, shaderMode));
      }

      Vision::RenderLoopHelper.RenderEntityWithSurfaceShaderList(pEnt, iNumSubmeshes, surfaceShaderList);
    }
  }

  Vision::RenderLoopHelper.EndEntityRendering();

  // Render Sky
  if (VSky::IsVisible())
  {
    // The sky has to be rendered without oblique clipping
    pContext->SetCustomProjectionMatrix(NULL);
    Vision::RenderLoopHelper.RenderSky();
    // set the oblique clipping plane after sky...
    pContext->SetCustomProjectionMatrix (m_pMirror->GetObliqueClippingProjection().getPointer ());
  }

  if (m_pMirror->GetExecuteRenderHooks())
  {
    VisRenderHookDataObject_cl data(&Vision::Callbacks.OnRenderHook,VRH_PRE_OCCLUSION_TESTS);
    Vision::Callbacks.OnRenderHook.TriggerCallbacks(&data);
  }

  // Render Coronas / Lens Flares
  VisRenderHookDataObject_cl data(&Vision::Callbacks.OnRenderHook,VRH_CORONAS_AND_FLARES);
  Vision::Callbacks.OnRenderHook.TriggerCallbacks(&data);
  TRIGGER_MIRROR_HOOK(VRH_PRE_OCCLUSION_TESTS)  

  if (iRenderFlags&VIS_RENDERCONTEXT_FLAG_USE_OCCLUSIONQUERY)
    Vision::RenderLoopHelper.PerformHardwareOcclusionQuery();

  if (iRenderFlags&VIS_RENDERCONTEXT_FLAG_USE_PIXELCOUNTER)
    Vision::RenderLoopHelper.PerformHardwarePixelCounterQuery();

  DrawDynamicLight();

  TRIGGER_MIRROR_HOOK(VRH_DECALS)
  TRIGGER_MIRROR_HOOK(VRH_CORONAS_AND_FLARES)

  TRIGGER_MIRROR_HOOK(VRH_PRE_TRANSPARENT_PASS_GEOMETRY)
  DrawStaticGeometry(*pVisibleGeoInstancesTransparentPass, VPT_TransparentPass);
  TRIGGER_MIRROR_HOOK(VRH_POST_TRANSPARENT_PASS_GEOMETRY)

  if (bUseScissorRect)
    Vision::RenderLoopHelper.SetScissorRect(NULL);
}
Example #25
0
// Simplified version of dynamic light rendering for mirrors
void MirrorRenderLoop_cl::DrawDynamicLight()
{
  INSERT_PERF_MARKER_SCOPE("MirrorRenderLoop_cl::DrawDynamicLight");

  // Some local variables for storing surfaces, shaders, surface shaders, and the like.
  VisDrawCallInfo_t SurfaceShaderList[RLP_MAX_ENTITY_SURFACESHADERS];
  VCompiledTechnique *pTechnique = NULL;

  VisMirror_cl::VReflectionShaderSets_e shaderMode = m_pMirror->m_eReflectionShaderMode;

  // Get all visible light sources
  IVisVisibilityCollector_cl *pVisColl = VisRenderContext_cl::GetCurrentContext()->GetVisibilityCollector();
  if (pVisColl == NULL)
    return;

  const VisLightSrcCollection_cl *pLightSourceCollection = pVisColl->GetVisibleLights();
  unsigned int i;
  unsigned int iNumLights = pLightSourceCollection->GetNumEntries();
  if (iNumLights == 0)
    return;

  // Set depth-stencil state
  VisRenderStates_cl::SetDepthStencilState(m_dynLightDefaultState);
  
  // For all visible lights...
  for (i=0; i<iNumLights; i++)
  {
    VisLightSource_cl *pLight = pLightSourceCollection->GetEntry(i);
    // We're only interested in dynamic lights
    if (!pLight->IsDynamic()) 
      continue;

    // Clear the collections of geo instances and entities, since we want to build them from scratch for each light
    s_LitEntityCollection.Clear();
    s_LitGeoInstanceCollection.Clear();

    // See which geometry types have to cast shadows
    int iReceiverFlags = GetLightReceiverFlags(pLight);

    // If nothing receives light from this light source, we can proceed to the next light.
    if (!iReceiverFlags)
      continue;

    // ***************** Create lists of illuminated scene elements *****************

    // If no shadows are cast, we simply illuminate all visible geometry within the range (spherical) of the light.
    VisEntityCollection_cl *pEntColl = NULL;
    if (iReceiverFlags & VIS_LIGHTSRCVIS_MODELS)
      pEntColl = &s_LitEntityCollection;
    VisStaticGeometryInstanceCollection_cl *pGeoInstanceColl = NULL;
    if (iReceiverFlags & VIS_LIGHTSRCVIS_PRIMITIVES)
    {
      pGeoInstanceColl = &s_LitGeoInstanceCollection;
    }

    Vision::RenderLoopHelper.GetVisibleGeometryInLightsourceRange(pGeoInstanceColl, pEntColl, NULL, *pLight);

    // For all illuminated entities: Render a dynamic lighting pass now.
    if (pLight->GetLightInfluenceBitMaskEntity())
    {
      int j;
      
      int iNumLitEntities = s_LitEntityCollection.GetNumEntries();

      Vision::RenderLoopHelper.BeginEntityRendering();

      for (j=0; j<iNumLitEntities; j++)
      {
        VisBaseEntity_cl *pEntity = s_LitEntityCollection.GetEntry(j);
        // Ignore foreground entities (they don't trivially support additive lighting)
        if (pEntity->IsObjectAlwaysInForegroundEnabled())
          continue;
        if (!(pEntity->GetLightInfluenceBitMask() & pLight->GetLightInfluenceBitMaskEntity()))
          continue;
        if (!pVisColl->IsEntityVisible(pEntity))
          continue;
          
        VDynamicMesh *pMesh = pEntity->GetMesh();
          
        // Get list of all the surfaces in the model
        int iNumSubmeshes = pMesh->GetSubmeshCount();
        int iNumSurfaceShaders = 0;
        VisSurface_cl **ppSurfaceArray = pEntity->GetSurfaceArray();

        // For all the surfaces...
        for (int k=0; k<iNumSubmeshes; k++)
        {
          VDynamicSubmesh *pSubmesh = pMesh->GetSubmesh(k);
          VASSERT(pSubmesh != NULL);
          VisSurface_cl* pSurface = &m_dummySurface; 
          VisSurface_cl* pMeshSurface = pSubmesh->m_pSurface;
          VASSERT(pMeshSurface != NULL);

          bool bHasManualTemplateShaderAssignment = pMeshSurface->GetShaderMode() == VisSurface_cl::VSM_Template 
            && pMeshSurface->GetMaterialTemplate() != NULL && pMeshSurface->GetMaterialTemplate()->HasManualAssignment();

          if (shaderMode == VisMirror_cl::AlwaysSurfaceShaders || 
            (shaderMode == VisMirror_cl::SimpleForAUTO && ( (pMeshSurface->GetShaderMode() == VisSurface_cl::VSM_Manual) || bHasManualTemplateShaderAssignment) ) )
          {
            pSurface = ppSurfaceArray[pSubmesh->m_iMaterialIndex]; // use the real surface
          }
          pTechnique = Vision::GetApplication()->GetShaderProvider()->GetDynamicLightShader(pLight, pSurface, true);
          if (pTechnique==NULL)
            continue;
            
          VisDrawCallInfo_t &info(SurfaceShaderList[iNumSurfaceShaders++]);
          info.Set(pSubmesh, pSurface, pTechnique->m_Shaders.GetAt(0));
        }
        // Finally, render the entity with a surface shader list.
        if (iNumSurfaceShaders>0)
          Vision::RenderLoopHelper.RenderEntityWithSurfaceShaderList(pEntity, iNumSurfaceShaders, SurfaceShaderList);
      }

      Vision::RenderLoopHelper.EndEntityRendering();
    }

    // For all illuminated world primitives: Render a dynamic lighting pass now
    if (pLight->GetLightInfluenceBitMaskWorld() > 0)
    {
      // For all illuminated static geometry instances: Render a dynamic lighting pass now.
      int iNumLitGeoInstances = s_LitGeoInstanceCollection.GetNumEntries();

      s_RenderGeoInstanceCollection.Clear();

      // Render illuminated geometry instances. 
      for (int j=0; j < iNumLitGeoInstances; j++)
      {
        VisStaticGeometryInstance_cl *pGI = s_LitGeoInstanceCollection.GetEntry(j);

        if (pGI->GetSurface()==NULL || pGI->GetSurface()->IsFullbright())
          continue;
       
        // We have to append the primitive to our collection
        s_RenderGeoInstanceCollection.AppendEntry(pGI);
      }

      // render the collection
      const int iLitGeoCount = s_RenderGeoInstanceCollection.GetNumEntries();
      if (iLitGeoCount > 0)
      {
        VCompiledTechnique *pLastTech = NULL;
        VisSurface_cl* pLastSurface = NULL;
        m_CustomGeoInstances.EnsureSize(iLitGeoCount);
        m_CustomGeoInstances.Clear();

        for (int j=0; j < iLitGeoCount; j++)
        {
          VisStaticGeometryInstance_cl *pGI = s_RenderGeoInstanceCollection.GetEntry(j);

          GetLightShader (pLight, pGI, m_pMirror->m_eReflectionShaderMode, pLastSurface, pLastTech, pLastSurface, pTechnique);
          
          // The current technique has changed, so we have to render the previously gathered geometry.
          if (pLastTech != pTechnique)
          {
            if ((m_CustomGeoInstances.GetNumEntries() > 0) && (pLastTech != NULL) && (pLastTech->GetShaderCount() > 0))
            {
              Vision::RenderLoopHelper.RenderStaticGeometryWithShader(m_CustomGeoInstances, *pLastTech->m_Shaders.GetAt(0) );
              m_CustomGeoInstances.Clear();
            }
            pLastTech = pTechnique;
          }
          m_CustomGeoInstances.AppendEntryFast(pGI);
        }
        // Render remaining geometry
        if ((m_CustomGeoInstances.GetNumEntries() > 0) && (pLastTech != NULL) && (pLastTech->GetShaderCount() > 0))
        {
          Vision::RenderLoopHelper.RenderStaticGeometryWithShader(m_CustomGeoInstances, *pTechnique->m_Shaders.GetAt(0) );
        }

        s_RenderGeoInstanceCollection.Clear();
      }
    }
  }

  // Restore default render state
  VisRenderStates_cl::SetDepthStencilState(*VisRenderStates_cl::GetDepthStencilDefaultState());
}
void AnimatedWarrior_cl::SetupAnimations()
{
  m_bModelValid = false;
  VDynamicMesh *pMesh = GetMesh();
  VVERIFY_OR_RET(pMesh);
  VisAnimEventList_cl *pEventList = NULL;

  // idle animations
  m_spSkeletalSequenceList[ANIMID_IDLE] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Idle", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_IDLE]);
  m_spSkeletalSequenceList[ANIMID_IDLE_TORCH] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Idle_Look_Torch", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_IDLE_TORCH]);

  // run animation
  m_spSkeletalSequenceList[ANIMID_RUN] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Run", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_RUN]);
  pEventList = m_spSkeletalSequenceList[ANIMID_RUN]->GetEventList();
  pEventList->AddEvent(0.0f, EVENT_ANIM_LEGSPARALLEL_FIRSTTIME);
  pEventList->AddEvent(0.396f, EVENT_ANIM_LEGSPARALLEL_SECONDTIME);

  // run with torch animation
  m_spSkeletalSequenceList[ANIMID_RUN_TORCH] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Run_Torch", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_RUN_TORCH]);
  pEventList = m_spSkeletalSequenceList[ANIMID_RUN_TORCH]->GetEventList();
  pEventList->AddEvent(0.0f, EVENT_ANIM_LEGSPARALLEL_FIRSTTIME);
  pEventList->AddEvent(0.396f, EVENT_ANIM_LEGSPARALLEL_SECONDTIME);

  // walk animation
  m_spSkeletalSequenceList[ANIMID_WALK] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Walk", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_WALK]);
  pEventList = m_spSkeletalSequenceList[ANIMID_WALK]->GetEventList();
  pEventList->AddEvent(0.0f, EVENT_ANIM_LEGSPARALLEL_FIRSTTIME);
  pEventList->AddEvent(0.495f, EVENT_ANIM_LEGSPARALLEL_SECONDTIME);

  // walk with torch animation
  m_spSkeletalSequenceList[ANIMID_WALK_TORCH] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Walk_Torch", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_WALK_TORCH]);
  pEventList = m_spSkeletalSequenceList[ANIMID_WALK_TORCH]->GetEventList();
  pEventList->AddEvent(0.0f, EVENT_ANIM_LEGSPARALLEL_FIRSTTIME);
  pEventList->AddEvent(0.495f, EVENT_ANIM_LEGSPARALLEL_SECONDTIME);
 
  // turn animation
  m_spSkeletalSequenceList[ANIMID_TURN] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Turn", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_TURN]);

  // turn with torch animation
  m_spSkeletalSequenceList[ANIMID_TURN_TORCH] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Turn_Torch", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_TURN_TORCH]);

  // walk backwards animation
  m_spSkeletalSequenceList[ANIMID_WALKBACKWARDS] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Run_BWD_V2", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_WALKBACKWARDS]);

  // walk backwards with torch animation
  m_spSkeletalSequenceList[ANIMID_WALKBACKWARDS_TORCH] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Run_BWD_Torch_V2", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_WALKBACKWARDS_TORCH]);

  // upper body animations (torch)
  m_spSkeletalSequenceList[ANIMID_UPPERBODY_ARM] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Draw_Dagger", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_UPPERBODY_ARM]);
  m_spSkeletalSequenceList[ANIMID_UPPERBODY_ARM]->RemoveOffsetDeltaTrack();
  pEventList = m_spSkeletalSequenceList[ANIMID_UPPERBODY_ARM]->GetEventList();
  pEventList->AddEvent(m_spSkeletalSequenceList[ANIMID_UPPERBODY_ARM]->GetLength(), EVENT_ANIM_UPPERBODY_ARMING_FINISHED);

  m_spSkeletalSequenceList[ANIMID_UPPERBODY_DISARM] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Holster_Dagger", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_UPPERBODY_DISARM]);
  m_spSkeletalSequenceList[ANIMID_UPPERBODY_DISARM]->RemoveOffsetDeltaTrack();
  pEventList = m_spSkeletalSequenceList[ANIMID_UPPERBODY_DISARM]->GetEventList();
  pEventList->AddEvent(m_spSkeletalSequenceList[ANIMID_UPPERBODY_DISARM]->GetLength(), EVENT_ANIM_UPPERBODY_DISARMING_FINISHED);
   
  m_spSkeletalSequenceList[ANIMID_UPPERBODY_ATTACK] = (VisSkeletalAnimSequence_cl*)pMesh->GetSequence("Strike_Dagger", VIS_MODELANIM_SKELETAL);
  VVERIFY_OR_RET(m_spSkeletalSequenceList[ANIMID_UPPERBODY_ATTACK]);
  m_spSkeletalSequenceList[ANIMID_UPPERBODY_ATTACK]->RemoveOffsetDeltaTrack();
  pEventList = m_spSkeletalSequenceList[ANIMID_UPPERBODY_ATTACK]->GetEventList();
  pEventList->AddEvent(m_spSkeletalSequenceList[ANIMID_UPPERBODY_ATTACK]->GetLength(), EVENT_ANIM_UPPERBODY_ATTACK_FINISHED);

  m_bModelValid = true;
}