/*=============================================================================
	UnSkeletalMesh.h: Unreal mesh objects.
	Copyright 1997-1999 Epic Games, Inc. All Rights Reserved.

	UAnimation: Unreal Animation object
	Objects containing skeletal or heirarchical animation keys.
	(Classic vertex animation is stored inside UMesh object.)

	Copyright 1999,2000 Epic Games, Inc. All Rights Reserved.

	Revision history:
		* ULodMesh, USkeletalMesh subclassing - Erik 
=============================================================================*/


/*-----------------------------------------------------------------------------
	USkeletalMesh.
-----------------------------------------------------------------------------*/

// Note: uses old-style resource loading, then saves it as an USkeletalMesh in the
// .u building phase.  That's why some of these structs are serializable and others aren't.

// A bone: an orientation, and a position, all relative to their parent.
struct VJointPos
{
	FQuat   	Orientation;  //
	FVector		Position;     //  needed or not ?

	FLOAT       Length;       //  For collision testing / debugging drawing...
	FLOAT       XSize;
	FLOAT       YSize;
	FLOAT       ZSize;

	friend FArchive &operator<<( FArchive& Ar, VJointPos& V )
	{
		return Ar << V.Orientation << V.Position << V.Length << V.XSize << V.XSize << V.ZSize;
	}
};

// Reference-skeleton bone, the package-serializable version.
struct FMeshBone
{
	FName 		Name;		  // Bone's name.
	DWORD		Flags;        // reserved
	VJointPos	BonePos;      // reference position
	INT         ParentIndex;  // 0/NULL if this is the root bone.  
	INT 		NumChildren;  // children  // only needed in animation ?
	INT         Depth;        // Number of steps to root in the skeletal hierarcy; root=0.
	friend FArchive &operator<<( FArchive& Ar, FMeshBone& F)
	{
		return Ar << F.Name << F.Flags << F.BonePos << F.NumChildren << F.ParentIndex;
	}
};

// Named bone for the animating skeleton data. 
struct FNamedBone
{
	FName	   Name;  // Bone's fname (== single 32-bit index to name)
	DWORD      Flags; // reserved
	INT        ParentIndex;  // 0/NULL if this is the root bone.  
	friend FArchive &operator<<( FArchive& Ar, FNamedBone& F)
	{
		return Ar << F.Name << F.Flags << F.ParentIndex;
	}
};

// Binary bone format to deal with raw animations as generated by various exporters.
struct FNamedBoneBinary
{
	ANSICHAR   Name[64];	// Bone's name
	DWORD      Flags;		// reserved
	INT        NumChildren; //
	INT		   ParentIndex;	// 0/NULL if this is the root bone.  
	VJointPos  BonePos;	    //
};


// Binary animation info format - used to organize raw animation keys into FAnimSeqs on rebuild
// Similar to MotionChunkDigestInfo..
struct AnimInfoBinary
{
	ANSICHAR Name[64];     // Animation's name
	ANSICHAR Group[64];    // Animation's group name	

	INT TotalBones;           // TotalBones * NumRawFrames is number of animation keys to digest.

	INT RootInclude;          // 0 none 1 included 		
	INT KeyCompressionStyle;  // Reserved: variants in tradeoffs for compression.
	INT KeyQuotum;            // Max key quotum for compression	
	FLOAT KeyReduction;       // desired 
	FLOAT TrackTime;            // explicit - can be overridden by the animation rate
	FLOAT AnimRate;           // frames per second.
	INT StartBone;            // - Reserved: for partial animations.
	INT FirstRawFrame;        //
	INT NumRawFrames;         // NumRawFrames and AnimRate dictate tracktime...
};


// File header structure. 
struct VChunkHeader
{
	ANSICHAR	ChunkID[20];  // string ID of up to 19 chars (usually zero-terminated)
	INT			TypeFlag;     // Flags/reserved
    INT         DataSize;     // size per struct following;
	INT         DataCount;    // number of structs/
};

// Raw data material.
struct VMaterial
{
	ANSICHAR            MaterialName[64];
	INT					TextureIndex;  // texture index ('multiskin index')
	DWORD				PolyFlags;     // ALL poly's with THIS material will have this flag.
	INT				    AuxMaterial;   // reserved: index into another material, eg. detailtexture/shininess/whatever.
	DWORD				AuxFlags;      // reserved: auxiliary flags 
	INT					LodBias;       // material-specific lod bias
	INT					LodStyle;      // material-specific lod style
};


