Jump to content

  • Log In with Google      Sign In   
  • Create Account

We need your help!

We need 7 developers from Canada and 18 more from Australia to help us complete a research survey.

Support our site by taking a quick sponsored survey and win a chance at a $50 Amazon gift card. Click here to get started!


Alundra

Member Since 19 Jul 2011
Offline Last Active Today, 12:50 PM

#5248421 Mirror hierarchy in local space

Posted by Alundra on 23 August 2015 - 03:41 PM

Here the actual code used to mirror the pose :

for( UInt32 t = 0; t < MirrorPose.m_TransformationArray.GetSize(); ++t )
{
  // Get the transformation where the mirrored pose is stored.
  CTransformation& MirrorTransformation = MirrorPose.m_TransformationArray[ t ];

  // Get the transformation which will be mirrored.
  const CTransformation& OutputTransformation = m_OutputPose.m_TransformationArray[ MirrorTableArray[ t ] ];

  // Mirror the translation.
  MirrorTransformation.m_Translation = VectorMirror( OutputTransformation.m_Translation, CVector3( 1.0f, 0.0f, 0.0f ) );

  // Mirror the rotation.
  const CQuaternion& OutputRotation = OutputTransformation.m_Rotation;
  const CVector3 MirrorQuatXYZ = VectorMirror( CVector3( OutputRotation.x, OutputRotation.y, OutputRotation.z ), CVector3( 1.0f, 0.0f, 0.0f ) );
  MirrorTransformation.m_Rotation = CQuaternion( MirrorQuatXYZ.x, MirrorQuatXYZ.y, MirrorQuatXYZ.z, -OutputRotation.w );

  // Set the scaling.
  MirrorTransformation.m_Scaling = OutputTransformation.m_Scaling;
}

I use Y as up axis and left handed coordinate system, my meshes are imported from FBX using the FBX SDK.

Transformation of each node is modified by the FBX to have correct orientation/translation for this coordinate system.

For example on this character, the bind pose of the root bone and all geometry node are stored as :

T: 0.000000,0.000000,0.000000
R: 0.000000,0.000000,0.000000,-1.000000
S: 1.000000,1.000000,1.000000

The mirror table logged to check it's correct :

