Esempio n. 1
0
 public MeshContainer(SkinnedMeshRenderer skinnedRenderer)
 {
     Mesh = skinnedRenderer.sharedMesh;
     transform = skinnedRenderer.GetComponent<Transform>();
     bones = skinnedRenderer.bones;
     isAnimated = true;
 }
Esempio n. 2
0
		public EJMMesh(SkinnedMeshRenderer component){
			isSkinned = true;
			_smRenderer = component;
			mRenderer = component.GetComponent<Renderer> ();
			targettransform = component.transform;
			SetSharedMesh (_smRenderer.sharedMesh);
			RefreshMatrix ();
		}
    public static void CreateControlPoints(SkinnedMeshRenderer skin)
    {
        if (skin.sharedMesh != null)
        {
            Skin2D skin2D = skin.GetComponent<Skin2D>();
            if (skin2D != null) {
                skin2D.controlPoints = new ControlPoints.Point[skin.sharedMesh.vertices.Length];
                if (skin2D.points == null) {
                    skin2D.points = skin2D.gameObject.AddComponent<ControlPoints>();
                }
            }
            for (int i = 0; i < skin.sharedMesh.vertices.Length; i++)
            {
                Vector3 originalPos = skin.sharedMesh.vertices[i];

                if (skin2D != null) {
                    skin2D.controlPoints[i] = new ControlPoints.Point(originalPos);
                    skin2D.controlPoints[i].index = i;
                    skin2D.points.SetPoint(skin2D.controlPoints[i]);
                }

                GameObject b = new GameObject(skin.name + " Control Point");
                // Unparent the skin temporarily before adding the control point
                Transform skinParent = skin.transform.parent;
                skin.transform.parent = null;

                // Reset the rotation before creating the mesh so the UV's will align properly
                Quaternion localRotation = skin.transform.localRotation;
                skin.transform.localRotation = Quaternion.identity;

                b.transform.position = new Vector3(skin.transform.position.x + (skin.sharedMesh.vertices[i].x * skin.transform.localScale.x), skin.transform.position.y + (skin.sharedMesh.vertices[i].y * skin.transform.localScale.y), skin.transform.position.z + (skin.sharedMesh.vertices[i].z * skin.transform.localScale.z));
                b.transform.parent = skin.transform;
                ControlPoint[] points = b.transform.parent.transform.GetComponentsInChildren<ControlPoint>();
                if (points != null && points.Length > 0)
                {
                    b.gameObject.name = b.gameObject.name + points.Length;
                }
                Undo.RegisterCreatedObjectUndo(b, "Add control point");
                ControlPoint controlPoint = b.AddComponent<ControlPoint>();
                controlPoint.index = i;
                controlPoint.skin = skin;
                controlPoint.originalPosition = b.transform.localPosition;

                // Reset the rotations of the object
                skin.transform.localRotation = localRotation;
                skin.transform.parent = skinParent;
            }
        }
    }