// Raw data bone.
struct VBone
{
	ANSICHAR    Name[64];     //
	DWORD		Flags;        // reserved / 0x02 = bone where skin is to be attached...	
	INT 		NumChildren;  // children  // only needed in animation ?
	INT         ParentIndex;  // 0/NULL if this is the root bone.  
	VJointPos	BonePos;      // reference position
};

// Bone influence blending
struct VBoneInfIndex // ,, ,, contains Index, number of influences per bone (+ N detail level sizers! ..)
{
	_WORD WeightIndex;
	_WORD Number;  // how many to process 
	_WORD DetailA;  // how many to process if we're up to 2 max influences
	_WORD DetailB;  // how many to process if we're up to full 3 max influences 

	friend FArchive &operator<<( FArchive& Ar, VBoneInfIndex& V )
	{
		return Ar << V.WeightIndex << V.Number << V.DetailA << V.DetailB;
	}
};

struct VBoneInfluence // Weight and vertex number
{
	_WORD PointIndex; // 3d vertex
	_WORD BoneWeight; // 0..1 scaled influence

	friend FArchive &operator<<( FArchive& Ar, VBoneInfluence& V )
	{
		return Ar << V.PointIndex << V.BoneWeight;
	}
};

// Raw data bone influence.
struct VRawBoneInfluence // just weight, vertex, and Bone, sorted later....
{
	FLOAT Weight;
	INT   PointIndex;
	INT   BoneIndex;
};


// An animation key.
struct VQuatAnimKey
{
	FVector		Position;           // relative to parent.
	FQuat       Orientation;        // relative to parent.
	FLOAT       Time;				// The duration until the next key (end key wraps to first...)

	friend FArchive &operator<<( FArchive& Ar, VQuatAnimKey& V )
	{
		return Ar << V.Position << V.Orientation << V.Time;
	}
};

//
// 'Analog' animation key track (for single bone/element.)
// Either KeyPos or KeyQuat can be single/empty? entries to signify no movement at all;
// for N>1 entries there's always N keytimers available.
//
struct AnalogTrack
{	
	DWORD Flags;       // reserved 
	TArray <FQuat>   KeyQuat;   // Orientation key track
	TArray <FVector> KeyPos;    // Position key track
	TArray <FLOAT>   KeyTime;  // For each key, time when next key takes effect (measured from start of track.)
	friend FArchive &operator<<( FArchive& Ar, AnalogTrack& A )
	{
		return Ar << A.Flags << A.KeyQuat << A.KeyPos << A.KeyTime;
	}
};

//
// Motion chunks as defined by Animsequences in script and/or exported raw data.
// Used during digestion phase only.
//
struct MotionChunkDigestInfo
{	
	FName	Name;		 // Sequence's name.
	FName	Group;		 // Group.	
	INT     RootInclude; // 0=none, 1=include, 2=store only root motion/
	INT     KeyCompressionStyle;
	INT     KeyQuotum;
	FLOAT   KeyReduction;
	FLOAT   TrackTime;
	FLOAT   AnimRate;
	INT     StartBone;
	INT     FirstRawFrame;
	INT     NumRawFrames;	
};




// Individual animation;  subgroup of bones with compressed animation.
struct MotionChunk
{
	FVector RootSpeed3D;  // Net 3d speed.
	FLOAT   TrackTime;    // Total time (Same for each track.)
	INT     StartBone;    // If we're a partial-hierarchy-movement, this is the lowest bone.
	DWORD   Flags;        // Reserved 

	TArray<INT>           BoneIndices;    // Refbones number of Bone indices (-1 or valid one) to fast-find tracks for a particular bone.
	// Frame-less, compressed animation tracks. NumBones times NumAnims tracks in total 
	TArray<AnalogTrack>   AnimTracks;     // Compressed key tracks (one for each bone)
	AnalogTrack           RootTrack;      // May or may not be used; actual traverse-a-scene root tracks for use
	// with cutscenes / special physics modes, in addition to the regular skeletal root track.