[2015/08/24-00:30:59] 0: 0 (Root: Root)
[2015/08/24-00:30:59] 1: 1 (Hips: Hips)
[2015/08/24-00:30:59] 2: 2 (Spine: Spine)
[2015/08/24-00:30:59] 3: 3 (Spine1: Spine1)
[2015/08/24-00:30:59] 4: 33 (LeftShoulder: RightShoulder)
[2015/08/24-00:30:59] 5: 34 (LeftArm: RightArm)
[2015/08/24-00:30:59] 6: 35 (LeftArmRoll: RightArmRoll)
[2015/08/24-00:30:59] 7: 36 (LeftForeArm: RightForeArm)
[2015/08/24-00:30:59] 8: 37 (LeftForeArmRoll: RightForeArmRoll)
[2015/08/24-00:30:59] 9: 38 (LeftHand: RightHand)
[2015/08/24-00:30:59] 10: 39 (LeftHandIndex1: RightHandIndex1)
[2015/08/24-00:30:59] 11: 40 (LeftHandIndex2: RightHandIndex2)
[2015/08/24-00:30:59] 12: 41 (LeftHandIndex3: RightHandIndex3)
[2015/08/24-00:30:59] 13: 42 (LeftHandIndex4: RightHandIndex4)
[2015/08/24-00:30:59] 14: 43 (LeftHandMiddle1: RightHandMiddle1)
[2015/08/24-00:30:59] 15: 44 (LeftHandMiddle2: RightHandMiddle2)
[2015/08/24-00:30:59] 16: 45 (LeftHandMiddle3: RightHandMiddle3)
[2015/08/24-00:30:59] 17: 46 (LeftHandMiddle4: RightHandMiddle4)
[2015/08/24-00:30:59] 18: 47 (LeftHandPinky1: RightHandPinky1)
[2015/08/24-00:30:59] 19: 48 (LeftHandPinky2: RightHandPinky2)
[2015/08/24-00:30:59] 20: 49 (LeftHandPinky3: RightHandPinky3)
[2015/08/24-00:30:59] 21: 50 (LeftHandPinky4: RightHandPinky4)
[2015/08/24-00:30:59] 22: 51 (LeftHandProp: RightHandProp)
[2015/08/24-00:30:59] 23: 52 (LeftHandRing1: RightHandRing1)
[2015/08/24-00:30:59] 24: 53 (LeftHandRing2: RightHandRing2)
[2015/08/24-00:30:59] 25: 54 (LeftHandRing3: RightHandRing3)
[2015/08/24-00:30:59] 26: 55 (LeftHandRing4: RightHandRing4)
[2015/08/24-00:30:59] 27: 56 (LeftHandThumb1: RightHandThumb1)
[2015/08/24-00:30:59] 28: 57 (LeftHandThumb2: RightHandThumb2)
[2015/08/24-00:30:59] 29: 58 (LeftHandThumb3: RightHandThumb3)
[2015/08/24-00:30:59] 30: 59 (LeftHandThumb4: RightHandThumb4)
[2015/08/24-00:30:59] 31: 31 (Neck: Neck)
[2015/08/24-00:30:59] 32: 32 (Head: Head)
[2015/08/24-00:30:59] 33: 4 (RightShoulder: LeftShoulder)
[2015/08/24-00:30:59] 34: 5 (RightArm: LeftArm)
[2015/08/24-00:30:59] 35: 6 (RightArmRoll: LeftArmRoll)
[2015/08/24-00:30:59] 36: 7 (RightForeArm: LeftForeArm)
[2015/08/24-00:30:59] 37: 8 (RightForeArmRoll: LeftForeArmRoll)
[2015/08/24-00:30:59] 38: 9 (RightHand: LeftHand)
[2015/08/24-00:30:59] 39: 10 (RightHandIndex1: LeftHandIndex1)
[2015/08/24-00:30:59] 40: 11 (RightHandIndex2: LeftHandIndex2)
[2015/08/24-00:30:59] 41: 12 (RightHandIndex3: LeftHandIndex3)
[2015/08/24-00:30:59] 42: 13 (RightHandIndex4: LeftHandIndex4)
[2015/08/24-00:30:59] 43: 14 (RightHandMiddle1: LeftHandMiddle1)
[2015/08/24-00:30:59] 44: 15 (RightHandMiddle2: LeftHandMiddle2)
[2015/08/24-00:30:59] 45: 16 (RightHandMiddle3: LeftHandMiddle3)
[2015/08/24-00:30:59] 46: 17 (RightHandMiddle4: LeftHandMiddle4)
[2015/08/24-00:30:59] 47: 18 (RightHandPinky1: LeftHandPinky1)
[2015/08/24-00:30:59] 48: 19 (RightHandPinky2: LeftHandPinky2)
[2015/08/24-00:30:59] 49: 20 (RightHandPinky3: LeftHandPinky3)
[2015/08/24-00:30:59] 50: 21 (RightHandPinky4: LeftHandPinky4)
[2015/08/24-00:30:59] 51: 22 (RightHandProp: LeftHandProp)
[2015/08/24-00:30:59] 52: 23 (RightHandRing1: LeftHandRing1)
[2015/08/24-00:30:59] 53: 24 (RightHandRing2: LeftHandRing2)
[2015/08/24-00:30:59] 54: 25 (RightHandRing3: LeftHandRing3)
[2015/08/24-00:30:59] 55: 26 (RightHandRing4: LeftHandRing4)
[2015/08/24-00:30:59] 56: 27 (RightHandThumb1: LeftHandThumb1)
[2015/08/24-00:30:59] 57: 28 (RightHandThumb2: LeftHandThumb2)
[2015/08/24-00:30:59] 58: 29 (RightHandThumb3: LeftHandThumb3)
[2015/08/24-00:30:59] 59: 30 (RightHandThumb4: LeftHandThumb4)
[2015/08/24-00:30:59] 60: 67 (LeftUpLeg: RightUpLeg)
[2015/08/24-00:30:59] 61: 68 (LeftLeg: RightLeg)
[2015/08/24-00:30:59] 62: 69 (LeftFoot: RightFoot)
[2015/08/24-00:30:59] 63: 70 (LeftToeBase: RightToeBase)
[2015/08/24-00:30:59] 64: 71 (LeftToeBase_END: RightToeBase_END)
[2015/08/24-00:30:59] 65: 72 (LeftLegRoll: RightLegRoll)
[2015/08/24-00:30:59] 66: 73 (LeftUpLegRoll: RightUpLegRoll)
[2015/08/24-00:30:59] 67: 60 (RightUpLeg: LeftUpLeg)
[2015/08/24-00:30:59] 68: 61 (RightLeg: LeftLeg)
[2015/08/24-00:30:59] 69: 62 (RightFoot: LeftFoot)
[2015/08/24-00:30:59] 70: 63 (RightToeBase: LeftToeBase)
[2015/08/24-00:31:00] 71: 64 (RightToeBase_END: LeftToeBase_END)
[2015/08/24-00:31:00] 72: 65 (RightLegRoll: LeftLegRoll)
[2015/08/24-00:31:00] 73: 66 (RightUpLegRoll: LeftUpLegRoll)
[2015/08/24-00:31:00] 74: 74 (BodyMESH: BodyMESH)
[2015/08/24-00:31:00] 75: 75 (GlassesMESH: GlassesMESH)
[2015/08/24-00:31:00] 76: 76 (HeadMESH: HeadMESH)
[2015/08/24-00:31:00] 77: 77 (HelmetMESH: HelmetMESH)
[2015/08/24-00:31:00] 78: 78 (BackpackMESH: BackpackMESH)
[2015/08/24-00:31:00] 79: 80 (ArmorArmRightMESH: ArmorArmLeftMESH)
[2015/08/24-00:31:00] 80: 79 (ArmorArmLeftMESH: ArmorArmRightMESH)
[2015/08/24-00:31:00] 81: 81 (StuffMESH: StuffMESH)
[2015/08/24-00:31:00] 82: 82 (RadioMESH: RadioMESH)
[2015/08/24-00:31:00] 83: 83 (HolsterMESH: HolsterMESH)
[2015/08/24-00:31:00] 84: 84 (LegStrapsMESH: LegStrapsMESH)
[2015/08/24-00:31:00] 85: 85 (ChestStrapsMESH: ChestStrapsMESH)

