Example #1
0
UINT OBSAPIInterface::CreateHotkey(DWORD hotkey, OBSHOTKEYPROC hotkeyProc, UPARAM param)
{
    if(!hotkey)
        return 0;

    //FIXME: vk and fsModifiers aren't used?
    DWORD vk = LOBYTE(hotkey);
    DWORD modifier = HIBYTE(hotkey);
    DWORD fsModifiers = 0;

    if(modifier & HOTKEYF_ALT)
        fsModifiers |= MOD_ALT;
    if(modifier & HOTKEYF_CONTROL)
        fsModifiers |= MOD_CONTROL;
    if(modifier & HOTKEYF_SHIFT)
        fsModifiers |= MOD_SHIFT;

    OSEnterMutex(App->hHotkeyMutex);
    HotkeyInfo &hi      = *hotkeys.CreateNew();
    hi.hotkeyID         = ++curHotkeyIDVal;
    hi.hotkey           = hotkey;
    hi.hotkeyProc       = hotkeyProc;
    hi.param            = param;
    hi.bModifiersDown   = false;
    hi.bHotkeyDown      = false;
    OSLeaveMutex(App->hHotkeyMutex);

    return curHotkeyIDVal;
}
Example #2
0
    void SendPacket(BYTE *data, UINT size, DWORD timestamp, PacketType type)
    {
        ProcessDelayedPackets(timestamp);

        NetworkPacket *newPacket = delayedPackets.CreateNew();
        newPacket->data.CopyArray(data, size);
        newPacket->timestamp = timestamp;
        newPacket->type = type;

        lastTimestamp = timestamp;
    }
 void MergeProfileInfo(ProfileNodeInfo *info, DWORD rootLastCall, DWORD updatedLastCall)
 {
     bSingular = info->bSingular;
     numCalls += info->numCalls;
     if(lastCall == rootLastCall) lastCall = updatedLastCall;
     totalTimeElapsed += info->totalTimeElapsed;
     lastTimeElapsed = info->lastTimeElapsed;
     cpuTimeElapsed += info->cpuTimeElapsed;
     lastCpuTimeElapsed = info->lastCpuTimeElapsed;
     numParallelCalls = info->numParallelCalls;
     for(UINT i = 0; i < info->Children.Num(); i++)
     {
         ProfileNodeInfo &child = info->Children[i];
         ProfileNodeInfo *sumChild = FindSubProfile(child.lpName);
         if(!sumChild)
         {
             sumChild = Children.CreateNew();
             sumChild->lpName = child.lpName;
         }
         sumChild->MergeProfileInfo(&child, rootLastCall, updatedLastCall);
     }
 }
