static sfx_t *S_FindName(const char *name, bool create) { guard(S_FindName); int i; sfx_t *sfx; if (!name) appError("NULL name\n"); if (!name[0]) appError("empty name\n"); if (strlen(name) >= MAX_QPATH) appError("Sound name too long: %s", name); TString<MAX_QPATH> Filename; Filename.filename(name); // see if already loaded for (i = 0, sfx = known_sfx; i < num_sfx; i++, sfx++) if (sfx->Name == Filename) return sfx; if (!create) return NULL; // find a free sfx for (i = 0, sfx = known_sfx; i < num_sfx; i++, sfx++) if (!sfx->Name[0]) break; if (i == num_sfx) { // not found if (num_sfx == MAX_SFX) { #if 0 appError("too much sfx records"); #else Com_DPrintf("too much sfx records\n"); return NULL; #endif } // alloc next free record num_sfx++; } memset(sfx, 0, sizeof(*sfx)); sfx->Name = Filename; sfx->registration_sequence = s_registration_sequence; return sfx; unguard; }
static void appDecompressLZX(byte *CompressedBuffer, int CompressedSize, byte *UncompressedBuffer, int UncompressedSize) { guard(appDecompressLZX); // setup streams mspack_file src, dst; src.buf = CompressedBuffer; src.bufSize = CompressedSize; src.pos = 0; src.rest = 0; dst.buf = UncompressedBuffer; dst.bufSize = UncompressedSize; dst.pos = 0; // prepare decompressor lzxd_stream *lzxd = lzxd_init(&lzxSys, &src, &dst, 17, 0, 256*1024, UncompressedSize); assert(lzxd); // decompress int r = lzxd_decompress(lzxd, UncompressedSize); if (r != MSPACK_ERR_OK) appError("lzxd_decompress(%d,%d) returned %d", CompressedSize, UncompressedSize, r); // free resources lzxd_free(lzxd); unguard; }
static sfx_t *S_AliasName(const char *aliasname, const char *truename) { guard(S_AliasName); // find a free sfx sfx_t *sfx; int i; for (i = 0, sfx = known_sfx; i < num_sfx; i++, sfx++) if (!sfx->Name[0]) break; if (i == num_sfx) { if (num_sfx == MAX_SFX) { #if 0 appError("too much sfx records"); #else Com_DPrintf("too much sfx records\n"); return NULL; #endif } num_sfx++; } memset(sfx, 0, sizeof(*sfx)); sfx->Name.filename(aliasname); sfx->TrueName = truename; sfx->registration_sequence = s_registration_sequence; return sfx; unguard; }
void UMeshAnimation::SerializeSCell(FArchive &Ar) { guard(SerializeSCell); // for logic of track decompression check UMeshAnimation::Moves() function int OldCompression = 0, CompressType = 0; TArray<MotionChunkFixedPoint> T0; // OldCompression!=0, CompressType=0 TArray<MotionChunkCompress<Quat16Track> > T1; // CompressType=1 TArray<MotionChunkCompress<FixPosTrack> > T2; // CompressType=2 TArray<MotionChunkCompress<FixTimeTrack> > T3; // CompressType=3 TArray<MotionChunkCompress<FixPosTimeTrack> > T4; // CompressType=4 if (Version >= 1000) { Ar << OldCompression << T0; // note: this compression type is not supported (absent BoneIndices in MotionChunkFixedPoint) } if (Version >= 2000) { Ar << CompressType << T1 << T2 << T3 << T4; // decompress motion if (CompressType) { int i = 0, Count = 1; while (i < Count) { MotionChunkCompressBase *M = NULL; switch (CompressType) { case 1: Count = T1.Num(); M = &T1[i]; break; case 2: Count = T2.Num(); M = &T2[i]; break; case 3: Count = T3.Num(); M = &T3[i]; break; case 4: Count = T4.Num(); M = &T4[i]; break; default: appError("Unsupported CompressType: %d", CompressType); } if (!Count) { appNotify("CompressType=%d with no tracks", CompressType); break; } if (!i) { // 1st iteration, prepare Moves[] array Moves.Empty(Count); Moves.AddZeroed(Count); } // decompress current track M->Decompress(Moves[i]); // next track i++; } } } // if (OldCompression) appNotify("OldCompression=%d", OldCompression, CompressType); unguard; }
FArchive& operator<<(FArchive &Ar, FCompactIndex &I) { #if UNREAL3 if (Ar.Engine() >= GAME_UE3) appError("FCompactIndex is missing in UE3"); #endif if (Ar.IsLoading) { byte b; Ar << b; int sign = b & 0x80; // sign bit int shift = 6; int r = b & 0x3F; if (b & 0x40) // has 2nd byte { do { Ar << b; r |= (b & 0x7F) << shift; shift += 7; } while (b & 0x80); // has more bytes } I.Value = sign ? -r : r; } else { int v = I.Value; byte b = 0; if (v < 0) { v = -v; b |= 0x80; // sign } b |= v & 0x3F; if (v <= 0x3F) { Ar << b; } else { b |= 0x40; // has 2nd byte v >>= 6; Ar << b; assert(v); while (v) { b = v & 0x7F; v >>= 7; if (v) b |= 0x80; // has more bytes Ar << b; } } } return Ar; }
static menuCommon_t *GetItem(menuFramework_t *menu, int index) { int i; menuCommon_t *item; for (i = 0, item = menu->itemList; i < index && item; i++, item = item->next) ; if (!item) appError("GetMenuItem: item index %d is out of bounds %d\n", index, menu->nitems); return item; }
static void SortBoneArray(CBoneProxy *Parent, int NumBones) { for (int i = 0; i < NumBones; i++) { CBoneProxy *Bone = &Bones[i]; if (Bone->Parent == Parent) { if (NumSortedBones >= NumBones) appError("Loop in skeleton"); SortedBones[NumSortedBones++] = Bone; SortBoneArray(Bone, NumBones); } } }
void SetApp::mouseReleaseEvent ( QMouseEvent * event ) { qDebug() <<"mr" ; //进入应用程序管理状态后,再次点击鼠标会崩溃 //apptimer的释放问题 if(appTimer != NULL && appTimer->isActive()) { appTimer->stop(); delete appTimer; appTimer = NULL; } if(appManagerStatus == true && readyRun == true) { qDebug() << "delete " << appName << "?"; uninstallAppMessageBox(); } else { if(readyRun == true) { qDebug() << "start up "<< appName; if (appStatus == 1) { qDebug() << "app is running!"; }else{ appProcess = new QProcess(); appProcess->start(appFullPath); appProcess->setWorkingDirectory(appWorkingDirectory); connect(appProcess,SIGNAL(started()),this,SLOT(appRunning())); connect(appProcess,SIGNAL(finished(int)),this,SLOT(appExiting())); connect(appProcess,SIGNAL(destroyed()),this,SLOT(appClear())); connect(appProcess,SIGNAL(error(QProcess::ProcessError)),this,SLOT(appError())); qDebug() << appProcess; } } }
int main(int argc, char **argv) { int i; struct timeval startTime, endTime; if (argc != 3) usage(argv[0]); // Record start of total time gettimeofday(&startTime, NULL); // Initialize global variables and data-structures. P = atoi(argv[1]); initialize(argv[2], &cells, &constraints); nodeCount = 0; found = 0; jobQueues = (job_queue_t*)calloc(sizeof(job_queue_t), P); if (!jobQueues) unixError("Failed to allocated memory for the job queues"); for (i = 0; i < P; i++) omp_init_lock(&(jobQueues[i].headLock)); // Add initial job (nothing assigned) to root processor jobQueues[0].tail = 1; runParallel(P); if (!found) appError("No solution found"); // Use final time to calculate total time gettimeofday(&endTime, NULL); totalTime = TIME_DIFF(endTime, startTime); // Print out number of nodes visited and calculated times printf("Nodes Visited: %lld\n", nodeCount); printf("Computation Time = %.3f millisecs\n", compTime); printf(" Total Time = %.3f millisecs\n", totalTime); return 0; }
void GL_SetMultitexture(int level) { int i; if (level > gl_config.maxActiveTextures) appError("R_SetMultitexture(%d > %d)", level, gl_config.maxActiveTextures); if (gl_state.locked) { for (i = 0; i < gl_config.maxActiveTextures; i++) if (i < level) { gl_state.newTexCoordEnabled[i] = true; } else { gl_state.newTexCoordEnabled[i] = false; gl_state.newTextureTarget[i] = 0; } return; } for (i = level; i < gl_config.maxActiveTextures; i++) if (gl_state.textureTarget[i] || gl_state.texCoordEnabled[i]) { GL_SelectTexture(i); GL_Bind(NULL); if (gl_state.texCoordEnabled[i]) { glDisableClientState(GL_TEXTURE_COORD_ARRAY); gl_state.texCoordEnabled[i] = false; } } for (i = level - 1; i >= 0; i--) if (!gl_state.texCoordEnabled[i]) { GL_SelectTexture(i); glEnableClientState(GL_TEXTURE_COORD_ARRAY); gl_state.texCoordEnabled[i] = true; } GL_SelectTexture(0); }
void GL_CheckError(const char *msg) { GLenum err = glGetError(); if (!err) return; appError("%s error %X", msg ? msg : "OpenGL", err); }
int UE4UnversionedPackage(int verMin, int verMax) { appError("Unversioned UE4 packages are not supported. Please restart UModel and select UE4 version in range %d-%d using UI or command line.", verMin, verMax); return -1; }
int appDecompress(byte *CompressedBuffer, int CompressedSize, byte *UncompressedBuffer, int UncompressedSize, int Flags) { guard(appDecompress); #if BLADENSOUL if (GForceGame == GAME_BladeNSoul && Flags == COMPRESS_LZO_ENC) // note: GForceGame is required (to not pass 'Game' here) { if (CompressedSize >= 32) { static const char *key = "qiffjdlerdoqymvketdcl0er2subioxq"; for (int i = 0; i < CompressedSize; i++) CompressedBuffer[i] ^= key[i % 32]; } // overide compression Flags = COMPRESS_LZO; } #endif // BLADENSOUL #if TAO_YUAN if (GForceGame == GAME_TaoYuan) // note: GForceGame is required (to not pass 'Game' here); { static const byte key[] = { 137, 35, 95, 142, 69, 136, 243, 119, 25, 35, 111, 94, 101, 136, 243, 204, 243, 67, 95, 158, 69, 106, 107, 187, 237, 35, 103, 142, 72, 142, 243 }; for (int i = 0; i < CompressedSize; i++) CompressedBuffer[i] ^= key[i % 31]; // note: "N % 31" is not the same as "N & 0x1F" } #endif // TAO_YUAN #if ALICE // this code exists in Alice: Madness Returns only if (GForceGame == GAME_Alice && CompressedSize == UncompressedSize) { // CompressedSize == UncompressedSize -> no compression memcpy(UncompressedBuffer, CompressedBuffer, UncompressedSize); return UncompressedSize; } #endif // ALICE if (Flags == COMPRESS_FIND && CompressedSize >= 2) { byte b1 = CompressedBuffer[0]; byte b2 = CompressedBuffer[1]; // detect compression // zlib: // http://tools.ietf.org/html/rfc1950 // http://stackoverflow.com/questions/9050260/what-does-a-zlib-header-look-like if ( b1 == 0x78 && // b1=CMF: 7=32k buffer (CINFO), 8=deflate (CM) (b2 == 0x9C || b2 == 0xDA) ) // b2=FLG { Flags = COMPRESS_ZLIB; } else Flags = COMPRESS_LZO; } if (Flags == COMPRESS_LZO) { int r; r = lzo_init(); if (r != LZO_E_OK) appError("lzo_init() returned %d", r); lzo_uint newLen = UncompressedSize; r = lzo1x_decompress_safe(CompressedBuffer, CompressedSize, UncompressedBuffer, &newLen, NULL); if (r != LZO_E_OK) appError("lzo_decompress(%d,%d) returned %d", CompressedSize, UncompressedSize, r); if (newLen != UncompressedSize) appError("len mismatch: %d != %d", newLen, UncompressedSize); return newLen; } if (Flags == COMPRESS_ZLIB) { #if 0 appError("appDecompress: Zlib compression is not supported"); #else unsigned long newLen = UncompressedSize; int r = uncompress(UncompressedBuffer, &newLen, CompressedBuffer, CompressedSize); if (r != Z_OK) appError("zlib uncompress(%d,%d) returned %d", CompressedSize, UncompressedSize, r); // if (newLen != UncompressedSize) appError("len mismatch: %d != %d", newLen, UncompressedSize); -- needed by Bioshock return newLen; #endif } if (Flags == COMPRESS_LZX) { #if SUPPORT_XBOX360 # if !USE_XDK appDecompressLZX(CompressedBuffer, CompressedSize, UncompressedBuffer, UncompressedSize); return UncompressedSize; # else void *context; int r; r = XMemCreateDecompressionContext(0, NULL, 0, &context); if (r < 0) appError("XMemCreateDecompressionContext failed"); unsigned int newLen = UncompressedSize; r = XMemDecompress(context, UncompressedBuffer, &newLen, CompressedBuffer, CompressedSize); if (r < 0) appError("XMemDecompress failed"); if (newLen != UncompressedSize) appError("len mismatch: %d != %d", newLen, UncompressedSize); XMemDestroyDecompressionContext(context); return newLen; # endif // USE_XDK #else // SUPPORT_XBOX360 appError("appDecompress: LZX compression is not supported"); #endif // SUPPORT_XBOX360 } appError("appDecompress: unknown compression flags: %d", Flags); return 0; unguardf("CompSize=%d UncompSize=%d Flags=0x%X", CompressedSize, UncompressedSize, Flags); }
void USkeleton::ConvertAnims(UAnimSequence4* Seq) { guard(USkeleton::ConvertAnims); CAnimSet* AnimSet = ConvertedAnim; if (!AnimSet) { AnimSet = new CAnimSet(this); ConvertedAnim = AnimSet; // Copy bone names AnimSet->TrackBoneNames.Empty(ReferenceSkeleton.RefBoneInfo.Num()); for (int i = 0; i < ReferenceSkeleton.RefBoneInfo.Num(); i++) { AnimSet->TrackBoneNames.Add(ReferenceSkeleton.RefBoneInfo[i].Name); } //TODO: verify if UE4 has AnimRotationOnly stuff AnimSet->AnimRotationOnly = false; } if (!Seq) return; // allow calling ConvertAnims(NULL) to create empty AnimSet // DBG("----------- Skeleton %s: %d seq, %d bones -----------\n", Name, Anims.Num(), ReferenceSkeleton.RefBoneInfo.Num()); int NumTracks = Seq->GetNumTracks(); #if DEBUG_DECOMPRESS appPrintf("Sequence %s: %d bones, %d offsets (%g per bone), %d frames, %d compressed data\n" " trans %s, rot %s, scale %s, key %s\n", Seq->Name, NumTracks, Seq->CompressedTrackOffsets.Num(), Seq->CompressedTrackOffsets.Num() / (float)NumTracks, Seq->NumFrames, Seq->CompressedByteStream.Num(), EnumToName(Seq->TranslationCompressionFormat), EnumToName(Seq->RotationCompressionFormat), EnumToName(Seq->ScaleCompressionFormat), EnumToName(Seq->KeyEncodingFormat) ); for (int i2 = 0; i2 < Seq->CompressedTrackOffsets.Num(); /*empty*/) { if (Seq->KeyEncodingFormat != AKF_PerTrackCompression) { FName BoneName = ReferenceSkeleton.RefBoneInfo[Seq->GetTrackBoneIndex(i2/4)].Name; int TransOffset = Seq->CompressedTrackOffsets[i2 ]; int TransKeys = Seq->CompressedTrackOffsets[i2+1]; int RotOffset = Seq->CompressedTrackOffsets[i2+2]; int RotKeys = Seq->CompressedTrackOffsets[i2+3]; appPrintf(" [%d] = trans %d[%d] rot %d[%d] - %s\n", i2/4, TransOffset, TransKeys, RotOffset, RotKeys, *BoneName); i2 += 4; } else { FName BoneName = ReferenceSkeleton.RefBoneInfo[Seq->GetTrackBoneIndex(i2/2)].Name; int TransOffset = Seq->CompressedTrackOffsets[i2 ]; int RotOffset = Seq->CompressedTrackOffsets[i2+1]; appPrintf(" [%d] = trans %d rot %d - %s\n", i2/2, TransOffset, RotOffset, *BoneName); i2 += 2; } } #endif // DEBUG_DECOMPRESS // some checks int offsetsPerBone = 4; if (Seq->KeyEncodingFormat == AKF_PerTrackCompression) offsetsPerBone = 2; if (Seq->CompressedTrackOffsets.Num() != NumTracks * offsetsPerBone && !Seq->RawAnimationData.Num()) { appNotify("AnimSequence %s has wrong CompressedTrackOffsets size (has %d, expected %d), removing track", Seq->Name, Seq->CompressedTrackOffsets.Num(), NumTracks * offsetsPerBone); return; } // create CAnimSequence CAnimSequence *Dst = new CAnimSequence; AnimSet->Sequences.Add(Dst); Dst->Name = Seq->Name; Dst->NumFrames = Seq->NumFrames; Dst->Rate = Seq->NumFrames / Seq->SequenceLength * Seq->RateScale; // bone tracks ... Dst->Tracks.Empty(NumTracks); FMemReader Reader(Seq->CompressedByteStream.GetData(), Seq->CompressedByteStream.Num()); Reader.SetupFrom(*Package); bool HasTimeTracks = (Seq->KeyEncodingFormat == AKF_VariableKeyLerp); for (int BoneIndex = 0; BoneIndex < ReferenceSkeleton.RefBoneInfo.Num(); BoneIndex++) { CAnimTrack *A = new (Dst->Tracks) CAnimTrack; int TrackIndex = Seq->FindTrackForBoneIndex(BoneIndex); if (TrackIndex < 0) { // this track has no animation, use static pose from ReferenceSkeleton const FTransform& RefPose = ReferenceSkeleton.RefBonePose[BoneIndex]; A->KeyPos.Add(CVT(RefPose.Translation)); A->KeyQuat.Add(CVT(RefPose.Rotation)); //!! RefPose.Scale3D continue; } int k; if (!Seq->CompressedTrackOffsets.Num()) //?? or if RawAnimData.Num() != 0 { // using RawAnimData array assert(Seq->RawAnimationData.Num() == NumTracks); CopyArray(A->KeyPos, CVT(Seq->RawAnimationData[TrackIndex].PosKeys)); CopyArray(A->KeyQuat, CVT(Seq->RawAnimationData[TrackIndex].RotKeys)); CopyArray(A->KeyTime, Seq->RawAnimationData[TrackIndex].KeyTimes); // may be empty for (int k = 0; k < A->KeyTime.Num(); k++) A->KeyTime[k] *= Dst->Rate; continue; } FVector Mins, Ranges; // common ... static const CVec3 nullVec = { 0, 0, 0 }; static const CQuat nullQuat = { 0, 0, 0, 1 }; int offsetIndex = TrackIndex * offsetsPerBone; // PARAGON has invalid data inside some animation tracks. Not sure if game engine ignores them // or trying to process (this game has holes in data due to wrong pointers in CompressedTrackOffsets). // This causes garbage data to appear instead of real animation track header, with wrong compression // method etc. We're going to skip such tracks with displaying a warning message. if (0) // this is just a placeholder for error handler - it should be located somewhere { track_error: AnimSet->Sequences.RemoveSingle(Dst); delete Dst; return; } //---------------------------------------------- // decode AKF_PerTrackCompression data //---------------------------------------------- if (Seq->KeyEncodingFormat == AKF_PerTrackCompression) { // this format uses different key storage guard(PerTrackCompression); assert(Seq->TranslationCompressionFormat == ACF_Identity); assert(Seq->RotationCompressionFormat == ACF_Identity); int TransOffset = Seq->CompressedTrackOffsets[offsetIndex ]; int RotOffset = Seq->CompressedTrackOffsets[offsetIndex+1]; uint32 PackedInfo; AnimationCompressionFormat KeyFormat; int ComponentMask; int NumKeys; #define DECODE_PER_TRACK_INFO(info) \ KeyFormat = (AnimationCompressionFormat)(info >> 28); \ ComponentMask = (info >> 24) & 0xF; \ NumKeys = info & 0xFFFFFF; \ HasTimeTracks = (ComponentMask & 8) != 0; guard(TransKeys); // read translation keys if (TransOffset == -1) { A->KeyPos.Add(nullVec); DBG(" [%d] no translation data\n", TrackIndex); } else { Reader.Seek(TransOffset); Reader << PackedInfo; DECODE_PER_TRACK_INFO(PackedInfo); A->KeyPos.Empty(NumKeys); DBG(" [%d] trans: fmt=%d (%s), %d keys, mask %d\n", TrackIndex, KeyFormat, EnumToName(KeyFormat), NumKeys, ComponentMask ); if (KeyFormat == ACF_IntervalFixed32NoW) { // read mins/maxs Mins.Set(0, 0, 0); Ranges.Set(0, 0, 0); if (ComponentMask & 1) Reader << Mins.X << Ranges.X; if (ComponentMask & 2) Reader << Mins.Y << Ranges.Y; if (ComponentMask & 4) Reader << Mins.Z << Ranges.Z; } for (k = 0; k < NumKeys; k++) { switch (KeyFormat) { // case ACF_None: case ACF_Float96NoW: { FVector v; if (ComponentMask & 7) { v.Set(0, 0, 0); if (ComponentMask & 1) Reader << v.X; if (ComponentMask & 2) Reader << v.Y; if (ComponentMask & 4) Reader << v.Z; } else { // ACF_Float96NoW has a special case for ((ComponentMask & 7) == 0) Reader << v; } A->KeyPos.Add(CVT(v)); } break; TPR(ACF_IntervalFixed32NoW, FVectorIntervalFixed32) case ACF_Fixed48NoW: { uint16 X, Y, Z; CVec3 v; v.Set(0, 0, 0); if (ComponentMask & 1) { Reader << X; v[0] = DecodeFixed48_PerTrackComponent<7>(X); } if (ComponentMask & 2) { Reader << Y; v[1] = DecodeFixed48_PerTrackComponent<7>(Y); } if (ComponentMask & 4) { Reader << Z; v[2] = DecodeFixed48_PerTrackComponent<7>(Z); } A->KeyPos.Add(v); } break; case ACF_Identity: A->KeyPos.Add(nullVec); break; default: { char buf[1024]; Seq->GetFullName(buf, 1024); appNotify("%s: unknown translation compression method: %d (%s) - dropping track", buf, KeyFormat, EnumToName(KeyFormat)); goto track_error; } } } // align to 4 bytes Reader.Seek(Align(Reader.Tell(), 4)); if (HasTimeTracks) ReadTimeArray(Reader, NumKeys, A->KeyPosTime, Seq->NumFrames); } unguard; guard(RotKeys); // read rotation keys if (RotOffset == -1) { A->KeyQuat.Add(nullQuat); DBG(" [%d] no rotation data\n", TrackIndex); } else { Reader.Seek(RotOffset); Reader << PackedInfo; DECODE_PER_TRACK_INFO(PackedInfo); A->KeyQuat.Empty(NumKeys); DBG(" [%d] rot : fmt=%d (%s), %d keys, mask %d\n", TrackIndex, KeyFormat, EnumToName(KeyFormat), NumKeys, ComponentMask ); if (KeyFormat == ACF_IntervalFixed32NoW) { // read mins/maxs Mins.Set(0, 0, 0); Ranges.Set(0, 0, 0); if (ComponentMask & 1) Reader << Mins.X << Ranges.X; if (ComponentMask & 2) Reader << Mins.Y << Ranges.Y; if (ComponentMask & 4) Reader << Mins.Z << Ranges.Z; } for (k = 0; k < NumKeys; k++) { switch (KeyFormat) { // TR (ACF_None, FQuat) case ACF_Float96NoW: { FQuatFloat96NoW q; Reader << q; FQuat q2 = q; // convert A->KeyQuat.Add(CVT(q2)); } break; case ACF_Fixed48NoW: { FQuatFixed48NoW q; q.X = q.Y = q.Z = 32767; // corresponds to 0 if (ComponentMask & 1) Reader << q.X; if (ComponentMask & 2) Reader << q.Y; if (ComponentMask & 4) Reader << q.Z; FQuat q2 = q; // convert A->KeyQuat.Add(CVT(q2)); } break; TR (ACF_Fixed32NoW, FQuatFixed32NoW) TRR(ACF_IntervalFixed32NoW, FQuatIntervalFixed32NoW) TR (ACF_Float32NoW, FQuatFloat32NoW) case ACF_Identity: A->KeyQuat.Add(nullQuat); break; default: { char buf[1024]; Seq->GetFullName(buf, 1024); appNotify("%s: unknown rotation compression method: %d (%s) - dropping track", buf, KeyFormat, EnumToName(KeyFormat)); goto track_error; } } } // align to 4 bytes Reader.Seek(Align(Reader.Tell(), 4)); if (HasTimeTracks) ReadTimeArray(Reader, NumKeys, A->KeyQuatTime, Seq->NumFrames); } unguard; unguard; continue; // end of AKF_PerTrackCompression block ... } //---------------------------------------------- // end of AKF_PerTrackCompression decoder //---------------------------------------------- // read animations int TransOffset = Seq->CompressedTrackOffsets[offsetIndex ]; int TransKeys = Seq->CompressedTrackOffsets[offsetIndex+1]; int RotOffset = Seq->CompressedTrackOffsets[offsetIndex+2]; int RotKeys = Seq->CompressedTrackOffsets[offsetIndex+3]; // appPrintf("[%d:%d:%d] : %d[%d] %d[%d] %d[%d]\n", j, Seq->RotationCompressionFormat, Seq->TranslationCompressionFormat, TransOffset, TransKeys, RotOffset, RotKeys, ScaleOffset, ScaleKeys); A->KeyPos.Empty(TransKeys); A->KeyQuat.Empty(RotKeys); // read translation keys if (TransKeys) { Reader.Seek(TransOffset); AnimationCompressionFormat TranslationCompressionFormat = Seq->TranslationCompressionFormat; if (TransKeys == 1) TranslationCompressionFormat = ACF_None; // single key is stored without compression // read mins/ranges if (TranslationCompressionFormat == ACF_IntervalFixed32NoW) { Reader << Mins << Ranges; } for (k = 0; k < TransKeys; k++) { switch (TranslationCompressionFormat) { TP (ACF_None, FVector) TP (ACF_Float96NoW, FVector) TPR(ACF_IntervalFixed32NoW, FVectorIntervalFixed32) TP (ACF_Fixed48NoW, FVectorFixed48) case ACF_Identity: A->KeyPos.Add(nullVec); break; default: appError("Unknown translation compression method: %d (%s)", TranslationCompressionFormat, EnumToName(TranslationCompressionFormat)); } } // align to 4 bytes Reader.Seek(Align(Reader.Tell(), 4)); if (HasTimeTracks) ReadTimeArray(Reader, TransKeys, A->KeyPosTime, Seq->NumFrames); } else { // A->KeyPos.Add(nullVec); // appNotify("No translation keys!"); }
static bool RegisterGameFile(const char *FullName, FVirtualFileSystem* parentVfs = NULL) { guard(RegisterGameFile); // printf("..file %s\n", FullName); // return false when MAX_GAME_FILES if (GNumGameFiles >= ARRAY_COUNT(GameFiles)) return false; if (!parentVfs) // no nested VFSs { const char* ext = strrchr(FullName, '.'); if (ext) { guard(MountVFS); ext++; FVirtualFileSystem* vfs = NULL; FArchive* reader = NULL; #if SUPPORT_ANDROID if (!stricmp(ext, "obb")) { GForcePlatform = PLATFORM_ANDROID; reader = new FFileReader(FullName); if (!reader) return true; reader->Game = GAME_UE3; vfs = new FObbVFS(); } #endif // SUPPORT_ANDROID #if UNREAL4 if (!stricmp(ext, "pak")) { reader = new FFileReader(FullName); if (!reader) return true; reader->Game = GAME_UE4; vfs = new FPakVFS(); //!! detect game by file name } #endif // UNREAL4 //!! process other VFS types here if (vfs) { assert(reader); // read VF directory if (!vfs->AttachReader(reader)) { // something goes wrong delete vfs; delete reader; return true; } // add game files int NumVFSFiles = vfs->NumFiles(); for (int i = 0; i < NumVFSFiles; i++) { if (!RegisterGameFile(vfs->FileName(i), vfs)) return false; } return true; } unguard; } } bool IsPackage; if (FindExtension(FullName, ARRAY_ARG(PackageExtensions))) { IsPackage = true; } else { #if HAS_SUPORT_FILES if (!FindExtension(FullName, ARRAY_ARG(KnownExtensions))) #endif { // perhaps this file was exported by our tool - skip it if (FindExtension(FullName, ARRAY_ARG(SkipExtensions))) return true; // unknown file type if (++GNumForeignFiles >= MAX_FOREIGN_FILES) appError("Too much unknown files - bad root directory (%s)?", RootDirectory); return true; } IsPackage = false; } // create entry CGameFileInfo *info = new CGameFileInfo; GameFiles[GNumGameFiles++] = info; info->IsPackage = IsPackage; info->FileSystem = parentVfs; if (IsPackage) GNumPackageFiles++; if (!parentVfs) { // regular file FILE* f = fopen(FullName, "rb"); if (f) { fseek(f, 0, SEEK_END); info->SizeInKb = (ftell(f) + 512) / 1024; fclose(f); } else { info->SizeInKb = 0; } // cut RootDirectory from filename const char *s = FullName + strlen(RootDirectory) + 1; assert(s[-1] == '/'); appStrncpyz(info->RelativeName, s, ARRAY_COUNT(info->RelativeName)); } else { // file in virtual file system info->SizeInKb = parentVfs->GetFileSize(FullName); appStrncpyz(info->RelativeName, FullName, ARRAY_COUNT(info->RelativeName)); } // find filename const char* s = strrchr(info->RelativeName, '/'); if (s) s++; else s = info->RelativeName; info->ShortFilename = s; // find extension s = strrchr(info->ShortFilename, '.'); if (s) s++; info->Extension = s; // printf(".. -> %s (pkg=%d)\n", info->ShortFilename, info->IsPackage); #if UNREAL3 if (info->IsPackage && (strnicmp(info->ShortFilename, "startup", 7) == 0)) { // Register a startup package // possible name variants: // - startup // - startup_int // - startup_* int startupWeight = 0; if (info->ShortFilename[7] == '.') startupWeight = 30; // "startup.upk" else if (strnicmp(info->ShortFilename+7, "_int.", 5) == 0) startupWeight = 20; // "startup_int.upk" else if (strnicmp(info->ShortFilename+7, "_loc_int.", 9) == 0) startupWeight = 20; // "startup_int.upk" else if (info->ShortFilename[7] == '_') startupWeight = 1; // non-int locale, lower priority - use if when other is not detected if (startupWeight > GStartupPackageInfoWeight) { GStartupPackageInfoWeight = startupWeight; GStartupPackageInfo = info; } } #endif // UNREAL3 // insert CGameFileInfo into hash table int hash = GetHashForFileName(info->ShortFilename); info->HashNext = GGameFileHash[hash]; GGameFileHash[hash] = info; return true; unguardf("%s", FullName); }
static void ExportSection(ExportContext& Context, const CBaseMeshLod& Lod, const CMeshVertex* Verts, int SectonIndex, FArchive& Ar) { guard(ExportSection); int VertexSize = Context.IsSkeletal() ? sizeof(CSkelMeshVertex) : sizeof(CStaticMeshVertex); const CMeshSection& S = Lod.Sections[SectonIndex]; bool bLast = (SectonIndex == Lod.Sections.Num()-1); // Remap section indices to local indices CIndexBuffer::IndexAccessor_t GetIndex = Lod.Indices.GetAccessor(); TArray<int> indexRemap; // old vertex index -> new vertex index indexRemap.Init(-1, Lod.NumVerts); int numLocalVerts = 0; int numLocalIndices = S.NumFaces * 3; for (int idx = 0; idx < numLocalIndices; idx++) { int vertIndex = GetIndex(S.FirstIndex + idx); if (indexRemap[vertIndex] == -1) { indexRemap[vertIndex] = numLocalVerts++; } } // Prepare buffers int IndexBufIndex = Context.Data.AddZeroed(); int PositionBufIndex = Context.Data.AddZeroed(); int NormalBufIndex = Context.Data.AddZeroed(); int TangentBufIndex = Context.Data.AddZeroed(); int BonesBufIndex = -1; int WeightsBufIndex = -1; if (Context.IsSkeletal()) { BonesBufIndex = Context.Data.AddZeroed(); WeightsBufIndex = Context.Data.AddZeroed(); } int UVBufIndex[MAX_MESH_UV_SETS]; for (int i = 0; i < Lod.NumTexCoords; i++) { UVBufIndex[i] = Context.Data.AddZeroed(); } BufferData& IndexBuf = Context.Data[IndexBufIndex]; BufferData& PositionBuf = Context.Data[PositionBufIndex]; BufferData& NormalBuf = Context.Data[NormalBufIndex]; BufferData& TangentBuf = Context.Data[TangentBufIndex]; BufferData* UVBuf[MAX_MESH_UV_SETS]; BufferData* BonesBuf = NULL; BufferData* WeightsBuf = NULL; PositionBuf.Setup(numLocalVerts, "VEC3", BufferData::FLOAT, sizeof(CVec3)); NormalBuf.Setup(numLocalVerts, "VEC3", BufferData::FLOAT, sizeof(CVec3)); TangentBuf.Setup(numLocalVerts, "VEC4", BufferData::FLOAT, sizeof(CVec4)); for (int i = 0; i < Lod.NumTexCoords; i++) { UVBuf[i] = &Context.Data[UVBufIndex[i]]; UVBuf[i]->Setup(numLocalVerts, "VEC2", BufferData::FLOAT, sizeof(CMeshUVFloat)); } if (Context.IsSkeletal()) { BonesBuf = &Context.Data[BonesBufIndex]; WeightsBuf = &Context.Data[WeightsBufIndex]; BonesBuf->Setup(numLocalVerts, "VEC4", BufferData::UNSIGNED_SHORT, sizeof(uint16)*4); WeightsBuf->Setup(numLocalVerts, "VEC4", BufferData::UNSIGNED_BYTE, sizeof(uint32), /*InNormalized=*/ true); } // Prepare and build indices TArray<int> localIndices; localIndices.AddUninitialized(numLocalIndices); int* pIndex = localIndices.GetData(); for (int i = 0; i < numLocalIndices; i++) { *pIndex++ = GetIndex(S.FirstIndex + i); } if (numLocalVerts <= 65536) { IndexBuf.Setup(numLocalIndices, "SCALAR", BufferData::UNSIGNED_SHORT, sizeof(uint16)); for (int idx = 0; idx < numLocalIndices; idx++) { IndexBuf.Put<uint16>(indexRemap[localIndices[idx]]); } } else { IndexBuf.Setup(numLocalIndices, "SCALAR", BufferData::UNSIGNED_INT, sizeof(uint32)); for (int idx = 0; idx < numLocalIndices; idx++) { IndexBuf.Put<uint32>(indexRemap[localIndices[idx]]); } } // Build reverse index map for fast lookup of vertex by its new index. // It maps new vertex index to old vertex index. TArray<int> revIndexMap; revIndexMap.AddUninitialized(numLocalVerts); for (int i = 0; i < indexRemap.Num(); i++) { int newIndex = indexRemap[i]; if (newIndex != -1) { revIndexMap[newIndex] = i; } } // Build vertices for (int i = 0; i < numLocalVerts; i++) { int vertIndex = revIndexMap[i]; const CMeshVertex& V = VERT(vertIndex); CVec3 Position = V.Position; CVec4 Normal, Tangent; Unpack(Normal, V.Normal); Unpack(Tangent, V.Tangent); // Unreal (and we are) using normal.w for computing binormal. glTF // uses tangent.w for that. Make this value exactly 1.0 of -1.0 to make glTF // validator happy. #if 0 // There's some problem: V.Normal.W == 0x80 -> -1.008 instead of -1.0 if (Normal.w > 1.001 || Normal.w < -1.001) { appError("%X -> %g\n", V.Normal.Data, Normal.w); } #endif Tangent.w = (Normal.w < 0) ? -1 : 1; TransformPosition(Position); TransformDirection(Normal); TransformDirection(Tangent); Normal.Normalize(); Tangent.Normalize(); // Fill buffers PositionBuf.Put(Position); NormalBuf.Put(Normal.xyz); TangentBuf.Put(Tangent); UVBuf[0]->Put(V.UV); } // Compute bounds for PositionBuf CVec3 Mins, Maxs; ComputeBounds((CVec3*)PositionBuf.Data, numLocalVerts, sizeof(CVec3), Mins, Maxs); char buf[256]; appSprintf(ARRAY_ARG(buf), "[ %g, %g, %g ]", VECTOR_ARG(Mins)); PositionBuf.BoundsMin = buf; appSprintf(ARRAY_ARG(buf), "[ %g, %g, %g ]", VECTOR_ARG(Maxs)); PositionBuf.BoundsMax = buf; if (Context.IsSkeletal()) { for (int i = 0; i < numLocalVerts; i++) { int vertIndex = revIndexMap[i]; const CMeshVertex& V0 = VERT(vertIndex); const CSkelMeshVertex& V = static_cast<const CSkelMeshVertex&>(V0); int16 Bones[NUM_INFLUENCES]; static_assert(NUM_INFLUENCES == 4, "Code designed for 4 influences"); static_assert(sizeof(Bones) == sizeof(V.Bone), "Unexpected V.Bones size"); memcpy(Bones, V.Bone, sizeof(Bones)); for (int j = 0; j < NUM_INFLUENCES; j++) { // We have INDEX_NONE as list terminator, should replace with something else for glTF if (Bones[j] == INDEX_NONE) { Bones[j] = 0; } } BonesBuf->Put(*(uint64*)&Bones); WeightsBuf->Put(V.PackedWeights); } } // Secondary UVs for (int uvIndex = 1; uvIndex < Lod.NumTexCoords; uvIndex++) { BufferData* pBuf = UVBuf[uvIndex]; const CMeshUVFloat* srcUV = Lod.ExtraUV[uvIndex-1]; for (int i = 0; i < numLocalVerts; i++) { int vertIndex = revIndexMap[i]; pBuf->Put(srcUV[vertIndex]); } } // Write primitive information to json Ar.Printf( " {\n" " \"attributes\" : {\n" " \"POSITION\" : %d,\n" " \"NORMAL\" : %d,\n" " \"TANGENT\" : %d,\n", PositionBufIndex, NormalBufIndex, TangentBufIndex ); if (Context.IsSkeletal()) { Ar.Printf( " \"JOINTS_0\" : %d,\n" " \"WEIGHTS_0\" : %d,\n", BonesBufIndex, WeightsBufIndex ); } for (int i = 0; i < Lod.NumTexCoords; i++) { Ar.Printf( " \"TEXCOORD_%d\" : %d%s\n", i, UVBufIndex[i], i < (Lod.NumTexCoords-1) ? "," : "" ); } Ar.Printf( " },\n" " \"indices\" : %d,\n" " \"material\" : %d\n" " }%s\n", IndexBufIndex, SectonIndex, SectonIndex < (Lod.Sections.Num()-1) ? "," : "" ); unguard; }
void* FArray::GetItem(int index, int elementSize) const { if (!IsValidIndex(index)) appError("TArray: index %d is out of range (%d)", index, DataCount); return OffsetPointer(DataPtr, index * elementSize); }