Esempio n. 4
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>());
    }
    private static string SkinnedMeshToString(SkinnedMeshRenderer skRenderer, Dictionary<string, ObjMaterial> materialList)
    {
        Mesh mTemp = skRenderer.sharedMesh;
        Vector3[] vertices = new Vector3[mTemp.vertexCount];
        Vector3[] normals = new Vector3[mTemp.vertexCount];

        Matrix4x4[] boneMatrices = new Matrix4x4[skRenderer.bones.Length];

        for (int i = 0; i < boneMatrices.Length; i++) {
            boneMatrices[i] = skRenderer.bones[i].localToWorldMatrix * mTemp.bindposes[i];
        }

        for (int i = 0; i < mTemp.vertexCount; i++) {
            BoneWeight weight = mTemp.boneWeights[i];

            Matrix4x4 bm0 = boneMatrices[weight.boneIndex0];
            Matrix4x4 bm1 = boneMatrices[weight.boneIndex1];
            Matrix4x4 bm2 = boneMatrices[weight.boneIndex2];
            Matrix4x4 bm3 = boneMatrices[weight.boneIndex3];

            Matrix4x4 vertexMatrix = new Matrix4x4();
            vertexMatrix = Matrix4x4.identity;

            for (int n=0; n<16; n++) {
                vertexMatrix[n] =
                    bm0[n] * weight.weight0 +
                    bm1[n] * weight.weight1 +
                    bm2[n] * weight.weight2 +
                    bm3[n] * weight.weight3;
            }

            /*
            Vector3 pos0 = bm0.MultiplyPoint(mTemp.vertices[i]);
            Vector3 pos1 = bm1.MultiplyPoint(mTemp.vertices[i]);
            Vector3 pos2 = bm2.MultiplyPoint(mTemp.vertices[i]);
            Vector3 pos3 = bm3.MultiplyPoint(mTemp.vertices[i]);

            Vector3 pos = pos0 * weight.weight0 + pos1 * weight.weight1 + pos2 * weight.weight2 + pos3 * weight.weight3;

            vertices[i] = pos;
            */
            vertices[i] = vertexMatrix.MultiplyPoint (mTemp.vertices[i]);
            normals[i] = vertexMatrix.MultiplyVector (mTemp.normals[i]);
        }

        Mesh m = new Mesh();
        m.vertices = vertices;
        m.normals = normals;
        m.uv = mTemp.uv;
        m.triangles = mTemp.triangles;
        m.subMeshCount = mTemp.subMeshCount;
        m.RecalculateBounds();
        m.RecalculateNormals();

        Material[] mats = skRenderer.GetComponent<Renderer>().sharedMaterials;

        StringBuilder sb = new StringBuilder();

        sb.Append("g ").Append(skRenderer.gameObject.name).Append("\n");
        foreach(Vector3 lv in m.vertices)
        {
            Vector3 wv = skRenderer.transform.TransformPoint(lv);

            //This is sort of ugly - inverting x-component since we're in
            //a different coordinate system than "everyone" is "used to".
            sb.Append(string.Format("v {0} {1} {2}\n",-wv.x,wv.y,wv.z));
        }
        sb.Append("\n");

        foreach(Vector3 lv in m.normals)
        {
            Vector3 wv = skRenderer.transform.TransformDirection(lv);

            sb.Append(string.Format("vn {0} {1} {2}\n",-wv.x,wv.y,wv.z));
        }
        sb.Append("\n");

        foreach(Vector3 v in m.uv)
        {
            sb.Append(string.Format("vt {0} {1}\n",v.x,v.y));
        }

        for (int material=0; material < m.subMeshCount; material ++) {
            sb.Append("\n");
            sb.Append("usemtl ").Append(mats[material].name).Append("\n");
            sb.Append("usemap ").Append(mats[material].name).Append("\n");

            //See if this material is already in the materiallist.
            try
         {
              ObjMaterial objMaterial = new ObjMaterial();

              objMaterial.name = mats[material].name;

              if (mats[material].mainTexture)
                objMaterial.textureName = AssetDatabase.GetAssetPath(mats[material].mainTexture);
              else
                objMaterial.textureName = null;

              materialList.Add(objMaterial.name, objMaterial);
            }
            catch (ArgumentException)
            {
                //Already in the dictionary
            }

            int[] triangles = m.GetTriangles(material);
            for (int i=0;i<triangles.Length;i+=3)
            {
                //Because we inverted the x-component, we also needed to alter the triangle winding.
                sb.Append(string.Format("f {1}/{1}/{1} {0}/{0}/{0} {2}/{2}/{2}\n",
                    triangles[i]+1 + vertexOffset, triangles[i+1]+1 + normalOffset, triangles[i+2]+1 + uvOffset));
            }
        }

        vertexOffset += m.vertices.Length;
        normalOffset += m.normals.Length;
        uvOffset += m.uv.Length;

        return sb.ToString();
    }