Example #4
0
void SkinMesh::LoadAnimations(CTSTR lpName)
{
    traceIn(SkinMesh::LoadAnimations);

    assert(lpName);

    DWORD i, j, k;

    String strMeshPath;
    if(!Engine::ConvertResourceName(lpName, TEXT("models"), strMeshPath))
        return;

    String strFilePath;
    strFilePath << GetPathWithoutExtension(strMeshPath) << TEXT(".xan");


    //-----------------------------------------------

    XFileInputSerializer animData;

    if(!animData.Open(strFilePath))
    {
        AppWarning(TEXT("Could not open animation file \"%s\""), (TSTR)strFilePath);
        return;
    }

    DWORD ver;
    animData << ver;

    if(ver != ANIMFILE_VER && ver != 0x100)
    {
        AppWarning(TEXT("'%s': Bad animation file version"), strFilePath);
        animData.Close();
        return;
    }

    //-----------------------------------------------

    unsigned int numSequences;
    animData << numSequences;
    SequenceList.SetSize(numSequences);
    for(i=0; i<numSequences; i++)
        animData << SequenceList[i];

    DWORD nBones;
    animData << nBones;
    BoneList.SetSize(nBones);
    for(i=0; i<nBones; i++)
    {
        Bone &bone = BoneList[i];

        List<DWORD>     RigidVerts;
        List<VWeight>   BlendedVerts;
        DWORD           nRigid, nBlended;

        //----------------------------

        animData << bone.Pos
                 << bone.Rot
                 << nRigid
                 << nBlended
                 << bone.flags
                 << bone.idParent;

        animData << RigidVerts;
        animData << BlendedVerts;

        if(bone.idParent != 0xFFFFFFFF)
        {
            bone.Parent = BoneList+bone.idParent;
            bone.LocalPos = bone.Pos - BoneList[bone.idParent].Pos;
            BoneList[bone.idParent].Children << &bone;
        }
        else
        {
            bone.Parent = NULL;
            bone.LocalPos = bone.Pos;

            bone.flags |= BONE_ROOT;
        }

        //----------------------------

        bone.Weights.SetSize(nRigid);

        for(j=0; j<RigidVerts.Num(); j++)
        {
            VWeight &weight = bone.Weights[j];

            weight.vert = RigidVerts[j];
            weight.weight = 1.0f;
        }

        bone.Weights.AppendList(BlendedVerts);

        //----------------------------

        DWORD nAnim;
        animData << nAnim;
        bone.seqKeys.SetSize(nAnim);
        for(j=0; j<nAnim; j++)
        {
            SeqKeys &keys = bone.seqKeys[j];

            DWORD nPosKeys, nRotKeys;

            //----------------------------
            
            animData << nRotKeys;
            keys.hasRotKeys = nRotKeys > 0;
            if(keys.hasRotKeys)
            {
                keys.lpRotKeys = (Quat*)Allocate(nRotKeys*sizeof(Quat));
                animData.Serialize(keys.lpRotKeys, nRotKeys*sizeof(Quat));

                keys.lpRotTans = (Quat*)Allocate(nRotKeys*sizeof(Quat));
                for(k=0; k<nRotKeys; k++)
                {
                    DWORD kp1 = (k == (nRotKeys-1)) ? k : (k+1);
                    DWORD km1 = (k == 0) ? 0 : k-1;

                    Quat &qk   = keys.lpRotKeys[k];
                    Quat &qkp1 = keys.lpRotKeys[kp1];
                    Quat &qkm1 = keys.lpRotKeys[km1];

                    keys.lpRotTans[k] = qk.GetInterpolationTangent(qkm1, qkp1);
                }
            }

            //----------------------------
            
            animData << nPosKeys;
            keys.hasPosKeys = nPosKeys > 0;
            if(keys.hasPosKeys)
            {
                keys.lpPosKeys = (Vect*)Allocate(nPosKeys*sizeof(Vect));
                Vect::SerializeArray(animData, keys.lpPosKeys, nPosKeys);
                
                keys.lpPosTans = (Vect*)Allocate(nPosKeys*sizeof(Vect));
                for(k=0; k<nPosKeys; k++)
                {
                    DWORD kp1 = (k == (nPosKeys-1)) ? k : (k+1);
                    DWORD km1 = (k == 0) ? 0 : k-1;

                    Vect &pk   = keys.lpPosKeys[k];
                    Vect &pkp1 = keys.lpPosKeys[kp1];
                    Vect &pkm1 = keys.lpPosKeys[km1];

                    keys.lpPosTans[k] = pk.GetInterpolationTangent(pkm1, pkp1);
                }
            }
        }
    }

    //-----------------------------------------------

    int num;
    animData << num;
    BoneExtensions.SetSize(num);
    BoneExtensionNames.SetSize(num);

    for(int i=0; i<num; i++)
    {
        animData << BoneExtensionNames[i];
        animData << BoneExtensions[i];
    }

    //-----------------------------------------------

    AnimatedSections.SetSize(nSections);

    if(ver == 0x100) //remove
    {
        UINT *indices = (UINT*)IdxBuffer->GetData();

        List<UINT> adjustedIndices;
        adjustedIndices.CopyArray(indices, IdxBuffer->NumIndices());

        VBData *vbd = VertBuffer->GetData();
        List<Vect> &verts = vbd->VertList;

        //--------- 
        // get vert data
        List<VertAnimInfo> vertInfo;
        vertInfo.SetSize(nVerts);

        for(int i=0; i<nBones; i++)
        {
            Bone &bone = BoneList[i];
            for(int j=0; j<bone.Weights.Num(); j++)
            {
                VWeight &vertWeight = bone.Weights[j];

                if(!vertInfo[vertWeight.vert].bones.HasValue(i))
                {
                    vertInfo[vertWeight.vert].bones << i;
                    vertInfo[vertWeight.vert].weights << vertWeight.weight;
                }
            }
        }

        //--------- 
        // remove excess bone influence from verts (let just set the max to 3 for this)
        /*for(int i=0; i<vertInfo.Num(); i++)
        {
            VertAnimInfo &vert = vertInfo[i];

            while(vert.bones.Num() > 3)
            {
                float weakestWeight = M_INFINITE;
                UINT weakestID;

                for(int j=0; j<vert.bones.Num(); j++)
                {
                    if(vert.weights[j] < weakestWeight)
                    {
                        weakestID = j;
                        weakestWeight = vert.weights[j];
                    }
                }

                float weightAdjust = 1.0f/(1.0f-weakestWeight);
                vert.weights.Remove(weakestID);
                vert.bones.Remove(weakestID);

                for(int j=0; j<vert.weights.Num(); j++)
                    vert.weights[j] *= weightAdjust;
            }
        }*/
        for(int i=0; i<vertInfo.Num(); i++)
        {
            VertAnimInfo &vert = vertInfo[i];

            for(int j=0; j<vert.bones.Num(); j++)
            {
                if(vert.weights[j] <= 0.15f)
                {
                    float weightAdjust = 1.0f/(1.0f-vert.weights[j]);
                    vert.weights.Remove(j);
                    vert.bones.Remove(j);

                    for(int k=0; k<vert.weights.Num(); k++)
                        vert.weights[k] *= weightAdjust;

                    --j;
                }
            }
        }

        //--------- 
        // remove excess bone influence from tris (can only have 4 bones influencing any triangle)
        for(int i=0; i<nSections; i++)
        {
            DrawSection &section = SectionList[i];
            if(!section.numFaces) continue;

            for(int j=0; j<section.numFaces; j++)
            {
                UINT *triVertIDs = &indices[(section.startFace+j)*3];

                List<UINT> bones;
                List<float> bestVertWeights;

                for(int k=0; k<3; k++)
                {
                    VertAnimInfo &info = vertInfo[triVertIDs[k]];

                    for(int l=0; l<info.bones.Num(); l++)
                    {
                        UINT id = bones.FindValueIndex(info.bones[l]);
                        if(id == INVALID)
                        {
                            bones.Add(info.bones[l]);
                            bestVertWeights.Add(info.weights[l]);
                        }
                        else
                            bestVertWeights[id] = MAX(bestVertWeights[id], info.weights[l]);
                    }
                }

                while(bones.Num() > 4)
                {
                    int removeBone, removeBoneID;
                    float bestWeight = M_INFINITE;

                    for(int k=0; k<bones.Num(); k++)
                    {
                        if(bestVertWeights[k] < bestWeight)
                        {
                            removeBone = bones[k];
                            removeBoneID = k;
                            bestWeight = bestVertWeights[k];
                        }
                    }

                    for(int k=0; k<3; k++)
                    {
                        VertAnimInfo &info = vertInfo[triVertIDs[k]];
                        UINT id = info.bones.FindValueIndex(removeBone);
                        if(id == INVALID) continue;

                        float weightAdjust = 1.0f/(1.0f-info.weights[id]);
                        info.weights.Remove(id);
                        info.bones.Remove(id);

                        for(int l=0; l<info.weights.Num(); l++)
                            info.weights[l] *= weightAdjust;
                    }

                    bones.Remove(removeBoneID);
                    bestVertWeights.Remove(removeBoneID);
                }
            }
        }

        //--------- 
        // sort out sections of triangles that are influenced up to a max of 4 bones
        // also, duplicate shared verts
        VBData *newVBD = new VBData;
        newVBD->CopyList(*vbd);

        newVBD->TVList.SetSize(2);
        newVBD->TVList[1].SetWidth(4);
        newVBD->TVList[1].SetSize(nVerts);

        List<SubSectionInfo> newSubSections;

        for(int i=0; i<nSections; i++)
        {
            List<TriBoneInfo> triInfo;

            DrawSection &section = SectionList[i];
            if(!section.numFaces) continue;

            for(int j=0; j<section.numFaces; j++)
            {
                UINT *triVertIDs = &indices[(section.startFace+j)*3];

                TriBoneInfo &newTri = *triInfo.CreateNew();

                for(int k=0; k<3; k++)
                {
                    VertAnimInfo &info = vertInfo[triVertIDs[k]];

                    for(int l=0; l<info.bones.Num(); l++)
                        newTri.bones.SafeAdd(info.bones[l]);
                }
            }

            BitList UsedTris;
            UsedTris.SetSize(section.numFaces);
            DWORD nUsedTris = 0;

            while(nUsedTris != section.numFaces)
            {
                DWORD triSectionID = newSubSections.Num();
                SubSectionInfo *curSubSecInfo = newSubSections.CreateNew();
                curSubSecInfo->section = i;

                for(int j=0; j<triInfo.Num(); j++)
                {
                    if(UsedTris[j]) continue;

                    TriBoneInfo &tri = triInfo[j];

                    List<UINT> secBones;
                    secBones.CopyList(curSubSecInfo->bones);

                    BOOL bBadTri = FALSE;
                    for(int k=0; k<tri.bones.Num(); k++)
                    {
                        secBones.SafeAdd(tri.bones[k]);
                        if(secBones.Num() > 4)
                            break;
                    }

                    if(secBones.Num() > 4) continue;

                    DWORD triID = section.startFace+j;

                    curSubSecInfo->bones.CopyList(secBones);
                    curSubSecInfo->tris << triID;

                    UINT *triVertIDs = &indices[triID*3];
                    for(int k=0; k<3; k++)
                    {
                        VertAnimInfo *info = &vertInfo[triVertIDs[k]];
                        UINT id = info->sections.FindValueIndex(triSectionID);
                        if(id == INVALID)
                        {
                            UINT vertID;
                            if(info->sections.Num() >= 1) //duplicate vertex
                            {
                                vertID = newVBD->DuplicateVertex(triVertIDs[k]);
                                adjustedIndices[(triID*3)+k] = vertID;

                                VertAnimInfo &newVertInfo = *vertInfo.CreateNew();
                                info = &vertInfo[triVertIDs[k]]; //reset pointer

                                newVertInfo.bones.CopyList(info->bones);
                                newVertInfo.weights.CopyList(info->weights);
                                newVertInfo.sections << triSectionID;
                            }
                            else
                                vertID = triVertIDs[k];

                            info->sections << triSectionID;
                            info->sectionVertIDs << vertID;

                            List<Vect4> &vertWeights = *newVBD->TVList[1].GetV4();
                            for(int l=0; l<4; l++)
                            {
                                if(l >= curSubSecInfo->bones.Num())
                                    vertWeights[vertID].ptr[l] = 0.0f;
                                else
                                {
                                    UINT boneID = curSubSecInfo->bones[l];
                                    UINT weightID = info->bones.FindValueIndex(boneID);
                                    if(weightID == INVALID)
                                        vertWeights[vertID].ptr[l] = 0.0f;
                                    else
                                        vertWeights[vertID].ptr[l] = info->weights[weightID];
                                }
                            }
                        }
                        else
                            adjustedIndices[(triID*3)+k] = info->sectionVertIDs[id];
                    }

                    UsedTris.Set(j);
                    ++nUsedTris;
                }
            }
            for(int j=0; j<triInfo.Num(); j++)
                triInfo[j].FreeData();
        }

        //---------
        // create animated draw sections and create new index buffer
        DWORD curTriID = 0;
        List<UINT> newIndices;

        for(int i=0; i<newSubSections.Num(); i++)
        {
            SubSectionInfo &subSecInfo = newSubSections[i];
            AnimSection &animSection = AnimatedSections[subSecInfo.section];
            AnimSubSection &subSection = *animSection.SubSections.CreateNew();

            subSection.numBones = subSecInfo.bones.Num();
            for(int j=0; j<subSecInfo.bones.Num(); j++)
                subSection.bones[j] = subSecInfo.bones[j];

            subSection.startFace = curTriID;

            for(int j=0; j<subSecInfo.tris.Num(); j++)
            {
                UINT *tri = &adjustedIndices[subSecInfo.tris[j]*3];
                newIndices << tri[0] << tri[1] << tri[2];

                ++curTriID;
            }

            subSection.numFaces = curTriID-subSection.startFace;

            subSecInfo.FreeData();
        }

        //rebuild original bone data
        for(int i=0; i<BoneList.Num(); i++)
            BoneList[i].Weights.Clear();

        for(int i=0; i<vertInfo.Num(); i++)
        {
            for(int j=0; j<vertInfo[i].bones.Num(); j++)
            {
                VWeight weight;
                weight.vert = i;
                weight.weight = vertInfo[i].weights[j];

                BoneList[vertInfo[i].bones[j]].Weights << weight;
            }

            vertInfo[i].FreeData();
        }

        delete VertBuffer;
        delete IdxBuffer;

        UINT numIndices;
        UINT *indexArray;
        newIndices.TransferTo(indexArray, numIndices);

        nVerts = newVBD->VertList.Num();

        IdxBuffer = CreateIndexBuffer(GS_UNSIGNED_LONG, indexArray, numIndices);
        VertBuffer = CreateVertexBuffer(newVBD);
    }
    else
    {
        for(int i=0; i<nSections; i++)
            animData << AnimatedSections[i].SubSections;
    }

    animData.Close();

    traceOut;
}
Example #5
0
    bool Encode(LPVOID picInPtr, List<DataPacket> &packets, List<PacketType> &packetTypes, DWORD outputTimestamp)
    {
        x264_picture_t *picIn = (x264_picture_t*)picInPtr;

        x264_nal_t *nalOut;
        int nalNum;

        packets.Clear();
        ClearPackets();

        if(bRequestKeyframe && picIn)
            picIn->i_type = X264_TYPE_IDR;

        if(x264_encoder_encode(x264, &nalOut, &nalNum, picIn, &picOut) < 0)
        {
            AppWarning(TEXT("x264 encode failed"));
            return false;
        }

        if(bRequestKeyframe && picIn)
        {
            picIn->i_type = X264_TYPE_AUTO;
            bRequestKeyframe = false;
        }

        if(!bFirstFrameProcessed && nalNum)
        {
            delayOffset = -picOut.i_dts;
            bFirstFrameProcessed = true;
        }

        INT64 ts = INT64(outputTimestamp);
        int timeOffset;

        //if frame duplication is being used, the shift will be insignificant, so just don't bother adjusting audio
        timeOffset = int(picOut.i_pts-picOut.i_dts);
        timeOffset += frameShift;

        if(nalNum && timeOffset < 0)
        {
            frameShift -= timeOffset;
            timeOffset = 0;
        }

        //Log(TEXT("inpts: %005d, dts: %005d, pts: %005d, timestamp: %005d, offset: %005d, newoffset: %005d"), picIn->i_pts, picOut.i_dts, picOut.i_pts, outputTimestamp, timeOffset, picOut.i_pts-picOut.i_dts);

        timeOffset = htonl(timeOffset);

        BYTE *timeOffsetAddr = ((BYTE*)&timeOffset)+1;

        VideoPacket *newPacket = NULL;

        PacketType bestType = PacketType_VideoDisposable;
        bool bFoundFrame = false;

        for(int i=0; i<nalNum; i++)
        {
            x264_nal_t &nal = nalOut[i];

            if(nal.i_type == NAL_SEI)
            {
                BYTE *skip = nal.p_payload;
                while(*(skip++) != 0x1);
                int skipBytes = (int)(skip-nal.p_payload);

                int newPayloadSize = (nal.i_payload-skipBytes);

                if (nal.p_payload[skipBytes+1] == 0x5) {
                    SEIData.Clear();
                    BufferOutputSerializer packetOut(SEIData);

                    packetOut.OutputDword(htonl(newPayloadSize));
                    packetOut.Serialize(nal.p_payload+skipBytes, newPayloadSize);
                } else {
                    if (!newPacket)
                        newPacket = CurrentPackets.CreateNew();

                    BufferOutputSerializer packetOut(newPacket->Packet);

                    packetOut.OutputDword(htonl(newPayloadSize));
                    packetOut.Serialize(nal.p_payload+skipBytes, newPayloadSize);
                }
            }
            else if(nal.i_type == NAL_FILLER)
            {
                BYTE *skip = nal.p_payload;
                while(*(skip++) != 0x1);
                int skipBytes = (int)(skip-nal.p_payload);

                int newPayloadSize = (nal.i_payload-skipBytes);

                if (!newPacket)
                    newPacket = CurrentPackets.CreateNew();

                BufferOutputSerializer packetOut(newPacket->Packet);

                packetOut.OutputDword(htonl(newPayloadSize));
                packetOut.Serialize(nal.p_payload+skipBytes, newPayloadSize);
            }
            else if(nal.i_type == NAL_SLICE_IDR || nal.i_type == NAL_SLICE)
            {
                BYTE *skip = nal.p_payload;
                while(*(skip++) != 0x1);
                int skipBytes = (int)(skip-nal.p_payload);

                if (!newPacket)
                    newPacket = CurrentPackets.CreateNew();

                if (!bFoundFrame)
                {
                    newPacket->Packet.Insert(0, (nal.i_type == NAL_SLICE_IDR) ? 0x17 : 0x27);
                    newPacket->Packet.Insert(1, 1);
                    newPacket->Packet.InsertArray(2, timeOffsetAddr, 3);

                    bFoundFrame = true;
                }

                int newPayloadSize = (nal.i_payload-skipBytes);
                BufferOutputSerializer packetOut(newPacket->Packet);

                packetOut.OutputDword(htonl(newPayloadSize));
                packetOut.Serialize(nal.p_payload+skipBytes, newPayloadSize);

                switch(nal.i_ref_idc)
                {
                    case NAL_PRIORITY_DISPOSABLE:   bestType = MAX(bestType, PacketType_VideoDisposable);  break;
                    case NAL_PRIORITY_LOW:          bestType = MAX(bestType, PacketType_VideoLow);         break;
                    case NAL_PRIORITY_HIGH:         bestType = MAX(bestType, PacketType_VideoHigh);        break;
                    case NAL_PRIORITY_HIGHEST:      bestType = MAX(bestType, PacketType_VideoHighest);     break;
                }
            }
            /*else if(nal.i_type == NAL_SPS)
            {
                VideoPacket *newPacket = CurrentPackets.CreateNew();
                BufferOutputSerializer headerOut(newPacket->Packet);

                headerOut.OutputByte(0x17);
                headerOut.OutputByte(0);
                headerOut.Serialize(timeOffsetAddr, 3);
                headerOut.OutputByte(1);
                headerOut.Serialize(nal.p_payload+5, 3);
                headerOut.OutputByte(0xff);
                headerOut.OutputByte(0xe1);
                headerOut.OutputWord(htons(nal.i_payload-4));
                headerOut.Serialize(nal.p_payload+4, nal.i_payload-4);

                x264_nal_t &pps = nalOut[i+1]; //the PPS always comes after the SPS

                headerOut.OutputByte(1);
                headerOut.OutputWord(htons(pps.i_payload-4));
                headerOut.Serialize(pps.p_payload+4, pps.i_payload-4);
            }*/
            else
                continue;
        }

        packetTypes << bestType;

        packets.SetSize(CurrentPackets.Num());
        for(UINT i=0; i<packets.Num(); i++)
        {
            packets[i].lpPacket = CurrentPackets[i].Packet.Array();
            packets[i].size     = CurrentPackets[i].Packet.Num();
        }

        return true;
    }
