static public void TransformKeyDataToWorld(this MotionDataInNative motionData) { var rotationKeyLength = motionData.StreamPool .Buffer(3) .Select(x => x[(int)KeyStreamSection.rotations].Stream.Length) .Sum() ; var dst = new NativeArray <KeyUnitInNative>(rotationKeyLength * 2, Allocator.Persistent); var qKeysPerMotions = from ma in motionData.pool.Motions.Select((x, i) => motionData.CreateAccessor(i)) from ibone in Enumerable.Range(0, motionData.BoneLength) select(ma, ime: ibone, iparent: ma.GetParentBoneIndex(ibone)) ; foreach (var(ma, ime, iparent) in qKeysPerMotions) { //if( iparent == -1 ) continue; if (iparent == -1) { } Debug.Log($"bone {ime} {iparent}"); var thisPositions = ma.GetStreamSlice(ime, KeyStreamSection.positions).Stream; var parentPositions = ma.GetStreamSlice(iparent, KeyStreamSection.positions).Stream; var thisRotations = ma.GetStreamSlice(ime, KeyStreamSection.rotations).Stream; var parentRotations = ma.GetStreamSlice(iparent, KeyStreamSection.rotations).Stream; var posNearKeys = new StreamNearKeysCacheData(); var posShifter = new StreamKeyShiftData() { Keys = parentPositions }; var rotNearKeys = new StreamNearKeysCacheData(); var rotShifter = new StreamKeyShiftData() { Keys = parentRotations }; StreamExtentions.InitializeKeys(ref rotNearKeys, ref rotShifter); for (var i = 0; i < thisRotations.Length; i++) { var thisRot = thisRotations[i]; rotNearKeys.TimeProgress = thisRot.Time.x; do { StreamExtentions.ShiftKeysIfOverKeyTime(ref rotNearKeys, ref rotShifter); }while(rotNearKeys.TimeProgress > rotNearKeys.Time_To); var lrot = new quaternion(thisRot.Value); var prot = new quaternion(rotNearKeys.Interpolate(rotNearKeys.CaluclateTimeNormalized())); thisRot.Value = math.mul(prot, lrot).value; thisRotations[i] = thisRot; // Debug.Log($"{thisRot.Time} {thisRot.Value}"); } } }
static public void ConvertFrom(this MotionDataInNative dst, MotionClip src) { // ボーン var qParentBones = from parentPath in src.StreamPaths.Select(path => getParent(path)) // ペアレントパス列挙 join pathIndex in src.StreamPaths.Select((path, i) => (path, i)) // 順序数を保持する索引と外部結合する on parentPath equals pathIndex.path into pathIndexes from pathIndex in pathIndexes.DefaultIfEmpty((path: "", i: -1)) // 結合できないパスは -1 select pathIndex.i ; string getParent(string path) => Path.GetDirectoryName(path).Replace("\\", "/"); // モーション var qMotions = from motion in src.MotionData.Motions select new MotionUnitInNative { TimeLength = motion.TimeLength }; // ソース全キー var qKeys = from motion in src.MotionData.Motions from section in motion.Sections from stream in section.Streams from key in Enumerable.Zip(stream.keys.Append(new KeyDataUnit()), stream.keys, (pre, now) => (pre, now)) select new KeyUnitInNative { // Time = new float4( key.now.Time - key.pre.Time, 0.0f, 0.0f, 0.0f ), Time = new float4(key.now.Time, 0.0f, 0.0f, 0.0f), Value = key.now.Value }; // インクリメンタルなキー位置を返す。苦肉の策。 var iKeyInPool = 0; Func <StreamDataUnit, int> indexResolver = stream => { var i = iKeyInPool; iKeyInPool += stream.keys.Length; return(i); }; //var baseSectionList = new [] { "m_LocalPosition", "m_LocalRotation", "m_LocalScale" }; // ストリームスライスの構築 var qStreamSlices = // モーションごとの3セクション配列を生成する。 from motion in src.MotionData.Motions let sections = motion.Sections.ToDictionary(section => section.SectionName) select new [] { sections.GetOrDefault("m_LocalPosition"), sections.GetOrDefault("m_LocalRotation"), sections.GetOrDefault("m_LocalScale") } into sectionArray // セクションは空の場合がある。空セクションのストリームも確保し、すべてデフォルトスライスを配置させる。 from section in sectionArray let streams = section.Streams?.ToDictionary(stream => stream.StreamPath) // ストリームも空の場合がある。空はデフォルトスライス。また並び順は src.StreamPaths の通り。 from streamPath in src.StreamPaths let stream = streams?.GetOrDefault(streamPath) ?? new StreamDataUnit() select new StreamSliceInNative { Stream = stream.keys != null ? new NativeSlice <KeyUnitInNative>(dst.pool.Keys, indexResolver(stream), stream.keys.Length) : new NativeSlice <KeyUnitInNative>() }; // 実体を確保 dst.pool.Motions = qMotions.ToNativeArray(Allocator.Persistent); dst.pool.Keys = qKeys.ToNativeArray(Allocator.Persistent); dst.pool.StreamSlices = qStreamSlices.ToNativeArray(Allocator.Persistent); dst.pool.BoneParents = qParentBones.ToNativeArray(Allocator.Persistent); dst.boneLength = src.StreamPaths.Length; }
static public void TransformKeyDataToWorld_(this MotionDataInNative motionData) { var qKeysPerMotions = from ma in motionData.pool.Motions.Select((x, i) => motionData.CreateAccessor(i)) from ibone in Enumerable.Range(0, motionData.BoneLength) select(ma, ime: ibone, iparent: ma.GetParentBoneIndex(ibone)) ; foreach (var(ma, ime, iparent) in qKeysPerMotions) { if (iparent == -1) { continue; } Debug.Log($"bone {ime} {iparent}"); var thisPositions = ma.GetStreamSlice(ime, KeyStreamSection.positions).Stream; var parentPositions = ma.GetStreamSlice(iparent, KeyStreamSection.positions).Stream; var thisRotations = ma.GetStreamSlice(ime, KeyStreamSection.rotations).Stream; var parentRotations = ma.GetStreamSlice(iparent, KeyStreamSection.rotations).Stream; var posNearKeys = new StreamNearKeysCacheData(); var posShifter = new StreamKeyShiftData() { Keys = parentPositions }; var rotNearKeys = new StreamNearKeysCacheData(); var rotShifter = new StreamKeyShiftData() { Keys = parentRotations }; StreamExtentions.InitializeKeys(ref rotNearKeys, ref rotShifter); for (var i = 0; i < thisRotations.Length; i++) { var thisRot = thisRotations[i]; rotNearKeys.TimeProgress = thisRot.Time.x; do { StreamExtentions.ShiftKeysIfOverKeyTime(ref rotNearKeys, ref rotShifter); }while(rotNearKeys.TimeProgress > rotNearKeys.Time_To); var lrot = new quaternion(thisRot.Value); var prot = new quaternion(rotNearKeys.Interpolate(rotNearKeys.CaluclateTimeNormalized())); thisRot.Value = math.mul(prot, lrot).value; thisRotations[i] = thisRot; // Debug.Log($"{thisRot.Time} {thisRot.Value}"); } StreamExtentions.InitializeKeys(ref posNearKeys, ref posShifter); StreamExtentions.InitializeKeys(ref rotNearKeys, ref rotShifter); for (var i = 0; i < thisPositions.Length; i++) { var thisPos = thisPositions[i]; posNearKeys.TimeProgress = thisPos.Time.x; do { StreamExtentions.ShiftKeysIfOverKeyTime(ref posNearKeys, ref posShifter); }while(posNearKeys.TimeProgress > posNearKeys.Time_To); rotNearKeys.TimeProgress = thisPos.Time.x; do { StreamExtentions.ShiftKeysIfOverKeyTime(ref rotNearKeys, ref rotShifter); }while(rotNearKeys.TimeProgress > rotNearKeys.Time_To); var lpos = thisPos.Value.As_float3(); var ppos = posNearKeys.Interpolate(posNearKeys.CaluclateTimeNormalized()); var prot = new quaternion(rotNearKeys.Interpolate(rotNearKeys.CaluclateTimeNormalized())); thisPos.Value = math.mul(prot, lpos).As_float4() + ppos; thisPositions[i] = thisPos; //Debug.Log( $"{thisPos.Time} {thisPos.Value}" ); } } }
//private async void Awake() private void Start() { var md = new MotionDataInNative(); md.ConvertFrom(MotionClipData); // md.TransformKeyDataToWorld_(); // メッシュの加工 var newmesh = new Mesh(); newmesh.vertices = meshSetting.mesh.vertices; newmesh.boneWeights = meshSetting.mesh.boneWeights; newmesh.bindposes = meshSetting.mesh.bindposes; newmesh.normals = meshSetting.mesh.normals; newmesh.uv = meshSetting.mesh.uv; newmesh.triangles = meshSetting.mesh.triangles; meshSetting.mesh = newmesh.ConvertForMotionable(useUvChannel: 1, MotionClipData); var bindposes = meshSetting.mesh.bindposes; meshSetting.material.SetMatrixArray("mts", bindposes); meshSetting.material.SetInt("boneLength", bindposes.Length); meshSetting.material.SetVectorArray("positions", new Vector4 [1023]); meshSetting.material.SetVectorArray("rotations", new Vector4 [1023]); // アーキタイプ var em = World.Active.GetOrCreateManager <EntityManager>(); var streamArch = em.CreateArchetype( typeof(StreamInitialLabel), typeof(StreamKeyShiftData), typeof(StreamNearKeysCacheData), typeof(StreamInterpolatedData) ); var boneArch = em.CreateArchetype( typeof(DrawBoneTargetLabel), typeof(BoneEntityLinkData), typeof(BoneIndexData), typeof(BonePostureData) ); var motionArch = em.CreateArchetype( typeof(MotionInitializeData), typeof(MotionComponentData) ); var rendererArch = em.CreateArchetype( typeof(MeshInstanceRenderer) ); // レンダラ var rent = em.CreateEntity(rendererArch); em.SetSharedComponentData(rent, meshSetting); var drawOrderId = 0; var boneSerialIndex = 0; // Enumerable.Range(0,num).ForEach( x => create( Random.Range( 0, 15 ) ) );//.AddTo( gameObject ); Observable.EveryGameObjectUpdate().Take(num).Subscribe(x => create(Random.Range(0, 15))).AddTo(gameObject); // motionIndex.Subscribe( x => create(x) ).AddTo( gameObject ); void create(int motionIndex) { var ma = md.CreateAccessor(motionIndex); // ボーン&ストリーム var nowTime = Time.time; Entity boneTop; using (var boneEntities = new NativeArray <Entity>(ma.boneLength, Allocator.Temp)) using (var streamEntities = new NativeArray <Entity>(ma.boneLength * 2, Allocator.Temp)) { em.CreateEntity(boneArch, boneEntities); em.CreateEntity(streamArch, streamEntities); boneTop = boneEntities[0]; Enumerable.Zip(boneEntities, streamEntities.Buffer(2), (bone, streams) => (bone, streams)) .ForEach((ents, ibone) => { var parentIndex = ma.GetParentBoneIndex(ibone); var siblingIndex = ibone + 1; em.SetComponentData(ents.bone, new BoneEntityLinkData { Self = ents.bone, Sibling = siblingIndex <ma.boneLength?boneEntities[siblingIndex] : Entity.Null, Parent = parentIndex> -1 ? boneEntities[parentIndex] : Entity.Null, positionEntity = ents.streams[0], rotationEntity = ents.streams[1], ParentIndex = parentIndex, // } ); em.SetComponentData(ents.bone, new BoneIndexData { Index = ibone, ParentIndex = parentIndex, } ); em.SetComponentData(ents.bone, new DrawBoneTargetLabel { drawingOrder = drawOrderId, boneIndex = ibone, } ); //em.SetComponentData( ents.bone, // new BonePostureData // { // boneSerialIndex = boneSerialIndex++,// // boneIndex = ibone, // parentBoneIndex = parentIndex// // } //); // em.AddComponentData( ents.streams[0], new StreamInitialData() ); // if( ibone != 0 ) em.AddComponentData( ents.streams[0], new StreamInitialDataFor1pos() ); createStreamSectionEntity(KeyStreamSection.positions, 0.1f); createStreamSectionEntity(KeyStreamSection.rotations, 0.1f); void createStreamSectionEntity(KeyStreamSection streamSection, float timeScale) { // em.AddComponentData( ents.streams[(int)streamSection], new StreamInitialData() ); em.SetComponentData(ents.streams[(int)streamSection], new StreamKeyShiftData { Self = ents.streams[(int)streamSection], Keys = ma.GetStreamSlice(ibone, streamSection).Stream } ); em.SetComponentData(ents.streams[(int)streamSection], new StreamNearKeysCacheData { TimeLength = ma.TimeLength, TimeScale = 0.1f } ); } }); } // モーション var motionEntity = em.CreateEntity(motionArch); // em.AddComponent( motionEntity, typeof(MotionInitializeData) ); em.AddComponentData <DrawTargetLabel>(motionEntity, new DrawTargetLabel { orderId = drawOrderId++ } ); em.SetComponentData <MotionComponentData>(motionEntity, new MotionComponentData { MotionIndex = motionIndex, DataAccessor = ma, Self = motionEntity, BoneTop = boneTop } ); em.SetComponentData <MotionInitializeData>(motionEntity, new MotionInitializeData { Self = motionEntity, BoneArche = boneArch, StreamArche = streamArch } ); } this.motionData = md; //await this.OnDestroyAsObservable(); }