diff --git a/PregnancyPlus/PregnancyPlus.Core/PPCharaController.MeshInflation.Main.cs b/PregnancyPlus/PregnancyPlus.Core/PPCharaController.MeshInflation.Main.cs
index b5abc9e..c51dfe9 100644
--- a/PregnancyPlus/PregnancyPlus.Core/PPCharaController.MeshInflation.Main.cs
+++ b/PregnancyPlus/PregnancyPlus.Core/PPCharaController.MeshInflation.Main.cs
@@ -226,6 +226,29 @@ internal bool GetInflatedVerticies(SkinnedMeshRenderer smr, float sphereRadius,
var bellyVertIndex = md[rendererName].bellyVerticieIndexes;
var alteredVerts = md[rendererName].alteredVerticieIndexes;
+ //Pre compute some values needed by SculptInflatedVerticie, doin it here saves on compute in the big loop
+ var vertsLength = origVerts.Length;
+ var sphereCenterLs = meshRootTf.InverseTransformPoint(sphereCenter);
+ var preMorphSphereCenter = sphereCenter - GetUserMoveTransform(meshRootTf);
+ var pmSphereCenterLs = meshRootTf.InverseTransformPoint(preMorphSphereCenter);
+ //calculate the furthest back morph point based on the back bone position, include character rotation
+ var backExtentPos = new Vector3(preMorphSphereCenter.x, sphereCenter.y, preMorphSphereCenter.z) + meshRootTf.forward * -bellyInfo.ZLimit;
+ var backExtentPosLs = meshRootTf.InverseTransformPoint(backExtentPos);
+ //calculate the furthest top morph point based under the breast position, include character animated height differences
+ var topExtentPos = new Vector3(preMorphSphereCenter.x, preMorphSphereCenter.y, preMorphSphereCenter.z) + meshRootTf.up * bellyInfo.YLimit;
+ var topExtentPosLs = meshRootTf.InverseTransformPoint(topExtentPos);
+ var vertNormalCaluRadius = sphereRadius + waistWidth/10;//Only recalculate normals for verts within this radius to prevent shadows under breast at small belly sizes
+ var yOffsetDir = Vector3.up * md[rendererName].yOffset;//Any offset direction needed to align all meshes to the same local y height
+ var reduceClothFlattenOffset = 0f;
+
+ //I dont think transforms are thread safe so get the values we need now
+ var meshRootTfPos = meshRootTf.position;
+ var meshRootTfUp = meshRootTf.up;
+ var mrTfTransPt = meshRootTf.localToWorldMatrix;
+ var mrTfInvTransPt = mrTfTransPt.inverse;
+ var smrTfTransPt = smr.transform.localToWorldMatrix;
+ var smrTfInvTransPt = smrTfTransPt.inverse;
+
//Heavy compute task below, run in separate thread
WaitCallback threadAction = (System.Object stateInfo) =>
{
@@ -239,30 +262,14 @@ internal bool GetInflatedVerticies(SkinnedMeshRenderer smr, float sphereRadius,
if (PregnancyPlusPlugin.DebugCalcs.Value) PregnancyPlusPlugin.Logger.LogInfo($" Mesh affected vert count {bellyVertsCount}");
#endif
- //Pre compute some values needed by SculptInflatedVerticie, doin it here saves on compute in the big loop
- var vertsLength = origVerts.Length;
- var sphereCenterLs = meshRootTf.InverseTransformPoint(sphereCenter);
- var preMorphSphereCenter = sphereCenter - GetUserMoveTransform(meshRootTf);
- var pmSphereCenterLs = meshRootTf.InverseTransformPoint(preMorphSphereCenter);
- //calculate the furthest back morph point based on the back bone position, include character rotation
- var backExtentPos = new Vector3(preMorphSphereCenter.x, sphereCenter.y, preMorphSphereCenter.z) + meshRootTf.forward * -bellyInfo.ZLimit;
- var backExtentPosLs = meshRootTf.InverseTransformPoint(backExtentPos);
- //calculate the furthest top morph point based under the breast position, include character animated height differences
- var topExtentPos = new Vector3(preMorphSphereCenter.x, preMorphSphereCenter.y, preMorphSphereCenter.z) + meshRootTf.up * bellyInfo.YLimit;
- var topExtentPosLs = meshRootTf.InverseTransformPoint(topExtentPos);
- var vertNormalCaluRadius = sphereRadius + waistWidth/10;//Only recalculate normals for verts within this radius to prevent shadows under breast at small belly sizes
- var yOffsetDir = Vector3.up * md[rendererName].yOffset;//Any offset direction needed to align all meshes to the same local y height
- var reduceClothFlattenOffset = 0f;
-
-
//Set each verticies inflated postion, with some constraints (SculptInflatedVerticie) to make it look more natural
for (int i = 0; i < vertsLength; i++)
{
//Only care about inflating belly verticies
if (!bellyVertIndex[i] && !PregnancyPlusPlugin.DebugVerts.Value) continue;
- //Convert to worldspace, and apply and mesh offset needed
- var origVertWs = smr.transform.TransformPoint(origVerts[i] - yOffsetDir);
+ //Convert to worldspace (in a threadsafe way), and apply and mesh offset needed
+ var origVertWs = smrTfTransPt.MultiplyPoint3x4(origVerts[i] - yOffsetDir);
var vertDistance = Vector3.Distance(origVertWs, sphereCenter);
//Ignore verts outside the sphere radius
@@ -287,13 +294,13 @@ internal bool GetInflatedVerticies(SkinnedMeshRenderer smr, float sphereRadius,
//Make adjustments to the shape to make it smooth, and feed in user slider input
inflatedVertWs = SculptInflatedVerticie(origVertWs, verticieToSpherePos, sphereCenter, waistWidth,
- meshRootTf, preMorphSphereCenter, sphereRadius, backExtentPos,
- topExtentPos, sphereCenterLs, pmSphereCenterLs, backExtentPosLs,
+ meshRootTf, mrTfTransPt, mrTfInvTransPt, meshRootTfPos, meshRootTfUp,
+ preMorphSphereCenter, sphereRadius,
+ backExtentPos, topExtentPos, sphereCenterLs, pmSphereCenterLs, backExtentPosLs,
topExtentPosLs);
//Convert back to local space, and undo any temporary offset
- inflatedVerts[i] = smr.transform.InverseTransformPoint(inflatedVertWs) + yOffsetDir;
-
+ inflatedVerts[i] = smrTfInvTransPt.MultiplyPoint3x4(inflatedVertWs) + yOffsetDir;
}
//When this thread task is complete, execute the below in main thread
@@ -428,9 +435,10 @@ public float ApplyConditionalSphereCenterOffset(bool isClothingMesh, Vector3 _sp
/// The center of the imaginary sphere
/// The characters waist width that limits the width of the belly (future implementation)
/// The transform used to convert a mesh vector from local space to worldspace and back, also servers as the point where we want to stop making mesh changes when Z < 0
- internal Vector3 SculptInflatedVerticie(Vector3 originalVerticeWs, Vector3 inflatedVerticieWs, Vector3 sphereCenterWs,
- float waistWidth, Transform meshRootTf, Vector3 preMorphSphereCenterWs, float sphereRadius,
- Vector3 backExtentPos, Vector3 topExtentPos, Vector3 sphereCenterLs, Vector3 pmSphereCenterLs,
+ internal Vector3 SculptInflatedVerticie(Vector3 originalVerticeWs, Vector3 inflatedVerticieWs, Vector3 sphereCenterWs, float waistWidth,
+ Transform meshRootTf, Matrix4x4 mrTfTransPt, Matrix4x4 mrTfInvTransPt, Vector3 meshRootTfPos, Vector3 meshRootTfUp,
+ Vector3 preMorphSphereCenterWs, float sphereRadius, Vector3 backExtentPos, Vector3 topExtentPos,
+ Vector3 sphereCenterLs, Vector3 pmSphereCenterLs,
Vector3 backExtentPosLs, Vector3 topExtentPosLs)
{
//No smoothing modification in debug mode
@@ -449,68 +457,68 @@ internal Vector3 SculptInflatedVerticie(Vector3 originalVerticeWs, Vector3 infla
//Pre compute some constant Vert values so we dont have to do it for each transform
//Most all of the measurements below are done in local space to ignore character rotation and position
- var originalVerticeLs = meshRootTf.InverseTransformPoint(originalVerticeWs);
- var inflatedVerticieLs = meshRootTf.InverseTransformPoint(inflatedVerticieWs);
+ var originalVerticeLs = mrTfInvTransPt.MultiplyPoint3x4(originalVerticeWs);
+ var inflatedVerticieLs = mrTfInvTransPt.MultiplyPoint3x4(inflatedVerticieWs);
//Get the base shape with XY plane size limits
- var smoothedVectorLs = SculptBaseShape(meshRootTf, originalVerticeLs, inflatedVerticieLs, sphereCenterLs);
+ var smoothedVectorLs = SculptBaseShape(originalVerticeLs, inflatedVerticieLs, sphereCenterLs);
//Allow user adjustment of the height and width placement of the belly
if (GetInflationShiftY() != 0 || GetInflationShiftZ() != 0)
{
- smoothedVectorLs = GetUserShiftTransform(meshRootTf, smoothedVectorLs, sphereCenterLs, skinToCenterDist);
+ smoothedVectorLs = GetUserShiftTransform(smoothedVectorLs, sphereCenterLs, skinToCenterDist);
}
//Allow user adjustment of the width of the belly
if (GetInflationStretchX() != 0)
{
- smoothedVectorLs = GetUserStretchXTransform(meshRootTf, smoothedVectorLs, sphereCenterLs);
+ smoothedVectorLs = GetUserStretchXTransform(smoothedVectorLs, sphereCenterLs);
}
//Allow user adjustment of the height of the belly
if (GetInflationStretchY() != 0)
{
- smoothedVectorLs = GetUserStretchYTransform(meshRootTf, smoothedVectorLs, sphereCenterLs);
+ smoothedVectorLs = GetUserStretchYTransform(smoothedVectorLs, sphereCenterLs);
}
if (GetInflationRoundness() != 0)
{
- smoothedVectorLs = GetUserRoundnessTransform(meshRootTf, originalVerticeLs, smoothedVectorLs, sphereCenterLs, skinToCenterDist);
+ smoothedVectorLs = GetUserRoundnessTransform(originalVerticeLs, smoothedVectorLs, sphereCenterLs, skinToCenterDist);
}
//Allow user adjustment of the egg like shape of the belly
if (GetInflationTaperY() != 0)
{
- smoothedVectorLs = GetUserTaperYTransform(meshRootTf, smoothedVectorLs, sphereCenterLs, skinToCenterDist);
+ smoothedVectorLs = GetUserTaperYTransform(smoothedVectorLs, sphereCenterLs, skinToCenterDist);
}
//Allow user adjustment of the front angle of the belly
if (GetInflationTaperZ() != 0)
{
- smoothedVectorLs = GetUserTaperZTransform(meshRootTf, originalVerticeLs, smoothedVectorLs, sphereCenterLs, skinToCenterDist, backExtentPosLs);
+ smoothedVectorLs = GetUserTaperZTransform(originalVerticeLs, smoothedVectorLs, sphereCenterLs, skinToCenterDist, backExtentPosLs);
}
//Allow user adjustment of the fat fold line through the middle of the belly
if (GetInflationFatFold() > 0)
{
- smoothedVectorLs = GetUserFatFoldTransform(meshRootTf, originalVerticeLs, smoothedVectorLs, sphereCenterLs, sphereRadius);
+ smoothedVectorLs = GetUserFatFoldTransform(originalVerticeLs, smoothedVectorLs, sphereCenterLs, sphereRadius);
}
//If the user has selected a drop slider value
if (GetInflationDrop() > 0)
{
- smoothedVectorLs = GetUserDropTransform(meshRootTf, smoothedVectorLs, sphereCenterLs, skinToCenterDist, sphereRadius);
+ smoothedVectorLs = GetUserDropTransform(meshRootTfUp, smoothedVectorLs, sphereCenterLs, skinToCenterDist, sphereRadius);
}
//After all user transforms are applied, remove the edges from the sides/top of the belly
- smoothedVectorLs = RoundToSides(meshRootTf, originalVerticeLs, smoothedVectorLs, backExtentPosLs);
+ smoothedVectorLs = RoundToSides(originalVerticeLs, smoothedVectorLs, backExtentPosLs);
//Less skin stretching under breast area with large slider values
if (originalVerticeLs.y > pmSphereCenterLs.y)
{
- smoothedVectorLs = ReduceRibStretchingZ(meshRootTf, originalVerticeLs, smoothedVectorLs, topExtentPosLs);
+ smoothedVectorLs = ReduceRibStretchingZ(originalVerticeLs, smoothedVectorLs, topExtentPosLs);
}
// //Experimental, move more polygons to the front of the belly at max, Measured by trying to keep belly button size the same at 0 and max inflation size
@@ -525,20 +533,20 @@ internal Vector3 SculptInflatedVerticie(Vector3 originalVerticeWs, Vector3 infla
//At this point if the smoothed vector is the originalVector just return it
- if (smoothedVectorLs.Equals(originalVerticeLs)) return meshRootTf.TransformPoint(smoothedVectorLs);
+ if (smoothedVectorLs.Equals(originalVerticeLs)) return mrTfTransPt.MultiplyPoint3x4(smoothedVectorLs);
//**** All of the below are post mesh change checks to make sure the vertex position don't go outside of bounds
//Smoothed vert back to worldspace
- var smoothedVectorWs = meshRootTf.TransformPoint(smoothedVectorLs);
+ var smoothedVectorWs = mrTfTransPt.MultiplyPoint3x4(smoothedVectorLs);
var currentVectorDistance = Math.Abs(Vector3.Distance(sphereCenterWs, smoothedVectorWs));
var pmCurrentVectorDistance = Math.Abs(Vector3.Distance(preMorphSphereCenterWs, smoothedVectorWs));
//Get core point on the same y plane as the original vert
- var coreLineVertWs = meshRootTf.position + meshRootTf.up * (meshRootTf.InverseTransformPoint(originalVerticeWs).y * bellyInfo.TotalCharScale.y);
+ var coreLineVertWs = meshRootTfPos + meshRootTfUp * (mrTfInvTransPt.MultiplyPoint3x4(originalVerticeWs).y * bellyInfo.TotalCharScale.y);
var origCoreDist = Math.Abs(Vector3.Distance(originalVerticeWs, coreLineVertWs));//Get line from feet to head that verts must respect distance from
//Get core point on the same y plane as the smoothed vert
- var coreLineSmoothedVertWs = meshRootTf.position + meshRootTf.up * (meshRootTf.InverseTransformPoint(smoothedVectorWs).y * bellyInfo.TotalCharScale.y);
+ var coreLineSmoothedVertWs = meshRootTfPos + meshRootTfUp * (mrTfInvTransPt.MultiplyPoint3x4(smoothedVectorWs).y * bellyInfo.TotalCharScale.y);
var currentCoreDist = Math.Abs(Vector3.Distance(smoothedVectorWs, coreLineSmoothedVertWs));
//Don't allow any morphs to shrink towards the sphere center more than its original distance, only outward morphs allowed
diff --git a/PregnancyPlus/PregnancyPlus.Core/PPCharaController.MeshInflation.transforms.cs b/PregnancyPlus/PregnancyPlus.Core/PPCharaController.MeshInflation.transforms.cs
index 032d505..f776175 100644
--- a/PregnancyPlus/PregnancyPlus.Core/PPCharaController.MeshInflation.transforms.cs
+++ b/PregnancyPlus/PregnancyPlus.Core/PPCharaController.MeshInflation.transforms.cs
@@ -25,7 +25,7 @@ internal Vector3 GetUserMoveTransform(Transform fromPosition)
///
/// This will help pvent too much XY direction change, keeping the belly more round than disk like at large sizes
///
- internal Vector3 SculptBaseShape(Transform meshRootTf, Vector3 originalVerticeLs, Vector3 smoothedVectorLs, Vector3 sphereCenterLs)
+ internal Vector3 SculptBaseShape(Vector3 originalVerticeLs, Vector3 smoothedVectorLs, Vector3 sphereCenterLs)
{
//We only want to limit expansion n XY plane for this lerp
var sphereCenterXY = new Vector2(sphereCenterLs.x, sphereCenterLs.y);
@@ -46,7 +46,7 @@ internal Vector3 SculptBaseShape(Transform meshRootTf, Vector3 originalVerticeLs
///
/// This will shift the sphereCenter position *After sphereifying* on Y or Z axis (This stretches the mesh, where pre sphereifying, it would move the sphere within the mesh like Move Y)
///
- internal Vector3 GetUserShiftTransform(Transform meshRootTf, Vector3 smoothedVectorLs, Vector3 sphereCenterLs, float skinToCenterDist)
+ internal Vector3 GetUserShiftTransform(Vector3 smoothedVectorLs, Vector3 sphereCenterLs, float skinToCenterDist)
{
//IF the user has selected a y value, lerp the top and bottom slower and lerp any verts closer to z = 0 slower
if (GetInflationShiftY() != 0)
@@ -81,7 +81,7 @@ internal Vector3 GetUserShiftTransform(Transform meshRootTf, Vector3 smoothedVec
///
/// This will stretch the belly mesh wider
///
- internal Vector3 GetUserStretchXTransform(Transform meshRootTf, Vector3 smoothedVectorLs, Vector3 sphereCenterLs)
+ internal Vector3 GetUserStretchXTransform(Vector3 smoothedVectorLs, Vector3 sphereCenterLs)
{
//local Distance left or right from sphere center
var distFromXCenterLs = smoothedVectorLs.x - sphereCenterLs.x;
@@ -94,7 +94,7 @@ internal Vector3 GetUserStretchXTransform(Transform meshRootTf, Vector3 smoothed
}
- internal Vector3 GetUserStretchYTransform(Transform meshRootTf, Vector3 smoothedVectorLs, Vector3 sphereCenterLs)
+ internal Vector3 GetUserStretchYTransform(Vector3 smoothedVectorLs, Vector3 sphereCenterLs)
{
//Allow user adjustment of the height of the belly
//local Distance up or down from sphere center
@@ -112,7 +112,7 @@ internal Vector3 GetUserStretchYTransform(Transform meshRootTf, Vector3 smoothed
///
/// This sill taper the belly shape based on user input slider. shrinking the top width, and expanding the bottom width along the YX adis
///
- internal Vector3 GetUserTaperYTransform(Transform meshRootTf, Vector3 smoothedVectorLs, Vector3 sphereCenterLs, float skinToCenterDist)
+ internal Vector3 GetUserTaperYTransform(Vector3 smoothedVectorLs, Vector3 sphereCenterLs, float skinToCenterDist)
{
//local Distance up or down from sphere center
var distFromYCenterLs = smoothedVectorLs.y - sphereCenterLs.y;
@@ -138,7 +138,7 @@ internal Vector3 GetUserTaperYTransform(Transform meshRootTf, Vector3 smoothedVe
///
/// This sill taper the belly shape based on user input slider. pulling out the bottom and pushing in the top along the XZ axis
///
- internal Vector3 GetUserTaperZTransform(Transform meshRootTf, Vector3 originalVerticeLs, Vector3 smoothedVectorLs, Vector3 sphereCenterLs,
+ internal Vector3 GetUserTaperZTransform(Vector3 originalVerticeLs, Vector3 smoothedVectorLs, Vector3 sphereCenterLs,
float skinToCenterDist, Vector3 backExtentPosLs)
{
//local Distance up or down from sphere center
@@ -168,7 +168,7 @@ internal Vector3 GetUserTaperZTransform(Transform meshRootTf, Vector3 originalVe
///
/// This will add a fat fold across the middle of the belly
///
- internal Vector3 GetUserFatFoldTransform(Transform meshRootTf, Vector3 originalVerticeLs, Vector3 smoothedVectorLs, Vector3 sphereCenterLs, float sphereRadius)
+ internal Vector3 GetUserFatFoldTransform(Vector3 originalVerticeLs, Vector3 smoothedVectorLs, Vector3 sphereCenterLs, float sphereRadius)
{
var origSmoothVectorLs = smoothedVectorLs;
var inflationFatFold = GetInflationFatFold();
@@ -201,7 +201,7 @@ internal Vector3 GetUserFatFoldTransform(Transform meshRootTf, Vector3 originalV
///
/// This will make the front of the belly more, or less round
///
- internal Vector3 GetUserRoundnessTransform(Transform meshRootTf, Vector3 originalVerticeLs, Vector3 smoothedVectorLs, Vector3 sphereCenterLs, float skinToCenterDist)
+ internal Vector3 GetUserRoundnessTransform(Vector3 originalVerticeLs, Vector3 smoothedVectorLs, Vector3 sphereCenterLs, float skinToCenterDist)
{
var zDistFromCenter = smoothedVectorLs.z - sphereCenterLs.z;
@@ -222,18 +222,18 @@ internal Vector3 GetUserRoundnessTransform(Transform meshRootTf, Vector3 origina
///
/// This Drop the belly down
///
- internal Vector3 GetUserDropTransform(Transform meshRootTf, Vector3 smoothedVectorLs, Vector3 sphereCenterLs, float skinToCenterDist, float sphereRadius)
+ internal Vector3 GetUserDropTransform(Vector3 meshRootTfUp, Vector3 smoothedVectorLs, Vector3 sphereCenterLs, float skinToCenterDist, float sphereRadius)
{
//Move the verts closest to sphere center Z more slowly than verts at the belly button. Otherwise you stretch the ones near the body too much
var lerpZ = Mathf.Lerp(0, GetInflationDrop(), (smoothedVectorLs.z - sphereCenterLs.z)/(bellyInfo.ScaledRadius(BellyDir.z) * 1.5f));
- return smoothedVectorLs + meshRootTf.up * -(sphereRadius * lerpZ);
+ return smoothedVectorLs + meshRootTfUp * -(sphereRadius * lerpZ);
}
///
/// Dampen any mesh changed near edged of the belly (sides, top, and bottom) to prevent too much vertex stretching. The more forward the vertex is from Z the more it's allowd to be altered by sliders
///
- internal Vector3 RoundToSides(Transform meshRootTf, Vector3 originalVerticeLs, Vector3 smoothedVectorLs, Vector3 backExtentPosLs)
+ internal Vector3 RoundToSides(Vector3 originalVerticeLs, Vector3 smoothedVectorLs, Vector3 backExtentPosLs)
{
var origRad = bellyInfo.ScaledOrigRadius(BellyDir.z)/1.8f;
var multipliedRad = bellyInfo.ScaledRadius(BellyDir.z)/2.5f;
@@ -252,7 +252,7 @@ internal Vector3 RoundToSides(Transform meshRootTf, Vector3 originalVerticeLs, V
///
/// Reduce the stretching of the skin at the top of the belly where it connects to the ribs at large Multiplier values
///
- internal Vector3 ReduceRibStretchingZ(Transform meshRootTf, Vector3 originalVerticeLs, Vector3 smoothedVectorLs, Vector3 topExtentPosLs)
+ internal Vector3 ReduceRibStretchingZ(Vector3 originalVerticeLs, Vector3 smoothedVectorLs, Vector3 topExtentPosLs)
{
//The distance from topExtent that we want to start lerping movement more slowly
var topExtentOffset = topExtentPosLs.y/10;