Link from the UDK documentation which shows correctly the feature with screenshots and explanations :

https://udn.epicgames.com/Three/AnimationMirroring.html




#5248359 Mirror hierarchy in local space

Posted by Alundra on 23 August 2015 - 08:57 AM

Using the naive/bad method of inversing translation.x, quaternion.x and quaternion.w (which is the same result as using (1,0,0) as normal).

I got simple animation mirrored correctly if the parent transformation is identity and 2 nodes are its children.

For a complex skeleton using the naive/bad method only some part of the hierarchy is correctly mirrored, here the result :

Without mirror : http://zupimages.net/up/15/34/pgb9.png

With mirror : http://zupimages.net/up/15/34/utwc.png

Looks like mirror axis problem.

The foot is badly oriented and the pelvis too and other parts.

Here the result of the skeleton :

Without mirror : http://zupimages.net/up/15/34/31so.png

With mirror : http://zupimages.net/up/15/34/un1a.png

The translation is correctly mirrored, only the quaternion is badly mirrored apparently.




#5248317 Mirror hierarchy in local space

Posted by Alundra on 22 August 2015 - 08:48 PM

You can see a screenshot of the result of the mirroring here :

https://udn.epicgames.com/Three/rsrc/Three/AnimationMirroring/SkeletalMeshMirrorExample.jpg

The only limitation is the symmetrical hierarchy needed. I already have the mirror table generated correctly to know the mirror node (same node if no mirror node found).

To compute the mirror, it's possible to use the full hierarchy of the pose in local space, each parent is known, each bind pose in local space is known.

Formula to mirror a vector V with a normal N : V - 2.0 * Dot(V, N) * N




#5247942 Fast sqrt for 64bit

Posted by Alundra on 20 August 2015 - 03:40 PM


Now, if you want a super fast sqrt on x86, you can use Greg Walsh's (in)famous approximation  
float Sqrt(float x){
int i = *(int*)&x;
i = 0x5f3759df - (i>>1);
float r = *(float*)&i;
r = r*(1.5f - 0.5f*x*r*r);
return r * x;
}
Just don't ask me how it works...

We have no evidence it's really Greg Walsh the author if i'm not wrong.




#5245803 Which techniques should I use for lights & shadows in my game engine (SSA...

Posted by Alundra on 11 August 2015 - 01:16 PM

You have lot of information here : http://www.filmicworlds.com/2014/04/21/optimizing-ggx-shaders-with-dotlh/




#5244889 Cascaded shadow mapping, shadow frustum generation

Posted by Alundra on 06 August 2015 - 05:04 PM

The problem using the bounding box is the change of projection which cause artefacts, using a stable cascade based on bounding sphere you got this problem removed.

You got also a problem called "the shimmering edge effect", this problem is caused by the move of the camera, to remove it you have to round to pixel size increments.

You can see the problem here :




#5244861 Cascaded shadow mapping, shadow frustum generation

Posted by Alundra on 06 August 2015 - 12:35 PM

The frustum can be represented by a triangle which cover the whole visible scene from the actual camera.

You split this frustum and for each split you compute the orthographic projection.

To have stable cascade you can compute the radius and set this radius on width and height of the orthographic projection.

If you use the SDSM algorithm to find the tighter cascade from the depth buffer, you don't need to use stable cascade, that produce wasted space.

To compute the radius you simply need to use trigonometry because the frustum can be represented by a triangle.

Here the code to compute the radius :

// Tangent values.
float TanFOVX = tan(0.5f * FieldOfViewRadian * AspectRatio);
float TanFOVY = tan(0.5f * FieldOfViewRadian);