	friend FArchive &operator<<( FArchive& Ar, MotionChunk& M)
	{
		return Ar << M.RootSpeed3D << M.TrackTime << M.StartBone << M.Flags << M.BoneIndices << M.AnimTracks << M.RootTrack;
	}
};


// Temp error structure for compression of animation key tracks.
struct TrackDiffs
{
	FLOAT  BoneBias;         // Bias in error tolerance for this bone (may depend on size, place in hierarchy)
	TArray <FLOAT> QuatErr;  // Error in orientation between this key and next
	TArray <FLOAT> PosErr;   // Error in position between this key and next
};

// Vertex with texturing info, akin to Hoppe's 'Wedge' concept - import only.
struct VVertex
{
	_WORD	PointIndex;	 // Index to a point.
	FLOAT   U,V;         // Scaled to BYTES, rather...-> Done in digestion phase, on-disk size doesn't matter here.
	BYTE    MatIndex;    // At runtime, this one will be implied by the face that's pointing to us.
	BYTE    Reserved;    // Top secret.
};

// Points: regular FVectors (for now..)
struct VPoint
{	
	FVector			Point; // Change into packed integer later IF necessary, for 3x size reduction...
};

// Textured triangle.
struct VTriangle
{
	_WORD   WedgeIndex[3];	 // point to three vertices in the vertex list.
	BYTE    MatIndex;	     // Materials can be anything.
	BYTE    AuxMatIndex;     // Second material (eg. damage skin, shininess, detail texture / detail mesh...
	DWORD   SmoothingGroups; // 32-bit flag for smoothing groups AND Lod-bias calculation.
};


// Bundle of raw data - from our 3DSMax plugin output.
struct USkelImport 
{
	TArray <VMaterial>   Materials; // Materials
	TArray <FVector>	 Points;    // 3D Points
	TArray <VVertex>     Wedges;    // Wedges
	TArray <VTriangle>   Faces;     // Faces
	TArray <VBone>       RefBonesBinary;   // reference skeleton
	TArray <VRawBoneInfluence> Influences; //
	//TArray <> AnimationKeys              //
	
};


// Skeletal mesh
class ENGINE_API USkeletalMesh : public ULodMesh
{
	DECLARE_CLASS(USkeletalMesh,ULodMesh,0,Engine)

    // Special skeletal data structures: 
	TArray<FMeshExtWedge>	ExtWedges;     // Extended wedges with floating point UV's      
	TArray<FVector>         Points;        // Floating point vectors directly form our skin vertex 3d points.

	// Skeletal specific data
	TArray<FMeshBone>       RefSkeleton;   // Reference skeleton.

	// Bone weights
	TArray <VBoneInfIndex>  BoneWeightIdx; // ,, ,, contains Index, number of influences per bone.
	TArray <VBoneInfluence> BoneWeights;   // Each element contians weight and vertex number.
	TArray <FVector>        LocalPoints;   // Each weighted point in local bone-space

	INT WeaponBoneIndex;   // -1 means it hasn't been assigned.
	FCoords WeaponAdjust;  // Weapon adjustment coordinate system - identity by default.
	INT SkeletalDepth;  // The max hierarchy depth.
	UAnimation* DefaultAnimation; // Link this up when no other animation is available - for backwards compatibility.

	// For debugging only - not serialized.
	TArray <FVector> DebugPivots;
	TArray <INT>	 DebugParents;
	TArray <BYTE>    DebugVerts;
	UBOOL   DisplayBones;
	UBOOL   DisplayInfluences;

	// Runtime weapon coords - not serialized
	FCoords ClassicWeaponCoords;
	
	//  UObject interface.
	USkeletalMesh();
	virtual void Serialize( FArchive& Ar );

	//  UMesh interface.
	virtual void SetScale( FVector NewScale );
	virtual void FlipFaces();

	// Special GetFrame for Skeletal animation
	virtual void GetFrame( FVector* Verts, INT Size, FCoords Coords, AActor* Owner, INT& LODRequest );
	virtual FBox GetRenderBoundingBox( const AActor* Owner, UBOOL Exact ); 
	
};

/*-----------------------------------------------------------------------------
	UAnimation definition.
-----------------------------------------------------------------------------*/
//
// UnAnimation, the base class of animating skeletal bones which are linked up by name dynamically to 
// USkeletalMesh skins/reference skeletons. 
//
class ENGINE_API UAnimation : public UObject
{
	DECLARE_CLASS(UAnimation,UObject,0,Engine)