Example #6
0
void EditorMesh::BuildLightmapUVs(float maxAngle, float adjVal, int seperationUnits)
{
    Vect maxSize = bounds.Max-bounds.Min;

    //adjVal *= MAX(maxSize.x, MAX(maxSize.y, maxSize.z));
    adjVal *= bounds.GetDiamater();

    int i, j;

    MakePolyEdges();

    maxAngle = cosf(RAD(maxAngle));

    BitList ProcessedPolys, ProcessedEdges, ProcessedVerts;
    List<UINT> UnprocessedPolys;

    ProcessedPolys.SetSize(PolyList.Num());
    ProcessedEdges.SetSize(PolyEdgeList.Num());
    ProcessedVerts.SetSize(VertList.Num());

    UnprocessedPolys.SetSize(PolyList.Num());
    for(i=0; i<UnprocessedPolys.Num(); i++)
        UnprocessedPolys[i] = i;

    List<UVSection> Sections;
    BitList         SplitVerts;

    SplitVerts.SetSize(VertList.Num());

    //go through each polygon and find neighboring polygons
    while(UnprocessedPolys.Num())
    {
        UINT curPoly = UnprocessedPolys[0];

        List<UINT> SectionPolys;
        UVSection &section = *Sections.CreateNew();
        section.mapDir = GetPolyDir(curPoly);

        List<Vect> PolyLines;

        // calling this recursively will build us up a section based upon this poly
        AddLMPolyInfo info(curPoly, maxAngle, section.mapDir, SectionPolys, PolyLines, UnprocessedPolys, ProcessedPolys, ProcessedEdges);
        AddLightmapUVPoly(info);

        section.mapDir.Norm();

        //find best mapping direction
        Vect XDir, YDir;

        BitList addedLines;
        addedLines.SetSize(PolyLines.Num());

        float bestLength = 0.0f;
        Vect bestDir;

        for(i=0; i<PolyLines.Num(); i++)
        {
            if(addedLines[i]) continue;

            addedLines.Set(i);

            Vect &line1 = PolyLines[i];
            Vect line1Norm = (line1 + (section.mapDir * -section.mapDir.Dot(line1))).Norm();

            Vect lineTotal = line1;

            for(j=i+1; j<PolyLines.Num(); j++)
            {
                if(addedLines[j]) continue;

                Vect &line2 = PolyLines[j];
                Vect line2Norm = (line2 + (section.mapDir * -section.mapDir.Dot(line2))).Norm();

                if(line1Norm.Dot(line2Norm) > 0.9f) //about 10 degrees
                {
                    lineTotal += line2;
                    addedLines.Set(j);
                }
            }

            float length = lineTotal.Len();
            if(length > bestLength)
            {
                bestDir = lineTotal.Norm();
                bestLength = length;
            }
        }

        if(section.mapDir.CloseTo(bestDir) || (-section.mapDir).CloseTo(bestDir))
        {
            if(bestDir.x > bestDir.y)
            {
                if(bestDir.x > bestDir.z)
                    *(DWORD*)&bestDir.x |= 0x80000000;
                else
                    *(DWORD*)&bestDir.z |= 0x80000000;
            }
            else
            {
                if(bestDir.y > bestDir.z)
                    *(DWORD*)&bestDir.y |= 0x80000000;
                else
                    *(DWORD*)&bestDir.z |= 0x80000000;
            }
        }

        YDir = bestDir.Cross(section.mapDir).Norm();
        XDir = YDir.Cross(section.mapDir).Norm();

        /*if(section.mapDir.GetAbs().CloseTo(Vect(0.0f, 1.0f, 0.0f)))
        {
            float fOne = (*(DWORD*)&section.mapDir.y & 0x80000000) ? -1.0f : 1.0f;

            XDir.Set(fOne, 0.0f, 0.0f);
            YDir.Set(0.0f, 0.0f, fOne);
        }
        else
        {
            XDir = Vect(0.0f, 1.0f, 0.0f).Cross(section.mapDir).Norm();
            YDir = XDir.Cross(section.mapDir).Norm();
        }*/

        float top, bottom, left, right;

        //project UVs onto this section
        for(i=0; i<SectionPolys.Num(); i++)
        {
            PolyFace &poly = PolyList[SectionPolys[i]];
            for(j=0; j<poly.Faces.Num(); j++)
            {
                UINT faceID = poly.Faces[j];
                Face &f = FaceList[faceID];

                section.Faces << faceID;

                for(int k=0; k<3; k++)
                {
                    UINT vert = f.ptr[k];

                    Vect &v = VertList[vert];

                    Vect2 uv;
                    uv.x = XDir.Dot(v);
                    uv.y = YDir.Dot(v);

                    if(!section.ProjectedVerts.Num())
                    {
                        left = right = uv.x;
                        top = bottom = uv.y;
                    }
                    else
                    {
                        if(uv.x < left) left = uv.x;
                        else if(uv.x > right) right = uv.x;

                        if(uv.y < top) top = uv.y;
                        else if(uv.y > bottom) bottom = uv.y;
                    }

                    section.Verts << vert;
                    section.ProjectedVerts << uv;
                }
            }
        }

        section.width  = (right-left)+(adjVal*2.0f);
        section.height = (bottom-top)+(adjVal*2.0f);

        for(i=0; i<section.Verts.Num(); i++)
        {
            section.ProjectedVerts[i].x -= left-adjVal;
            section.ProjectedVerts[i].y -= top-adjVal;
        }

        //find any verts that might need splitting
        section.SplitVerts.SetSize(section.Verts.Num());

        for(i=0; i<section.Verts.Num(); i++)
        {
            BOOL bFoundVert = FALSE;
            UINT vert = section.Verts[i];

            if(SplitVerts[vert])
                bFoundVert = TRUE;
            else 
            {
                for(j=0; j<Sections.Num()-1; j++)
                {
                    UVSection &prevSection = Sections[j];

                    if(prevSection.Verts.HasValue(vert))
                    {
                        SplitVerts.Set(vert);
                        bFoundVert = TRUE;
                        break;
                    }
                }
            }

            if(bFoundVert)
                section.SplitVerts.Set(i);
        }
    }

    //split verts where the lightmap coordinates are
    for(i=1; i<Sections.Num(); i++)
    {
        UVSection &section = Sections[i];
        for(j=0; j<section.SplitVerts.Num(); j++)
        {
            if(section.SplitVerts[j])
            {
                UINT faceID  = j/3;
                UINT faceVert = j%3;
                UINT vertID = section.Verts[j];

                UINT newVertID = VertList.Num();
                Face &f = FaceList[faceID];

                f.ptr[faceVert] = newVertID;

                VertList.Add(VertList[vertID]);
                UVList.Add(UVList[vertID]);
                NormalList.Add(NormalList[vertID]);
                if(TangentList.Num())
                    TangentList.Add(TangentList[vertID]);
            }
        }
    }

    LMUVList.SetSize(VertList.Num());

    //find the most optimal way to put sections together
    BestStorageInfo info(Sections, seperationUnits);
    FindBestUVStorage(info);

    float curSizeI = 1.0f/MAX(info.curSize.x, info.curSize.y);

    for(i=0; i<info.CurStorage.Num(); i++)
    {
        StorageData &data = info.CurStorage[i];
        UVSection &section = Sections[data.item];
        for(j=0; j<section.Verts.Num(); j++)
        {
            UINT vertID = section.Verts[j];
            if(ProcessedVerts[vertID]) continue;

            Vect2 &v = section.ProjectedVerts[j];
            Vect2 newPos;

            if(data.bRot)
            {
                newPos.x = section.height-v.y;
                newPos.y = v.x;
            }
            else
                newPos = v;

            LMUVList[vertID] = (data.pos+newPos)*curSizeI;

            ProcessedVerts.Set(vertID);
        }
    }

    //free data
    for(i=0; i<Sections.Num(); i++)
        Sections[i].FreeData();
    Sections.Clear();

    FreePolyEdges();
}
Example #7
0
UINT MMDeviceAudioSource::GetNextBuffer(float curVolume)
{
    UINT captureSize = 0;
    HRESULT err = mmCapture->GetNextPacketSize(&captureSize);
    if(FAILED(err))
    {
        RUNONCE AppWarning(TEXT("MMDeviceAudioSource::GetBuffer: GetNextPacketSize failed"));
        return NoAudioAvailable;
    }

    float *outputBuffer = NULL;

    if(captureSize)
    {
        LPBYTE captureBuffer;
        DWORD dwFlags = 0;
        UINT numAudioFrames = 0;

        UINT64 devPosition;
        UINT64 qpcTimestamp;
        err = mmCapture->GetBuffer(&captureBuffer, &numAudioFrames, &dwFlags, &devPosition, &qpcTimestamp);
        if(FAILED(err))
        {
            RUNONCE AppWarning(TEXT("MMDeviceAudioSource::GetBuffer: GetBuffer failed"));
            return NoAudioAvailable;
        }

        QWORD newTimestamp;

        if(dwFlags & AUDCLNT_BUFFERFLAGS_TIMESTAMP_ERROR)
        {
            RUNONCE AppWarning(TEXT("MMDeviceAudioSource::GetBuffer: woa woa woa, getting timestamp errors from the audio subsystem.  device = %s"), GetDeviceName().Array());
            if(!bBrokenTimestamp)
                newTimestamp = lastUsedTimestamp + numAudioFrames*1000/inputSamplesPerSec;
        }
        else
        {
            if(!bBrokenTimestamp)
                newTimestamp = qpcTimestamp/10000;

            /*UINT64 freq;
            mmClock->GetFrequency(&freq);
            Log(TEXT("position: %llu, numAudioFrames: %u, freq: %llu, newTimestamp: %llu, test: %llu"), devPosition, numAudioFrames, freq, newTimestamp, devPosition*8000/freq);*/
        }

        //have to do this crap to account for broken devices or device drivers.  absolutely unbelievable.
        if(!bFirstFrameReceived)
        {
            LARGE_INTEGER clockFreq;
            QueryPerformanceFrequency(&clockFreq);
            QWORD curTime = GetQPCTimeMS(clockFreq.QuadPart);

            if(newTimestamp < (curTime-1000) || newTimestamp > (curTime+1000))
            {
                bBrokenTimestamp = true;

                Log(TEXT("MMDeviceAudioSource::GetNextBuffer: Got bad audio timestamp offset %lld from device: '%s', timestamps for this device will be calculated.  curTime: %llu, newTimestamp: %llu"), (LONGLONG)(newTimestamp - curTime), GetDeviceName().Array(), curTime, newTimestamp);
                lastUsedTimestamp = newTimestamp = curTime;
            }
            else
                lastUsedTimestamp = newTimestamp;

            bFirstFrameReceived = true;
        }

        if(tempBuffer.Num() < numAudioFrames*2)
            tempBuffer.SetSize(numAudioFrames*2);

        outputBuffer = tempBuffer.Array();
        float *tempOut = outputBuffer;

        //------------------------------------------------------------
        // channel upmix/downmix

        if(inputChannels == 1)
        {
            UINT  numFloats   = numAudioFrames;
            float *inputTemp  = (float*)captureBuffer;
            float *outputTemp = outputBuffer;

            if(App->SSE2Available() && (UPARAM(inputTemp) & 0xF) == 0 && (UPARAM(outputTemp) & 0xF) == 0)
            {
                UINT alignedFloats = numFloats & 0xFFFFFFFC;
                for(UINT i=0; i<alignedFloats; i += 4)
                {
                    __m128 inVal   = _mm_load_ps(inputTemp+i);

                    __m128 outVal1 = _mm_unpacklo_ps(inVal, inVal);
                    __m128 outVal2 = _mm_unpackhi_ps(inVal, inVal);

                    _mm_store_ps(outputTemp+(i*2),   outVal1);
                    _mm_store_ps(outputTemp+(i*2)+4, outVal2);
                }

                numFloats  -= alignedFloats;
                inputTemp  += alignedFloats;
                outputTemp += alignedFloats*2;
            }

            while(numFloats--)
            {
                float inputVal = *inputTemp;
                *(outputTemp++) = inputVal;
                *(outputTemp++) = inputVal;

                inputTemp++;
            }
        }
        else if(inputChannels == 2) //straight up copy
        {
            if(App->SSE2Available())
                SSECopy(outputBuffer, captureBuffer, numAudioFrames*2*sizeof(float));
            else
                mcpy(outputBuffer, captureBuffer, numAudioFrames*2*sizeof(float));
        }
        else
        {
            //todo: downmix optimization, also support for other speaker configurations than ones I can merely "think" of.  ugh.
            float *inputTemp  = (float*)captureBuffer;
            float *outputTemp = outputBuffer;

            if(inputChannelMask == KSAUDIO_SPEAKER_QUAD)
            {
                UINT numFloats = numAudioFrames*4;
                float *endTemp = inputTemp+numFloats;

                while(inputTemp < endTemp)
                {
                    float left      = inputTemp[0];
                    float right     = inputTemp[1];
                    float rear      = (inputTemp[2]+inputTemp[3])*surroundMix;

                    *(outputTemp++) = left  - rear;
                    *(outputTemp++) = right + rear;

                    inputTemp  += 4;
                }
            }
            else if(inputChannelMask == KSAUDIO_SPEAKER_2POINT1)
            {
                UINT numFloats = numAudioFrames*3;
                float *endTemp = inputTemp+numFloats;

                while(inputTemp < endTemp)
                {
                    float left      = inputTemp[0];
                    float right     = inputTemp[1];
                    float lfe       = inputTemp[2]*lowFreqMix;

                    *(outputTemp++) = left  + lfe;
                    *(outputTemp++) = right + lfe;

                    inputTemp  += 3;
                }
            }
            else if(inputChannelMask == KSAUDIO_SPEAKER_4POINT1)
            {
                UINT numFloats = numAudioFrames*5;
                float *endTemp = inputTemp+numFloats;

                while(inputTemp < endTemp)
                {
                    float left      = inputTemp[0];
                    float right     = inputTemp[1];
                    float lfe       = inputTemp[2]*lowFreqMix;
                    float rear      = (inputTemp[3]+inputTemp[4])*surroundMix;

                    *(outputTemp++) = left  + lfe - rear;
                    *(outputTemp++) = right + lfe + rear;

                    inputTemp  += 5;
                }
            }
            else if(inputChannelMask == KSAUDIO_SPEAKER_SURROUND)
            {
                UINT numFloats = numAudioFrames*4;
                float *endTemp = inputTemp+numFloats;

                while(inputTemp < endTemp)
                {
                    float left      = inputTemp[0];
                    float right     = inputTemp[1];
                    float center    = inputTemp[2]*centerMix;
                    float rear      = inputTemp[3]*(surroundMix*dbMinus3);

                    *(outputTemp++) = left  + center - rear;
                    *(outputTemp++) = right + center + rear;

                    inputTemp  += 4;
                }
            }
            //don't think this will work for both
            else if(inputChannelMask == KSAUDIO_SPEAKER_5POINT1)
            {
                UINT numFloats = numAudioFrames*6;
                float *endTemp = inputTemp+numFloats;

                while(inputTemp < endTemp)
                {
                    float left      = inputTemp[0];
                    float right     = inputTemp[1];
                    float center    = inputTemp[2]*centerMix;
                    float lowFreq   = inputTemp[3]*lowFreqMix;
                    float rear      = (inputTemp[4]+inputTemp[5])*surroundMix;

                    *(outputTemp++) = left  + center + lowFreq - rear;
                    *(outputTemp++) = right + center + lowFreq + rear;

                    inputTemp  += 6;
                }
            }
            //todo ------------------
            //not sure if my 5.1/7.1 downmixes are correct
            else if(inputChannelMask == KSAUDIO_SPEAKER_5POINT1_SURROUND)
            {
                UINT numFloats = numAudioFrames*6;
                float *endTemp = inputTemp+numFloats;

                while(inputTemp < endTemp)
                {
                    float left      = inputTemp[0];
                    float right     = inputTemp[1];
                    float center    = inputTemp[2]*centerMix;
                    float lowFreq   = inputTemp[3]*lowFreqMix;
                    float sideLeft  = inputTemp[4]*dbMinus3;
                    float sideRight = inputTemp[5]*dbMinus3;

                    *(outputTemp++) = left  + center + sideLeft  + lowFreq;
                    *(outputTemp++) = right + center + sideRight + lowFreq;

                    inputTemp  += 6;
                }
            }
            else if(inputChannelMask == KSAUDIO_SPEAKER_7POINT1)
            {
                UINT numFloats = numAudioFrames*8;
                float *endTemp = inputTemp+numFloats;

                while(inputTemp < endTemp)
                {
                    float left          = inputTemp[0];
                    float right         = inputTemp[1];
                    float center        = inputTemp[2]*(centerMix*dbMinus3);
                    float lowFreq       = inputTemp[3]*lowFreqMix;
                    float rear          = (inputTemp[4]+inputTemp[5])*surroundMix;
                    float centerLeft    = inputTemp[6]*dbMinus6;
                    float centerRight   = inputTemp[7]*dbMinus6;

                    *(outputTemp++) = left  + centerLeft  + center + lowFreq - rear;
                    *(outputTemp++) = right + centerRight + center + lowFreq + rear;

                    inputTemp  += 8;
                }
            }
            else if(inputChannelMask == KSAUDIO_SPEAKER_7POINT1_SURROUND)
            {
                UINT numFloats = numAudioFrames*8;
                float *endTemp = inputTemp+numFloats;

                while(inputTemp < endTemp)
                {
                    float left      = inputTemp[0];
                    float right     = inputTemp[1];
                    float center    = inputTemp[2]*centerMix;
                    float lowFreq   = inputTemp[3]*lowFreqMix;
                    float rear      = (inputTemp[4]+inputTemp[5])*(surroundMix*dbMinus3);
                    float sideLeft  = inputTemp[6]*dbMinus6;
                    float sideRight = inputTemp[7]*dbMinus6;

                    *(outputTemp++) = left  + sideLeft + center + lowFreq - rear;
                    *(outputTemp++) = right + sideLeft + center + lowFreq + rear;

                    inputTemp  += 8;
                }
            }
        }

        mmCapture->ReleaseBuffer(numAudioFrames);

        //------------------------------------------------------------
        // resample

        if(bResample)
        {
            UINT frameAdjust = UINT((double(numAudioFrames) * resampleRatio) + 1.0);
            UINT newFrameSize = frameAdjust*2;

            if(tempResampleBuffer.Num() < newFrameSize)
                tempResampleBuffer.SetSize(newFrameSize);

            SRC_DATA data;
            data.src_ratio = resampleRatio;

            data.data_in = tempBuffer.Array();
            data.input_frames = numAudioFrames;

            data.data_out = tempResampleBuffer.Array();
            data.output_frames = frameAdjust;

            data.end_of_input = 0;

            int err = src_process(resampler, &data);
            if(err)
            {
                RUNONCE AppWarning(TEXT("Was unable to resample audio"));
                return NoAudioAvailable;
            }

            if(data.input_frames_used != numAudioFrames)
            {
                RUNONCE AppWarning(TEXT("Failed to downsample buffer completely, which shouldn't actually happen because it should be using 10ms of samples"));
                return NoAudioAvailable;
            }

            numAudioFrames = data.output_frames_gen;
        }

        //-----------------------------------------------------------------------------
        // sort all audio frames into 10 millisecond increments (done because not all devices output in 10ms increments)
        // NOTE: 0.457+ - instead of using the timestamps from windows, just compare and make sure it stays within a 100ms of their timestamps

        float *newBuffer = (bResample) ? tempResampleBuffer.Array() : tempBuffer.Array();

        if(storageBuffer.Num() == 0 && numAudioFrames == 441)
        {
            lastUsedTimestamp += 10;
            if(!bBrokenTimestamp) 
            {
                QWORD difVal = GetQWDif(newTimestamp, lastUsedTimestamp);
                if(difVal > 70)
                    lastUsedTimestamp = newTimestamp;
            }

            if(lastUsedTimestamp > lastSentTimestamp)
            {
                QWORD adjustVal = (lastUsedTimestamp-lastSentTimestamp);
                if(adjustVal < 10)
                    lastUsedTimestamp += 10-adjustVal;

                AudioSegment &newSegment = *audioSegments.CreateNew();
                newSegment.audioData.CopyArray(newBuffer, numAudioFrames*2);
                newSegment.timestamp = lastUsedTimestamp;
                MultiplyAudioBuffer(newSegment.audioData.Array(), numAudioFrames*2, curVolume);

                lastSentTimestamp = lastUsedTimestamp;
            }
        }
        else
        {
            UINT storedFrames = storageBuffer.Num();

            storageBuffer.AppendArray(newBuffer, numAudioFrames*2);
            if(storageBuffer.Num() >= (441*2))
            {
                lastUsedTimestamp += 10;
                if(!bBrokenTimestamp)
                {
                    QWORD difVal = GetQWDif(newTimestamp, lastUsedTimestamp);
                    if(difVal > 70)
                        lastUsedTimestamp = newTimestamp - (QWORD(storedFrames)/2*1000/44100);
                }

                //------------------------
                // add new data

                if(lastUsedTimestamp > lastSentTimestamp)
                {
                    QWORD adjustVal = (lastUsedTimestamp-lastSentTimestamp);
                    if(adjustVal < 10)
                        lastUsedTimestamp += 10-adjustVal;

                    AudioSegment &newSegment = *audioSegments.CreateNew();
                    newSegment.audioData.CopyArray(storageBuffer.Array(), (441*2));
                    newSegment.timestamp = lastUsedTimestamp;
                    MultiplyAudioBuffer(newSegment.audioData.Array(), 441*2, curVolume);

                    storageBuffer.RemoveRange(0, (441*2));
                }

                //------------------------
                // if still data pending (can happen)

                while(storageBuffer.Num() >= (441*2))
                {
                    lastUsedTimestamp += 10;

                    if(lastUsedTimestamp > lastSentTimestamp)
                    {
                        QWORD adjustVal = (lastUsedTimestamp-lastSentTimestamp);
                        if(adjustVal < 10)
                            lastUsedTimestamp += 10-adjustVal;

                        AudioSegment &newSegment = *audioSegments.CreateNew();
                        newSegment.audioData.CopyArray(storageBuffer.Array(), (441*2));
                        storageBuffer.RemoveRange(0, (441*2));
                        MultiplyAudioBuffer(newSegment.audioData.Array(), 441*2, curVolume);

                        newSegment.timestamp = lastUsedTimestamp;

                        lastSentTimestamp = lastUsedTimestamp;
                    }
                }
            }
        }

        //-----------------------------------------------------------------------------

        return ContinueAudioRequest;
    }

    return NoAudioAvailable;
}
Example #8
0
void  Triangulator::ConnectChibiLoops(ChibiLoopNode &loopNode, List<LoopVerts> &LoopList, List<LoopVerts> &NewLoopList)
{
    DWORD i, j, k, l;

    List<PolyLine> CurLoop;
    CurLoop.CopyList(LoopList[loopNode.loop]);

    if(!ChibiLoopFacingUp(CurLoop))
        ReverseLoop(CurLoop);

    List<DWORD> AlreadyUsed;

    for(i=0; i<loopNode.Children.Num(); i++)
    {
        ChibiLoopNode &childNode = loopNode.Children[i];
        List<PolyLine> &childLoop = LoopList[childNode.loop];

        if(ChibiLoopFacingUp(childLoop))
            ReverseLoop(childLoop);
    }

    List<DWORD> CurChildren;
    CurChildren.SetSize(loopNode.Children.Num());
    for(i=0; i<loopNode.Children.Num(); i++)
        CurChildren[i] = i;

    i = 0;

    while(CurChildren.Num())
    {
        ChibiLoopNode &childNode = loopNode.Children[CurChildren[i]];
        List<PolyLine> &childLoop = LoopList[childNode.loop];

        //---------------------------------------------
        // find closest points between loops

        DWORD curBestChoiceLoop1 = INVALID;
        DWORD curBestChoiceLoop2 = INVALID;
        float closestPos = 0.0f;

        for(j=0; j<CurLoop.Num(); j++)
        {
            if(AlreadyUsed.FindValueIndex(CurLoop[j].v1) != INVALID)
                continue;

            Vect2 &v1 = Verts[CurLoop[j].v1];

            for(k=0; k<childLoop.Num(); k++)
            {
                if(AlreadyUsed.FindValueIndex(childLoop[k].v1) != INVALID)
                    continue;

                Vect2 &v2 = Verts[childLoop[k].v1];

                BOOL bBadChoice = LineIntersectsShape(v1, v2, CurLoop);

                if(bBadChoice)
                    continue;

                for(l=0; l<CurChildren.Num(); l++)
                {
                    if(LineIntersectsShape(v1, v2, LoopList[loopNode.Children[CurChildren[l]].loop]))
                    {
                        bBadChoice = TRUE;
                        break;
                    }
                }

                if(bBadChoice)
                    continue;

                float dist = v2.Dist(v1);

                if((curBestChoiceLoop1 != INVALID) && (dist > closestPos))
                    continue;

                closestPos = dist;
                curBestChoiceLoop1 = j;
                curBestChoiceLoop2 = k;
            }
        }

        if(curBestChoiceLoop1 == INVALID)
        {
            i = (i == CurChildren.Num()-1) ? 0 : (i+1);
            if(i == 0)
            {
                AppWarning(TEXT("...almost infinitely looped there.  Fortunately I have measures against such devious things."));
                break;
            }
            continue;
        }

        AlreadyUsed << CurLoop[curBestChoiceLoop1].v1;
        AlreadyUsed << childLoop[curBestChoiceLoop2].v1;

        //---------------------------------------------
        // connect loops

        if(CurLoop[0].lineData && !childLoop[0].lineData)
        {
            for(j=0; j<childLoop.Num(); j++)
                childLoop[j].lineData = CurLoop[0].lineData;
        }

        SetNewLoopStartPosition(CurLoop,   curBestChoiceLoop1);
        SetNewLoopStartPosition(childLoop, curBestChoiceLoop2);

        if(!CurLoop[0].lineData && childLoop[0].lineData)
        {
            for(j=0; j<CurLoop.Num(); j++)
                CurLoop[j].lineData = childLoop[0].lineData;
        }

        PolyLine &lastLine = CurLoop.Last();
        PolyLine *pLine = CurLoop.CreateNew();
        pLine->v1 = lastLine.v2;
        pLine->v2 = childLoop[0].v1;

        CurLoop.AppendList(childLoop);
        pLine = CurLoop.CreateNew();
        pLine->v1 = childLoop[0].v1;
        pLine->v2 = CurLoop[0].v1;

        /*for(j=0; j<CurLoop.Num(); j++)
        {
            String chong;
            chong << long(j) << TEXT(": x: ") << FormattedString(TEXT("%0.4f"), Verts[CurLoop[j].v1].x) << TEXT("\ty: ") << FormattedString(TEXT("%0.4f"), Verts[CurLoop[j].v1].y) << TEXT("\r\n");
            OutputDebugString(chong);
        }
        OutputDebugString(TEXT("====================================\r\n"));*/

        CurChildren.Remove(i);
        i = 0;
    }

    NewLoopList.CreateNew()->CopyList(CurLoop);
    CurLoop.Clear();

    for(i=0; i<loopNode.Children.Num(); i++)
    {
        ChibiLoopNode &childNode = loopNode.Children[i];

        for(j=0; j<childNode.Children.Num(); j++)
            ConnectChibiLoops(childNode.Children[j], LoopList, NewLoopList);
    }
}
Example #9
0
void  Triangulator::CreateChibiLoopTree(List<ChibiLoopNode> &LoopNodeList, List<DWORD> &LoopRefs, List<LoopVerts> &LoopList)
{
    int i, j;

    // find top loops

    /*for(i=0; i<LoopRefs.Num(); i++)
    {
        LoopVerts &loop1 = LoopList[LoopRefs[i]];
        BOOL bTopLoop = TRUE;
        //Vect2 &testVert = Verts[LoopList[LoopRefs[i]][0].v1];

        List<DWORD> ChildRefs;

        for(j=0; j<LoopRefs.Num(); j++)
        {
            if(j == i)
                continue;

            LoopVerts &loop2 = LoopList[LoopRefs[j]];

            DWORD val = LoopInsideLoop(loop2, loop1);

            if(val == 2)
            {
                if(!ChibiLoopFacingUp(loop2))
                    val = 1;
            }

            if(val == 1)
            {
                bTopLoop = FALSE;
                break;
            }
            else if(LoopInsideLoop(loop1, loop2))
                ChildRefs << LoopRefs[j];
        }

        if(bTopLoop)
        {
            ChibiLoopNode &chibiLoopNode = *LoopNodeList.CreateNew();
            chibiLoopNode.loop = LoopRefs[i];

            CreateChibiLoopTree(chibiLoopNode.Children, ChildRefs, LoopList);
        }
    }*/

    for(i=0; LoopRefs.Num(); i++)  //works like a while(LoopRefs.Num())
    {
        LoopVerts &loop1 = LoopList[LoopRefs[i]];
        BOOL bTopLoop = TRUE;

        List<DWORD> ChildRefs;

        ChildRefs.Clear();

        for(j=0; j<LoopRefs.Num(); j++)
        {
            if(j == i)
                continue;

            LoopVerts &loop2 = LoopList[LoopRefs[j]];

            DWORD val = LoopInsideLoop(loop2, loop1);

            if(val == 2)
            {
                if(!ChibiLoopFacingUp(loop2))
                    val = 1;
            }

            if(val == 1)
            {
                bTopLoop = FALSE;
                break;
            }
            else
            {
                DWORD val2 = LoopInsideLoop(loop1, loop2);
                if((val2 == 1) || ((val2 & val) == 2))
                    ChildRefs << LoopRefs[j];
            }
        }

        if(bTopLoop)
        {
            ChibiLoopNode &chibiLoopNode = *LoopNodeList.CreateNew();
            chibiLoopNode.loop = LoopRefs[i];

            LoopRefs.Remove(i);

            if(ChildRefs.Num())
            {
                for(j=0; j<ChildRefs.Num(); j++)
                    LoopRefs.RemoveItem(ChildRefs[j]);

                CreateChibiLoopTree(chibiLoopNode.Children, ChildRefs, LoopList);
            }

            i=-1; //because it'll do the i++
        }
    }
}
Example #10
0
void  Triangulator::Triangulate()
{
    assert(Verts.Num());

    if(!Verts.Num())
        return;

    DWORD i;

    //if no lines available, build lines list from vert list
    if(!Lines.Num())
    {
        Lines.SetSize(Verts.Num());

        for(i=0; i<Verts.Num(); i++)
        {
            PolyLine &line = Lines[i];
            int ip1 = (i == Verts.Num()-1) ? 0 : (i+1);

            line.v1 = i;
            line.v2 = ip1;
        }
    }

    List<ChibiLoopNode> ChibiLoopTree;
    List<LoopVerts> LoopList;

    DWORD curLoop=0;

    //-----------------------------------------------------------
    // find loops!

	if(blablabla == 1)
		blablabla = 0;

    List<DWORD> LineIDs;
    LineIDs.SetSize(Lines.Num());
    for(i=0; i<LineIDs.Num(); i++) LineIDs[i] = i;

    while(LineIDs.Num())
    {
        LoopVerts &CurLoop = *LoopList.CreateNew();
        DWORD lastLine = 0;

        CurLoop.Clear();

        while(TRUE)
        {
            PolyLine &line1 = Lines[LineIDs[lastLine]];
            LineIDs.Remove(lastLine);

            CurLoop << line1;

            BOOL bNoResults = TRUE;

            if(line1.v2 == CurLoop[0].v1)
                break;

            for(i=0; i<LineIDs.Num(); i++)
            {
                PolyLine &line2 = Lines[LineIDs[i]];
                if((line2.v1 == line1.v2) && (line2.v2 != line1.v1) && (!line2.lineData || (line1.lineData == line2.lineData)))
                {
                    lastLine = i;
                    line2.lineData = line1.lineData;
                    bNoResults = FALSE;
                    break;
                }
            }

            if(bNoResults)
            {
                AppWarning(TEXT("Invalid Loop data sent to triangulation."));
                LineIDs.Clear();
                break;
            }
        }
    }

    //-----------------------------------------------------------
    // sort loops!

    List<DWORD> LoopRefs;

    LoopRefs.SetSize(LoopList.Num());
    for(i=0; i<LoopList.Num(); i++) LoopRefs[i] = i;

    CreateChibiLoopTree(ChibiLoopTree, LoopRefs, LoopList);

    LoopRefs.Clear();

    //-----------------------------------------------------------
    // connect loops

    //SpreadLoopData(ChibiLoopTree, LoopList, 0);

    List<LoopVerts> NewLoopList;

    for(i=0; i<ChibiLoopTree.Num(); i++)
        ConnectChibiLoops(ChibiLoopTree[i], LoopList, NewLoopList);

    DestroyChibiLoopTree(ChibiLoopTree);

    for(int i=0; i<LoopList.Num(); i++)
        LoopList[i].Clear();
    LoopList.Clear();

    LoopList.SetSize(NewLoopList.Num());
    for(i=0; i<NewLoopList.Num(); i++)
    {
        LoopList[i].CopyList(NewLoopList[i]);
        NewLoopList[i].Clear();
    }
    NewLoopList.Clear();

    for(i=0; i<LoopList.Num(); i++)
    {
        LoopVerts &loop = LoopList[i];
        PolyLine &firstLine = loop[0];

        for(int j=1; j<loop.Num(); j++)
        {
            PolyLine &line = loop[j];
            line.lineData = firstLine.lineData;
        }
    }

    //-----------------------------------------------------------
    // triangulate!

    for(i=0; i<LoopList.Num(); i++)
        TriangulateShape(LoopList[i]);

    //-----------------------------------------------------------
    // clean up!

    Lines.Clear();

    for(i=0; i<LoopList.Num(); i++)
    {
        Lines.AppendList(LoopList[i]);
        LoopList[i].Clear();
    }
    LoopList.Clear();
}