// Compute the bounding sphere.
Vector3 Center = CameraPos + CameraForward * (Near + HalfDistance);
CornerPoint = CameraPos + (CameraRight * TanFOVX + CameraUp * TanFOVY + CameraForward) * Far;
float Radius = (CornerPoint - Center).Length();

Here the code to compute the AABB :

// Scale needed to extract frustum points.
float scaleXInv = 1.0f / cameraProj(1, 1);
float scaleYInv = 1.0f / cameraProj(2, 2);

// Matrix needed to transform frustum corners into light view space.
Matrix cameraViewToLightProj = cameraViewInv * lightViewProj;

// Compute corners.
Vector3 corners[8];
float nearX = scaleXInv * nearZ;
float nearY = scaleYInv * nearZ;
corners[0] = Vector3(-nearX,  nearY, nearZ);
corners[1] = Vector3( nearX,  nearY, nearZ);
corners[2] = Vector3(-nearX, -nearY, nearZ);
corners[3] = Vector3( nearX, -nearY, nearZ);
float farX = scaleXInv * farZ;
float farY = scaleYInv * farZ;
corners[4] = Vector3(-farX,  farY, farZ);
corners[5] = Vector3( farX,  farY, farZ);
corners[6] = Vector3(-farX, -farY, farZ);
corners[7] = Vector3( farX, -farY, farZ);

// Compute corners in light space.
Vector3 cornersLightView[8];
for(int i = 0; i < 8; ++i)
  cornersLightView[i] = cameraViewToLightProj.Transform(corners, 1.0f);

// Compute the AABB.
ComputeAABBFromPoints(cornersLightView, 8, outMin, outMax);



#5244678 Clone functions

Posted by Alundra on 05 August 2015 - 10:36 AM

Yes it's part of a factory but for the property system the clone function is also used when undo command need to store a copy to redo the command.

This is where all start about the question, sometime only a simple instance is needed and sometimes a full copy.

To be coherent all clone function should do the same thing full or just instance.

But sometimes, the full copy is not needed.




#5244459 Fbx light attenuation

Posted by Alundra on 04 August 2015 - 03:22 AM

Using "Start Attenuation" and "End Attenuation" you can compute the attenuation factor using smoothstep :

float3 LightDirection = Light.Position - SurfaceData.Position;
float d = length(LightDirection);
float Attenuation = smoothstep(Light.EndAttenuation, Light.StartAttenuation, d);

But on the FBX doc I see the Decay param which contains : None, Linear, Quadratic and Cubic.

None = No attenuation
Linear = lerp(Light.EndAttenuation, Light.StartAttenuation, d);
Quadratic = 1.0f / dot(Attenuation, float3(1.0f, d, d*d));
Cubic = ?

From a paper of Unreal Engine 4, here the formula used :

float Factor = clamp(1.0f - pow(d / Light.EndAttenuation, 4.0f), 0.0f, 1.0f);
float Attenuation = (Factor * Factor) / ((d * d) + 1.0f);



#5242804 3d file format with skeletal animation and normal mapping

Posted by Alundra on 26 July 2015 - 01:19 PM

I import FBX and convert it to my mesh and animation format. This is the way used by Unreal and Unity too.

The other way is to write your plugin, I used this way on 3dsmax and maya before FBX was good enough.

One limitation from the FBX is to not support shear on the transformation matrix.

FBX SDK is not thread safe too.




#5241355 D language enum question

Posted by Alundra on 19 July 2015 - 06:36 AM

I see, maybe it's a good way to help users to not miss the keyword.




#5241313 D language enum question

Posted by Alundra on 18 July 2015 - 08:43 PM

The difference is surely the need of the lookup function as I said. I don't know the D language but surely the enum can be used directly.




#5238839 Avoid problem when roughness is 0

Posted by Alundra on 07 July 2015 - 01:28 PM

Is it better to remap the value [0,1] -> [0.001,1] to avoid confusion for the artist ?




#5223286 Template or Macro

Posted by Alundra on 14 April 2015 - 07:14 PM

"sandwich" is needed to survive, "screwdriver" was not there in paleolithic era and all was fine.

You can look at this link to learn what is paleothic era : http://en.wikipedia.org/wiki/Paleolithic




#5221964 make an object rotate to face a vector (Opengl 3D)

Posted by Alundra on 07 April 2015 - 06:58 PM

I don't understand well your question, if you want to move your object on its current rotation, only compute the forward vector from the quaternion and use that to move :

glm::vec3 ForwardDirection = glm::normalize(Rotation * glm::vec3(0.0f, 0.0f, 1.0f));
glm::vec3 NewPosition = CurrentPosition + (ForwardVector * Speed * ElapsedTime);





PARTNERS