	// Variables.
	// FBox BoundingBox;
	// FSphere BoundingSphere;

	// UObject interface.
	UAnimation();
	void Serialize( FArchive& Ar );

	

	virtual const FMeshAnimSeq* GetAnimSeq( FName SeqName ) const
	{
		guardSlow(UAnimation::GetAnimSeq);
		for( INT i=0; i<AnimSeqs.Num(); i++ )
		{
			if( SeqName == AnimSeqs(i).Name )
				return &AnimSeqs(i);
		}
		return NULL;
		unguardSlow;
	}

	virtual FMeshAnimSeq* GetAnimSeq( FName SeqName )
	{
		guardSlow(UAnimation::GetAnimSeq);
		for( INT i=0; i<AnimSeqs.Num(); i++ )
		{
			if( SeqName == AnimSeqs(i).Name )
				return &AnimSeqs(i);
		}
		return NULL;
		unguardSlow;
	}

	virtual const MotionChunk* GetMovement( FName SeqName ) const 
	{
		guardSlow(UAnimation::GetAnimSeq);
		for( INT i=0; i<AnimSeqs.Num(); i++ )
		{
			if( SeqName == AnimSeqs(i).Name )
				return &Moves(i);
		}
		return NULL;
		unguardSlow;
	}

	virtual MotionChunk* GetMovement( FName SeqName )
	{
		guardSlow(UAnimation::GetAnimSeq);
		for( INT i=0; i<AnimSeqs.Num(); i++ )
		{
			if( SeqName == AnimSeqs(i).Name )
				return &Moves(i);
		}
		return NULL;
		unguardSlow;
	}

	// Estimates memory footprint in bytes of digested data only
	virtual INT MemFootprint()
	{
		guard(UAnimation::MemFootprint);

		INT TotalMem = 0;
		for(INT i=0;i<Moves.Num();i++)
		{
			for(INT j=0;j< Moves(i).AnimTracks.Num(); j++)
			{
				TotalMem += sizeof(DWORD); // Flags
				TotalMem += sizeof(FQuat)* Moves(i).AnimTracks(j).KeyQuat.Num();
				TotalMem += sizeof(FVector)* Moves(i).AnimTracks(j).KeyPos.Num();
				TotalMem += sizeof(FLOAT)* Moves(i).AnimTracks(j).KeyTime.Num();
				
				//Moves(i).AnimTracks.Num();
				//RootTrack->
				//DWORD Flags;       // reserved 
				//TArray <FQuat>   KeyQuat;   // Orientation key track
				//TArray <FVector> KeyPos;    // Position key track
				//TArray <FLOAT>   KeyTime;  // For each key, time when next key takes effect (measured from start of track.)
			}
			TotalMem += sizeof(FQuat)* Moves(i).RootTrack.KeyQuat.Num();
			TotalMem += sizeof(FVector)* Moves(i).RootTrack.KeyPos.Num();
			TotalMem += sizeof(FLOAT)* Moves(i).RootTrack.KeyTime.Num();
		}
		return TotalMem;
		unguard;
	}

	// Skeletal animation data. Linked up to a reference skeleton at runtime.
	TArray<FNamedBone>    RefBones;        // Name.
	TArray<MotionChunk>   Moves;           // One for every animation - has hierarchy starting point,
	                                       // speed, flags, compression, and actual animation.

	// MeshAnimSeq information; per-animation names/data/notifies.
	TArray<FMeshAnimSeq>  AnimSeqs;        // Classic AnimSeqs.

	// Raw uncompressed animation keys - not to be serialized.
	
	TArray<MotionChunkDigestInfo>  MovesInfo;		  // Moves info from file or script, instructions to build the AnimSeqs.
	INT                     RawNumFrames;			  // Raw number of frames.
	TArray<VQuatAnimKey>    RawAnimKeys;			  // Raw keys (bones * frames), ordered by frames.
	TArray<AnimInfoBinary>  RawAnimSeqInfo;	          // Moves info from file (optional)
	FLOAT                   CompFactor;               // Default global compression factor when digesting animations.
};

/*----------------------------------------------------------------------------
	The End.
----------------------------------------------------------------------------*/
