Example #1
0
 public static List<float> GetArray_FLOAT(string sNameBlenderModule, string sBlenderAccessString)
 {
     CByteArray oByteArray = new CByteArray(sNameBlenderModule, sBlenderAccessString);
     int nArrayElements = oByteArray.GetLengthPayload() / sizeof(float);
     List<float> aBlenderArray = new List<float>(nArrayElements);
     if (nArrayElements > 0) {
         for (int nArrayElement = 0; nArrayElement  < nArrayElements; nArrayElement++)
             aBlenderArray.Add(oByteArray.ReadFloat());
     } else {
         Debug.LogWarningFormat("###WARNING: CByteArray.GetArray() gets zero-sided array on '{0}'", oByteArray._sBlenderAccessString);
     }
     return aBlenderArray;
 }
Example #2
0
    //---------------------------------------------------------------------------	INIT
    public override void OnDeserializeFromBlender()
    {
        base.OnDeserializeFromBlender();			// First call the CBMesh base class to serialize the mesh itself...

        _oSkinMeshRendNow = (SkinnedMeshRenderer)CUtility.FindOrCreateComponent(transform, typeof(SkinnedMeshRenderer));

        ////=== Send blender command to obtain the skinned mesh info ===
        CByteArray oBA = new CByteArray("'CBody'", _oBodyBase._sBlenderInstancePath_CBodyBase + _sNameCBodyInstanceMember + ".Unity_GetMesh_SkinnedInfo()");

        //===== RECEIVE SKINNING INFORMATION =====
        Matrix4x4[] aSkinBindPoses 		= null;			//###WEAK: A bit of unfortunate structure imposed on the code because of how late we read the stream versus how we must init vars for skinned mesh...  Can be improved.
        Transform[]	aSkinBones 			= null;
        List<BoneWeight> aBoneWeights 	= null;

        //=== Read in the flat array of names of vertex groups.  This will enable us to map the Blender vertex group blends to our fixed Unity bone rig ===
        byte nVertGroupsMesh = oBA.ReadByte();
        aSkinBones = new Transform[nVertGroupsMesh];
        aSkinBindPoses = new Matrix4x4[nVertGroupsMesh];

        //=== Find the root of our skinning bones from our body's main skinned mesh ===
        Transform oNodeBoneParentRoot = CUtility.FindChild(_oBodyBase._oBodyRootGO.transform, "Bones");

        if (oNodeBoneParentRoot == null)
            CUtility.ThrowException("CBMesh is attempting to reconstruct a skinned mesh but was not able to find root node of bones!");
        for (byte nVertGroup = 0; nVertGroup < nVertGroupsMesh; nVertGroup++) {
            string sVertGroup = oBA.ReadString();
            Transform oNodeBone = CUtility.FindNodeByName(oNodeBoneParentRoot, sVertGroup);     //###OPT: Recursive on hundreds of bones for hundreds of bones = O squared!!  ###IMPROVE: Find by direct path!
            if (oNodeBone != null) {
                //Debug.Log("Bone found for '" + sVertGroup + "'");
                aSkinBones[nVertGroup] = oNodeBone;
                aSkinBindPoses[nVertGroup] = oNodeBone.worldToLocalMatrix;	//###CHECK
            } else {
                Debug.LogError("**ERROR: CBMesh.ctor() could not find bone '" + sVertGroup + "'");		//###DESIGN?: Throw?
            }
        }

        //=== Stream in the bone weight info ===		###NOTE: Note that this code assumes a compatible bone tree between Blender and Unity!!!  To update Unity bones from Blender bones use the CBodyEd.UpdateBonesFromBlender() function
        aBoneWeights = new List<BoneWeight>();
        int[] aBoneIndex = new int[32];			// Temp arrays
        float[] aBoneWeight = new float[32];
        int nErrSumOutOfRange = 0;

        int nVerts = GetNumVerts();
        for (int nVert = 0; nVert < nVerts; nVert++) {
            byte nVertGroups = oBA.ReadByte();
            float nBoneWeightSum = 0;
            if (nVertGroups >= 5) {
                Debug.LogWarningFormat("Warning: Skinned mesh '{0}' at vert {1} has {2} vert groups!", _sNameBlenderMesh, nVert, nVertGroups);
                CUtility.ThrowException("CBMesh.ctor() encountered a vertex with " + nVertGroups + " vertex groups!");
            }

            for (byte nVertGroup = 0; nVertGroup < nVertGroups; nVertGroup++) {		//###IMPROVE: It might be more elegant to shift this code to Blender Python?
                aBoneIndex[nVertGroup]  = oBA.ReadByte();
                float nBoneWeight = oBA.ReadFloat();
                if (nBoneWeight < 0)
                    //Debug.LogError("CBMesh.ctor() encountered a bone weight below 0 at vert " + nVert + " and vert group " + nVertGroup);
                    CUtility.ThrowException("CBSkin.ctor() encountered a bone weight below 0 at vert " + nVert + " and vert group " + nVertGroup);
                if (nBoneWeight > 1)
                    //CUtility.ThrowException("CBMesh.ctor() encountered a bone weight over 1 at vert " + nVert + " and vert group " + nVertGroup);	//###IMPROVE: Common!  What to do? cap??
                    Debug.LogWarning("CBSkin.ctor() encountered a bone weight over 1 = " + nBoneWeight + " at vert " + nVert + " and vert group " + nVertGroup);	//###IMPROVE: Common!  What to do? cap??
                aBoneWeight[nVertGroup] = nBoneWeight;
                nBoneWeightSum += nBoneWeight;
            }

            if (nBoneWeightSum < 0.999 || nBoneWeightSum > 1.001) {
                Debug.LogWarning("###W: CBMesh.ctor() vertex " + nVert + " had out of range weight of " + nBoneWeightSum);
                nErrSumOutOfRange++;
            }
            BoneWeight oBoneWeight = new BoneWeight();
            if (nVertGroups > 0) { oBoneWeight.boneIndex0 = aBoneIndex[0]; oBoneWeight.weight0 = aBoneWeight[0]; }
            if (nVertGroups > 1) { oBoneWeight.boneIndex1 = aBoneIndex[1]; oBoneWeight.weight1 = aBoneWeight[1]; }
            if (nVertGroups > 2) { oBoneWeight.boneIndex2 = aBoneIndex[2]; oBoneWeight.weight2 = aBoneWeight[2]; }
            if (nVertGroups > 3) { oBoneWeight.boneIndex3 = aBoneIndex[3]; oBoneWeight.weight3 = aBoneWeight[3]; }

            aBoneWeights.Add(oBoneWeight);
        }

        if (nErrSumOutOfRange > 0)		//###CHECK: What to do???
            Debug.LogWarning("###ERROR: CBSkin.ctor() found " + nErrSumOutOfRange + " bones with out-of-range sums!");

        //=== Read the number of errors detected when sending over the blender bone weights... what to do?? ===
        int nErrorsBoneGroups = oBA.ReadInt();
        if (nErrorsBoneGroups > 0)			//###IMPROVE ###CHECK: What to do???
            Debug.LogError("###ERROR: CBSkin.ctor() detected " + nErrorsBoneGroups + "	blender-side errors while reading in blender mesh!");

        oBA.CheckMagicNumber_End();

        //=== Finalize the mesh creation by stuffing _oMeshRender into mesh filter or skinned mesh renderer as appropriate ===
        UpdateNormals();									// Fix the normals with the just-serialized map of shared normals
        _oMeshNow.bindposes 	= aSkinBindPoses;
        _oMeshNow.boneWeights 	= aBoneWeights.ToArray();
        _oSkinMeshRendNow.sharedMesh = _oMeshNow;					//###TODO: skinned mesh complex bounds!
        _oSkinMeshRendNow.materials = _aMats;
        _oSkinMeshRendNow.bones = aSkinBones;

        //=== Conveniently reset skinned mesh renderer flags we always keep constant... makes it easier to override the defaults which go the other way ===
        _oSkinMeshRendNow.updateWhenOffscreen = true;                               //###OPT: Should some mesh have this off?
        _oSkinMeshRendNow.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On;       //###PERF: Runtime performance of shadows?  (All done in different quality settings?)
        _oSkinMeshRendNow.receiveShadows = true;
        if (_oSkinMeshRendNow.GetComponent<Collider>() != null)						//###CHECK: ReleaseGlobalHandles mesh collider here if it exists at gameplay
            Destroy(_oSkinMeshRendNow.GetComponent<Collider>());
    }