/** The mask is inpainted with ValidValue in this function. */ void FinishVertex(VertexDescriptorType targetNode, VertexDescriptorType sourceNode)// __attribute__((optimize(0))) // This supposedly makes this function build in debug mode (-g -O0) when the rest of the program is built in -O3 or similar) { // Mark this pixel and the area around it as filled, and mark the mask in this region as filled. // Determine the new boundary, and setup the nodes in the boundary queue. // std::cout << "InpaintingVisitor::FinishVertex()" << std::endl; // Construct the region around the vertex itk::Index<2> indexToFinish = ITKHelpers::CreateIndex(targetNode); itk::ImageRegion<2> regionToFinishFull = ITKHelpers::GetRegionInRadiusAroundPixel(indexToFinish, this->PatchHalfWidth); // Copy this region so that we can change (crop) the regionToFinish and still have a copy of the original region itk::ImageRegion<2> regionToFinish = regionToFinishFull; // Make sure the region is entirely inside the image // (because we allow target patches to not be entirely inside the image to handle the case where // the hole boundary is near the image boundary) regionToFinish.Crop(this->Image->GetLargestPossibleRegion()); if(this->DebugImages) { ITKHelpers::WriteImage(this->MaskImage, Helpers::GetSequentialFileName("Mask_Before", this->NumberOfFinishedPatches, "png", 3)); } // Mark all the pixels in this region as filled in the mask. ITKHelpers::SetRegionToConstant(this->MaskImage, regionToFinish, this->MaskImage->GetValidValue()); if(this->DebugImages) { ITKHelpers::WriteImage(this->MaskImage, Helpers::GetSequentialFileName("Mask_After", this->NumberOfFinishedPatches, "png", 3)); typename TImage::PixelType red; red.Fill(0); red[0] = 255; typename TImage::PixelType green; green.Fill(0); green[1] = 255; typename TImage::Pointer patchesCopiedImage = TImage::New(); ITKHelpers::DeepCopy(this->Image, patchesCopiedImage.GetPointer()); ITKHelpers::OutlineRegion(patchesCopiedImage.GetPointer(), regionToFinish, red); itk::Index<2> sourceRegionCenter = ITKHelpers::CreateIndex(sourceNode); itk::ImageRegion<2> sourceRegion = ITKHelpers::GetRegionInRadiusAroundPixel(sourceRegionCenter, this->PatchHalfWidth); sourceRegion = ITKHelpers::CropRegionAtPosition(sourceRegion, this->Image->GetLargestPossibleRegion(), regionToFinishFull); ITKHelpers::OutlineRegion(patchesCopiedImage.GetPointer(), sourceRegion, green); ITKHelpers::WriteRGBImage(patchesCopiedImage.GetPointer(), Helpers::GetSequentialFileName("PatchesCopied", this->NumberOfFinishedPatches, "png", 3)); } // Update the priority function. This must be done AFTER the mask is filled, // as some of the Priority functors only compute things on the hole boundary, or only // use data from the valid region of the image (indicated by valid pixels in the mask). this->PriorityFunction->Update(sourceNode, targetNode, this->NumberOfFinishedPatches); // Initialize (if requested) all vertices in the newly filled region because they may now be valid source nodes. // (You may not want to do this in some cases (i.e. if the descriptors needed cannot be // computed on newly filled regions)) if(this->AllowNewPatches) { itk::ImageRegionConstIteratorWithIndex<TImage> gridIterator(Image, regionToFinish); while(!gridIterator.IsAtEnd()) { VertexDescriptorType v = Helpers::ConvertFrom<VertexDescriptorType, itk::Index<2> >(gridIterator.GetIndex()); InitializeVertex(v); ++gridIterator; } } // Add pixels that are on the new boundary to the queue, and mark other pixels as not in the queue. itk::ImageRegionConstIteratorWithIndex<Mask> imageIterator(this->MaskImage, regionToFinish); typedef typename TBoundaryNodeQueue::HandleType HandleType; while(!imageIterator.IsAtEnd()) { VertexDescriptorType v = Helpers::ConvertFrom<VertexDescriptorType, itk::Index<2> >(imageIterator.GetIndex()); if(this->MaskImage->HasHoleNeighbor(imageIterator.GetIndex())) { float priority = this->PriorityFunction->ComputePriority(imageIterator.GetIndex()); this->BoundaryNodeQueue.push_or_update(v, priority); } else { this->BoundaryNodeQueue.mark_as_invalid(v); } ++imageIterator; } // std::cout << "FinishVertex after traversing finishing region there are " // << BoostHelpers::CountValidQueueNodes(BoundaryNodeQueue, BoundaryStatusMap) // << " valid nodes in the queue." << std::endl; // Sometimes pixels that are not in the finishing region that were boundary pixels are no longer // boundary pixels after the filling. Check for these. // E.g. (H=hole, B=boundary, V=valid, Q=query, F=filled, N=new boundary, // R=old boundary pixel that needs to be removed because it is no longer on the boundary) // Before filling /* V V V B H H H H * V V V B H H H H * V V V B H H H H * V V V B B Q B B * V V V V V V V V */ // After filling /* V V V B H H H H * V V V B H H H H * V V V B F F F H * V V V B F F F B * V V V V F F F V */ // New boundary /* V V V B H H H H * V V V B H H H H * V V V B N N N H * V V V R F F N B * V V V V F F F V */ // Expand the region itk::ImageRegion<2> expandedRegion = ITKHelpers::GetRegionInRadiusAroundPixel(indexToFinish, PatchHalfWidth + 1); // Make sure the region is entirely inside the image (to allow for target regions near the image boundary) expandedRegion.Crop(this->Image->GetLargestPossibleRegion()); std::vector<itk::Index<2> > boundaryPixels = ITKHelpers::GetBoundaryPixels(expandedRegion); for(unsigned int i = 0; i < boundaryPixels.size(); ++i) { // the region (the entire image) can be omitted, as this function automatically checks if the pixels are inside the image if(!this->MaskImage->HasHoleNeighbor(boundaryPixels[i])) { VertexDescriptorType v = Helpers::ConvertFrom<VertexDescriptorType, itk::Index<2> >(boundaryPixels[i]); put(this->BoundaryNodeQueue.BoundaryStatusMap, v, false); } } // std::cout << "FinishVertex after removing stale nodes outside finishing region there are " // << BoostHelpers::CountValidQueueNodes(BoundaryNodeQueue, BoundaryStatusMap) // << " valid nodes in the queue." << std::endl; this->NumberOfFinishedPatches++; // std::cout << "Leave InpaintingVisitor::FinishVertex()" << std::endl; } // end FinishVertex
/** The mask is inpainted with ValidValue in this function. */ void FinishVertex(VertexDescriptorType targetNode, VertexDescriptorType sourceNode) override { // Mark this pixel and the area around it as filled, and mark the mask in this region as filled. // Determine the new boundary, and setup the nodes in the boundary queue. // std::cout << "InpaintingVisitor::FinishVertex()" << std::endl; // Construct the region around the vertex itk::Index<2> indexToFinish = ITKHelpers::CreateIndex(targetNode); // Mark this node as having been used as a source node. this->UsedNodesSet.insert(indexToFinish); itk::ImageRegion<2> regionToFinishFull = ITKHelpers::GetRegionInRadiusAroundPixel(indexToFinish, this->PatchHalfWidth); // Copy this region so that we can change (crop) the regionToFinish and still have a copy of the original region itk::ImageRegion<2> regionToFinish = regionToFinishFull; // Make sure the region is entirely inside the image // (because we allow target patches to not be entirely inside the image to handle the case where // the hole boundary is near the image boundary) regionToFinish.Crop(this->FullRegion); itk::Index<2> sourceRegionCenter = ITKHelpers::CreateIndex(sourceNode); itk::ImageRegion<2> sourceRegion = ITKHelpers::GetRegionInRadiusAroundPixel(sourceRegionCenter, this->PatchHalfWidth); sourceRegion = ITKHelpers::CropRegionAtPosition(sourceRegion, this->MaskImage->GetLargestPossibleRegion(), regionToFinishFull); // Mark all pixels that were copied (in the hole region of the source patch) as having been used. // std::cout << "InpaintingVisitor::FinishVertex() mark pixels as used" << std::endl; itk::ImageRegionConstIteratorWithIndex<SourcePixelMapImageType> sourcePatchIterator(this->SourcePixelMapImage, sourceRegion); itk::ImageRegionConstIteratorWithIndex<Mask> targetPatchIterator(this->MaskImage, regionToFinish); while(!sourcePatchIterator.IsAtEnd()) { if(targetPatchIterator.Get() == this->MaskImage->GetHoleValue()) { this->CopiedPixelsImage->SetPixel(sourcePatchIterator.GetIndex(), true); // Mark this pixel as used // Save the location from which this pixel came. We want to use the index value in the SourcePixelMapImage, // because the value might not equal the current index in the case where new patches are allowed. this->SourcePixelMapImage->SetPixel(targetPatchIterator.GetIndex(), sourcePatchIterator.Get()); } ++sourcePatchIterator; ++targetPatchIterator; } if(this->DebugImages) { if(this->DebugLevel > 1) { ITKHelpers::WriteBoolImage(this->CopiedPixelsImage, Helpers::GetSequentialFileName("CopiedPixels", this->NumberOfFinishedPatches, "png", 3)); ITKHelpers::WriteImage(this->MaskImage, Helpers::GetSequentialFileName("Mask_Before", this->NumberOfFinishedPatches, "png", 3)); } } // Mark all the pixels in this region as filled in the mask. // std::cout << "InpaintingVisitor::FinishVertex() fill the mask" << std::endl; ITKHelpers::SetRegionToConstant(this->MaskImage, regionToFinish, this->MaskImage->GetValidValue()); // Write an image of where the source and target patch were in this iteration. // if(this->DebugImages && this->Image) // { // typename TImage::PixelType red; // red.Fill(0); // red[0] = 255; // typename TImage::PixelType green; // green.Fill(0); // green[1] = 255; // typename TImage::Pointer patchesCopiedImage = TImage::New(); // ITKHelpers::DeepCopy(this->Image, patchesCopiedImage.GetPointer()); // ITKHelpers::OutlineRegion(patchesCopiedImage.GetPointer(), regionToFinish, red); // ITKHelpers::OutlineRegion(patchesCopiedImage.GetPointer(), sourceRegion, green); // ITKHelpers::WriteRGBImage(patchesCopiedImage.GetPointer(), Helpers::GetSequentialFileName("PatchesCopied", this->NumberOfFinishedPatches, "png", 3)); // if(this->DebugLevel > 1) // { // ITKHelpers::WriteImage(this->MaskImage, Helpers::GetSequentialFileName("Mask_After", this->NumberOfFinishedPatches, "png", 3)); // } // } // Update the priority function. This must be done AFTER the mask is filled, // as some of the Priority functors only compute things on the hole boundary, or only // use data from the valid region of the image (indicated by valid pixels in the mask). // std::cout << "InpaintingVisitor::FinishVertex() update priority" << std::endl; this->PriorityFunction->Update(sourceNode, targetNode, this->NumberOfFinishedPatches); // std::cout << "InpaintingVisitor::FinishVertex() finish update priority" << std::endl; // Initialize (if requested) all vertices in the newly filled region because they may now be valid source nodes. // (You may not want to do this in some cases (i.e. if the descriptors needed cannot be // computed on newly filled regions)) if(this->AllowNewPatches) { // std::cout << "Initializing new vertices..." << std::endl; itk::ImageRegionConstIteratorWithIndex<Mask> gridIterator(this->MaskImage, regionToFinish); while(!gridIterator.IsAtEnd()) { VertexDescriptorType v = Helpers::ConvertFrom<VertexDescriptorType, itk::Index<2> >(gridIterator.GetIndex()); InitializeVertex(v); ++gridIterator; } } // Add pixels that are on the new boundary to the queue, and mark other pixels as not in the queue. // std::cout << "InpaintingVisitor::FinishVertex() iterator" << std::endl; itk::ImageRegionConstIteratorWithIndex<Mask> imageIterator(this->MaskImage, regionToFinish); // std::cout << "InpaintingVisitor::FinishVertex() finish iterator" << std::endl; typedef typename TBoundaryNodeQueue::HandleType HandleType; // Naive, unparallelizable way // while(!imageIterator.IsAtEnd()) // { // VertexDescriptorType v = Helpers::ConvertFrom<VertexDescriptorType, itk::Index<2> >(imageIterator.GetIndex()); // if(this->MaskImage->HasHoleNeighbor(imageIterator.GetIndex())) // { // float priority = this->PriorityFunction->ComputePriority(imageIterator.GetIndex()); // this->BoundaryNodeQueue.push_or_update(v, priority); // } // else // { // this->BoundaryNodeQueue.mark_as_invalid(v); // } // ++imageIterator; // } // Parallelizable way - collect the pixels that need their priority computed // std::cout << "InpaintingVisitor::FinishVertex() Parallelizable way" << std::endl; typedef std::vector<itk::Index<2> > IndexVectorType; IndexVectorType pixelsToCompute; while(!imageIterator.IsAtEnd()) { VertexDescriptorType v = Helpers::ConvertFrom<VertexDescriptorType, itk::Index<2> >(imageIterator.GetIndex()); if(this->MaskImage->GetPixel(imageIterator.GetIndex()) == this->MaskImage->GetValidValue() && this->MaskImage->HasHoleNeighbor(imageIterator.GetIndex())) { pixelsToCompute.push_back(imageIterator.GetIndex()); } else { this->BoundaryNodeQueue->mark_as_invalid(v); } ++imageIterator; } // std::cout << "InpaintingVisitor::FinishVertex() update queue" << std::endl; #pragma omp parallel for for(IndexVectorType::const_iterator pixelIterator = pixelsToCompute.begin(); pixelIterator < pixelsToCompute.end(); ++pixelIterator) { VertexDescriptorType v = Helpers::ConvertFrom<VertexDescriptorType, itk::Index<2> >(*pixelIterator); float priority = this->PriorityFunction->ComputePriority(*pixelIterator); #pragma omp critical // There are weird crashes without this guard this->BoundaryNodeQueue->push_or_update(v, priority); } // std::cout << "FinishVertex after traversing finishing region there are " // << BoostHelpers::CountValidQueueNodes(BoundaryNodeQueue, BoundaryStatusMap) // << " valid nodes in the queue." << std::endl; // Sometimes pixels that are not in the finishing region that were boundary pixels are no longer // boundary pixels after the filling. Check for these. // E.g. (H=hole, B=boundary, V=valid, Q=query, F=filled, N=new boundary, // R=old boundary pixel that needs to be removed because it is no longer on the boundary) // Before filling /* V V V B H H H H * V V V B H H H H * V V V B H H H H * V V V B B Q B B * V V V V V V V V */ // After filling /* V V V B H H H H * V V V B H H H H * V V V B F F F H * V V V B F F F B * V V V V F F F V */ // New boundary /* V V V B H H H H * V V V B H H H H * V V V B N N N H * V V V R F F N B * V V V V F F F V */ // Expand the region // std::cout << "InpaintingVisitor::FinishVertex() expand" << std::endl; itk::ImageRegion<2> expandedRegion = ITKHelpers::GetRegionInRadiusAroundPixel(indexToFinish, PatchHalfWidth + 1); // Make sure the region is entirely inside the image (to allow for target regions near the image boundary) expandedRegion.Crop(this->FullRegion); std::vector<itk::Index<2> > boundaryPixels = ITKHelpers::GetBoundaryPixels(expandedRegion); // std::cout << "InpaintingVisitor::FinishVertex() boundary pixels" << std::endl; for(unsigned int i = 0; i < boundaryPixels.size(); ++i) { // the region (the entire image) can be omitted, as this function automatically checks if the pixels are inside the image if(!this->MaskImage->HasHoleNeighbor(boundaryPixels[i])) { VertexDescriptorType v = Helpers::ConvertFrom<VertexDescriptorType, itk::Index<2> >(boundaryPixels[i]); put(this->BoundaryNodeQueue->BoundaryStatusMap, v, false); } } // std::cout << "FinishVertex after removing stale nodes outside finishing region there are " // << BoostHelpers::CountValidQueueNodes(BoundaryNodeQueue, BoundaryStatusMap) // << " valid nodes in the queue." << std::endl; this->NumberOfFinishedPatches++; // std::cout << "Leave InpaintingVisitor::FinishVertex()" << std::endl; } // end FinishVertex
void Encoder::Encode(DWORD ID, DWORD Class, DWORD CTNumber, DWORD MType) { BOOL bInsertSurfaceNode = FALSE; BOOL bInsertTextureNode = FALSE; m_pCurrentNode = m_pRootNode; // COBRA - RED - Missing Last Texture Initialization to INVALID DWORD dwCurrentTexture=-1; DWORD dwCurrentzBias=0; NodeType LastType=ROOT; DXFlagsType LastFlags; LastFlags.w=0x00; bool ChangeSurface=false; while(m_pCurrentNode != NULL) { IdleMode(); NodeType Type=m_pCurrentNode->Type; DXFlagsType Flags; Flags.w=m_pCurrentNode->Flags.w; // Make all checks here ChangeSurface=false; if(Type!=LastType || Type==DOF || Type==CLOSEDOF || Type==SLOT ) ChangeSurface = true; if(Flags.b.Texture && m_pCurrentNode->Texture!=dwCurrentTexture) ChangeSurface = true; if(Flags.b.Texture != LastFlags.b.Texture) ChangeSurface=true; if(Flags.b.Alpha != LastFlags.b.Alpha) ChangeSurface=true; if(Flags.b.Gouraud != LastFlags.b.Gouraud ) ChangeSurface=true; if(Flags.b.Lite != LastFlags.b.Lite ) ChangeSurface=true; if((Flags.b.VColor) != (LastFlags.b.VColor)) ChangeSurface=true; if(Flags.b.zBias != LastFlags.b.zBias) ChangeSurface=true; if(Flags.b.zBias && m_pCurrentNode->dwzBias!=dwCurrentzBias) ChangeSurface=true; if(Flags.b.ChromaKey != LastFlags.b.ChromaKey) ChangeSurface=true; // if any change if(ChangeSurface){ // Patch the segments PatchDWORD(); switch (Type){ case DOT: case LINE: case TRIANGLE: // Check if a Textured new surace and last texture still valid if(Flags.b.Texture && m_pCurrentNode->Texture!=dwCurrentTexture){ // No moer used Texture node //WriteTextureNode(m_pCurrentNode); dwCurrentTexture=m_pCurrentNode->Texture; } dwCurrentzBias=m_pCurrentNode->dwzBias; // Write the new Surface WriteSurfaceNode(m_pCurrentNode, dwCurrentTexture); // New ID m_dwNodeID++; break; case DOF: // We've to insert a new DOF node {DXDof *pDof = (DXDof*)m_pCurrentNode; WriteDofNode(pDof);} // and reset surfaces properties Flags.w=0; dwCurrentTexture=-1; // New ID m_dwNodeID++; break; case SLOT: // We've to insert a new SLOT node WriteSlotNode((DXSlot*)m_pCurrentNode); // New ID m_dwNodeID++; break; case CLOSEDOF: // We've to insert a new END DOF node WriteDofEndNode(); // and reset surfaces properties Flags.w=0; dwCurrentTexture=-1; // New ID m_dwNodeID++; break; default : MessageBox(NULL, "Unknown SURFACE TYPE!!", "Encoder", 0); } ChangeSurface=false; LastFlags=Flags; LastType=Type; } switch(Type) { case DOT: { DXVertex *pVertex = (DXVertex*)m_pCurrentNode; D3DVERTEXEX dxVertex; InitializeVertex(&dxVertex); CopyVertex(&(pVertex->Vertex), pVertex->VColor, &dxVertex); /*memcpy((void*)&dxVertex, (const void*)&pVertex->Vertex, sizeof(pVertex->Vertex)); memcpy((void*)(&dxVertex + sizeof(pVertex->Vertex)), (const void*)&pVertex->VColor, sizeof(pVertex->VColor));*/ // Add vertex in NON INDEXED MODE Int16 iIndex = AddVertexToPool(&dxVertex, false); WriteBuffer((const void*)&iIndex, sizeof(iIndex)); } break; case LINE: { DXLine *pLine = (DXLine*)m_pCurrentNode; for(int i=0; i<2; i++) { D3DVERTEXEX dxVertex; InitializeVertex(&dxVertex); CopyVertex(&(pLine->Vertex[i]), pLine->VColor[i], &dxVertex); /*memcpy((void*)&dxVertex, (const void*)&pLine->Vertex[i], sizeof(pLine->Vertex[i])); memcpy((void*)(&dxVertex + sizeof(pLine->Vertex[i])), (const void*)&pLine->VColor[i], sizeof(pLine->VColor[0]));*/ Int16 iIndex = AddVertexToPool(&dxVertex); WriteBuffer((const void*)&iIndex, sizeof(iIndex)); } } break; case TRIANGLE: { DXTriangle *pTriangle = (DXTriangle*)m_pCurrentNode; for(int i=0; i<3; i++) { D3DVERTEXEX dxVertex; InitializeVertex(&dxVertex); CopyVertex(&(pTriangle->Vertex[i]), pTriangle->VColor[i], &dxVertex); /*BYTE *pVertex = (BYTE*)&dxVertex; memcpy((void*)&dxVertex, (const void*)&pTriangle->Vertex[i], sizeof(pTriangle->Vertex[i])); memcpy((void*)(pVertex + sizeof(pTriangle->Vertex[i])), (const void*)&pTriangle->VColor[i], sizeof(pTriangle->VColor[0]));*/ Int16 iIndex = AddVertexToPool(&dxVertex); WriteBuffer((const void*)&iIndex, sizeof(iIndex)); } } break; } // Update pointers //m_pPreviousNode = m_pCurrentNode; m_pCurrentNode = m_pCurrentNode->Next; //m_pNextNode = m_pCurrentNode != NULL ? m_pCurrentNode->Next : NULL; } //// Set last node total size (Node + Data (total indexes size)) //DWORD dwTotalNodeSize = (m_dwTotalSurfaceVertexes*sizeof(Int16) + sizeof(DxSurfaceType)); //memcpy((void*)m_pLastSurfaceNode, (const void*)&dwTotalNodeSize, sizeof(dwTotalNodeSize)); //// Add last node Vertex Counter to last surface node //memcpy(m_pLastSurfaceNode + 12, (const void*)&m_dwTotalSurfaceVertexes, sizeof(m_dwTotalSurfaceVertexes)); // Patch the segments PatchDWORD(); // Write ENDMODEL node DxEndModelType dxEndModelNode; dxEndModelNode.h.dwNodeSize = sizeof(DxEndModelType); dxEndModelNode.h.Type = DX_MODELEND; WriteBuffer((void*)&dxEndModelNode, sizeof(dxEndModelNode)); // Write total number of nodes ((DxDbHeader*)m_pHeader)->dwNodesNr=m_dwTotalNodeCount; // Write other header fields //DWORD dwVertexesPoolStart = (DWORD)(m_pBuffer + m_dwBufferOffset); ((DxDbHeader*)m_pHeader)->pVPool=m_dwBufferOffset; ((DxDbHeader*)m_pHeader)->dwPoolSize=m_dwVertexesPoolSize; ((DxDbHeader*)m_pHeader)->dwNVertices=m_dwVertexesNumber; // Copy vertexes pool after nodes section WriteBuffer((const void*)m_pVertexesPool, m_dwVertexesPoolSize); ((DxDbHeader*)m_pHeader)->Id=ID; ((DxDbHeader*)m_pHeader)->ModelSize= m_dwBufferOffset; ((DxDbHeader*)m_pHeader)->VBClass=Class; ((DxDbHeader*)m_pHeader)->Version=MODEL_VERSION|((MODEL_VERSION^0xffff)<<16); // Assign Materials Features m_dwBufferOffset=AssignSurfaceFeatures(m_pBuffer, CTNumber, MType); #ifdef CRYPTED_MODELS TheVbManager.Encrypt((DWORD*)m_pBuffer); #endif // Write file //WriteFile(); }
void Encoder::Encode() { BOOL bInsertSurfaceNode = FALSE; BOOL bInsertTextureNode = FALSE; m_pCurrentNode = m_pRootNode; while(m_pCurrentNode != NULL) { m_pPreviousNode = m_pCurrentNode->Prev; //m_pNextNode = m_pCurrentNode->Next; if(m_pCurrentNode == m_pRootNode) { // Root node, insert Texture and Surface node if(m_pCurrentNode->Flags.b.Texture) WriteTextureNode(m_pCurrentNode); WriteSurfaceNode(m_pCurrentNode); } else { // Check for node property changes if(m_pCurrentNode->Type != DOF && m_pCurrentNode->Type != CLOSEDOF) { if(m_pPreviousNode->Type == DOF || m_pPreviousNode->Type == CLOSEDOF) { if(m_pCurrentNode->Flags.b.Texture) WriteTextureNode(m_pCurrentNode); WriteSurfaceNode(m_pCurrentNode); } else { if(m_pCurrentNode->Flags.b.Texture) { if(m_pCurrentNode->Texture != m_pPreviousNode->Texture) { // Texture of current node differs from previous node, we've to insert a TEXTURE node before new SURFACE node WriteTextureNode(m_pCurrentNode); WriteSurfaceNode(m_pCurrentNode); } else { // Check if other fields are changed (in this case we've to insert a new SURFACE node if( m_pCurrentNode->Flags.b.ALpha != m_pPreviousNode->Flags.b.ALpha || m_pCurrentNode->Flags.b.Gouraud != m_pPreviousNode->Flags.b.Gouraud || m_pCurrentNode->Flags.b.Lite != m_pPreviousNode->Flags.b.Lite || m_pCurrentNode->Type != m_pPreviousNode->Type ) WriteSurfaceNode(m_pCurrentNode); } } else if(m_pCurrentNode->Flags.b.Solid || m_pCurrentNode->Flags.b.VColor) { // Colour node, check only for Alpha changes if( m_pCurrentNode->Flags.b.ALpha != m_pPreviousNode->Flags.b.ALpha || m_pCurrentNode->Type != m_pPreviousNode->Type ) WriteSurfaceNode(m_pCurrentNode); } } } } switch(m_pCurrentNode->Type) { case DOT: { DXVertex *pVertex = (DXVertex*)m_pCurrentNode; D3DVERTEXEX dxVertex; InitializeVertex(&dxVertex); memcpy((void*)&dxVertex, (const void*)&pVertex->Vertex, sizeof(pVertex->Vertex)); memcpy((void*)(&dxVertex + sizeof(pVertex->Vertex)), (const void*)&pVertex->VColor, sizeof(pVertex->VColor)); Int16 iIndex = AddVertexToPool(&dxVertex); WriteBuffer((const void*)&iIndex, sizeof(iIndex)); //if(m_pCurrentNode->Flags.b.Texture) //{ // // Write all D3DVertex information // WriteBuffer((void*)&pVertex->Vertex, sizeof(pVertex->Vertex)); //} //else //{ // // In this case, write only x,y,z,nx,ny,nz (24 bytes total) and VColour // WriteBuffer((void*)&pVertex->Vertex, 24); // WriteBuffer((void*)&pVertex->VColor, sizeof(pVertex->VColor)); //} //m_dwTotalSurfaceVertexes++; } break; case LINE: { DXLine *pLine = (DXLine*)m_pCurrentNode; for(int i=0; i<2; i++) { D3DVERTEXEX dxVertex; InitializeVertex(&dxVertex); memcpy((void*)&dxVertex, (const void*)&pLine->Vertex[i], sizeof(pLine->Vertex[i])); memcpy((void*)(&dxVertex + sizeof(pLine->Vertex[i])), (const void*)&pLine->VColor[i], sizeof(pLine->VColor[0])); Int16 iIndex = AddVertexToPool(&dxVertex); WriteBuffer((const void*)&iIndex, sizeof(iIndex)); } //if(m_pCurrentNode->Flags.b.Texture) //{ // // Write all D3DVertex information // WriteBuffer((void*)&pLine->Vertex, sizeof(pLine->Vertex)); //} //else //{ // // In this case, write only x,y,z,nx,ny,nz (24 bytes total) and VColour // for(int i=0;i<2;i++) // { // WriteBuffer((void*)&pLine->Vertex[i], 24); // WriteBuffer((void*)&pLine->VColor[i], sizeof(pLine->VColor[0])); // } //} //m_dwTotalSurfaceVertexes += 2; } break; case TRIANGLE: { DXTriangle *pTriangle = (DXTriangle*)m_pCurrentNode; for(int i=0; i<3; i++) { D3DVERTEXEX dxVertex; InitializeVertex(&dxVertex); BYTE *pVertex = (BYTE*)&dxVertex; memcpy((void*)&dxVertex, (const void*)&pTriangle->Vertex[i], sizeof(pTriangle->Vertex[i])); memcpy((void*)(pVertex + sizeof(pTriangle->Vertex[i])), (const void*)&pTriangle->VColor[i], sizeof(pTriangle->VColor[0])); Int16 iIndex = AddVertexToPool(&dxVertex); WriteBuffer((const void*)&iIndex, sizeof(iIndex)); } //if(m_pCurrentNode->Flags.b.Texture) //{ // // Write all D3DVertex information // WriteBuffer((void*)&pTriangle->Vertex, sizeof(pTriangle->Vertex)); //} //else //{ // // In this case, write only x,y,z,nx,ny,nz (24 bytes total) and VColour // for(int i=0;i<3;i++) // { // WriteBuffer((void*)&pTriangle->Vertex[i], 24); // WriteBuffer((void*)&pTriangle->VColor[i], sizeof(pTriangle->VColor[0])); // } //} //m_dwTotalSurfaceVertexes += 3; } break; case DOF: { // We've to insert a new DOF node DXDof *pDof = (DXDof*)m_pCurrentNode; WriteDofNode(pDof); } break; case CLOSEDOF: { // We've to insert a new END DOF node WriteDofEndNode(); } break; } // Update pointers //m_pPreviousNode = m_pCurrentNode; m_pCurrentNode = m_pCurrentNode->Next; //m_pNextNode = m_pCurrentNode != NULL ? m_pCurrentNode->Next : NULL; } // Set last node total size (Node + Data (total indexes size)) DWORD dwTotalNodeSize = (m_dwTotalSurfaceVertexes*sizeof(Int16) + sizeof(DxSurfaceType)); memcpy((void*)m_pLastSurfaceNode, (const void*)&dwTotalNodeSize, sizeof(dwTotalNodeSize)); // Add last node Vertex Counter to last surface node memcpy(m_pLastSurfaceNode + 12, (const void*)&m_dwTotalSurfaceVertexes, sizeof(m_dwTotalSurfaceVertexes)); // Write ENDMODEL node DxEndModelType dxEndModelNode; dxEndModelNode.h.dwNodeSize = sizeof(DxEndModelType); dxEndModelNode.h.Type = DX_MODELEND; WriteBuffer((void*)&dxEndModelNode, sizeof(dxEndModelNode)); // Write total number of nodes memcpy((void*)m_pHeader, (const void*)&m_dwTotalNodeCount, sizeof(m_dwTotalNodeCount)); // Write other header fields //DWORD dwVertexesPoolStart = (DWORD)(m_pBuffer + m_dwBufferOffset); memcpy((void*)(m_pHeader+4), (const void*)&m_dwBufferOffset, sizeof(DWORD)); memcpy((void*)(m_pHeader+8), (const void*)&m_dwVertexesPoolSize, sizeof(DWORD)); memcpy((void*)(m_pHeader+12), (const void*)&m_dwVertexesNumber, sizeof(DWORD)); // Copy vertexes pool after nodes section WriteBuffer((const void*)m_pVertexesPool, m_dwVertexesPoolSize); // Write file WriteFile(); }