oops
This commit is contained in:
26
DSMeshConvert.sln
Normal file
26
DSMeshConvert.sln
Normal file
@@ -0,0 +1,26 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||
# Visual Studio 2010
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DSMeshConvert", "DSMeshConvert\DSMeshConvert.vcxproj", "{97670E69-B730-46FA-AC5B-43A04C8E1F54}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DSMeshLoad", "DSMeshLoad\DSMeshLoad.vcxproj", "{F97FBD13-23BC-42C4-A1DC-FA263214ED05}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{97670E69-B730-46FA-AC5B-43A04C8E1F54}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{97670E69-B730-46FA-AC5B-43A04C8E1F54}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{97670E69-B730-46FA-AC5B-43A04C8E1F54}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{97670E69-B730-46FA-AC5B-43A04C8E1F54}.Release|Win32.Build.0 = Release|Win32
|
||||
{F97FBD13-23BC-42C4-A1DC-FA263214ED05}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{F97FBD13-23BC-42C4-A1DC-FA263214ED05}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{F97FBD13-23BC-42C4-A1DC-FA263214ED05}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{F97FBD13-23BC-42C4-A1DC-FA263214ED05}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
BIN
DSMeshConvert/Assimp32.dll
Normal file
BIN
DSMeshConvert/Assimp32.dll
Normal file
Binary file not shown.
BIN
DSMeshConvert/Assimp32d.dll
Normal file
BIN
DSMeshConvert/Assimp32d.dll
Normal file
Binary file not shown.
@@ -2,9 +2,9 @@
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9,00"
|
||||
Name="DSTexCompress"
|
||||
ProjectGUID="{126B132C-BACE-403D-A643-CF31C47672C8}"
|
||||
RootNamespace="DSTexCompress"
|
||||
Name="DSMeshConvert"
|
||||
ProjectGUID="{97670E69-B730-46FA-AC5B-43A04C8E1F54}"
|
||||
RootNamespace="DSMeshConvert"
|
||||
TargetFrameworkVersion="196613"
|
||||
>
|
||||
<Platforms>
|
||||
@@ -40,7 +40,7 @@
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="FreeImage\Dist"
|
||||
AdditionalIncludeDirectories="assimp--1.1.700-sdk\include"
|
||||
PreprocessorDefinitions="_CRT_SECURE_NO_WARNINGS"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
@@ -59,8 +59,8 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="FreeImagePlus.lib"
|
||||
AdditionalLibraryDirectories="FreeImage\Dist"
|
||||
AdditionalDependencies="assimp.lib"
|
||||
AdditionalLibraryDirectories="assimp--1.1.700-sdk\lib\assimp_debug-dll_win32"
|
||||
GenerateDebugInformation="true"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
@@ -113,7 +113,8 @@
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
EnableIntrinsicFunctions="true"
|
||||
AdditionalIncludeDirectories="FreeImage\Dist"
|
||||
AdditionalIncludeDirectories="assimp--1.1.700-sdk\include"
|
||||
PreprocessorDefinitions="_CRT_SECURE_NO_WARNINGS"
|
||||
RuntimeLibrary="2"
|
||||
EnableFunctionLevelLinking="true"
|
||||
WarningLevel="3"
|
||||
@@ -130,8 +131,8 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="FreeImage.lib FreeImagePlus.lib"
|
||||
AdditionalLibraryDirectories="FreeImage\Dist"
|
||||
AdditionalDependencies="assimp.lib nvtristrip.lib"
|
||||
AdditionalLibraryDirectories="assimp--1.1.700-sdk\lib\assimp_release-dll_win32"
|
||||
GenerateDebugInformation="true"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
@@ -164,61 +165,97 @@
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Header"
|
||||
Name="nvtristrip"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\src\Color.h"
|
||||
RelativePath=".\NvTriStrip\NvTriStrip.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\Compressor.h"
|
||||
RelativePath=".\NvTriStrip\NvTriStrip.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\Cut.h"
|
||||
RelativePath=".\NvTriStrip\NvTriStripObjects.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\Histogram.h"
|
||||
RelativePath=".\NvTriStrip\NvTriStripObjects.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\Palette.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\types.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\wingetopt.h"
|
||||
RelativePath=".\NvTriStrip\VertexCache.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Source"
|
||||
Name="cets-pterdiman"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\src\Compressor.cpp"
|
||||
RelativePath=".\cets-pterdiman\Adjacency.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\Histogram.cpp"
|
||||
RelativePath=".\cets-pterdiman\Adjacency.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\main.cpp"
|
||||
RelativePath=".\cets-pterdiman\CustomArray.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\Palette.cpp"
|
||||
RelativePath=".\cets-pterdiman\CustomArray.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\wingetopt.c"
|
||||
RelativePath=".\cets-pterdiman\RevisitedRadix.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\cets-pterdiman\RevisitedRadix.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\cets-pterdiman\Striper.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\cets-pterdiman\Striper.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\cets-pterdiman\Strips.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="ac"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\ac\tc.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ac\tc.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\main.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stripping.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\stripping.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\types.h"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
115
DSMeshConvert/DSMeshConvert.vcxproj
Normal file
115
DSMeshConvert/DSMeshConvert.vcxproj
Normal file
@@ -0,0 +1,115 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{97670E69-B730-46FA-AC5B-43A04C8E1F54}</ProjectGuid>
|
||||
<RootNamespace>DSMeshConvert</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>assimp--1.1.700-sdk\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>assimp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>assimp--1.1.700-sdk\lib\assimp_debug-dll_win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>assimp--1.1.700-sdk\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>assimp.lib;nvtristrip.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>assimp--1.1.700-sdk\lib\assimp_release-dll_win32;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="NvTriStrip\NvTriStrip.cpp" />
|
||||
<ClCompile Include="NvTriStrip\NvTriStripObjects.cpp" />
|
||||
<ClCompile Include="cets-pterdiman\Adjacency.cpp" />
|
||||
<ClCompile Include="cets-pterdiman\CustomArray.cpp" />
|
||||
<ClCompile Include="cets-pterdiman\RevisitedRadix.cpp" />
|
||||
<ClCompile Include="cets-pterdiman\Striper.cpp" />
|
||||
<ClCompile Include="cets-pterdiman\Strips.cpp" />
|
||||
<ClCompile Include="ac\tc.c" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="stripping.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="NvTriStrip\NvTriStrip.h" />
|
||||
<ClInclude Include="NvTriStrip\NvTriStripObjects.h" />
|
||||
<ClInclude Include="NvTriStrip\VertexCache.h" />
|
||||
<ClInclude Include="cets-pterdiman\Adjacency.h" />
|
||||
<ClInclude Include="cets-pterdiman\CustomArray.h" />
|
||||
<ClInclude Include="cets-pterdiman\RevisitedRadix.h" />
|
||||
<ClInclude Include="cets-pterdiman\Striper.h" />
|
||||
<ClInclude Include="ac\tc.h" />
|
||||
<ClInclude Include="stripping.h" />
|
||||
<ClInclude Include="types.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
70
DSMeshConvert/DSMeshConvert.vcxproj.filters
Normal file
70
DSMeshConvert/DSMeshConvert.vcxproj.filters
Normal file
@@ -0,0 +1,70 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="nvtristrip">
|
||||
<UniqueIdentifier>{71079b66-3d1e-47a0-8158-a600e6e49bc7}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="cets-pterdiman">
|
||||
<UniqueIdentifier>{19ec309f-4480-4f3c-9048-b163e75ee401}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="ac">
|
||||
<UniqueIdentifier>{a6a88c29-17fe-49f9-a515-c61464a7bed6}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="NvTriStrip\NvTriStrip.cpp">
|
||||
<Filter>nvtristrip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NvTriStrip\NvTriStripObjects.cpp">
|
||||
<Filter>nvtristrip</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="cets-pterdiman\Adjacency.cpp">
|
||||
<Filter>cets-pterdiman</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="cets-pterdiman\CustomArray.cpp">
|
||||
<Filter>cets-pterdiman</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="cets-pterdiman\RevisitedRadix.cpp">
|
||||
<Filter>cets-pterdiman</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="cets-pterdiman\Striper.cpp">
|
||||
<Filter>cets-pterdiman</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="cets-pterdiman\Strips.cpp">
|
||||
<Filter>cets-pterdiman</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ac\tc.c">
|
||||
<Filter>ac</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="stripping.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="NvTriStrip\NvTriStrip.h">
|
||||
<Filter>nvtristrip</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NvTriStrip\NvTriStripObjects.h">
|
||||
<Filter>nvtristrip</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NvTriStrip\VertexCache.h">
|
||||
<Filter>nvtristrip</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="cets-pterdiman\Adjacency.h">
|
||||
<Filter>cets-pterdiman</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="cets-pterdiman\CustomArray.h">
|
||||
<Filter>cets-pterdiman</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="cets-pterdiman\RevisitedRadix.h">
|
||||
<Filter>cets-pterdiman</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="cets-pterdiman\Striper.h">
|
||||
<Filter>cets-pterdiman</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ac\tc.h">
|
||||
<Filter>ac</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="stripping.h" />
|
||||
<ClInclude Include="types.h" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
145
DSMeshConvert/NvTriStrip.h
Normal file
145
DSMeshConvert/NvTriStrip.h
Normal file
@@ -0,0 +1,145 @@
|
||||
#ifndef NVTRISTRIP_H
|
||||
#define NVTRISTRIP_H
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#pragma comment(lib, "nvtristrip")
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Public interface for stripifier
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//GeForce1 and 2 cache size
|
||||
#define CACHESIZE_GEFORCE1_2 16
|
||||
|
||||
//GeForce3 cache size
|
||||
#define CACHESIZE_GEFORCE3 24
|
||||
|
||||
enum PrimType
|
||||
{
|
||||
PT_LIST,
|
||||
PT_STRIP,
|
||||
PT_FAN
|
||||
};
|
||||
|
||||
struct PrimitiveGroup
|
||||
{
|
||||
PrimType type;
|
||||
unsigned int numIndices;
|
||||
unsigned short* indices;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PrimitiveGroup() : type(PT_STRIP), numIndices(0), indices(NULL) {}
|
||||
~PrimitiveGroup()
|
||||
{
|
||||
if(indices)
|
||||
delete[] indices;
|
||||
indices = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// EnableRestart()
|
||||
//
|
||||
// For GPUs that support primitive restart, this sets a value as the restart index
|
||||
//
|
||||
// Restart is meaningless if strips are not being stitched together, so enabling restart
|
||||
// makes NvTriStrip forcing stitching. So, you'll get back one strip.
|
||||
//
|
||||
// Default value: disabled
|
||||
//
|
||||
void EnableRestart(const unsigned int restartVal);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// DisableRestart()
|
||||
//
|
||||
// For GPUs that support primitive restart, this disables using primitive restart
|
||||
//
|
||||
void DisableRestart();
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SetCacheSize()
|
||||
//
|
||||
// Sets the cache size which the stripfier uses to optimize the data.
|
||||
// Controls the length of the generated individual strips.
|
||||
// This is the "actual" cache size, so 24 for GeForce3 and 16 for GeForce1/2
|
||||
// You may want to play around with this number to tweak performance.
|
||||
//
|
||||
// Default value: 16
|
||||
//
|
||||
void SetCacheSize(const unsigned int cacheSize);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SetStitchStrips()
|
||||
//
|
||||
// bool to indicate whether to stitch together strips into one huge strip or not.
|
||||
// If set to true, you'll get back one huge strip stitched together using degenerate
|
||||
// triangles.
|
||||
// If set to false, you'll get back a large number of separate strips.
|
||||
//
|
||||
// Default value: true
|
||||
//
|
||||
void SetStitchStrips(const bool bStitchStrips);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SetMinStripSize()
|
||||
//
|
||||
// Sets the minimum acceptable size for a strip, in triangles.
|
||||
// All strips generated which are shorter than this will be thrown into one big, separate list.
|
||||
//
|
||||
// Default value: 0
|
||||
//
|
||||
void SetMinStripSize(const unsigned int minSize);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SetListsOnly()
|
||||
//
|
||||
// If set to true, will return an optimized list, with no strips at all.
|
||||
//
|
||||
// Default value: false
|
||||
//
|
||||
void SetListsOnly(const bool bListsOnly);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// GenerateStrips()
|
||||
//
|
||||
// in_indices: input index list, the indices you would use to render
|
||||
// in_numIndices: number of entries in in_indices
|
||||
// primGroups: array of optimized/stripified PrimitiveGroups
|
||||
// numGroups: number of groups returned
|
||||
//
|
||||
// Be sure to call delete[] on the returned primGroups to avoid leaking mem
|
||||
//
|
||||
bool GenerateStrips(const unsigned short* in_indices, const unsigned int in_numIndices,
|
||||
PrimitiveGroup** primGroups, unsigned short* numGroups, bool validateEnabled = false);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// RemapIndices()
|
||||
//
|
||||
// Function to remap your indices to improve spatial locality in your vertex buffer.
|
||||
//
|
||||
// in_primGroups: array of PrimitiveGroups you want remapped
|
||||
// numGroups: number of entries in in_primGroups
|
||||
// numVerts: number of vertices in your vertex buffer, also can be thought of as the range
|
||||
// of acceptable values for indices in your primitive groups.
|
||||
// remappedGroups: array of remapped PrimitiveGroups
|
||||
//
|
||||
// Note that, according to the remapping handed back to you, you must reorder your
|
||||
// vertex buffer.
|
||||
//
|
||||
// Credit goes to the MS Xbox crew for the idea for this interface.
|
||||
//
|
||||
void RemapIndices(const PrimitiveGroup* in_primGroups, const unsigned short numGroups,
|
||||
const unsigned short numVerts, PrimitiveGroup** remappedGroups);
|
||||
|
||||
#endif
|
||||
BIN
DSMeshConvert/NvTriStrip.lib
Normal file
BIN
DSMeshConvert/NvTriStrip.lib
Normal file
Binary file not shown.
500
DSMeshConvert/NvTriStrip/NvTriStrip.cpp
Normal file
500
DSMeshConvert/NvTriStrip/NvTriStrip.cpp
Normal file
@@ -0,0 +1,500 @@
|
||||
|
||||
#include "NvTriStripObjects.h"
|
||||
#include "NvTriStrip.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
//private data
|
||||
static unsigned int cacheSize = CACHESIZE_GEFORCE1_2;
|
||||
static bool bStitchStrips = true;
|
||||
static unsigned int minStripSize = 0;
|
||||
static bool bListsOnly = false;
|
||||
static unsigned int restartVal = 0;
|
||||
static bool bRestart = false;
|
||||
|
||||
void EnableRestart(const unsigned int _restartVal)
|
||||
{
|
||||
bRestart = true;
|
||||
restartVal = _restartVal;
|
||||
}
|
||||
|
||||
void DisableRestart()
|
||||
{
|
||||
bRestart = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SetListsOnly()
|
||||
//
|
||||
// If set to true, will return an optimized list, with no strips at all.
|
||||
//
|
||||
// Default value: false
|
||||
//
|
||||
void SetListsOnly(const bool _bListsOnly)
|
||||
{
|
||||
bListsOnly = _bListsOnly;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SetCacheSize()
|
||||
//
|
||||
// Sets the cache size which the stripfier uses to optimize the data.
|
||||
// Controls the length of the generated individual strips.
|
||||
// This is the "actual" cache size, so 24 for GeForce3 and 16 for GeForce1/2
|
||||
// You may want to play around with this number to tweak performance.
|
||||
//
|
||||
// Default value: 16
|
||||
//
|
||||
void SetCacheSize(const unsigned int _cacheSize)
|
||||
{
|
||||
cacheSize = _cacheSize;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SetStitchStrips()
|
||||
//
|
||||
// bool to indicate whether to stitch together strips into one huge strip or not.
|
||||
// If set to true, you'll get back one huge strip stitched together using degenerate
|
||||
// triangles.
|
||||
// If set to false, you'll get back a large number of separate strips.
|
||||
//
|
||||
// Default value: true
|
||||
//
|
||||
void SetStitchStrips(const bool _bStitchStrips)
|
||||
{
|
||||
bStitchStrips = _bStitchStrips;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SetMinStripSize()
|
||||
//
|
||||
// Sets the minimum acceptable size for a strip, in triangles.
|
||||
// All strips generated which are shorter than this will be thrown into one big, separate list.
|
||||
//
|
||||
// Default value: 0
|
||||
//
|
||||
void SetMinStripSize(const unsigned int _minStripSize)
|
||||
{
|
||||
minStripSize = _minStripSize;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
//Cleanup strips / faces, used by generatestrips
|
||||
void Cleanup(NvStripInfoVec& tempStrips, NvFaceInfoVec& tempFaces)
|
||||
{
|
||||
int i;
|
||||
//delete strips
|
||||
for(i = 0; i < tempStrips.size(); i++)
|
||||
{
|
||||
for(int j = 0; j < tempStrips[i]->m_faces.size(); j++)
|
||||
{
|
||||
delete tempStrips[i]->m_faces[j];
|
||||
tempStrips[i]->m_faces[j] = NULL;
|
||||
}
|
||||
tempStrips[i]->m_faces.resize(0);
|
||||
delete tempStrips[i];
|
||||
tempStrips[i] = NULL;
|
||||
}
|
||||
|
||||
//delete faces
|
||||
for(i = 0; i < tempFaces.size(); i++)
|
||||
{
|
||||
delete tempFaces[i];
|
||||
tempFaces[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
//SameTriangle()
|
||||
//
|
||||
//Returns true if the two triangles defined by firstTri and secondTri are the same
|
||||
// The "same" is defined in this case as having the same indices with the same winding order
|
||||
//
|
||||
bool SameTriangle(unsigned short firstTri0, unsigned short firstTri1, unsigned short firstTri2,
|
||||
unsigned short secondTri0, unsigned short secondTri1, unsigned short secondTri2)
|
||||
{
|
||||
bool isSame = false;
|
||||
|
||||
if (firstTri0 == secondTri0)
|
||||
{
|
||||
if (firstTri1 == secondTri1)
|
||||
{
|
||||
if (firstTri2 == secondTri2)
|
||||
isSame = true;
|
||||
}
|
||||
}
|
||||
else if (firstTri0 == secondTri1)
|
||||
{
|
||||
if (firstTri1 == secondTri2)
|
||||
{
|
||||
if (firstTri2 == secondTri0)
|
||||
isSame = true;
|
||||
}
|
||||
}
|
||||
else if (firstTri0 == secondTri2)
|
||||
{
|
||||
if (firstTri1 == secondTri0)
|
||||
{
|
||||
if (firstTri2 == secondTri1)
|
||||
isSame = true;
|
||||
}
|
||||
}
|
||||
|
||||
return isSame;
|
||||
}
|
||||
|
||||
|
||||
bool TestTriangle(const unsigned short v0, const unsigned short v1, const unsigned short v2, const std::vector<NvFaceInfo>* in_bins, const int NUMBINS)
|
||||
{
|
||||
//hash this triangle
|
||||
bool isLegit = false;
|
||||
int ctr = v0 % NUMBINS;
|
||||
for (int k = 0; k < in_bins[ctr].size(); ++k)
|
||||
{
|
||||
//check triangles in this bin
|
||||
if (SameTriangle(in_bins[ctr][k].m_v0, in_bins[ctr][k].m_v1, in_bins[ctr][k].m_v2,
|
||||
v0, v1, v2))
|
||||
{
|
||||
isLegit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isLegit)
|
||||
{
|
||||
ctr = v1 % NUMBINS;
|
||||
for (int k = 0; k < in_bins[ctr].size(); ++k)
|
||||
{
|
||||
//check triangles in this bin
|
||||
if (SameTriangle(in_bins[ctr][k].m_v0, in_bins[ctr][k].m_v1, in_bins[ctr][k].m_v2,
|
||||
v0, v1, v2))
|
||||
{
|
||||
isLegit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isLegit)
|
||||
{
|
||||
ctr = v2 % NUMBINS;
|
||||
for (int k = 0; k < in_bins[ctr].size(); ++k)
|
||||
{
|
||||
//check triangles in this bin
|
||||
if (SameTriangle(in_bins[ctr][k].m_v0, in_bins[ctr][k].m_v1, in_bins[ctr][k].m_v2,
|
||||
v0, v1, v2))
|
||||
{
|
||||
isLegit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return isLegit;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// GenerateStrips()
|
||||
//
|
||||
// in_indices: input index list, the indices you would use to render
|
||||
// in_numIndices: number of entries in in_indices
|
||||
// primGroups: array of optimized/stripified PrimitiveGroups
|
||||
// numGroups: number of groups returned
|
||||
//
|
||||
// Be sure to call delete[] on the returned primGroups to avoid leaking mem
|
||||
//
|
||||
bool GenerateStrips(const unsigned short* in_indices, const unsigned int in_numIndices,
|
||||
PrimitiveGroup** primGroups, unsigned short* numGroups, bool validateEnabled)
|
||||
{
|
||||
//put data in format that the stripifier likes
|
||||
WordVec tempIndices;
|
||||
tempIndices.resize(in_numIndices);
|
||||
unsigned short maxIndex = 0;
|
||||
unsigned short minIndex = 0xFFFF;
|
||||
for(int i = 0; i < in_numIndices; i++)
|
||||
{
|
||||
tempIndices[i] = in_indices[i];
|
||||
if (in_indices[i] > maxIndex)
|
||||
maxIndex = in_indices[i];
|
||||
if (in_indices[i] < minIndex)
|
||||
minIndex = in_indices[i];
|
||||
}
|
||||
NvStripInfoVec tempStrips;
|
||||
NvFaceInfoVec tempFaces;
|
||||
|
||||
NvStripifier stripifier;
|
||||
|
||||
//do actual stripification
|
||||
stripifier.Stripify(tempIndices, cacheSize, minStripSize, maxIndex, tempStrips, tempFaces);
|
||||
|
||||
//stitch strips together
|
||||
IntVec stripIndices;
|
||||
unsigned int numSeparateStrips = 0;
|
||||
|
||||
if(bListsOnly)
|
||||
{
|
||||
//if we're outputting only lists, we're done
|
||||
*numGroups = 1;
|
||||
(*primGroups) = new PrimitiveGroup[*numGroups];
|
||||
PrimitiveGroup* primGroupArray = *primGroups;
|
||||
|
||||
int i;
|
||||
//count the total number of indices
|
||||
unsigned int numIndices = 0;
|
||||
for( i = 0; i < tempStrips.size(); i++)
|
||||
{
|
||||
numIndices += tempStrips[i]->m_faces.size() * 3;
|
||||
}
|
||||
|
||||
//add in the list
|
||||
numIndices += tempFaces.size() * 3;
|
||||
|
||||
primGroupArray[0].type = PT_LIST;
|
||||
primGroupArray[0].numIndices = numIndices;
|
||||
primGroupArray[0].indices = new unsigned short[numIndices];
|
||||
|
||||
//do strips
|
||||
unsigned int indexCtr = 0;
|
||||
for(i = 0; i < tempStrips.size(); i++)
|
||||
{
|
||||
for(int j = 0; j < tempStrips[i]->m_faces.size(); j++)
|
||||
{
|
||||
//degenerates are of no use with lists
|
||||
if(!NvStripifier::IsDegenerate(tempStrips[i]->m_faces[j]))
|
||||
{
|
||||
primGroupArray[0].indices[indexCtr++] = tempStrips[i]->m_faces[j]->m_v0;
|
||||
primGroupArray[0].indices[indexCtr++] = tempStrips[i]->m_faces[j]->m_v1;
|
||||
primGroupArray[0].indices[indexCtr++] = tempStrips[i]->m_faces[j]->m_v2;
|
||||
}
|
||||
else
|
||||
{
|
||||
//we've removed a tri, reduce the number of indices
|
||||
primGroupArray[0].numIndices -= 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//do lists
|
||||
for(i = 0; i < tempFaces.size(); i++)
|
||||
{
|
||||
primGroupArray[0].indices[indexCtr++] = tempFaces[i]->m_v0;
|
||||
primGroupArray[0].indices[indexCtr++] = tempFaces[i]->m_v1;
|
||||
primGroupArray[0].indices[indexCtr++] = tempFaces[i]->m_v2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stripifier.CreateStrips(tempStrips, stripIndices, bStitchStrips, numSeparateStrips, bRestart, restartVal);
|
||||
|
||||
//if we're stitching strips together, we better get back only one strip from CreateStrips()
|
||||
assert( (bStitchStrips && (numSeparateStrips == 1)) || !bStitchStrips);
|
||||
|
||||
//convert to output format
|
||||
*numGroups = numSeparateStrips; //for the strips
|
||||
if(tempFaces.size() != 0)
|
||||
(*numGroups)++; //we've got a list as well, increment
|
||||
(*primGroups) = new PrimitiveGroup[*numGroups];
|
||||
|
||||
PrimitiveGroup* primGroupArray = *primGroups;
|
||||
|
||||
//first, the strips
|
||||
int startingLoc = 0;
|
||||
for(int stripCtr = 0; stripCtr < numSeparateStrips; stripCtr++)
|
||||
{
|
||||
int stripLength = 0;
|
||||
|
||||
if(!bStitchStrips)
|
||||
{
|
||||
int i;
|
||||
//if we've got multiple strips, we need to figure out the correct length
|
||||
for( i = startingLoc; i < stripIndices.size(); i++)
|
||||
{
|
||||
if(stripIndices[i] == -1)
|
||||
break;
|
||||
}
|
||||
|
||||
stripLength = i - startingLoc;
|
||||
}
|
||||
else
|
||||
stripLength = stripIndices.size();
|
||||
|
||||
primGroupArray[stripCtr].type = PT_STRIP;
|
||||
primGroupArray[stripCtr].indices = new unsigned short[stripLength];
|
||||
primGroupArray[stripCtr].numIndices = stripLength;
|
||||
|
||||
int indexCtr = 0;
|
||||
for(int i = startingLoc; i < stripLength + startingLoc; i++)
|
||||
primGroupArray[stripCtr].indices[indexCtr++] = stripIndices[i];
|
||||
|
||||
//we add 1 to account for the -1 separating strips
|
||||
//this doesn't break the stitched case since we'll exit the loop
|
||||
startingLoc += stripLength + 1;
|
||||
}
|
||||
|
||||
//next, the list
|
||||
if(tempFaces.size() != 0)
|
||||
{
|
||||
int faceGroupLoc = (*numGroups) - 1; //the face group is the last one
|
||||
primGroupArray[faceGroupLoc].type = PT_LIST;
|
||||
primGroupArray[faceGroupLoc].indices = new unsigned short[tempFaces.size() * 3];
|
||||
primGroupArray[faceGroupLoc].numIndices = tempFaces.size() * 3;
|
||||
int indexCtr = 0;
|
||||
for(int i = 0; i < tempFaces.size(); i++)
|
||||
{
|
||||
primGroupArray[faceGroupLoc].indices[indexCtr++] = tempFaces[i]->m_v0;
|
||||
primGroupArray[faceGroupLoc].indices[indexCtr++] = tempFaces[i]->m_v1;
|
||||
primGroupArray[faceGroupLoc].indices[indexCtr++] = tempFaces[i]->m_v2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//validate generated data against input
|
||||
if (validateEnabled)
|
||||
{
|
||||
const int NUMBINS = 100;
|
||||
|
||||
std::vector<NvFaceInfo> in_bins[NUMBINS];
|
||||
int i;
|
||||
//hash input indices on first index
|
||||
for ( i = 0; i < in_numIndices; i += 3)
|
||||
{
|
||||
NvFaceInfo faceInfo(in_indices[i], in_indices[i + 1], in_indices[i + 2]);
|
||||
in_bins[in_indices[i] % NUMBINS].push_back(faceInfo);
|
||||
}
|
||||
|
||||
for (i = 0; i < *numGroups; ++i)
|
||||
{
|
||||
switch ((*primGroups)[i].type)
|
||||
{
|
||||
case PT_LIST:
|
||||
{
|
||||
for (int j = 0; j < (*primGroups)[i].numIndices; j += 3)
|
||||
{
|
||||
unsigned short v0 = (*primGroups)[i].indices[j];
|
||||
unsigned short v1 = (*primGroups)[i].indices[j + 1];
|
||||
unsigned short v2 = (*primGroups)[i].indices[j + 2];
|
||||
|
||||
//ignore degenerates
|
||||
if (NvStripifier::IsDegenerate(v0, v1, v2))
|
||||
continue;
|
||||
|
||||
if (!TestTriangle(v0, v1, v2, in_bins, NUMBINS))
|
||||
{
|
||||
Cleanup(tempStrips, tempFaces);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PT_STRIP:
|
||||
{
|
||||
int brokenCtr = 0;
|
||||
bool flip = false;
|
||||
for (int j = 2; j < (*primGroups)[i].numIndices; ++j)
|
||||
{
|
||||
unsigned short v0 = (*primGroups)[i].indices[j - 2];
|
||||
unsigned short v1 = (*primGroups)[i].indices[j - 1];
|
||||
unsigned short v2 = (*primGroups)[i].indices[j];
|
||||
|
||||
if (flip)
|
||||
{
|
||||
//swap v1 and v2
|
||||
unsigned short swap = v1;
|
||||
v1 = v2;
|
||||
v2 = swap;
|
||||
}
|
||||
|
||||
//ignore degenerates
|
||||
if (NvStripifier::IsDegenerate(v0, v1, v2))
|
||||
{
|
||||
flip = !flip;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!TestTriangle(v0, v1, v2, in_bins, NUMBINS))
|
||||
{
|
||||
Cleanup(tempStrips, tempFaces);
|
||||
return false;
|
||||
}
|
||||
|
||||
flip = !flip;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PT_FAN:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//clean up everything
|
||||
Cleanup(tempStrips, tempFaces);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// RemapIndices()
|
||||
//
|
||||
// Function to remap your indices to improve spatial locality in your vertex buffer.
|
||||
//
|
||||
// in_primGroups: array of PrimitiveGroups you want remapped
|
||||
// numGroups: number of entries in in_primGroups
|
||||
// numVerts: number of vertices in your vertex buffer, also can be thought of as the range
|
||||
// of acceptable values for indices in your primitive groups.
|
||||
// remappedGroups: array of remapped PrimitiveGroups
|
||||
//
|
||||
// Note that, according to the remapping handed back to you, you must reorder your
|
||||
// vertex buffer.
|
||||
//
|
||||
void RemapIndices(const PrimitiveGroup* in_primGroups, const unsigned short numGroups,
|
||||
const unsigned short numVerts, PrimitiveGroup** remappedGroups)
|
||||
{
|
||||
(*remappedGroups) = new PrimitiveGroup[numGroups];
|
||||
|
||||
//caches oldIndex --> newIndex conversion
|
||||
int *indexCache;
|
||||
indexCache = new int[numVerts];
|
||||
memset(indexCache, -1, sizeof(int)*numVerts);
|
||||
|
||||
//loop over primitive groups
|
||||
unsigned int indexCtr = 0;
|
||||
for(int i = 0; i < numGroups; i++)
|
||||
{
|
||||
unsigned int numIndices = in_primGroups[i].numIndices;
|
||||
|
||||
//init remapped group
|
||||
(*remappedGroups)[i].type = in_primGroups[i].type;
|
||||
(*remappedGroups)[i].numIndices = numIndices;
|
||||
(*remappedGroups)[i].indices = new unsigned short[numIndices];
|
||||
|
||||
for(int j = 0; j < numIndices; j++)
|
||||
{
|
||||
int cachedIndex = indexCache[in_primGroups[i].indices[j]];
|
||||
if(cachedIndex == -1) //we haven't seen this index before
|
||||
{
|
||||
//point to "last" vertex in VB
|
||||
(*remappedGroups)[i].indices[j] = indexCtr;
|
||||
|
||||
//add to index cache, increment
|
||||
indexCache[in_primGroups[i].indices[j]] = indexCtr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
//we've seen this index before
|
||||
(*remappedGroups)[i].indices[j] = cachedIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete[] indexCache;
|
||||
}
|
||||
112
DSMeshConvert/NvTriStrip/NvTriStrip.dsp
Normal file
112
DSMeshConvert/NvTriStrip/NvTriStrip.dsp
Normal file
@@ -0,0 +1,112 @@
|
||||
# Microsoft Developer Studio Project File - Name="NvTriStrip" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 60000
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||
|
||||
CFG=NvTriStrip - Win32 Debug
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "NvTriStrip.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "NvTriStrip.mak" CFG="NvTriStrip - Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "NvTriStrip - Win32 Release" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "NvTriStrip - Win32 Debug" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName "NVIDIA_XBOX03"
|
||||
# PROP Scc_LocalPath "."
|
||||
CPP=xicl6.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "NvTriStrip - Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "Release"
|
||||
# PROP BASE Intermediate_Dir "Release"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release"
|
||||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /I "..\..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=xilink6.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo /out:"..\..\lib\Release\NvTriStrip.lib"
|
||||
|
||||
!ELSEIF "$(CFG)" == "NvTriStrip - Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "Debug"
|
||||
# PROP BASE Intermediate_Dir "Debug"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug"
|
||||
# PROP Intermediate_Dir "Debug"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=xilink6.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo /out:"..\..\lib\Debug\NvTriStrip.lib"
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "NvTriStrip - Win32 Release"
|
||||
# Name "NvTriStrip - Win32 Debug"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\NvTriStrip.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\NvTriStripObjects.cpp
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\include\NvTriStrip.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\NvTriStripObjects.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\VertexCache.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
33
DSMeshConvert/NvTriStrip/NvTriStrip.dsw
Normal file
33
DSMeshConvert/NvTriStrip/NvTriStrip.dsw
Normal file
@@ -0,0 +1,33 @@
|
||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
||||
|
||||
###############################################################################
|
||||
|
||||
Project: "NvTriStrip"=.\NvTriStrip.dsp - Package Owner=<4>
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
begin source code control
|
||||
NVIDIA_XBOX03
|
||||
.
|
||||
end source code control
|
||||
}}}
|
||||
|
||||
Package=<4>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
Global:
|
||||
|
||||
Package=<5>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
Package=<3>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
||||
145
DSMeshConvert/NvTriStrip/NvTriStrip.h
Normal file
145
DSMeshConvert/NvTriStrip/NvTriStrip.h
Normal file
@@ -0,0 +1,145 @@
|
||||
#ifndef NVTRISTRIP_H
|
||||
#define NVTRISTRIP_H
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#pragma comment(lib, "nvtristrip")
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Public interface for stripifier
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//GeForce1 and 2 cache size
|
||||
#define CACHESIZE_GEFORCE1_2 16
|
||||
|
||||
//GeForce3 cache size
|
||||
#define CACHESIZE_GEFORCE3 24
|
||||
|
||||
enum PrimType
|
||||
{
|
||||
PT_LIST,
|
||||
PT_STRIP,
|
||||
PT_FAN
|
||||
};
|
||||
|
||||
struct PrimitiveGroup
|
||||
{
|
||||
PrimType type;
|
||||
unsigned int numIndices;
|
||||
unsigned short* indices;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PrimitiveGroup() : type(PT_STRIP), numIndices(0), indices(NULL) {}
|
||||
~PrimitiveGroup()
|
||||
{
|
||||
if(indices)
|
||||
delete[] indices;
|
||||
indices = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// EnableRestart()
|
||||
//
|
||||
// For GPUs that support primitive restart, this sets a value as the restart index
|
||||
//
|
||||
// Restart is meaningless if strips are not being stitched together, so enabling restart
|
||||
// makes NvTriStrip forcing stitching. So, you'll get back one strip.
|
||||
//
|
||||
// Default value: disabled
|
||||
//
|
||||
void EnableRestart(const unsigned int restartVal);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// DisableRestart()
|
||||
//
|
||||
// For GPUs that support primitive restart, this disables using primitive restart
|
||||
//
|
||||
void DisableRestart();
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SetCacheSize()
|
||||
//
|
||||
// Sets the cache size which the stripfier uses to optimize the data.
|
||||
// Controls the length of the generated individual strips.
|
||||
// This is the "actual" cache size, so 24 for GeForce3 and 16 for GeForce1/2
|
||||
// You may want to play around with this number to tweak performance.
|
||||
//
|
||||
// Default value: 16
|
||||
//
|
||||
void SetCacheSize(const unsigned int cacheSize);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SetStitchStrips()
|
||||
//
|
||||
// bool to indicate whether to stitch together strips into one huge strip or not.
|
||||
// If set to true, you'll get back one huge strip stitched together using degenerate
|
||||
// triangles.
|
||||
// If set to false, you'll get back a large number of separate strips.
|
||||
//
|
||||
// Default value: true
|
||||
//
|
||||
void SetStitchStrips(const bool bStitchStrips);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SetMinStripSize()
|
||||
//
|
||||
// Sets the minimum acceptable size for a strip, in triangles.
|
||||
// All strips generated which are shorter than this will be thrown into one big, separate list.
|
||||
//
|
||||
// Default value: 0
|
||||
//
|
||||
void SetMinStripSize(const unsigned int minSize);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SetListsOnly()
|
||||
//
|
||||
// If set to true, will return an optimized list, with no strips at all.
|
||||
//
|
||||
// Default value: false
|
||||
//
|
||||
void SetListsOnly(const bool bListsOnly);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// GenerateStrips()
|
||||
//
|
||||
// in_indices: input index list, the indices you would use to render
|
||||
// in_numIndices: number of entries in in_indices
|
||||
// primGroups: array of optimized/stripified PrimitiveGroups
|
||||
// numGroups: number of groups returned
|
||||
//
|
||||
// Be sure to call delete[] on the returned primGroups to avoid leaking mem
|
||||
//
|
||||
bool GenerateStrips(const unsigned short* in_indices, const unsigned int in_numIndices,
|
||||
PrimitiveGroup** primGroups, unsigned short* numGroups, bool validateEnabled = false);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// RemapIndices()
|
||||
//
|
||||
// Function to remap your indices to improve spatial locality in your vertex buffer.
|
||||
//
|
||||
// in_primGroups: array of PrimitiveGroups you want remapped
|
||||
// numGroups: number of entries in in_primGroups
|
||||
// numVerts: number of vertices in your vertex buffer, also can be thought of as the range
|
||||
// of acceptable values for indices in your primitive groups.
|
||||
// remappedGroups: array of remapped PrimitiveGroups
|
||||
//
|
||||
// Note that, according to the remapping handed back to you, you must reorder your
|
||||
// vertex buffer.
|
||||
//
|
||||
// Credit goes to the MS Xbox crew for the idea for this interface.
|
||||
//
|
||||
void RemapIndices(const PrimitiveGroup* in_primGroups, const unsigned short numGroups,
|
||||
const unsigned short numVerts, PrimitiveGroup** remappedGroups);
|
||||
|
||||
#endif
|
||||
BIN
DSMeshConvert/NvTriStrip/NvTriStrip.ncb
Normal file
BIN
DSMeshConvert/NvTriStrip/NvTriStrip.ncb
Normal file
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual Studio 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fipTest", "fipTest.2008.vcproj", "{66DCA866-A381-42D5-97FB-9792066C0F20}"
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NvTriStrip", "NvTriStrip.vcproj", "{D9F6019E-E223-4C1F-ABE2-539308020302}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
@@ -9,10 +9,10 @@ Global
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{66DCA866-A381-42D5-97FB-9792066C0F20}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{66DCA866-A381-42D5-97FB-9792066C0F20}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{66DCA866-A381-42D5-97FB-9792066C0F20}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{66DCA866-A381-42D5-97FB-9792066C0F20}.Release|Win32.Build.0 = Release|Win32
|
||||
{D9F6019E-E223-4C1F-ABE2-539308020302}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{D9F6019E-E223-4C1F-ABE2-539308020302}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{D9F6019E-E223-4C1F-ABE2-539308020302}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{D9F6019E-E223-4C1F-ABE2-539308020302}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
BIN
DSMeshConvert/NvTriStrip/NvTriStrip.suo
Normal file
BIN
DSMeshConvert/NvTriStrip/NvTriStrip.suo
Normal file
Binary file not shown.
239
DSMeshConvert/NvTriStrip/NvTriStrip.vcproj
Normal file
239
DSMeshConvert/NvTriStrip/NvTriStrip.vcproj
Normal file
@@ -0,0 +1,239 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9,00"
|
||||
Name="NvTriStrip"
|
||||
ProjectGUID="{D9F6019E-E223-4C1F-ABE2-539308020302}"
|
||||
TargetFrameworkVersion="0"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory=".\Debug"
|
||||
IntermediateDirectory=".\Debug"
|
||||
ConfigurationType="4"
|
||||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="false"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\..\include"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
PrecompiledHeaderFile=".\Debug/NvTriStrip.pch"
|
||||
AssemblerListingLocation=".\Debug/"
|
||||
ObjectFile=".\Debug/"
|
||||
ProgramDataBaseFileName=".\Debug/"
|
||||
BrowseInformation="1"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="true"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
Culture="1033"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="..\NvTriStripd.lib"
|
||||
SuppressStartupBanner="true"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
SuppressStartupBanner="true"
|
||||
OutputFile=".\Debug/NvTriStrip.bsc"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory=".\Release"
|
||||
IntermediateDirectory=".\Release"
|
||||
ConfigurationType="4"
|
||||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="false"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
InlineFunctionExpansion="1"
|
||||
AdditionalIncludeDirectories="..\..\include"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
|
||||
StringPooling="true"
|
||||
RuntimeLibrary="0"
|
||||
EnableFunctionLevelLinking="true"
|
||||
PrecompiledHeaderFile=".\Release/NvTriStrip.pch"
|
||||
AssemblerListingLocation=".\Release/"
|
||||
ObjectFile=".\Release/"
|
||||
ProgramDataBaseFileName=".\Release/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="true"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="NDEBUG"
|
||||
Culture="1033"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="..\NvTriStrip.lib"
|
||||
SuppressStartupBanner="true"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
SuppressStartupBanner="true"
|
||||
OutputFile=".\Release/NvTriStrip.bsc"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
>
|
||||
<File
|
||||
RelativePath="NvTriStrip.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="NvTriStripObjects.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\include\NvTriStrip.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="NvTriStripObjects.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="VertexCache.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
1769
DSMeshConvert/NvTriStrip/NvTriStripObjects.cpp
Normal file
1769
DSMeshConvert/NvTriStrip/NvTriStripObjects.cpp
Normal file
File diff suppressed because it is too large
Load Diff
244
DSMeshConvert/NvTriStrip/NvTriStripObjects.h
Normal file
244
DSMeshConvert/NvTriStrip/NvTriStripObjects.h
Normal file
@@ -0,0 +1,244 @@
|
||||
|
||||
#ifndef NV_TRISTRIP_OBJECTS_H
|
||||
#define NV_TRISTRIP_OBJECTS_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <windows.h>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include "VertexCache.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Types defined for stripification
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct MyVertex {
|
||||
float x, y, z;
|
||||
float nx, ny, nz;
|
||||
};
|
||||
|
||||
typedef MyVertex MyVector;
|
||||
|
||||
struct MyFace {
|
||||
int v1, v2, v3;
|
||||
float nx, ny, nz;
|
||||
};
|
||||
|
||||
|
||||
class NvFaceInfo {
|
||||
public:
|
||||
|
||||
// vertex indices
|
||||
NvFaceInfo(int v0, int v1, int v2, bool bIsFake = false){
|
||||
m_v0 = v0; m_v1 = v1; m_v2 = v2;
|
||||
m_stripId = -1;
|
||||
m_testStripId = -1;
|
||||
m_experimentId = -1;
|
||||
m_bIsFake = bIsFake;
|
||||
}
|
||||
|
||||
// data members are left public
|
||||
int m_v0, m_v1, m_v2;
|
||||
int m_stripId; // real strip Id
|
||||
int m_testStripId; // strip Id in an experiment
|
||||
int m_experimentId; // in what experiment was it given an experiment Id?
|
||||
bool m_bIsFake; //if true, will be deleted when the strip it's in is deleted
|
||||
};
|
||||
|
||||
// nice and dumb edge class that points knows its
|
||||
// indices, the two faces, and the next edge using
|
||||
// the lesser of the indices
|
||||
class NvEdgeInfo {
|
||||
public:
|
||||
|
||||
// constructor puts 1 ref on us
|
||||
NvEdgeInfo (int v0, int v1){
|
||||
m_v0 = v0;
|
||||
m_v1 = v1;
|
||||
m_face0 = NULL;
|
||||
m_face1 = NULL;
|
||||
m_nextV0 = NULL;
|
||||
m_nextV1 = NULL;
|
||||
|
||||
// we will appear in 2 lists. this is a good
|
||||
// way to make sure we delete it the second time
|
||||
// we hit it in the edge infos
|
||||
m_refCount = 2;
|
||||
|
||||
}
|
||||
|
||||
// ref and unref
|
||||
void Unref () { if (--m_refCount == 0) delete this; }
|
||||
|
||||
// data members are left public
|
||||
UINT m_refCount;
|
||||
NvFaceInfo *m_face0, *m_face1;
|
||||
int m_v0, m_v1;
|
||||
NvEdgeInfo *m_nextV0, *m_nextV1;
|
||||
};
|
||||
|
||||
|
||||
// This class is a quick summary of parameters used
|
||||
// to begin a triangle strip. Some operations may
|
||||
// want to create lists of such items, so they were
|
||||
// pulled out into a class
|
||||
class NvStripStartInfo {
|
||||
public:
|
||||
NvStripStartInfo(NvFaceInfo *startFace, NvEdgeInfo *startEdge, bool toV1){
|
||||
m_startFace = startFace;
|
||||
m_startEdge = startEdge;
|
||||
m_toV1 = toV1;
|
||||
}
|
||||
NvFaceInfo *m_startFace;
|
||||
NvEdgeInfo *m_startEdge;
|
||||
bool m_toV1;
|
||||
};
|
||||
|
||||
|
||||
typedef std::vector<NvFaceInfo*> NvFaceInfoVec;
|
||||
typedef std::list <NvFaceInfo*> NvFaceInfoList;
|
||||
typedef std::list <NvFaceInfoVec*> NvStripList;
|
||||
typedef std::vector<NvEdgeInfo*> NvEdgeInfoVec;
|
||||
|
||||
typedef std::vector<WORD> WordVec;
|
||||
typedef std::vector<int> IntVec;
|
||||
typedef std::vector<MyVertex> MyVertexVec;
|
||||
typedef std::vector<MyFace> MyFaceVec;
|
||||
|
||||
template<class T>
|
||||
inline void SWAP(T& first, T& second)
|
||||
{
|
||||
T temp = first;
|
||||
first = second;
|
||||
second = temp;
|
||||
}
|
||||
|
||||
// This is a summary of a strip that has been built
|
||||
class NvStripInfo {
|
||||
public:
|
||||
|
||||
// A little information about the creation of the triangle strips
|
||||
NvStripInfo(const NvStripStartInfo &startInfo, int stripId, int experimentId = -1) :
|
||||
m_startInfo(startInfo)
|
||||
{
|
||||
m_stripId = stripId;
|
||||
m_experimentId = experimentId;
|
||||
visited = false;
|
||||
m_numDegenerates = 0;
|
||||
}
|
||||
|
||||
// This is an experiment if the experiment id is >= 0
|
||||
inline bool IsExperiment () const { return m_experimentId >= 0; }
|
||||
|
||||
inline bool IsInStrip (const NvFaceInfo *faceInfo) const
|
||||
{
|
||||
if(faceInfo == NULL)
|
||||
return false;
|
||||
|
||||
return (m_experimentId >= 0 ? faceInfo->m_testStripId == m_stripId : faceInfo->m_stripId == m_stripId);
|
||||
}
|
||||
|
||||
bool SharesEdge(const NvFaceInfo* faceInfo, NvEdgeInfoVec &edgeInfos);
|
||||
|
||||
// take the given forward and backward strips and combine them together
|
||||
void Combine(const NvFaceInfoVec &forward, const NvFaceInfoVec &backward);
|
||||
|
||||
//returns true if the face is "unique", i.e. has a vertex which doesn't exist in the faceVec
|
||||
bool Unique(NvFaceInfoVec& faceVec, NvFaceInfo* face);
|
||||
|
||||
// mark the triangle as taken by this strip
|
||||
bool IsMarked (NvFaceInfo *faceInfo);
|
||||
void MarkTriangle(NvFaceInfo *faceInfo);
|
||||
|
||||
// build the strip
|
||||
void Build(NvEdgeInfoVec &edgeInfos, NvFaceInfoVec &faceInfos);
|
||||
|
||||
// public data members
|
||||
NvStripStartInfo m_startInfo;
|
||||
NvFaceInfoVec m_faces;
|
||||
int m_stripId;
|
||||
int m_experimentId;
|
||||
|
||||
bool visited;
|
||||
|
||||
int m_numDegenerates;
|
||||
};
|
||||
|
||||
typedef std::vector<NvStripInfo*> NvStripInfoVec;
|
||||
|
||||
|
||||
//The actual stripifier
|
||||
class NvStripifier {
|
||||
public:
|
||||
|
||||
// Constructor
|
||||
NvStripifier();
|
||||
~NvStripifier();
|
||||
|
||||
//the target vertex cache size, the structure to place the strips in, and the input indices
|
||||
void Stripify(const WordVec &in_indices, const int in_cacheSize, const int in_minStripLength,
|
||||
const unsigned short maxIndex, NvStripInfoVec &allStrips, NvFaceInfoVec &allFaces);
|
||||
void CreateStrips(const NvStripInfoVec& allStrips, IntVec& stripIndices, const bool bStitchStrips, unsigned int& numSeparateStrips, const bool bRestart, const unsigned int restartVal);
|
||||
|
||||
static int GetUniqueVertexInB(NvFaceInfo *faceA, NvFaceInfo *faceB);
|
||||
//static int GetSharedVertex(NvFaceInfo *faceA, NvFaceInfo *faceB);
|
||||
static void GetSharedVertices(NvFaceInfo *faceA, NvFaceInfo *faceB, int* vertex0, int* vertex1);
|
||||
|
||||
static bool IsDegenerate(const NvFaceInfo* face);
|
||||
static bool IsDegenerate(const unsigned short v0, const unsigned short v1, const unsigned short v2);
|
||||
|
||||
protected:
|
||||
|
||||
WordVec indices;
|
||||
int cacheSize;
|
||||
int minStripLength;
|
||||
float meshJump;
|
||||
bool bFirstTimeResetPoint;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Big mess of functions called during stripification
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//********************
|
||||
bool IsMoneyFace(const NvFaceInfo& face);
|
||||
bool FaceContainsIndex(const NvFaceInfo& face, const unsigned int index);
|
||||
|
||||
bool IsCW(NvFaceInfo *faceInfo, int v0, int v1);
|
||||
bool NextIsCW(const int numIndices);
|
||||
|
||||
static int GetNextIndex(const WordVec &indices, NvFaceInfo *face);
|
||||
static NvEdgeInfo *FindEdgeInfo(NvEdgeInfoVec &edgeInfos, int v0, int v1);
|
||||
static NvFaceInfo *FindOtherFace(NvEdgeInfoVec &edgeInfos, int v0, int v1, NvFaceInfo *faceInfo);
|
||||
NvFaceInfo *FindGoodResetPoint(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos);
|
||||
|
||||
void FindAllStrips(NvStripInfoVec &allStrips, NvFaceInfoVec &allFaceInfos, NvEdgeInfoVec &allEdgeInfos, int numSamples);
|
||||
void SplitUpStripsAndOptimize(NvStripInfoVec &allStrips, NvStripInfoVec &outStrips, NvEdgeInfoVec& edgeInfos, NvFaceInfoVec& outFaceList);
|
||||
void RemoveSmallStrips(NvStripInfoVec& allStrips, NvStripInfoVec& allBigStrips, NvFaceInfoVec& faceList);
|
||||
|
||||
bool FindTraversal(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos, NvStripInfo *strip, NvStripStartInfo &startInfo);
|
||||
int CountRemainingTris(std::list<NvStripInfo*>::iterator iter, std::list<NvStripInfo*>::iterator end);
|
||||
|
||||
void CommitStrips(NvStripInfoVec &allStrips, const NvStripInfoVec &strips);
|
||||
|
||||
float AvgStripSize(const NvStripInfoVec &strips);
|
||||
int FindStartPoint(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos);
|
||||
|
||||
void UpdateCacheStrip(VertexCache* vcache, NvStripInfo* strip);
|
||||
void UpdateCacheFace(VertexCache* vcache, NvFaceInfo* face);
|
||||
float CalcNumHitsStrip(VertexCache* vcache, NvStripInfo* strip);
|
||||
int CalcNumHitsFace(VertexCache* vcache, NvFaceInfo* face);
|
||||
int NumNeighbors(NvFaceInfo* face, NvEdgeInfoVec& edgeInfoVec);
|
||||
|
||||
void BuildStripifyInfo(NvFaceInfoVec &faceInfos, NvEdgeInfoVec &edgeInfos, const unsigned short maxIndex);
|
||||
bool AlreadyExists(NvFaceInfo* faceInfo, NvFaceInfoVec& faceInfos);
|
||||
|
||||
// let our strip info classes and the other classes get
|
||||
// to these protected stripificaton methods if they want
|
||||
friend NvStripInfo;
|
||||
};
|
||||
|
||||
#endif
|
||||
32
DSMeshConvert/NvTriStrip/README.txt
Normal file
32
DSMeshConvert/NvTriStrip/README.txt
Normal file
@@ -0,0 +1,32 @@
|
||||
README for NvTriStrip, library version
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To use:
|
||||
-#include "NvTriStrip.h"
|
||||
-put nvtristrip.lib in your library path (the pragma in nvtristrip.h will automatically look for the library).
|
||||
|
||||
Check out NvTriStrip.h for the interface.
|
||||
|
||||
See the StripTest source code (in function LoadXFileStripped) for an example of using the library.
|
||||
|
||||
Features:
|
||||
-generates strips from arbitrary geometry.
|
||||
-flexibly optimizes for post TnL vertex caches (16 on GeForce1/2, 24 on GeForce3).
|
||||
-can stitch together strips using degenerate triangles, or not.
|
||||
-can output lists instead of strips.
|
||||
-can optionally throw excessively small strips into a list instead.
|
||||
-can remap indices to improve spatial locality in your vertex buffers.
|
||||
|
||||
On cache sizes:
|
||||
Note that it's better to UNDERESTIMATE the cache size instead of OVERESTIMATING.
|
||||
So, if you're targetting GeForce1, 2, and 3, be conservative and use the GeForce1_2 cache
|
||||
size, NOT the GeForce3 cache size.
|
||||
This will make sure you don't "blow" the cache of the GeForce1 and 2.
|
||||
Also note that the cache size you specify is the "actual" cache size, not the "effective"
|
||||
cache size you may have heard about. This is 16 for GeForce1 and 2, and 24 for GeForce3.
|
||||
|
||||
Credit goes to Curtis Beeson and Joe Demers for the basis for this stripifier and to Jason Regier and
|
||||
Jon Stone at Blizzard for providing a much cleaner version of CreateStrips().
|
||||
|
||||
Questions/comments email cem@nvidia.com
|
||||
|
||||
88
DSMeshConvert/NvTriStrip/VertexCache.cpp
Normal file
88
DSMeshConvert/NvTriStrip/VertexCache.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
|
||||
|
||||
#include "VertexCache.h"
|
||||
|
||||
VertexCache::VertexCache()
|
||||
{
|
||||
VertexCache(16);
|
||||
}
|
||||
|
||||
|
||||
VertexCache::VertexCache(int size)
|
||||
{
|
||||
numEntries = size;
|
||||
|
||||
entries = new unsigned short[numEntries];
|
||||
|
||||
for(int i = 0; i < numEntries; i++)
|
||||
entries[i] = -1;
|
||||
}
|
||||
|
||||
|
||||
VertexCache::~VertexCache()
|
||||
{
|
||||
delete[] entries;
|
||||
}
|
||||
|
||||
|
||||
int VertexCache::At(int index)
|
||||
{
|
||||
return entries[index];
|
||||
}
|
||||
|
||||
|
||||
void VertexCache::Set(int index, int value)
|
||||
{
|
||||
entries[index] = value;
|
||||
}
|
||||
|
||||
|
||||
void VertexCache::Clear()
|
||||
{
|
||||
for(int i = 0; i < numEntries; i++)
|
||||
entries[i] = -1;
|
||||
}
|
||||
|
||||
void VertexCache::Copy(VertexCache* inVcache)
|
||||
{
|
||||
for(int i = 0; i < numEntries; i++)
|
||||
{
|
||||
inVcache->Set(i, entries[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bool VertexCache::InCache(int entry)
|
||||
{
|
||||
bool returnVal = false;
|
||||
|
||||
for(int i = 0; i < numEntries; i++)
|
||||
{
|
||||
if(entries[i] == entry)
|
||||
{
|
||||
returnVal = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
|
||||
int VertexCache::AddEntry(int entry)
|
||||
{
|
||||
int removed;
|
||||
|
||||
removed = entries[numEntries - 1];
|
||||
|
||||
//push everything right one
|
||||
for(int i = numEntries - 2; i >= 0; i--)
|
||||
{
|
||||
entries[i + 1] = entries[i];
|
||||
}
|
||||
|
||||
entries[0] = entry;
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
|
||||
81
DSMeshConvert/NvTriStrip/VertexCache.h
Normal file
81
DSMeshConvert/NvTriStrip/VertexCache.h
Normal file
@@ -0,0 +1,81 @@
|
||||
|
||||
#ifndef VERTEX_CACHE_H
|
||||
|
||||
#define VERTEX_CACHE_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
class VertexCache
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
VertexCache(int size)
|
||||
{
|
||||
numEntries = size;
|
||||
|
||||
entries = new int[numEntries];
|
||||
|
||||
for(int i = 0; i < numEntries; i++)
|
||||
entries[i] = -1;
|
||||
}
|
||||
|
||||
VertexCache() { VertexCache(16); }
|
||||
~VertexCache() { delete[] entries; entries = 0; }
|
||||
|
||||
bool InCache(int entry)
|
||||
{
|
||||
bool returnVal = false;
|
||||
for(int i = 0; i < numEntries; i++)
|
||||
{
|
||||
if(entries[i] == entry)
|
||||
{
|
||||
returnVal = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return returnVal;
|
||||
}
|
||||
|
||||
int AddEntry(int entry)
|
||||
{
|
||||
int removed;
|
||||
|
||||
removed = entries[numEntries - 1];
|
||||
|
||||
//push everything right one
|
||||
for(int i = numEntries - 2; i >= 0; i--)
|
||||
{
|
||||
entries[i + 1] = entries[i];
|
||||
}
|
||||
|
||||
entries[0] = entry;
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
memset(entries, -1, sizeof(int) * numEntries);
|
||||
}
|
||||
|
||||
void Copy(VertexCache* inVcache)
|
||||
{
|
||||
for(int i = 0; i < numEntries; i++)
|
||||
{
|
||||
inVcache->Set(i, entries[i]);
|
||||
}
|
||||
}
|
||||
|
||||
int At(int index) { return entries[index]; }
|
||||
void Set(int index, int value) { entries[index] = value; }
|
||||
|
||||
private:
|
||||
|
||||
int *entries;
|
||||
int numEntries;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
BIN
DSMeshConvert/NvTriStripd.lib
Normal file
BIN
DSMeshConvert/NvTriStripd.lib
Normal file
Binary file not shown.
25
DSMeshConvert/ac/COPYRIGHT
Normal file
25
DSMeshConvert/ac/COPYRIGHT
Normal file
@@ -0,0 +1,25 @@
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. All advertising materials mentioning features or use of this software
|
||||
must display the following acknowledgement:
|
||||
This product includes software developed by Brad Grantham and
|
||||
Applied Conjecture.
|
||||
4. Neither the name Brad Grantham nor Applied Conjecture
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
5. Notification must be made to Brad Grantham about inclusion of this
|
||||
software in a product including the author of the product and the name
|
||||
and purpose of the product. Notification can be made using email
|
||||
to Brad Grantham's current address (grantham@plunk.org as of September
|
||||
20th, 2000) or current U.S. mail address.
|
||||
|
||||
$Header: /home/grantham/cvsroot/projects/modules/tc/COPYRIGHT,v 1.1 2000/09/21 19:36:56 grantham Exp $
|
||||
|
||||
# vi:tabstop=8
|
||||
#
|
||||
31
DSMeshConvert/ac/README
Normal file
31
DSMeshConvert/ac/README
Normal file
@@ -0,0 +1,31 @@
|
||||
ACTC 1.1 - Brad's Triangle Consolidator
|
||||
|
||||
ACTC converts independent triangles into triangle strips or fans. You
|
||||
can approach a three times geometry speedup on OpenGL and Direct3D
|
||||
using triangle strips and fans. If the speed of your application is
|
||||
limited by how fast your graphics card can paint pixels (and not
|
||||
transform vertices) then this speedup won't help your frame rate, but
|
||||
it may free up CPU cycles for more work in your program, which can in
|
||||
turn do a better job of telling the card what to draw. You'll find
|
||||
a more detailed introduction to using ACTC in "manual.html".
|
||||
|
||||
ACTC does *not* turn unindexed triangle data into indexed triangle data.
|
||||
In other words, it will not turn find duplicate vertices in raw 3D vertex
|
||||
data. (I'm hoping to write a layer on ACTC for that.)
|
||||
|
||||
I am not aware of any bugs but I haven't tested the module very
|
||||
thoroughly against real-life data. If you find bugs, please visit the
|
||||
ACTC page on SourceForge at ... and submit a descriptive bug report
|
||||
including the offending data file, and ACTC's version number.
|
||||
|
||||
You can find the most recent release of ACTC by navigating my home page
|
||||
at http://www.plunk.org/~grantham/.
|
||||
|
||||
A quick note about clause #5 in the COPYRIGHT. All I really want is
|
||||
to feel some amount of satisfaction that you're using something on
|
||||
which I worked hard. An email saying something like "Hey, I'm Joe
|
||||
Shmoe, and I'm using your code in my widget counter for Orchard Supply
|
||||
Hardware" is sufficient.
|
||||
|
||||
-Brad Grantham
|
||||
November 23rd, 2000
|
||||
578
DSMeshConvert/ac/manual.html
Normal file
578
DSMeshConvert/ac/manual.html
Normal file
@@ -0,0 +1,578 @@
|
||||
<html>
|
||||
<body bgcolor="#ffffff">
|
||||
|
||||
<title>Triangle Consolidator 1.1</title>
|
||||
<h1>Triangle Consolidator 1.1</h1>
|
||||
|
||||
<center><h2>Introduction</h2></center>
|
||||
|
||||
I imagine most people would only have come looking for TC if they
|
||||
knew what they wanted in the first place. The programmers' guide
|
||||
that you probably want is in the next section. The following is
|
||||
just a little purpose and history.<p>
|
||||
|
||||
TC, or "triangle consolidator", constructs triangle strips or triangle
|
||||
fans from independent triangle data. The geometric transformation of
|
||||
3D points onto a 2D screen involves some heavy math, and you can realize
|
||||
a performance benefit by reusing the results of that math where possible.
|
||||
Each new triangle strip or fan is constructed from one of the edges of
|
||||
the previous triangle and a new vertex. <p>
|
||||
|
||||
<center><img src=prims.gif></center><p>
|
||||
|
||||
You can achieve 3x performance minus the cost of
|
||||
transforming the first two vertices per strip. Thus it's important
|
||||
that strips and fans are made as long as possible (fewer strips and
|
||||
fans). Some architectures have a
|
||||
maximum preferred strip length, after which the engine may stall.<p>
|
||||
|
||||
I wrote <i>meshifier</i> in 1995 because Sharon Clay at Silicon Graphics
|
||||
asked me how I might construct strips from a lattice of triangles
|
||||
as an interview question. It has some fundamental architectural
|
||||
limitations. Some, like an error in the reset code and being able
|
||||
to specify that triangles should not be output in reverse order,
|
||||
have been fixed by Neal Tringham and are incorporated in the new version
|
||||
available from his web page. Others, such as the limitation on numbers
|
||||
of vertices and connectivity, are harder to repair.<p>
|
||||
|
||||
In "TC" I've attempted to fix those old errors.
|
||||
TC attempts to consolidate triangles limited only by the
|
||||
limits of the machine' available memory and
|
||||
speed. I have changed the API, using OpenGL as a loose model
|
||||
(although OpenGL arguably has its shape because it provides a hardware
|
||||
abstraction layer), so that more algorithmic abstractions and
|
||||
optimizations are possible. I have tried to build in features which
|
||||
are useful to modelers and offline optimization tools, such as whether
|
||||
or not to honor vertex ordering. I have also spent a few days
|
||||
trying to test the code nominally and attempt to have some confidence
|
||||
that even its low-memory behavior is predictable.<p>
|
||||
|
||||
I hope you find it useful. ---<a href="mailto:grantham@plunk.org">Brad
|
||||
Grantham</a><p>
|
||||
|
||||
<p><hr><p>
|
||||
|
||||
<center><h2>Triangle Consolidator API</h2></center>
|
||||
|
||||
TC is meant to be used in an offline modeling process. It is probably
|
||||
too slow to be used to optimize data per frame for the purpose of
|
||||
interactive display. It also does not provide any facility (yet) for
|
||||
merging spacial coordinates together to form an indexed vertex list. TC only
|
||||
operates on the indices of indexed triangles. Maintaining the actual
|
||||
vertex array (containing the traditional v3f, n3f, etc) is up to the
|
||||
application. I perceive this is useful, however, in that TC needs no
|
||||
knowledge of how vertex data is stored; it only needs to know
|
||||
connectivity information. An application program creates an ACTCData
|
||||
structure and then repeats a cycle of optionally setting flags,
|
||||
inputting triangles, and then receiving the output primitives.<p>
|
||||
|
||||
<h3>Language and Namespace</h3>
|
||||
|
||||
TC 1.1 is provided with a C language interface. Mostly this is
|
||||
because many people (including me) still prefer to program in C and I
|
||||
don't want to force people to write C++. TC is also implemented in
|
||||
C, but I don't think this is that important, since you could implement
|
||||
the library internals in C++ and still export a C API.<p>
|
||||
|
||||
The namespace of all functions and identifiers in TC is protected using
|
||||
the initials of my software organization <i>Applied Conjecture</i> and
|
||||
<code>TC</code>. All functions in TC are prefixed with <code>actc</code>.
|
||||
All symbolic constants and <code>#defines</code> are prefixed with
|
||||
<code>ACTC_</code>. All exported data structures are prefixed with
|
||||
<code>ACTC</code>.<p>
|
||||
|
||||
<h3>Initialization and Errors</h3>
|
||||
|
||||
An <code>ACTCData</code> consolidator object is created using the
|
||||
following code. This structure contains state data about optional
|
||||
parameters and triangle connectivity. <code>actcNew</code> returns
|
||||
either an initialized <code>ACTCData</code> object if successful or
|
||||
NULL if memory cannot be allocated.<p>
|
||||
|
||||
|
||||
<pre>
|
||||
#include <ac/tc.h>
|
||||
|
||||
ACTCData *tc;
|
||||
|
||||
tc = actcNew();
|
||||
if(tc == NULL) {
|
||||
/* memory allocation failed */
|
||||
/* print error here and exit or whatever */
|
||||
}
|
||||
</pre>
|
||||
|
||||
Any errors encountered during execution are typically both returned as
|
||||
results from a TC function and stored in the structure. The error
|
||||
can be retrieved using <code>actcGetError</code>. Here is an example of adding a
|
||||
triangle and checking the error.<p>
|
||||
|
||||
<pre>
|
||||
actcAddTriangle(tc, v1, v2, v3);
|
||||
if((e = actcGetError(tc)) != ACTC_NO_ERROR) {
|
||||
/* something bad happened */
|
||||
/* print error and exit or whatever */
|
||||
}
|
||||
</pre>
|
||||
|
||||
A more compact representation may not use <code>actcGetError</code> at
|
||||
all, since many functions return either the error or
|
||||
<code>ACTC_NO_ERROR</code>.<p>
|
||||
|
||||
<pre>
|
||||
if((e = actcAddTriangle(tc, v1, v2, v3)) != ACTC_NO_ERROR) {
|
||||
/* something bad happened */
|
||||
/* print error and exit or whatever */
|
||||
}
|
||||
</pre>
|
||||
|
||||
Since the error is reset in the structure by
|
||||
<code>actcGetError</code>, it makes sense to go with either one style or
|
||||
the other, to avoid being confused when a later return from
|
||||
<code>actcGetError</code> returns an error which has already been
|
||||
handled. Errors are represented by negative integers, so some
|
||||
functions may return non-error information as a positive integer.
|
||||
Slightly smarter applications may try
|
||||
to detect some failure conditions and proceed after some kind of
|
||||
repair.<p>
|
||||
|
||||
<pre>
|
||||
actcAddTriangle(tc, v1, v2, v3);
|
||||
e = actcGetError(tc);
|
||||
if(e == ACTC_ALLOC_FAILED) {
|
||||
/* couldn't alloc memory using one of the malloc(3) family */
|
||||
/* application can free unused memory and try again */
|
||||
} else if(e != ACTC_NO_ERROR) {
|
||||
/* something bad happened other than malloc failure */
|
||||
/* print error and exit or whatever */
|
||||
}
|
||||
</pre>
|
||||
|
||||
For simplicity, examples in the remainder of the programmers' guide will not
|
||||
check for errors but will mention where errors may occur. Several
|
||||
functions can result in the error ACTC_DATABASE_CORRUPT but are not
|
||||
noted here; that particular error return indicates corruption of
|
||||
ACTC's internal data structures and really requires debugging (as
|
||||
described below).<p>
|
||||
|
||||
<h3>Parameters</h3>
|
||||
|
||||
There are several options that may be set in the TC structure. For
|
||||
example, whether TC honors triangle vertex ordering is controlled by
|
||||
the <code>ACTC_OUT_HONOR_WINDING</code> symbolic constant. These values are set
|
||||
by <code>actcParami</code> and retrieved by <code>actcGetParami</code>.<p>
|
||||
|
||||
<pre>
|
||||
int isHonoringWinding;
|
||||
|
||||
actcParami(tc, ACTC_OUT_HONOR_WINDING, ACTC_TRUE);
|
||||
actcGetParami(tc, ACTC_OUT_HONOR_WINDING, &isHonoringWinding);
|
||||
</pre>
|
||||
|
||||
<code>actcGetParami</code> accepts two additional symbolic
|
||||
constants which may
|
||||
not be set by the application. <code>ACTC_MAJOR_VERSION</code> and
|
||||
<code>ACTC_MINOR_VERSION</code> return the major version number and
|
||||
minor version number, respectively.<p>
|
||||
|
||||
Parameters are differentiated by the direction of the data they
|
||||
control. <code>OUT</code> parameters control how TC hands its
|
||||
consolidated primitives back to you. <code>IN</code> parameters tell
|
||||
TC the limits you intend to guarantee on your input data, which may
|
||||
used for optimization purposes. <code>ALG</code> parameters directly
|
||||
affect the internal algorithms used by TC. Some parameters require
|
||||
the extended range of <code>unsigned int</code>, and they can be set
|
||||
and queried by <code>actcParamu</code> and <code>actcGetParamu</code>,
|
||||
but both sets of <code>Param...</code> functions take the same symbolic
|
||||
constants and convert to-and-from the range of their parameter or
|
||||
return variable. Here are the parameters available in TC 1.1:<p>
|
||||
|
||||
<table border=3 width=100%>
|
||||
<tr><th>Enumerant</th><th>Data type</th><th>Meaning</th><th>Prefer Param<i>u</i></th></tr>
|
||||
<tr><td>ACTC_OUT_MIN_FAN_VERTS</td><td>integer</td><td>Minimum number of vertices
|
||||
returnable in a triangle fan</td><td>No</td></tr>
|
||||
<tr><td>ACTC_OUT_HONOR_WINDING</td><td>boolean</td><td>Whether triangles may be output in reverse vertex order</td><td>No</td></tr>
|
||||
<tr><td>ACTC_OUT_MAX_PRIM_VERTS</td><td>integer</td><td>Maximum number of <i>vertices</i> to output in a primitive</td><td>No</td></tr>
|
||||
<tr><td>ACTC_IN_MIN_VERT</td><td>integer</td><td>Minimum vertex index</td><td>Yes</td></tr>
|
||||
<tr><td>ACTC_IN_MAX_VERT</td><td>integer</td><td>Maximum vertex index</td><td>Yes</td></tr>
|
||||
<tr><td>ACTC_IN_MAX_VERT_SHARING</td><td>integer</td><td>Maximum number of edges that will share a vertex</td><td>No</td></tr>
|
||||
<tr><td>ACTC_IN_MAX_EDGE_SHARING</td><td>integer</td><td>Maximum number of triangles that will share an edge</td><td>No</td></tr>
|
||||
</table><p>
|
||||
|
||||
If called during <code>INPUT</code> or <code>OUTPUT</code>,
|
||||
<code>actcParami</code> can result in <code>ACTC_DURING_INPUT</code>,
|
||||
or <code>ACTC_DURING_OUTPUT</code>, respectively. If called to set
|
||||
<code>ACTC_IN_MIN_VERT</code> or <code>ACTC_IN_MAX_VERT</code> so the
|
||||
vertex range is negative, or to set
|
||||
<code>ACTC_OUT_MAX_PRIM_VERTS</code> to less than 3, or to set a value
|
||||
associated with a symbolic constant ACTC does not know about, then the
|
||||
error <code>ACTC_INVALID_VALUE</code> will result.<p>
|
||||
|
||||
<h3>Input/Output</h3>
|
||||
|
||||
A TC structure is always in one of three modes; idle, inputting, or
|
||||
outputting. Some operations are valid only in some modes. For example,
|
||||
setting a parameter is an error unless the consolidator object is idle.
|
||||
Triangle data may only be entered in input mode. Primitives may only
|
||||
be fetched in output mode. Here's an example of how the modes work.
|
||||
Please keep in mind that this example assumes a particular
|
||||
primitive.<p>
|
||||
|
||||
<pre>
|
||||
actcParami(tc, ACTC_OUT_MAX_PRIM_VERTS, 14);
|
||||
actcBeginInput(tc);
|
||||
actcAddTriangle(tc, 1, 2, 3);
|
||||
actcEndInput(tc);
|
||||
actcBeginOutput(tc);
|
||||
prim = actcStartNextPrim(tc, &v1, &v2);
|
||||
actcGetNextVert(tc, &v3);
|
||||
actcEndOutput(tc);
|
||||
|
||||
/* v1, v2, and v3 are now set to 1, 2, and 3. */
|
||||
</pre>
|
||||
|
||||
<code>actcEndInput</code> and <code>actcEndOutput</code> are intended as
|
||||
checkpoints for optimization, compaction, etc. Your application can
|
||||
call <code>actcGetIsDuringInput</code> and
|
||||
<code>actcGetIsDuringOutput</code> to determine if the TC object is
|
||||
currently ready in the input or output stages (or is otherwise idle).
|
||||
If <code>actcParami</code> is called during input or output, an error of
|
||||
either <code>ACTC_DURING_INPUT</code> or <code>ACTC_DURING_OUTPUT</code>
|
||||
results, respectively.<p>
|
||||
|
||||
<h3>Giving Triangles as Input</h3>
|
||||
|
||||
Each triangle is entered into the TC database using
|
||||
<code>actcAddTriangle</code>, and the possible results may be
|
||||
<code>ACTC_DURING_OUTPUT</code> if TC is in output mode,
|
||||
<code>ACTC_IDLE</code> if TC is not in input mode, or
|
||||
<code>ACTC_ALLOC_FAILED</code> if an internal data structure could not
|
||||
be allocated. In the last case, the database is not altered. An
|
||||
application could perform compaction on its own data and try
|
||||
<code>actcAddTriangle</code> again, or it could attempt to retrieve all
|
||||
the primitives currently available from the database. This would
|
||||
probably give worse results (more primitives, fewer vertices per
|
||||
primitive) than retrieving primitives from the complete database but
|
||||
may be better than getting no primitives at all.<p>
|
||||
|
||||
<pre>
|
||||
int triCount;
|
||||
int tris[][3];
|
||||
|
||||
actcBeginInput(tc);
|
||||
for(i = 0; i < triCount; i++)
|
||||
actcAddTriangle(tc, tris[i][0], tris[i][1], tris[i][2]);
|
||||
actcEndInput(tc);
|
||||
</pre>
|
||||
|
||||
<h3>Ranges of Various Input Data</h3>
|
||||
|
||||
Vertex indices can be any <code>unsigned int</code>, and so
|
||||
anywhere from 0 to <code>UINT_MAX</code>, inclusive. Internal data
|
||||
structures allow quantity <code>INT_MAX</code> vertices, edges, triangles,
|
||||
vertex valences, and edge valences to be input. With the data
|
||||
structures TC uses
|
||||
as of version 1.1, on most machines at the time of writing, a process'
|
||||
memory space will be exhausted before the range of any of these items
|
||||
is exhausted. As of version 1.1, TC has not been tested on an
|
||||
architecture with integers or pointers larger that 32 bits.<p>
|
||||
|
||||
<h3>Getting the Output Primitives</h3>
|
||||
|
||||
Strips and fans are retrieved one at a time from TC starting with
|
||||
<code>actcStartNextPrim</code>. The primitive type is returned, either
|
||||
<code>ACTC_PRIM_STRIP</code> or <code>ACTC_PRIM_FAN</code>.
|
||||
<code>actcStartNextPrim</code> may also return
|
||||
<code>ACTC_DATABASE_EMPTY</code> if all triangles input so far have been
|
||||
returned in primitives. <code>actcStartNextPrim</code> stores the first
|
||||
two vertices by reference, and
|
||||
<code>actcGetNextVert</code> provides each subsequent vertex.
|
||||
<code>actcGetNextVert</code> will return <code>ACTC_PRIM_COMPLETE</code>
|
||||
when their are no more vertices to return.
|
||||
|
||||
<pre>
|
||||
int prim;
|
||||
int v1, v2;
|
||||
|
||||
actcBeginOutput(tc);
|
||||
while((prim = actcStartNextPrim(tc, &v1, &v2) != ACTC_DATABASE_EMPTY) {
|
||||
/* start a primitive of type "prim" with v1 and v2 */
|
||||
while(actcGetNextVert(tc, &v3) != ACTC_PRIM_COMPLETE)
|
||||
/* continue primitive using v3 */
|
||||
}
|
||||
actcEndOutput(tc);
|
||||
</pre>
|
||||
|
||||
<h3>One-Stop-Shopping (Convenience Function)</h3>
|
||||
|
||||
There is a single function called
|
||||
<code>actcTrianglesToPrimitives</code> which inputs triangles and
|
||||
extracts primitives, including attempting to recover from low-memory
|
||||
situations by first draining the primitive database, and then by
|
||||
cleaning up unused memory if draining is not sufficient. Since TC
|
||||
cannot know in advance how many primitives it can find (and thus how
|
||||
many vertices), the application will have to provide primitive storage
|
||||
large enough to hold the input data as independent triangles. The
|
||||
application may also tell <code>actcTrianglesToPrimitives</code> how
|
||||
many triangles to input to TC before draining the database.
|
||||
The following example shows how an application might call
|
||||
<code>actcTrianglesToPrimitives</code>; here the application has provided
|
||||
<code>INT_MAX</code> as the maximum batch size in triangles, which
|
||||
effectively means input all the triangles first before outputting.<p>
|
||||
|
||||
|
||||
<pre>
|
||||
int triangleCount;
|
||||
int triangles[][3];
|
||||
int *primLengths;
|
||||
int *primVerts;
|
||||
int *primCount;
|
||||
|
||||
/* get triangleCount and triangles from somewhere */
|
||||
primLengths = (int *)malloc(sizeof(int) * triangleCount);
|
||||
primTypes = (int *)malloc(sizeof(int) * triangleCount);
|
||||
primVerts = (int *)malloc(sizeof(int) * 3 * triangleCount);
|
||||
primCount = actcTrianglesToPrimitives(tc, triangleCount, triangles,
|
||||
primTypes, primLengths, primVerts, INT_MAX);
|
||||
if(primCount < 0) {
|
||||
/* something bad happened */
|
||||
/* print error and exit or whatever */
|
||||
}
|
||||
</pre>
|
||||
|
||||
<code>actcTrianglesToPrimitives</code> calls
|
||||
<code>actc{Begin,End}{Input,Output}</code>, <code>actcAddTriangle</code>,
|
||||
<code>actcGetNext{Prim,Vertex}</code>, and <code>actcMakeEmpty</code>.
|
||||
It returns any unrecoverable error it may receive from these functions,
|
||||
or it will return the total number of strips and fans it finds. The types
|
||||
and length in vertices of all primitives are stored in primTypes and
|
||||
primLengths, and then the vertices for each primitive in turn are
|
||||
stored sequentially in primVerts.<p>
|
||||
|
||||
<h3>Memory Usage Statistics</h3>
|
||||
|
||||
Call <code>actcGetMemoryAllocation</code> to make TC search how much
|
||||
memory is being used in data structures. This may be an expensive
|
||||
operation in TC 1.1 in that it searches the allocated data structures.<p>
|
||||
|
||||
<h3>Dumping Internal State</h3>
|
||||
|
||||
See below for information on compiled TC so that it automatically dumps
|
||||
debugging
|
||||
information on an internal error. If you believe you are getting
|
||||
incorrect results from TC, your application can call
|
||||
<code>actcDumpState</code> to print out the internal state of a TC
|
||||
object (in no particular format). In order for me to help you debug a
|
||||
problem, it would be useful to print out the TC version number, the
|
||||
triangles you input to TC (in the order you input them), and the
|
||||
output of <code>actcDumpState</code> at the beginning and end of your
|
||||
output phase. <code>actcDumpState</code> has no return value.<p>
|
||||
|
||||
<h3>Cleaning Up</h3>
|
||||
|
||||
To stop input or output with TC and empty the database for a
|
||||
particular TC object, use <code>actcMakeEmpty</code>; the TC object will
|
||||
be reset to idle, contain no triangles, and will be ready for another
|
||||
set of input triangles. <code>actcMakeEmpty</code> returns any error
|
||||
that occurs during cleanup, but for the 1.1 release it can only return
|
||||
<code>ACTC_NO_ERROR</code>.<p>
|
||||
|
||||
To free the memory associated with a TC object, call
|
||||
<code>actcDelete</code> with the pointer to the object; this function
|
||||
effectively calls <code>actcMakeEmpty</code> and then frees the TC
|
||||
internal data. Further use of that TC object pointer will have
|
||||
undefined results but will probably crash your application.<p>
|
||||
|
||||
<p><hr><p>
|
||||
<center><h2>Specific Solutions</h2></center>
|
||||
|
||||
<h3>Producing Only Strips</h3>
|
||||
|
||||
To produce only triangle strips, set
|
||||
<code>ACTC_OUT_MIN_FAN_VERTS</code> to INT_MAX. Technically, a very
|
||||
large triangle fan could still be formed, but when someone creates a
|
||||
two billion vertex triangle fan with TC, I will consider it a success
|
||||
rather than a failure.<p>
|
||||
|
||||
<pre>
|
||||
actcParami(tc, ACTC_OUT_MIN_FAN_VERTS, INT_MAX);
|
||||
</pre>
|
||||
|
||||
<h3>Producing Limited-Length Primitives</h3>
|
||||
|
||||
I have heard that Silicon Graphics' RealityEngine graphics and
|
||||
derivatives have an optimium strip size of 12 vertices. Set
|
||||
<code>ACTC_OUT_MAX_PRIM_VERTS</code> to set the maximum number of vertices to produce
|
||||
per primitive.<p>
|
||||
|
||||
<pre>
|
||||
actcParami(tc, ACTC_OUT_MAX_PRIM_VERTS, 12);
|
||||
</pre>
|
||||
|
||||
<h3>Ignoring Triangle Winding</h3>
|
||||
|
||||
If your triangle set does not have a preferred triangle winding,
|
||||
set <code>ACTC_OUT_HONOR_WINDING</code> to FALSE or 0. This has the effect of allowing
|
||||
a triangle to be included in a primitive even if its vertices would
|
||||
be drawn in reverse order. Note that every odd triangle in a strip
|
||||
(counting from 0) will normally be wound backwards if winding is
|
||||
honored.<p>
|
||||
|
||||
<pre>
|
||||
actcParami(tc, ACTC_OUT_HONOR_WINDING, ACTC_TRUE);
|
||||
</pre>
|
||||
|
||||
<p><hr><p>
|
||||
<center><h2>TC SDK</h2></center>
|
||||
|
||||
<h3>Building TC</h3>
|
||||
|
||||
My preference for using this module is to compile tc into a <code>.a</code>
|
||||
library. The makefile provided by default has targets for the library and
|
||||
the sample programs:
|
||||
|
||||
<pre>
|
||||
make libactc.a
|
||||
</pre>
|
||||
|
||||
To turn on some simple debugging assistance, compile TC with the
|
||||
<code>DEBUG</code> preprocessor symbol defined (<code>-DDEBUG</code>
|
||||
for most UNIX compilers). Error conditions should print the reason
|
||||
and the function in which the error occurred. Any function finding an
|
||||
unexpected inconsistency in data structures (like performing a table
|
||||
search and not finding an element which must be there) will call
|
||||
<code>abort()</code> and presumably dump core. I wouldn't expect any
|
||||
ordinary application developer to be able to debug TC from a core
|
||||
file, of course. If <code>INFO</code> is also defined, then the
|
||||
<code>abort()</code> call will be preceded by a dump of the internal
|
||||
data structures in tc. If you would like me to debug TC based on your
|
||||
input, it would help me to have this output as well as the set of
|
||||
triangles originally input to TC.<p>
|
||||
|
||||
<h3>Sample Programs and Tests</h3>
|
||||
|
||||
The <code>actctest</code> program makes sure the basic TC functions
|
||||
work. If it prints anything when compiled with actc.c without
|
||||
<code>DEBUG</code> and <code>INFO</code>, then something bad
|
||||
happened.<p>
|
||||
|
||||
The <code>actctest2</code> program repeatedly inputs random data into TC
|
||||
and makes sure it gets the same thing out as it received. You can
|
||||
specify settings for any of the <code>OUT</code> parameters, and change the
|
||||
seed that <code>actctest2</code> uses to initialize the random number
|
||||
generator.<p>
|
||||
|
||||
The <code>actcsample</code> program takes in a particular word-based format
|
||||
containing
|
||||
vertices and triangles, and converts that data into strips and fans. It
|
||||
passes the vertex list through verbatim. Someone could
|
||||
use this either as an element in a tool pipeline or as the basis for a
|
||||
new offline or interactive stripping tool. Here's what the input format
|
||||
looks like:
|
||||
<pre>
|
||||
[x y z nx ny nz r g b]
|
||||
[x y z nx ny nz r g b]
|
||||
[...]
|
||||
end
|
||||
triangle v1 v2 v3 end
|
||||
[triangle v1 v2 v3 end]
|
||||
[...]
|
||||
end
|
||||
</pre>
|
||||
In this example, <i>x</i>, <i>y</i>, and <i>z</i> are the vertex coordinates,
|
||||
<i>nx</i>, <i>ny</i>, and <i>nz</i> are the vertex normals, and
|
||||
<i>r</i>, <i>g</i>, and <i>b</i> are the vertex colors. The set of
|
||||
vertices are terminated by the word <code>end</code>. Vertices are
|
||||
optional and are only passed straight through. For each triangle, <i>v1</i>,
|
||||
<i>v2</i>, and <i>v3</i> are the indices of each vertex in the triangle.
|
||||
Each triangle is terminated by the word <code>end</code>, and the list
|
||||
of triangles is terminated by <code>end</code>. The output format is
|
||||
similar, except that the <code>triangle</code> section is replaced by a list
|
||||
of primitives. Here's what the output format looks like:
|
||||
<pre>
|
||||
[x y z nx ny nz r g b]
|
||||
[x y z nx ny nz r g b]
|
||||
[...]
|
||||
end
|
||||
strip v1 v2 v3 [v4 [v5 [...]]] end
|
||||
fan v1 v2 v3 [v4 [v5 [...]]] end
|
||||
[...]
|
||||
end
|
||||
</pre>
|
||||
Running
|
||||
|
||||
<h3>Portability</h3>
|
||||
|
||||
TC should be pretty portable, for the most part. I placed my "timer"
|
||||
snippet in <code>actctest2</code>, and it will need tweaking on anything
|
||||
but Linux, IRIX, and Windows 98. If you'd like to submit a patch to
|
||||
"timer" for another operating system, I will place it on my web page
|
||||
and incorporate it into TC.<p>
|
||||
|
||||
<p><hr><p>
|
||||
<center><h2>Miscellaneous</h2></center>
|
||||
|
||||
<h3>Reliability</h3>
|
||||
|
||||
I've spent some time testing TC against some strange triangle sets. I've
|
||||
gone so far as to create random triangle data (random numbers of
|
||||
triangles with random ranges of vertices), put it in to TC, and check
|
||||
to make sure the same triangles come out as went in. I've even gone
|
||||
as far as to artificially reduce the amount of memory available to 8M,
|
||||
under which TC seems to reliably consolidate triangles, but the data set
|
||||
may degenerate under such conditions to being exactly the input data.<p>
|
||||
|
||||
<h3>Runtime Performance</h3>
|
||||
|
||||
TC 1.1 looks like it can consolidate somewhere around one hundred
|
||||
thousand triangles per second on a 400 MHz Pentium III for data sets
|
||||
in the thousands of vertices, and somewhere around thirty thousand
|
||||
triangles per second for data sets around three hundred thousand
|
||||
vertices. I suspect this could be improved only a little bit more with
|
||||
some clever avoidance of searching the vertex-to-edge mapping.
|
||||
Most of the data structures internal to TC are constant-time operations,
|
||||
especially if the vertex range is small.<p>
|
||||
|
||||
I have tested TC's performance against an optimized <i>meshifier</i>
|
||||
modified by Randall Frank at Lawrence Livermore National Labs and
|
||||
<i>meshifier</i> appears to run about twice as fast, probably because it
|
||||
doesn't check for errors internally very well and makes some assumptions
|
||||
about vertex and edge connectivity. Perhaps TC could approach that
|
||||
performance level if the internal consistency checks were made to compile
|
||||
conditionally.<p>
|
||||
|
||||
<h3>Stripping Performance</h3>
|
||||
|
||||
TC uses a least-connected-vertex approach to making triangle strips,
|
||||
under the assumption that such vertices will be at the corners of
|
||||
patches of connected triangles, and the stripification algorithm will
|
||||
hopefully peel triangle strips off the outside of the patch first,
|
||||
in order to avoid fragmenting the triangle set. This is the same
|
||||
approach Neal Tringham's improved <i>meshifier</i> used.
|
||||
I have yet to test TC's vertices-per-strip performance against other
|
||||
triangle strippers, but it should do at least as well as <i>meshifier</i>.<p>
|
||||
|
||||
The algorithm attempts to remove all the triangle fans first. I've found
|
||||
that this works for fewer than half of the simple data files I've tried.
|
||||
For 1.1 the default value associated with <code>ACTC_OUT_MIN_FAN_VERTS</code>
|
||||
is set to INT_MAX. Other good values appear to be near 8 and 16. You'll
|
||||
have to try it yourself to see how it works with your data.<p>
|
||||
|
||||
One could conceivably implement simulated annealing with TC. An
|
||||
application would repeatedly calculate solutions to triangle sets with
|
||||
TC, swapping the order of some number of triangles, each time choosing
|
||||
the better solution. As time goes on, the number of triangles rotated
|
||||
could be reduced. Simulated annealing will typically give a pretty
|
||||
good solution while allowing the application to choose how much time
|
||||
it cares to spend to find a solution.<p>
|
||||
|
||||
<p><hr><p>
|
||||
|
||||
Revision Control Information: $Header: /home/grantham/cvsroot/projects/modules/tc/manual.html,v 1.15 2000/11/22 20:18:26 grantham Exp $<p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<!--
|
||||
vi:tabstop=8
|
||||
-->
|
||||
BIN
DSMeshConvert/ac/prims.gif
Normal file
BIN
DSMeshConvert/ac/prims.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
1448
DSMeshConvert/ac/tc.c
Normal file
1448
DSMeshConvert/ac/tc.c
Normal file
File diff suppressed because it is too large
Load Diff
86
DSMeshConvert/ac/tc.h
Normal file
86
DSMeshConvert/ac/tc.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* $Header: /home/grantham/cvsroot/projects/modules/tc/tc.h,v 1.14 2000/10/03 07:19:20 grantham Exp $
|
||||
*/
|
||||
|
||||
#if !defined(_ACTC_H_)
|
||||
#define _ACTC_H_
|
||||
|
||||
#include "../types.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct _ACTCData ACTCData;
|
||||
|
||||
/*
|
||||
Abbreviated:
|
||||
vertex vert
|
||||
primitive prim
|
||||
maximum max
|
||||
minimum min
|
||||
parameter param
|
||||
*/
|
||||
|
||||
#define ACTC_NO_ERROR 0
|
||||
#define ACTC_ALLOC_FAILED -0x2000
|
||||
#define ACTC_DURING_INPUT -0x2001
|
||||
#define ACTC_DURING_OUTPUT -0x2002
|
||||
#define ACTC_IDLE -0x2003
|
||||
#define ACTC_INVALID_VALUE -0x2004
|
||||
#define ACTC_DATABASE_EMPTY -0x2005
|
||||
#define ACTC_DATABASE_CORRUPT -0x2006
|
||||
#define ACTC_PRIM_COMPLETE -0x2007
|
||||
|
||||
#define ACTC_OUT_MIN_FAN_VERTS 0x1000
|
||||
#define ACTC_OUT_HONOR_WINDING 0x1001
|
||||
#define ACTC_OUT_MAX_PRIM_VERTS 0x1004
|
||||
#define ACTC_IN_MIN_VERT 0x1005
|
||||
#define ACTC_IN_MAX_VERT 0x1006
|
||||
#define ACTC_IN_MAX_VERT_SHARING 0x1007
|
||||
#define ACTC_IN_MAX_EDGE_SHARING 0x1008
|
||||
#define ACTC_MINOR_VERSION 0x1009
|
||||
#define ACTC_MAJOR_VERSION 0x1010
|
||||
|
||||
#define ACTC_PRIM_FAN 0x2000
|
||||
#define ACTC_PRIM_STRIP 0x2001
|
||||
|
||||
#define ACTC_TRUE 1
|
||||
#define ACTC_FALSE 0
|
||||
|
||||
ACTCData *actcNew(void);
|
||||
int actcParami(ACTCData *tc, int param, int value);
|
||||
int actcGetParami(ACTCData *tc, int param, int *value);
|
||||
int actcParamu(ACTCData *tc, int param, u32 value);
|
||||
int actcGetParamu(ACTCData *tc, int param, u32 *value);
|
||||
int actcGetError(ACTCData *tc);
|
||||
int actcMakeEmpty(ACTCData *tc);
|
||||
void actcDelete(ACTCData *tc);
|
||||
void actcDumpState(ACTCData *tc, FILE *fp);
|
||||
|
||||
int actcBeginInput(ACTCData *tc);
|
||||
int actcGetIsDuringInput(ACTCData *tc);
|
||||
int actcAddTriangle(ACTCData *tc, u32 v1, u32 v2, u32 v3);
|
||||
int actcEndInput(ACTCData *tc);
|
||||
|
||||
int actcBeginOutput(ACTCData *tc);
|
||||
int actcGetIsDuringOutput(ACTCData *tc);
|
||||
int actcStartNextPrim(ACTCData *tc, u32 *v1Return, u32 *v2Return);
|
||||
int actcGetNextVert(ACTCData *tc, u32 *vReturn);
|
||||
int actcEndOutput(ACTCData *tc);
|
||||
|
||||
int actcGetMemoryAllocation(ACTCData *tc, size_t *bytesAllocated);
|
||||
|
||||
int actcTrianglesToPrimitives(ACTCData *tc, int triangleCount,
|
||||
u32 (*triangles)[3], int primTypes[], int primLengths[], u32 vertices[],
|
||||
int maxBatchSize);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ACTC_H_ */
|
||||
|
||||
/* vi:tabstop=8
|
||||
*/
|
||||
290
DSMeshConvert/cets-pterdiman/Adjacency.cpp
Normal file
290
DSMeshConvert/cets-pterdiman/Adjacency.cpp
Normal file
@@ -0,0 +1,290 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Source code for "Creating Efficient Triangle Strips"
|
||||
// (C) 2000, Pierre Terdiman (p.terdiman@wanadoo.fr)
|
||||
//
|
||||
// Version is 2.0.
|
||||
//
|
||||
// Following adjacency structures have been successfully used to implement:
|
||||
// - a triangle striper
|
||||
// - a silhouette tracker [used for shadow volumes, occlusion culling, and glow!]
|
||||
// - local search for collision detection on terrains
|
||||
// - subdivision surfaces
|
||||
//
|
||||
// So that one IS useful....
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Precompiled Header
|
||||
//#include "Stdafx.h"
|
||||
#include "Adjacency.h"
|
||||
#include "RevisitedRadix.h"
|
||||
#define RELEASEARRAY(x) { if ( x ) delete[] (x); }
|
||||
#define RELEASE(x) { if ( x ) delete (x); }
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Adjacencies Class Implementation
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Adjacencies::Adjacencies() : mNbEdges(0), mCurrentNbFaces(0), mEdges(0), mNbFaces(0), mFaces(0)
|
||||
{
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Destructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Adjacencies::~Adjacencies()
|
||||
{
|
||||
RELEASEARRAY(mEdges);
|
||||
RELEASEARRAY(mFaces);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// A method to initialize the component
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Input : create, the creation structure
|
||||
// Output : -
|
||||
// Return : true if success
|
||||
// Exception: -
|
||||
// Remark : -
|
||||
bool Adjacencies::Init(ADJACENCIESCREATE& create)
|
||||
{
|
||||
// Get some bytes
|
||||
mNbFaces = create.NbFaces;
|
||||
mFaces = new AdjTriangle[mNbFaces]; if(!mFaces) return false;
|
||||
mEdges = new AdjEdge[mNbFaces*3]; if(!mEdges) return false;
|
||||
|
||||
// Feed me with triangles.....
|
||||
for(u32 i=0;i<mNbFaces;i++)
|
||||
{
|
||||
// Get correct vertex references
|
||||
u32 Ref0 = create.DFaces ? create.DFaces[i*3+0] : create.WFaces ? create.WFaces[i*3+0] : 0;
|
||||
u32 Ref1 = create.DFaces ? create.DFaces[i*3+1] : create.WFaces ? create.WFaces[i*3+1] : 1;
|
||||
u32 Ref2 = create.DFaces ? create.DFaces[i*3+2] : create.WFaces ? create.WFaces[i*3+2] : 2;
|
||||
|
||||
// Add a triangle to the database
|
||||
AddTriangle(Ref0, Ref1, Ref2);
|
||||
}
|
||||
|
||||
// At this point of the process we have mFaces & mEdges filled with input data. That is:
|
||||
// - a list of triangles with 3 0 links (i.e. -1)
|
||||
// - a list of mNbFaces*3 edges, each edge having 2 vertex references and an owner face.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// A method to add a new triangle to the database
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Input : ref0, ref1, ref2, vertex references for the new triangle
|
||||
// Output : -
|
||||
// Return : true if success
|
||||
// Exception: -
|
||||
// Remark : -
|
||||
bool Adjacencies::AddTriangle(u32 ref0, u32 ref1, u32 ref2)
|
||||
{
|
||||
// Store vertex-references
|
||||
mFaces[mCurrentNbFaces].VRef[0] = ref0;
|
||||
mFaces[mCurrentNbFaces].VRef[1] = ref1;
|
||||
mFaces[mCurrentNbFaces].VRef[2] = ref2;
|
||||
|
||||
// Reset links
|
||||
mFaces[mCurrentNbFaces].ATri[0] = -1;
|
||||
mFaces[mCurrentNbFaces].ATri[1] = -1;
|
||||
mFaces[mCurrentNbFaces].ATri[2] = -1;
|
||||
|
||||
// Add edge 01 to database
|
||||
if(ref0<ref1) AddEdge(ref0, ref1, mCurrentNbFaces);
|
||||
else AddEdge(ref1, ref0, mCurrentNbFaces);
|
||||
// Add edge 02 to database
|
||||
if(ref0<ref2) AddEdge(ref0, ref2, mCurrentNbFaces);
|
||||
else AddEdge(ref2, ref0, mCurrentNbFaces);
|
||||
// Add edge 12 to database
|
||||
if(ref1<ref2) AddEdge(ref1, ref2, mCurrentNbFaces);
|
||||
else AddEdge(ref2, ref1, mCurrentNbFaces);
|
||||
|
||||
mCurrentNbFaces++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// A method to add a new edge to the database
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Input : ref0, ref1, vertex references for the new edge
|
||||
// face, owner face
|
||||
// Output : -
|
||||
// Return : true if success
|
||||
// Exception: -
|
||||
// Remark : -
|
||||
bool Adjacencies::AddEdge(u32 ref0, u32 ref1, u32 face)
|
||||
{
|
||||
// Store edge data
|
||||
mEdges[mNbEdges].Ref0 = ref0;
|
||||
mEdges[mNbEdges].Ref1 = ref1;
|
||||
mEdges[mNbEdges].FaceNb = face;
|
||||
mNbEdges++;
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// A method to create the adjacency structures
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Input : -
|
||||
// Output : -
|
||||
// Return : true if success
|
||||
// Exception: -
|
||||
// Remark : -
|
||||
bool Adjacencies::CreateDatabase()
|
||||
{
|
||||
// Here mNbEdges should be equal to mCurrentNbFaces*3.
|
||||
|
||||
RadixSorter Core;
|
||||
|
||||
u32* FaceNb = new u32[mNbEdges]; if(!FaceNb) return false;
|
||||
u32* VRefs0 = new u32[mNbEdges]; if(!VRefs0) return false;
|
||||
u32* VRefs1 = new u32[mNbEdges]; if(!VRefs1) return false;
|
||||
|
||||
for(u32 i=0;i<mNbEdges;i++)
|
||||
{
|
||||
FaceNb[i] = mEdges[i].FaceNb;
|
||||
VRefs0[i] = mEdges[i].Ref0;
|
||||
VRefs1[i] = mEdges[i].Ref1;
|
||||
}
|
||||
|
||||
// Multiple sort
|
||||
u32* Sorted = Core.Sort(FaceNb, mNbEdges).Sort(VRefs0, mNbEdges).Sort(VRefs1, mNbEdges).GetIndices();
|
||||
|
||||
// Read the list in sorted order, look for similar edges
|
||||
u32 LastRef0 = VRefs0[Sorted[0]];
|
||||
u32 LastRef1 = VRefs1[Sorted[0]];
|
||||
u32 Count = 0;
|
||||
u32 TmpBuffer[3];
|
||||
|
||||
for(u32 i=0;i<mNbEdges;i++)
|
||||
{
|
||||
u32 Face = FaceNb[Sorted[i]]; // Owner face
|
||||
u32 Ref0 = VRefs0[Sorted[i]]; // Vertex ref #1
|
||||
u32 Ref1 = VRefs1[Sorted[i]]; // Vertex ref #2
|
||||
if(Ref0==LastRef0 && Ref1==LastRef1)
|
||||
{
|
||||
// Current edge is the same as last one
|
||||
TmpBuffer[Count++] = Face; // Store face number
|
||||
if(Count==3)
|
||||
{
|
||||
RELEASEARRAY(VRefs1);
|
||||
RELEASEARRAY(VRefs0);
|
||||
RELEASEARRAY(FaceNb);
|
||||
return false; // Only works with manifold meshes (i.e. an edge is not shared by more than 2 triangles)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Here we have a new edge (LastRef0, LastRef1) shared by Count triangles stored in TmpBuffer
|
||||
if(Count==2)
|
||||
{
|
||||
// if Count==1 => edge is a boundary edge: it belongs to a single triangle.
|
||||
// Hence there's no need to update a link to an adjacent triangle.
|
||||
bool Status = UpdateLink(TmpBuffer[0], TmpBuffer[1], LastRef0, LastRef1);
|
||||
if(!Status)
|
||||
{
|
||||
RELEASEARRAY(VRefs1);
|
||||
RELEASEARRAY(VRefs0);
|
||||
RELEASEARRAY(FaceNb);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
// Reset for next edge
|
||||
Count = 0;
|
||||
TmpBuffer[Count++] = Face;
|
||||
LastRef0 = Ref0;
|
||||
LastRef1 = Ref1;
|
||||
}
|
||||
}
|
||||
bool Status = true;
|
||||
if(Count==2) Status = UpdateLink(TmpBuffer[0], TmpBuffer[1], LastRef0, LastRef1);
|
||||
|
||||
RELEASEARRAY(VRefs1);
|
||||
RELEASEARRAY(VRefs0);
|
||||
RELEASEARRAY(FaceNb);
|
||||
|
||||
// We don't need the edges anymore
|
||||
RELEASEARRAY(mEdges);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// A method to update the links in two adjacent triangles
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Input : firsttri, index of the first triangle
|
||||
// secondtri, index of the second triangle
|
||||
// ref0, ref1, the common edge
|
||||
// Output : -
|
||||
// Return : true if success
|
||||
// Exception: -
|
||||
// Remark : -
|
||||
bool Adjacencies::UpdateLink(u32 firsttri, u32 secondtri, u32 ref0, u32 ref1)
|
||||
{
|
||||
AdjTriangle* Tri0 = &mFaces[firsttri]; // Catch the first triangle
|
||||
AdjTriangle* Tri1 = &mFaces[secondtri]; // Catch the second triangle
|
||||
|
||||
// Get the edge IDs. 0xff means input references are wrong.
|
||||
u8 EdgeNb0 = Tri0->FindEdge(ref0, ref1); if(EdgeNb0==0xff) return false;
|
||||
u8 EdgeNb1 = Tri1->FindEdge(ref0, ref1); if(EdgeNb1==0xff) return false;
|
||||
|
||||
// Update links. The two most significant bits contain the counterpart edge's ID.
|
||||
Tri0->ATri[EdgeNb0] = secondtri |(u32(EdgeNb1)<<30);
|
||||
Tri1->ATri[EdgeNb1] = firsttri |(u32(EdgeNb0)<<30);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// A method to find an edge in a tri, given two vertex references
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Input : vref0, vref1, the two vertex references
|
||||
// Output : -
|
||||
// Return : the edge number between 0 and 2, or 0xff if input refs are wrong
|
||||
// Exception: -
|
||||
// Remark : -
|
||||
u8 AdjTriangle::FindEdge(u32 vref0, u32 vref1)
|
||||
{
|
||||
u8 EdgeNb = 0xff;
|
||||
if(VRef[0]==vref0 && VRef[1]==vref1) EdgeNb = 0;
|
||||
else if(VRef[0]==vref1 && VRef[1]==vref0) EdgeNb = 0;
|
||||
else if(VRef[0]==vref0 && VRef[2]==vref1) EdgeNb = 1;
|
||||
else if(VRef[0]==vref1 && VRef[2]==vref0) EdgeNb = 1;
|
||||
else if(VRef[1]==vref0 && VRef[2]==vref1) EdgeNb = 2;
|
||||
else if(VRef[1]==vref1 && VRef[2]==vref0) EdgeNb = 2;
|
||||
return EdgeNb;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// A method to get the last reference given the first two
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Input : vref0, vref1, the two vertex references
|
||||
// Output : -
|
||||
// Return : the last reference, or 0xffffffff if input refs are wrong
|
||||
// Exception: -
|
||||
// Remark : -
|
||||
u32 AdjTriangle::OppositeVertex(u32 vref0, u32 vref1)
|
||||
{
|
||||
u32 Ref = 0xffffffff;
|
||||
if(VRef[0]==vref0 && VRef[1]==vref1) Ref = VRef[2];
|
||||
else if(VRef[0]==vref1 && VRef[1]==vref0) Ref = VRef[2];
|
||||
else if(VRef[0]==vref0 && VRef[2]==vref1) Ref = VRef[1];
|
||||
else if(VRef[0]==vref1 && VRef[2]==vref0) Ref = VRef[1];
|
||||
else if(VRef[1]==vref0 && VRef[2]==vref1) Ref = VRef[0];
|
||||
else if(VRef[1]==vref1 && VRef[2]==vref0) Ref = VRef[0];
|
||||
return Ref;
|
||||
}
|
||||
81
DSMeshConvert/cets-pterdiman/Adjacency.h
Normal file
81
DSMeshConvert/cets-pterdiman/Adjacency.h
Normal file
@@ -0,0 +1,81 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Source code for "Creating Efficient Triangle Strips"
|
||||
// (C) 2000, Pierre Terdiman (p.terdiman@wanadoo.fr)
|
||||
//
|
||||
// Version is 2.0.
|
||||
//
|
||||
// Following adjacency structures have been successfully used to implement:
|
||||
// - a triangle striper
|
||||
// - a silhouette tracker [used for shadow volumes, occlusion culling, and glow!]
|
||||
// - local search for collision detection on terrains
|
||||
// - subdivision surfaces
|
||||
//
|
||||
// So that one IS useful....
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __ADJACENCY_H__
|
||||
#define __ADJACENCY_H__
|
||||
#include "../types.h"
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Class Adjacencies
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// MACROS
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#define MAKE_ADJ_TRI(x) (x&0x3fffffff)
|
||||
#define GET_EDGE_NB(x) (x>>30)
|
||||
#define IS_BOUNDARY(x) (x==0xffffffff)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Structures
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct AdjTriangle{ // Should be derived from a triangle structure
|
||||
u32 VRef[3]; // Vertex-references
|
||||
u32 ATri[3]; // Links/References of adjacent triangles. The 2 most significant bits contains
|
||||
// the counterpart edge in the adjacent triangle.
|
||||
u8 FindEdge(u32 vref0, u32 vref1);
|
||||
u32 OppositeVertex(u32 vref0, u32 vref1);
|
||||
};
|
||||
|
||||
struct AdjEdge{
|
||||
u32 Ref0; // Vertex reference
|
||||
u32 Ref1; // Vertex reference
|
||||
u32 FaceNb; // Owner face
|
||||
};
|
||||
|
||||
struct ADJACENCIESCREATE{
|
||||
ADJACENCIESCREATE() { DFaces = 0; WFaces = 0; NbFaces = 0; }
|
||||
u32 NbFaces; // #faces in source topo
|
||||
u32* DFaces; // list of faces (dwords) or 0
|
||||
u16* WFaces; // list of faces (words) or 0
|
||||
};
|
||||
|
||||
class Adjacencies
|
||||
{
|
||||
private:
|
||||
u32 mNbEdges;
|
||||
u32 mCurrentNbFaces;
|
||||
AdjEdge* mEdges;
|
||||
|
||||
bool AddTriangle(u32 ref0, u32 ref1, u32 ref2);
|
||||
bool AddEdge(u32 ref0, u32 ref1, u32 face);
|
||||
bool UpdateLink(u32 firsttri, u32 secondtri, u32 ref0, u32 ref1);
|
||||
u8 FindEdge(AdjTriangle* tri, u32 vref0, u32 vref1);
|
||||
public:
|
||||
Adjacencies();
|
||||
~Adjacencies();
|
||||
|
||||
u32 mNbFaces;
|
||||
AdjTriangle* mFaces;
|
||||
|
||||
bool Init(ADJACENCIESCREATE& create);
|
||||
bool CreateDatabase();
|
||||
};
|
||||
|
||||
#endif // __ADJACENCY_H__
|
||||
1304
DSMeshConvert/cets-pterdiman/CustomArray.cpp
Normal file
1304
DSMeshConvert/cets-pterdiman/CustomArray.cpp
Normal file
File diff suppressed because it is too large
Load Diff
291
DSMeshConvert/cets-pterdiman/CustomArray.h
Normal file
291
DSMeshConvert/cets-pterdiman/CustomArray.h
Normal file
@@ -0,0 +1,291 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Source code for "Creating Efficient Triangle Strips"
|
||||
// (C) 2000, Pierre Terdiman (p.terdiman@wanadoo.fr)
|
||||
//
|
||||
// Version is 2.0.
|
||||
//
|
||||
// This is a versatile and customized import/export array class I use for a long time.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Notes :
|
||||
//
|
||||
// CustomArray is a special array class especially designed for import/export goals, even if you can use it in many other ways.
|
||||
// Here are some basic usages and code examples:
|
||||
//
|
||||
// 1) Saving heterogeneous data to disk
|
||||
//
|
||||
// Say you want to create a chunk-based file (e.g. a .3DS one). Such files may contain a chunk type (e.g. "FACE", i.e. a string) followed by
|
||||
// chars or ints (e.g. vertex references) or floats (e.g. vertices). Saving such a file may be painful, and is usually done with an ugly list
|
||||
// of putc/fputc. It also can be done with a single fwrite, but you must have stored your heterogeneous data beforehand, hence usually dealing
|
||||
// with multiple pointers (e.g. a char*, an int*, a float*...) Well, that's ugly. With the CustomArray class you can solve this problem in an
|
||||
// elegant way, with the following code:
|
||||
//
|
||||
// CustomArray Array; // constructor does all the painful stuff for you, destructor frees everything as well
|
||||
//
|
||||
// // Store heterogeneous data in any order...
|
||||
// Array.Store((char)1);
|
||||
// Array.Store(10.0f);
|
||||
// Array.Store((long)1);
|
||||
// Array.Store("Test");
|
||||
//
|
||||
// // ...and just save to disk
|
||||
// Array.ExportToDisk("c:\\datas.bin");
|
||||
//
|
||||
// Saved file is a linear binary file, made of following bytes:
|
||||
// - 01
|
||||
// - 10.0 in float
|
||||
// - 00 00 00 01 (or 01 00 00 00, depends on your computer's little/big endian way of dealing with data)
|
||||
// - the string "Test" (not ended by a 0 character)
|
||||
//
|
||||
// And that's all. Very easy to use, and you don't have to know how many bytes you'll need. This is very useful when packing a file for example,
|
||||
// as explained in the second example.
|
||||
//
|
||||
//
|
||||
// 2) Packing a buffer
|
||||
//
|
||||
// Say you want to encode a buffer with an arithmetic coder, and your encoder gives you one packed byte at a time. You don't know the final packed size,
|
||||
// but you don't need it if you use a CustomArray.
|
||||
//
|
||||
// CustomArray Array;
|
||||
// int EncodedByte;
|
||||
//
|
||||
// do
|
||||
// {
|
||||
// EncodedByte = EncodeSymbol(); // Get next packed byte or EOF (-1)
|
||||
// if(EncodedByte!=EOF) Array.Store(EncodedByte); // Save packed byte
|
||||
// }while(EncodedByte!=EOF);
|
||||
//
|
||||
// Array.ExportToDisk("c:\\packed.bin"); // Save packed file
|
||||
//
|
||||
//
|
||||
// You even can store bits in your CustomArray, with the StoreBit method. Call the StoreBit method 8 times, and a new byte will be added to the array.
|
||||
// If you call StoreBit, say 6 times, and then call a standard Store method, 2 extra bits are automatically added to padd the address on a byte boundary.
|
||||
//
|
||||
//
|
||||
// Now let's say you want your saved file to begin with the size of the packed data. (you could take the file's length, but imagine the packed data
|
||||
// is part of a bigger file) As you don't know the final packed size before actually having packed it, this is painful: you must leave room for the
|
||||
// final packed size at the start of the file, and fill it at the end of the process. If you save your file with some putc/fputc this is a real pain.
|
||||
// The CustomArray class has a neat way of dealing with this problem: the PushAddress and PopAddressAndStore methods. Let's modify the example code:
|
||||
//
|
||||
// CustomArray Array;
|
||||
// int EncodedByte;
|
||||
// long PackedSize = 0;
|
||||
//
|
||||
// Array.Store((long)0).PushAddress(); // Leave room for a long, save the address
|
||||
//
|
||||
// do
|
||||
// {
|
||||
// EncodedByte = EncodeSymbol(); // Get next packed byte or EOF (-1)
|
||||
// if(EncodedByte!=EOF) Array.Store(EncodedByte); // Save packed byte
|
||||
// if(EncodedByte!=EOF) PackedSize++; // Update packed size
|
||||
// }while(EncodedByte!=EOF);
|
||||
//
|
||||
// Array.PopAddressAndStore(PackedSize); // Store packed size where the PushAddress has been done.
|
||||
//
|
||||
// Array.ExportToDisk("c:\\packed.bin"); // Save packed file
|
||||
//
|
||||
// Of course you can push more than one address (as many as you want):
|
||||
//
|
||||
// Array.Store((long)0).PushAddress(); // Push address 1 on the stack
|
||||
// Array.Store((long)0).PushAddress(); // Push address 2 on the stack
|
||||
// Array.Store((long)0).PushAddress(); // Push address 3 on the stack
|
||||
// ...
|
||||
// Array.Store((long)0).PushAddress(); // Push address N on the stack
|
||||
//
|
||||
// Array.PopAddressAndStore((long)1); // Pop address N and store value 1
|
||||
// ...
|
||||
// Array.PopAddressAndStore((long)N-2); // Pop address 3 and store value N-2
|
||||
// Array.PopAddressAndStore((long)N-1); // Pop address 2 and store value N-1
|
||||
// Array.PopAddressAndStore((long)N); // Pop address 1 and store value N
|
||||
//
|
||||
//
|
||||
// 3) Creating a log file
|
||||
//
|
||||
// The StoreASCII methods provide a very easy way to create log files (e.g. for debug purpose). Example:
|
||||
//
|
||||
// Array.StoreASCII(10.0f); // Store the string "10.0"
|
||||
// Array.StoreASCII((long)1234); // Store the string "1234"
|
||||
// Array.StoreASCII(Boolean); // Store the string "true" or "false", depends on the boolean value
|
||||
//
|
||||
// Say "Score" is an unsigned long whose value is 500:
|
||||
// Array.StoreASCII("Your score is ").StoreASCII(Score).StoreASCII(".\n"); // Store the string "Your score is 500." (followed by a carriage return)
|
||||
//
|
||||
// ...and so on...
|
||||
//
|
||||
//
|
||||
// 4) Getting the data back
|
||||
//
|
||||
// This is easily done with the Collapse method, which creates a linear buffer filled with all stored data.
|
||||
//
|
||||
//
|
||||
// 5) Importing data
|
||||
//
|
||||
// You can initialize a CustomArray with your own buffer, or even with a file:
|
||||
//
|
||||
// CustomArray Array("c:\\data.bin"); // Read the whole file data.bin, fill the array with it
|
||||
//
|
||||
// MyByte = Array.GetByte(); // Get the first byte of the array, move the inner pointer one byte beyond
|
||||
// MyFloat = Array.GetFloat(); // Get the next 4 bytes of the array, read as a float, move the inner pointer 4 bytes beyond
|
||||
// ...
|
||||
//
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// History : 01/15/99: first version for Irion MAX Plug-In
|
||||
// 02/04/99: ASCII support added
|
||||
// 02/05/99: GetOffset(), Padd(), LinkTo(CustomArray* array) added
|
||||
// 03/xx/99: Collapse() added, self-references added
|
||||
// 03/xx/99: BOOL definition added in header if not defined yet, addies-stack mecanism added
|
||||
// 04/xx/99: "push" renamed to "store", for a more coherent name since people were expecting a "pop" method to be used.............
|
||||
// 04/xx/99: BOOL handled as a long. Use bool (in lower case) for a real boolean value.
|
||||
// 05/xx/99: heap size is now 4Kb, and allocated ram is doubled for each new block. The more you eat, the more ram you're given.
|
||||
// 09/xx/99: bit-storage methods added (StoreBit, EndBits) for data-compression
|
||||
// 29/10/99: bug fixed: mLastAddress was not initialized. Was crashing if the first thing done was a PushAddress. Well, a PushAddress should NOT
|
||||
// be the first thing done anyway!
|
||||
// 04/11/99: address stack is now resizable.
|
||||
// 06/01/00: local memory manager and local error codes removed, CustomArray class added to IrionBasics
|
||||
//
|
||||
// More notes: - always keep in mind that an CustomArray eats CUSTOMARRAY_BLOCKSIZE bytes when initialized, even if you don't use it later.
|
||||
// That's why you may use this class for very specific reasons, or even change this #define to match your own needs.
|
||||
//
|
||||
// - I know I could've used templates.
|
||||
//
|
||||
// - THIS IS NOT THREAD-SAFE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Include Guard
|
||||
#ifndef __CUSTOMARRAY_H__
|
||||
#define __CUSTOMARRAY_H__
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// MACROS
|
||||
|
||||
// Define BOOL if needed
|
||||
#ifndef BOOL
|
||||
typedef int BOOL;
|
||||
#endif
|
||||
#include "../types.h"
|
||||
#include <stdio.h>
|
||||
#define CUSTOMARRAY_BLOCKSIZE (4*1024) // 4 Kb => heap size
|
||||
#define RELEASEARRAY(x) { if ( x ) delete[] (x); }
|
||||
#define RELEASE(x) { if ( x ) delete (x); }
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CustomArray Class Definition
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CustomArray
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Structures and enums
|
||||
struct CustomBlock{
|
||||
CustomBlock() { Addy = 0; }
|
||||
~CustomBlock() { RELEASEARRAY(Addy); }
|
||||
void* Addy; // Stored data
|
||||
unsigned long Size; // Length of stored data
|
||||
unsigned long Max; // Heap size
|
||||
};
|
||||
|
||||
struct CustomCell{
|
||||
CustomCell() { NextCustomCell = 0; }
|
||||
|
||||
struct CustomCell* NextCustomCell;
|
||||
CustomBlock Item;
|
||||
};
|
||||
|
||||
private:
|
||||
CustomCell* mCurrentCell; // Current block cell
|
||||
CustomCell* mInitCell; // First block cell
|
||||
|
||||
void* mCollapsed; // Possible collapsed buffer
|
||||
void** mAddresses; // Stack to store addresses
|
||||
void* mLastAddress; // Last address used in current block cell
|
||||
unsigned short mNbPushedAddies; // #saved addies
|
||||
unsigned short mNbAllocatedAddies; // #allocated addies
|
||||
unsigned char mBitCount;
|
||||
unsigned char mBitMask;
|
||||
|
||||
// Management methods
|
||||
CustomArray& CheckArray(unsigned long bytesneeded);
|
||||
CustomArray& NewBlock(CustomCell* previouscell, unsigned long size=0);
|
||||
bool SaveCell(CustomCell* p, FILE* fp);
|
||||
CustomArray& StoreASCIICode(char code);
|
||||
// Helpers
|
||||
u32 FileSize(const char* name);
|
||||
public:
|
||||
// Constructor / destructor
|
||||
CustomArray(unsigned long startsize=CUSTOMARRAY_BLOCKSIZE, void* inputbuffer=0);
|
||||
CustomArray(const char* filename);
|
||||
~CustomArray();
|
||||
|
||||
// Store methods
|
||||
CustomArray& StoreBit(bool bit);
|
||||
CustomArray& EndBits();
|
||||
|
||||
CustomArray& Store(BOOL Bo);
|
||||
CustomArray& Store(bool Bo);
|
||||
CustomArray& Store(char b);
|
||||
CustomArray& Store(unsigned char b);
|
||||
CustomArray& Store(short w);
|
||||
CustomArray& Store(unsigned short w);
|
||||
CustomArray& Store(long d);
|
||||
CustomArray& Store(unsigned long d);
|
||||
// CustomArray& Store(int d);
|
||||
CustomArray& Store(unsigned int d);
|
||||
CustomArray& Store(float f);
|
||||
CustomArray& Store(double f);
|
||||
CustomArray& Store(const char* String);
|
||||
|
||||
CustomArray& StoreASCII(BOOL Bo);
|
||||
CustomArray& StoreASCII(bool Bo);
|
||||
CustomArray& StoreASCII(char b);
|
||||
CustomArray& StoreASCII(unsigned char b);
|
||||
CustomArray& StoreASCII(short w);
|
||||
CustomArray& StoreASCII(unsigned short w);
|
||||
CustomArray& StoreASCII(long d);
|
||||
CustomArray& StoreASCII(unsigned long d);
|
||||
// CustomArray& StoreASCII(int d);
|
||||
CustomArray& StoreASCII(unsigned int d);
|
||||
CustomArray& StoreASCII(float f);
|
||||
CustomArray& StoreASCII(double f);
|
||||
CustomArray& StoreASCII(const char* String);
|
||||
|
||||
// Management methods
|
||||
bool ExportToDisk(const char* FileName);
|
||||
bool ExportToDisk(FILE* fp);
|
||||
|
||||
unsigned long GetOffset();
|
||||
CustomArray& Padd();
|
||||
CustomArray& LinkTo(CustomArray* array);
|
||||
void* GetAddress() { char* CurrentAddy = (char*)mCurrentCell->Item.Addy; CurrentAddy+=mCurrentCell->Item.Size; return CurrentAddy; }
|
||||
void* Collapse(void* userbuffer=0);
|
||||
|
||||
// Address methods
|
||||
bool PushAddress();
|
||||
CustomArray& PopAddressAndStore(BOOL Bo);
|
||||
CustomArray& PopAddressAndStore(bool Bo);
|
||||
CustomArray& PopAddressAndStore(char b);
|
||||
CustomArray& PopAddressAndStore(unsigned char b);
|
||||
CustomArray& PopAddressAndStore(short w);
|
||||
CustomArray& PopAddressAndStore(unsigned short w);
|
||||
CustomArray& PopAddressAndStore(long d);
|
||||
CustomArray& PopAddressAndStore(unsigned long d);
|
||||
// CustomArray& PopAddressAndStore(int d);
|
||||
CustomArray& PopAddressAndStore(unsigned int d);
|
||||
CustomArray& PopAddressAndStore(float f);
|
||||
CustomArray& PopAddressAndStore(double f);
|
||||
|
||||
// Read methods
|
||||
char GetByte();
|
||||
short GetWord();
|
||||
long GetDword();
|
||||
float GetFloat();
|
||||
};
|
||||
|
||||
#endif // __CUSTOMARRAY_H__
|
||||
423
DSMeshConvert/cets-pterdiman/RevisitedRadix.cpp
Normal file
423
DSMeshConvert/cets-pterdiman/RevisitedRadix.cpp
Normal file
@@ -0,0 +1,423 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Source code for "Radix Sort Revisited"
|
||||
// (C) 2000, Pierre Terdiman (p.terdiman@wanadoo.fr)
|
||||
//
|
||||
// Works with IEEE floats only.
|
||||
// Version is 1.1.
|
||||
//
|
||||
// This is my new radix routine:
|
||||
// - it uses indices and doesn't recopy the values anymore, hence wasting less ram
|
||||
// - it creates all the histograms in one run instead of four
|
||||
// - it sorts words faster than dwords and bytes faster than words
|
||||
// - it correctly sorts negative floats by patching the offsets
|
||||
// - it automatically takes advantage of temporal coherence
|
||||
// - multiple keys support is a side effect of temporal coherence
|
||||
// - it may be worth recoding in asm...
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
To do:
|
||||
- add an offset parameter between two input values (avoid some data recopy sometimes)
|
||||
- unroll ? asm ?
|
||||
- warning when skipping last pass
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Precompiled Header
|
||||
//#include "Stdafx.h"
|
||||
#include "RevisitedRadix.h"
|
||||
#include <string.h>
|
||||
#define RELEASEARRAY(x) { if ( x ) delete[] (x); }
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// RadixSorter Class Implementation
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
RadixSorter::RadixSorter()
|
||||
{
|
||||
// Initialize
|
||||
mIndices = 0;
|
||||
mIndices2 = 0;
|
||||
mCurrentSize = 0;
|
||||
|
||||
// Allocate input-independent ram
|
||||
mHistogram = new u32[256*4];
|
||||
mOffset = new u32[256];
|
||||
|
||||
// Initialize indices
|
||||
ResetIndices();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Destructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
RadixSorter::~RadixSorter()
|
||||
{
|
||||
// Release everything
|
||||
RELEASEARRAY(mOffset);
|
||||
RELEASEARRAY(mHistogram);
|
||||
RELEASEARRAY(mIndices2);
|
||||
RELEASEARRAY(mIndices);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Main sort routine
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Input : input, a list of integer values to sort
|
||||
// nb, #values to sort
|
||||
// signedvalues, true to handle negative values, false if you know your input buffer only contains positive values
|
||||
// Output : mIndices, a list of indices in sorted order, i.e. in the order you may process your data
|
||||
// Return : Self-Reference
|
||||
// Exception: -
|
||||
// Remark : this one is for integer values
|
||||
RadixSorter& RadixSorter::Sort(u32* input, u32 nb, bool signedvalues)
|
||||
{
|
||||
// Resize lists if needed
|
||||
if(nb>mCurrentSize)
|
||||
{
|
||||
// Free previously used ram
|
||||
RELEASEARRAY(mIndices2);
|
||||
RELEASEARRAY(mIndices);
|
||||
|
||||
// Get some fresh one
|
||||
mIndices = new u32[nb];
|
||||
mIndices2 = new u32[nb];
|
||||
mCurrentSize = nb;
|
||||
|
||||
// Initialize indices so that the input buffer is read in sequential order
|
||||
ResetIndices();
|
||||
}
|
||||
|
||||
// Clear counters
|
||||
memset(mHistogram, 0, 256*4*sizeof(u32));
|
||||
|
||||
// Create histograms (counters). Counters for all passes are created in one run.
|
||||
// Pros: read input buffer once instead of four times
|
||||
// Cons: mHistogram is 4Kb instead of 1Kb
|
||||
// We must take care of signed/unsigned values for temporal coherence.... I just
|
||||
// have 2 code paths even if just a single opcode changes. Self-modifying code, someone?
|
||||
|
||||
// Temporal coherence
|
||||
bool AlreadySorted = true; // Optimism...
|
||||
u32* Indices = mIndices;
|
||||
// Prepare to count
|
||||
u8* p = (u8*)input;
|
||||
u8* pe = &p[nb*4];
|
||||
u32* h0= &mHistogram[0]; // Histogram for first pass (LSB)
|
||||
u32* h1= &mHistogram[256]; // Histogram for second pass
|
||||
u32* h2= &mHistogram[512]; // Histogram for third pass
|
||||
u32* h3= &mHistogram[768]; // Histogram for last pass (MSB)
|
||||
if(!signedvalues)
|
||||
{
|
||||
// Temporal coherence
|
||||
u32 PrevVal = input[mIndices[0]];
|
||||
|
||||
while(p!=pe)
|
||||
{
|
||||
// Temporal coherence
|
||||
u32 Val = input[*Indices++]; // Read input buffer in previous sorted order
|
||||
if(Val<PrevVal) AlreadySorted = false; // Check whether already sorted or not
|
||||
PrevVal = Val; // Update for next iteration
|
||||
|
||||
// Create histograms
|
||||
h0[*p++]++; h1[*p++]++; h2[*p++]++; h3[*p++]++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Temporal coherence
|
||||
s32 PrevVal = (s32)input[mIndices[0]];
|
||||
|
||||
while(p!=pe)
|
||||
{
|
||||
// Temporal coherence
|
||||
s32 Val = (s32)input[*Indices++]; // Read input buffer in previous sorted order
|
||||
if(Val<PrevVal) AlreadySorted = false; // Check whether already sorted or not
|
||||
PrevVal = Val; // Update for next iteration
|
||||
|
||||
// Create histograms
|
||||
h0[*p++]++; h1[*p++]++; h2[*p++]++; h3[*p++]++;
|
||||
}
|
||||
}
|
||||
|
||||
// If all input values are already sorted, we just have to return and leave the previous list unchanged.
|
||||
// That way the routine may take advantage of temporal coherence, for example when used to sort transparent faces.
|
||||
if(AlreadySorted) return *this;
|
||||
|
||||
// Compute #negative values involved if needed
|
||||
u32 NbNegativeValues = 0;
|
||||
if(signedvalues)
|
||||
{
|
||||
// An efficient way to compute the number of negatives values we'll have to deal with is simply to sum the 128
|
||||
// last values of the last histogram. Last histogram because that's the one for the Most Significant Byte,
|
||||
// responsible for the sign. 128 last values because the 128 first ones are related to positive numbers.
|
||||
u32* h3= &mHistogram[768];
|
||||
for(u32 i=128;i<256;i++) NbNegativeValues += h3[i]; // 768 for last histogram, 128 for negative part
|
||||
}
|
||||
|
||||
// Radix sort, j is the pass number (0=LSB, 3=MSB)
|
||||
for(u32 j=0;j<4;j++)
|
||||
{
|
||||
// Shortcut to current counters
|
||||
u32* CurCount = &mHistogram[j<<8];
|
||||
|
||||
// Reset flag. The sorting pass is supposed to be performed. (default)
|
||||
bool PerformPass = true;
|
||||
|
||||
// Check pass validity [some cycles are lost there in the generic case, but that's ok, just a little loop]
|
||||
for(u32 i=0;i<256;i++)
|
||||
{
|
||||
// If all values have the same byte, sorting is useless. It may happen when sorting bytes or words instead of dwords.
|
||||
// This routine actually sorts words faster than dwords, and bytes faster than words. Standard running time (O(4*n))is
|
||||
// reduced to O(2*n) for words and O(n) for bytes. Running time for floats depends on actual values...
|
||||
if(CurCount[i]==nb)
|
||||
{
|
||||
PerformPass=false;
|
||||
break;
|
||||
}
|
||||
// If at least one count is not 0, we suppose the pass must be done. Hence, this test takes very few CPU time in the generic case.
|
||||
if(CurCount[i]) break;
|
||||
}
|
||||
|
||||
// Sometimes the fourth (negative) pass is skipped because all numbers are negative and the MSB is 0xFF (for example). This is
|
||||
// not a problem, numbers are correctly sorted anyway.
|
||||
if(PerformPass)
|
||||
{
|
||||
// Should we care about negative values?
|
||||
if(j!=3 || !signedvalues)
|
||||
{
|
||||
// Here we deal with positive values only
|
||||
|
||||
// Create offsets
|
||||
mOffset[0] = 0;
|
||||
for(u32 i=1;i<256;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1];
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is a special case to correctly handle negative integers. They're sorted in the right order but at the wrong place.
|
||||
|
||||
// Create biased offsets, in order for negative numbers to be sorted as well
|
||||
mOffset[0] = NbNegativeValues; // First positive number takes place after the negative ones
|
||||
for(u32 i=1;i<128;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; // 1 to 128 for positive numbers
|
||||
|
||||
// Fixing the wrong place for negative values
|
||||
mOffset[128] = 0;
|
||||
for(u32 i=129;i<256;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1];
|
||||
}
|
||||
|
||||
// Perform Radix Sort
|
||||
u8* InputBytes = (u8*)input;
|
||||
u32* Indices = mIndices;
|
||||
u32* IndicesEnd = &mIndices[nb];
|
||||
InputBytes += j;
|
||||
while(Indices!=IndicesEnd)
|
||||
{
|
||||
u32 id = *Indices++;
|
||||
mIndices2[mOffset[InputBytes[id<<2]]++] = id;
|
||||
}
|
||||
|
||||
// Swap pointers for next pass
|
||||
u32* Tmp = mIndices;
|
||||
mIndices = mIndices2;
|
||||
mIndices2 = Tmp;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Main sort routine
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Input : input, a list of floating-point values to sort
|
||||
// nb, #values to sort
|
||||
// Output : mIndices, a list of indices in sorted order, i.e. in the order you may process your data
|
||||
// Return : Self-Reference
|
||||
// Exception: -
|
||||
// Remark : this one is for floating-point values
|
||||
RadixSorter& RadixSorter::Sort(float* input2, u32 nb)
|
||||
{
|
||||
u32* input = (u32*)input2;
|
||||
|
||||
// Resize lists if needed
|
||||
if(nb>mCurrentSize)
|
||||
{
|
||||
// Free previously used ram
|
||||
RELEASEARRAY(mIndices2);
|
||||
RELEASEARRAY(mIndices);
|
||||
|
||||
// Get some fresh one
|
||||
mIndices = new u32[nb];
|
||||
mIndices2 = new u32[nb];
|
||||
mCurrentSize = nb;
|
||||
|
||||
// Initialize indices so that the input buffer is read in sequential order
|
||||
ResetIndices();
|
||||
}
|
||||
|
||||
// Clear counters
|
||||
memset(mHistogram, 0, 256*4*sizeof(u32));
|
||||
|
||||
// Create histograms (counters). Counters for all passes are created in one run.
|
||||
// Pros: read input buffer once instead of four times
|
||||
// Cons: mHistogram is 4Kb instead of 1Kb
|
||||
// Floating-point values are always supposed to be signed values, so there's only one code path there.
|
||||
// Please note the floating point comparison needed for temporal coherence! Although the resulting asm code
|
||||
// is dreadful, this is surprisingly not such a performance hit - well, I suppose that's a big one on first
|
||||
// generation Pentiums....We can't make comparison on integer representations because, as Chris said, it just
|
||||
// wouldn't work with mixed positive/negative values....
|
||||
{
|
||||
// 3 lines for temporal coherence support
|
||||
float PrevVal = input2[mIndices[0]];
|
||||
bool AlreadySorted = true; // Optimism...
|
||||
u32* Indices = mIndices;
|
||||
|
||||
// Prepare to count
|
||||
u8* p = (u8*)input;
|
||||
u8* pe = &p[nb*4];
|
||||
u32* h0= &mHistogram[0]; // Histogram for first pass (LSB)
|
||||
u32* h1= &mHistogram[256]; // Histogram for second pass
|
||||
u32* h2= &mHistogram[512]; // Histogram for third pass
|
||||
u32* h3= &mHistogram[768]; // Histogram for last pass (MSB)
|
||||
while(p!=pe)
|
||||
{
|
||||
// Temporal coherence
|
||||
float Val = input2[*Indices++]; // Read input buffer in previous sorted order
|
||||
if(Val<PrevVal) AlreadySorted = false; // Check whether already sorted or not
|
||||
PrevVal = Val; // Update for next iteration
|
||||
|
||||
// Create histograms
|
||||
h0[*p++]++; h1[*p++]++; h2[*p++]++; h3[*p++]++;
|
||||
}
|
||||
|
||||
// If all input values are already sorted, we just have to return and leave the previous list unchanged.
|
||||
// That way the routine may take advantage of temporal coherence, for example when used to sort transparent faces.
|
||||
if(AlreadySorted) return *this;
|
||||
}
|
||||
|
||||
// Compute #negative values involved if needed
|
||||
u32 NbNegativeValues = 0;
|
||||
// An efficient way to compute the number of negatives values we'll have to deal with is simply to sum the 128
|
||||
// last values of the last histogram. Last histogram because that's the one for the Most Significant Byte,
|
||||
// responsible for the sign. 128 last values because the 128 first ones are related to positive numbers.
|
||||
u32* h3= &mHistogram[768];
|
||||
for(u32 i=128;i<256;i++) NbNegativeValues += h3[i]; // 768 for last histogram, 128 for negative part
|
||||
|
||||
// Radix sort, j is the pass number (0=LSB, 3=MSB)
|
||||
for(u32 j=0;j<4;j++)
|
||||
{
|
||||
// Shortcut to current counters
|
||||
u32* CurCount = &mHistogram[j<<8];
|
||||
|
||||
// Reset flag. The sorting pass is supposed to be performed. (default)
|
||||
bool PerformPass = true;
|
||||
|
||||
// Check pass validity [some cycles are lost there in the generic case, but that's ok, just a little loop]
|
||||
for(u32 i=0;i<256;i++)
|
||||
{
|
||||
// If all values have the same byte, sorting is useless. It may happen when sorting bytes or words instead of dwords.
|
||||
// This routine actually sorts words faster than dwords, and bytes faster than words. Standard running time (O(4*n))is
|
||||
// reduced to O(2*n) for words and O(n) for bytes. Running time for floats depends on actual values...
|
||||
if(CurCount[i]==nb)
|
||||
{
|
||||
PerformPass=false;
|
||||
break;
|
||||
}
|
||||
// If at least one count is not 0, we suppose the pass must be done. Hence, this test takes very few CPU time in the generic case.
|
||||
if(CurCount[i]) break;
|
||||
}
|
||||
|
||||
if(PerformPass)
|
||||
{
|
||||
// Should we care about negative values?
|
||||
if(j!=3)
|
||||
{
|
||||
// Here we deal with positive values only
|
||||
|
||||
// Create offsets
|
||||
mOffset[0] = 0;
|
||||
for(u32 i=1;i<256;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1];
|
||||
|
||||
// Perform Radix Sort
|
||||
u8* InputBytes = (u8*)input;
|
||||
u32* Indices = mIndices;
|
||||
u32* IndicesEnd = &mIndices[nb];
|
||||
InputBytes += j;
|
||||
while(Indices!=IndicesEnd)
|
||||
{
|
||||
u32 id = *Indices++;
|
||||
mIndices2[mOffset[InputBytes[id<<2]]++] = id;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is a special case to correctly handle negative values
|
||||
|
||||
// Create biased offsets, in order for negative numbers to be sorted as well
|
||||
mOffset[0] = NbNegativeValues; // First positive number takes place after the negative ones
|
||||
for(u32 i=1;i<128;i++) mOffset[i] = mOffset[i-1] + CurCount[i-1]; // 1 to 128 for positive numbers
|
||||
|
||||
// We must reverse the sorting order for negative numbers!
|
||||
mOffset[255] = 0;
|
||||
for(u32 i=0;i<127;i++) mOffset[254-i] = mOffset[255-i] + CurCount[255-i]; // Fixing the wrong order for negative values
|
||||
for(u32 i=128;i<256;i++) mOffset[i] += CurCount[i]; // Fixing the wrong place for negative values
|
||||
|
||||
// Perform Radix Sort
|
||||
for(u32 i=0;i<nb;i++)
|
||||
{
|
||||
u32 Radix = input[mIndices[i]]>>24; // Radix byte, same as above. AND is useless here (u32).
|
||||
// ### cmp to be killed. Not good. Later.
|
||||
if(Radix<128) mIndices2[mOffset[Radix]++] = mIndices[i]; // Number is positive, same as above
|
||||
else mIndices2[--mOffset[Radix]] = mIndices[i]; // Number is negative, flip the sorting order
|
||||
}
|
||||
}
|
||||
|
||||
// Swap pointers for next pass
|
||||
u32* Tmp = mIndices;
|
||||
mIndices = mIndices2;
|
||||
mIndices2 = Tmp;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// A method to reset the indices.
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Input : -
|
||||
// Output : mIndices is reset
|
||||
// Return : Self-Reference
|
||||
// Exception: -
|
||||
// Remark : -
|
||||
RadixSorter& RadixSorter::ResetIndices()
|
||||
{
|
||||
for(u32 i=0;i<mCurrentSize;i++)
|
||||
{
|
||||
mIndices[i] = i;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// A method to get the ram used.
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Input : -
|
||||
// Output : -
|
||||
// Return : u32, memory used in bytes
|
||||
// Exception: -
|
||||
// Remark : -
|
||||
u32 RadixSorter::GetUsedRam()
|
||||
{
|
||||
u32 UsedRam = 0;
|
||||
UsedRam += 256*4*sizeof(u32); // Histograms
|
||||
UsedRam += 256*sizeof(u32); // Offsets
|
||||
UsedRam += 2*mCurrentSize*sizeof(u32); // 2 lists of indices
|
||||
return UsedRam;
|
||||
}
|
||||
|
||||
57
DSMeshConvert/cets-pterdiman/RevisitedRadix.h
Normal file
57
DSMeshConvert/cets-pterdiman/RevisitedRadix.h
Normal file
@@ -0,0 +1,57 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Source code for "Radix Sort Revisited"
|
||||
// (C) 2000, Pierre Terdiman (p.terdiman@wanadoo.fr)
|
||||
//
|
||||
// Works with IEEE floats only.
|
||||
// Version is 1.1.
|
||||
//
|
||||
// This is my new radix routine:
|
||||
// - it uses indices and doesn't recopy the values anymore, hence wasting less ram
|
||||
// - it creates all the histograms in one run instead of four
|
||||
// - it sorts words faster than dwords and bytes faster than words
|
||||
// - it correctly sorts negative floats by patching the offsets
|
||||
// - it automatically takes advantage of temporal coherence
|
||||
// - multiple keys support is a side effect of temporal coherence
|
||||
// - it may be worth recoding in asm...
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __RADIXSORT_H__
|
||||
#define __RADIXSORT_H__
|
||||
#include "../types.h"
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Class RadixSorter
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
class RadixSorter
|
||||
{
|
||||
public:
|
||||
// Constructor/Destructor
|
||||
RadixSorter();
|
||||
~RadixSorter();
|
||||
|
||||
// Sorting methods
|
||||
RadixSorter& Sort(u32* input, u32 nb, bool signedvalues=true);
|
||||
RadixSorter& Sort(float* input, u32 nb);
|
||||
|
||||
// Access to results
|
||||
// mIndices is a list of indices in sorted order, i.e. in the order you may further process your data
|
||||
u32* GetIndices() { return mIndices; }
|
||||
|
||||
// Reset the inner indices
|
||||
RadixSorter& ResetIndices();
|
||||
|
||||
// Stats
|
||||
u32 GetUsedRam();
|
||||
private:
|
||||
u32* mHistogram; // Counters for each byte
|
||||
u32* mOffset; // Offsets (nearly a cumulative distribution function)
|
||||
|
||||
u32 mCurrentSize; // Current size of the indices list
|
||||
u32* mIndices; // Two lists, swapped each pass
|
||||
u32* mIndices2;
|
||||
};
|
||||
|
||||
#endif // __RADIXSORT_H__
|
||||
421
DSMeshConvert/cets-pterdiman/Striper.cpp
Normal file
421
DSMeshConvert/cets-pterdiman/Striper.cpp
Normal file
@@ -0,0 +1,421 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Source code for "Creating Efficient Triangle Strips"
|
||||
// (C) 2000, Pierre Terdiman (p.terdiman@wanadoo.fr)
|
||||
//
|
||||
// Version is 2.0.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Precompiled Header
|
||||
//#include "Stdafx.h"
|
||||
#include "Striper.h"
|
||||
#include <string.h>
|
||||
#include "RevisitedRadix.h"
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Striper Class Implementation
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Striper::Striper() : mAdj(0), mTags(0), mStripLengths(0), mStripRuns(0), mSingleStrip(0)
|
||||
{
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Destructor
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Striper::~Striper()
|
||||
{
|
||||
FreeUsedRam();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// A method to free possibly used ram
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Input : -
|
||||
// Output : -
|
||||
// Return : Self-reference
|
||||
// Exception: -
|
||||
// Remark : -
|
||||
Striper& Striper::FreeUsedRam()
|
||||
{
|
||||
RELEASE(mSingleStrip);
|
||||
RELEASE(mStripRuns);
|
||||
RELEASE(mStripLengths);
|
||||
RELEASEARRAY(mTags);
|
||||
RELEASE(mAdj);
|
||||
return *this;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// A method to initialize the striper
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Input : create, the creation structure
|
||||
// Output : -
|
||||
// Return : true if success
|
||||
// Exception: -
|
||||
// Remark : -
|
||||
bool Striper::Init(STRIPERCREATE& create)
|
||||
{
|
||||
// Release possibly already used ram
|
||||
FreeUsedRam();
|
||||
|
||||
// Create adjacencies
|
||||
{
|
||||
mAdj = new Adjacencies;
|
||||
if(!mAdj) return false;
|
||||
|
||||
ADJACENCIESCREATE ac;
|
||||
ac.NbFaces = create.NbFaces;
|
||||
ac.DFaces = create.DFaces;
|
||||
ac.WFaces = create.WFaces;
|
||||
bool Status = mAdj->Init(ac);
|
||||
if(!Status) { RELEASE(mAdj); return false; }
|
||||
|
||||
Status = mAdj->CreateDatabase();
|
||||
if(!Status) { RELEASE(mAdj); return false; }
|
||||
|
||||
mAskForWords = create.AskForWords;
|
||||
mOneSided = create.OneSided;
|
||||
mSGIAlgorithm = create.SGIAlgorithm;
|
||||
mConnectAllStrips = create.ConnectAllStrips;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// A method to create the triangle strips
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Input : result, the result structure
|
||||
// Output : -
|
||||
// Return : true if success
|
||||
// Exception: -
|
||||
// Remark : -
|
||||
bool Striper::Compute(STRIPERRESULT& result)
|
||||
{
|
||||
// You must call Init() first
|
||||
if(!mAdj) return false;
|
||||
|
||||
// Get some bytes
|
||||
mStripLengths = new CustomArray; if(!mStripLengths) return false;
|
||||
mStripRuns = new CustomArray; if(!mStripRuns) return false;
|
||||
mTags = new bool[mAdj->mNbFaces]; if(!mTags) return false;
|
||||
u32* Connectivity = new u32[mAdj->mNbFaces]; if(!Connectivity) return false;
|
||||
|
||||
// mTags contains one bool/face. True=>the face has already been included in a strip
|
||||
memset(mTags, 0, mAdj->mNbFaces*sizeof(bool));
|
||||
|
||||
// Compute the number of connections for each face. This buffer is further recycled into
|
||||
// the insertion order, ie contains face indices in the order we should treat them
|
||||
memset(Connectivity, 0, mAdj->mNbFaces*sizeof(u32));
|
||||
if(mSGIAlgorithm)
|
||||
{
|
||||
// Compute number of adjacent triangles for each face
|
||||
for(u32 i=0;i<mAdj->mNbFaces;i++)
|
||||
{
|
||||
AdjTriangle* Tri = &mAdj->mFaces[i];
|
||||
if(!IS_BOUNDARY(Tri->ATri[0])) Connectivity[i]++;
|
||||
if(!IS_BOUNDARY(Tri->ATri[1])) Connectivity[i]++;
|
||||
if(!IS_BOUNDARY(Tri->ATri[2])) Connectivity[i]++;
|
||||
}
|
||||
|
||||
// Sort by number of neighbors
|
||||
RadixSorter RS;
|
||||
u32* Sorted = RS.Sort(Connectivity, mAdj->mNbFaces).GetIndices();
|
||||
|
||||
// The sorted indices become the order of insertion in the strips
|
||||
memcpy(Connectivity, Sorted, mAdj->mNbFaces*sizeof(u32));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default order
|
||||
for(u32 i=0;i<mAdj->mNbFaces;i++) Connectivity[i] = i;
|
||||
}
|
||||
|
||||
mNbStrips = 0; // #strips created
|
||||
u32 TotalNbFaces = 0; // #faces already transformed into strips
|
||||
u32 Index = 0; // Index of first face
|
||||
|
||||
while(TotalNbFaces!=mAdj->mNbFaces)
|
||||
{
|
||||
// Look for the first face [could be optimized]
|
||||
while(mTags[Connectivity[Index]]) Index++;
|
||||
u32 FirstFace = Connectivity[Index];
|
||||
|
||||
// Compute the three possible strips from this face and take the best
|
||||
TotalNbFaces += ComputeBestStrip(FirstFace);
|
||||
|
||||
// Let's wrap
|
||||
mNbStrips++;
|
||||
}
|
||||
|
||||
// Free now useless ram
|
||||
RELEASEARRAY(Connectivity);
|
||||
RELEASEARRAY(mTags);
|
||||
|
||||
// Fill result structure and exit
|
||||
result.NbStrips = mNbStrips;
|
||||
result.StripLengths = (u32*) mStripLengths ->Collapse();
|
||||
result.StripRuns = mStripRuns ->Collapse();
|
||||
|
||||
if(mConnectAllStrips) ConnectAllStrips(result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// A method to compute the three possible strips starting from a given face
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Input : face, the first face
|
||||
// Output : -
|
||||
// Return : u32, the #faces included in the strip
|
||||
// Exception: -
|
||||
// Remark : mStripLengths and mStripRuns are filled with strip data
|
||||
u32 Striper::ComputeBestStrip(u32 face)
|
||||
{
|
||||
u32* Strip[3]; // Strips computed in the 3 possible directions
|
||||
u32* Faces[3]; // Faces involved in the 3 previous strips
|
||||
u32 Length[3]; // Lengths of the 3 previous strips
|
||||
|
||||
u32 FirstLength[3]; // Lengths of the first parts of the strips are saved for culling
|
||||
|
||||
// Starting references
|
||||
u32 Refs0[3];
|
||||
u32 Refs1[3];
|
||||
Refs0[0] = mAdj->mFaces[face].VRef[0];
|
||||
Refs1[0] = mAdj->mFaces[face].VRef[1];
|
||||
|
||||
// Bugfix by Eric Malafeew!
|
||||
Refs0[1] = mAdj->mFaces[face].VRef[2];
|
||||
Refs1[1] = mAdj->mFaces[face].VRef[0];
|
||||
|
||||
Refs0[2] = mAdj->mFaces[face].VRef[1];
|
||||
Refs1[2] = mAdj->mFaces[face].VRef[2];
|
||||
|
||||
// Compute 3 strips
|
||||
for(u32 j=0;j<3;j++)
|
||||
{
|
||||
// Get some bytes for the strip and its faces
|
||||
Strip[j] = new u32[mAdj->mNbFaces+2+1+2]; // max possible length is NbFaces+2, 1 more if the first index gets replicated
|
||||
Faces[j] = new u32[mAdj->mNbFaces+2];
|
||||
memset(Strip[j], 0xff, (mAdj->mNbFaces+2+1+2)*sizeof(u32));
|
||||
memset(Faces[j], 0xff, (mAdj->mNbFaces+2)*sizeof(u32));
|
||||
|
||||
// Create a local copy of the tags
|
||||
bool* Tags = new bool[mAdj->mNbFaces];
|
||||
memcpy(Tags, mTags, mAdj->mNbFaces*sizeof(bool));
|
||||
|
||||
// Track first part of the strip
|
||||
Length[j] = TrackStrip(face, Refs0[j], Refs1[j], &Strip[j][0], &Faces[j][0], Tags);
|
||||
|
||||
// Save first length for culling
|
||||
FirstLength[j] = Length[j];
|
||||
// if(j==1) FirstLength[j]++; // ...because the first face is written in reverse order for j==1
|
||||
|
||||
// Reverse first part of the strip
|
||||
for(u32 i=0;i<Length[j]/2;i++)
|
||||
{
|
||||
Strip[j][i] ^= Strip[j][Length[j]-i-1];
|
||||
Strip[j][Length[j]-i-1] ^= Strip[j][i];
|
||||
Strip[j][i] ^= Strip[j][Length[j]-i-1];
|
||||
}
|
||||
for(u32 i=0;i<(Length[j]-2)/2;i++)
|
||||
{
|
||||
Faces[j][i] ^= Faces[j][Length[j]-i-3];
|
||||
Faces[j][Length[j]-i-3] ^= Faces[j][i];
|
||||
Faces[j][i] ^= Faces[j][Length[j]-i-3];
|
||||
}
|
||||
|
||||
// Track second part of the strip
|
||||
u32 NewRef0 = Strip[j][Length[j]-3];
|
||||
u32 NewRef1 = Strip[j][Length[j]-2];
|
||||
u32 ExtraLength = TrackStrip(face, NewRef0, NewRef1, &Strip[j][Length[j]-3], &Faces[j][Length[j]-3], Tags);
|
||||
Length[j]+=ExtraLength-3;
|
||||
|
||||
// Free temp ram
|
||||
RELEASEARRAY(Tags);
|
||||
}
|
||||
|
||||
// Look for the best strip among the three
|
||||
u32 Longest = Length[0];
|
||||
u32 Best = 0;
|
||||
if(Length[1] > Longest) { Longest = Length[1]; Best = 1; }
|
||||
if(Length[2] > Longest) { Longest = Length[2]; Best = 2; }
|
||||
|
||||
u32 NbFaces = Longest-2;
|
||||
|
||||
// Update global tags
|
||||
for(u32 j=0;j<Longest-2;j++) mTags[Faces[Best][j]] = true;
|
||||
|
||||
// Flip strip if needed ("if the length of the first part of the strip is odd, the strip must be reversed")
|
||||
if(mOneSided && FirstLength[Best]&1)
|
||||
{
|
||||
// Here the strip must be flipped. I hardcoded a special case for triangles and quads.
|
||||
if(Longest==3 || Longest==4)
|
||||
{
|
||||
// Flip isolated triangle or quad
|
||||
Strip[Best][1] ^= Strip[Best][2];
|
||||
Strip[Best][2] ^= Strip[Best][1];
|
||||
Strip[Best][1] ^= Strip[Best][2];
|
||||
}
|
||||
else
|
||||
{
|
||||
// "to reverse the strip, write it in reverse order"
|
||||
for(u32 j=0;j<Longest/2;j++)
|
||||
{
|
||||
Strip[Best][j] ^= Strip[Best][Longest-j-1];
|
||||
Strip[Best][Longest-j-1] ^= Strip[Best][j];
|
||||
Strip[Best][j] ^= Strip[Best][Longest-j-1];
|
||||
}
|
||||
|
||||
// "If the position of the original face in this new reversed strip is odd, you're done"
|
||||
u32 NewPos = Longest-FirstLength[Best];
|
||||
if(NewPos&1)
|
||||
{
|
||||
// "Else replicate the first index"
|
||||
for(u32 j=0;j<Longest;j++) Strip[Best][Longest-j] = Strip[Best][Longest-j-1];
|
||||
Longest++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy best strip in the strip buffers
|
||||
for(u32 j=0;j<Longest;j++)
|
||||
{
|
||||
u32 Ref = Strip[Best][j];
|
||||
if(mAskForWords) mStripRuns->Store((u16)Ref); // Saves word reference
|
||||
else mStripRuns->Store(Ref); // Saves dword reference
|
||||
}
|
||||
mStripLengths->Store(Longest);
|
||||
|
||||
// Free local ram
|
||||
for(u32 j=0;j<3;j++)
|
||||
{
|
||||
RELEASEARRAY(Faces[j]);
|
||||
RELEASEARRAY(Strip[j]);
|
||||
}
|
||||
|
||||
// Returns #faces involved in the strip
|
||||
return NbFaces;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// A method to extend a strip in a given direction, starting from a given face
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Input : face, the starting face
|
||||
// oldest, middle, the two first indices of the strip == a starting edge == a direction
|
||||
// Output : strip, a buffer to store the strip
|
||||
// faces, a buffer to store the faces of the strip
|
||||
// tags, a buffer to mark the visited faces
|
||||
// Return : u32, the strip length
|
||||
// Exception: -
|
||||
// Remark : -
|
||||
u32 Striper::TrackStrip(u32 face, u32 oldest, u32 middle, u32* strip, u32* faces, bool* tags)
|
||||
{
|
||||
u32 Length = 2; // Initial length is 2 since we have 2 indices in input
|
||||
strip[0] = oldest; // First index of the strip
|
||||
strip[1] = middle; // Second index of the strip
|
||||
|
||||
bool DoTheStrip = true;
|
||||
while(DoTheStrip)
|
||||
{
|
||||
u32 Newest = mAdj->mFaces[face].OppositeVertex(oldest, middle); // Get the third index of a face given two of them
|
||||
strip[Length++] = Newest; // Extend the strip,...
|
||||
*faces++ = face; // ...keep track of the face,...
|
||||
tags[face] = true; // ...and mark it as "done".
|
||||
|
||||
u8 CurEdge = mAdj->mFaces[face].FindEdge(middle, Newest); // Get the edge ID...
|
||||
|
||||
u32 Link = mAdj->mFaces[face].ATri[CurEdge]; // ...and use it to catch the link to adjacent face.
|
||||
if(IS_BOUNDARY(Link)) DoTheStrip = false; // If the face is no more connected, we're done...
|
||||
else
|
||||
{
|
||||
face = MAKE_ADJ_TRI(Link); // ...else the link gives us the new face index.
|
||||
if(tags[face]) DoTheStrip=false; // Is the new face already done?
|
||||
}
|
||||
oldest = middle; // Shift the indices and wrap
|
||||
middle = Newest;
|
||||
}
|
||||
return Length;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// A method to link all strips in a single one.
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Input : result, the result structure
|
||||
// Output : the result structure is updated
|
||||
// Return : true if success
|
||||
// Exception: -
|
||||
// Remark : -
|
||||
bool Striper::ConnectAllStrips(STRIPERRESULT& result)
|
||||
{
|
||||
mSingleStrip = new CustomArray;
|
||||
if(!mSingleStrip) return false;
|
||||
|
||||
mTotalLength = 0;
|
||||
u16* wrefs = mAskForWords ? (u16*)result.StripRuns : 0;
|
||||
u32* drefs = mAskForWords ? 0 : (u32*)result.StripRuns;
|
||||
|
||||
// Loop over strips and link them together
|
||||
for(u32 k=0;k<result.NbStrips;k++)
|
||||
{
|
||||
// Nothing to do for the first strip, we just copy it
|
||||
if(k)
|
||||
{
|
||||
// This is not the first strip, so we must copy two void vertices between the linked strips
|
||||
u32 LastRef = drefs ? drefs[-1] : (u32)wrefs[-1];
|
||||
u32 FirstRef = drefs ? drefs[0] : (u32)wrefs[0];
|
||||
if(mAskForWords) mSingleStrip->Store((u16)LastRef).Store((u16)FirstRef);
|
||||
else mSingleStrip->Store(LastRef).Store(FirstRef);
|
||||
mTotalLength += 2;
|
||||
|
||||
// Linking two strips may flip their culling. If the user asked for single-sided strips we must fix that
|
||||
if(mOneSided)
|
||||
{
|
||||
// Culling has been inverted only if mTotalLength is odd
|
||||
if(mTotalLength&1)
|
||||
{
|
||||
// We can fix culling by replicating the first vertex once again...
|
||||
u32 SecondRef = drefs ? drefs[1] : (u32)wrefs[1];
|
||||
if(FirstRef!=SecondRef)
|
||||
{
|
||||
if(mAskForWords) mSingleStrip->Store((u16)FirstRef);
|
||||
else mSingleStrip->Store(FirstRef);
|
||||
mTotalLength++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// ...but if flipped strip already begin with a replicated vertex, we just can skip it.
|
||||
result.StripLengths[k]--;
|
||||
if(wrefs) wrefs++;
|
||||
if(drefs) drefs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy strip
|
||||
for(u32 j=0;j<result.StripLengths[k];j++)
|
||||
{
|
||||
u32 Ref = drefs ? drefs[j] : (u32)wrefs[j];
|
||||
if(mAskForWords) mSingleStrip->Store((u16)Ref);
|
||||
else mSingleStrip->Store(Ref);
|
||||
}
|
||||
if(wrefs) wrefs += result.StripLengths[k];
|
||||
if(drefs) drefs += result.StripLengths[k];
|
||||
mTotalLength += result.StripLengths[k];
|
||||
}
|
||||
|
||||
// Update result structure
|
||||
result.NbStrips = 1;
|
||||
result.StripRuns = mSingleStrip->Collapse();
|
||||
result.StripLengths = &mTotalLength;
|
||||
|
||||
return true;
|
||||
}
|
||||
82
DSMeshConvert/cets-pterdiman/Striper.h
Normal file
82
DSMeshConvert/cets-pterdiman/Striper.h
Normal file
@@ -0,0 +1,82 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Source code for "Creating Efficient Triangle Strips"
|
||||
// (C) 2000, Pierre Terdiman (p.terdiman@wanadoo.fr)
|
||||
//
|
||||
// Version is 2.0.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __STRIPER_H__
|
||||
#define __STRIPER_H__
|
||||
|
||||
#include "Adjacency.h"
|
||||
#include "CustomArray.h"
|
||||
#include "../types.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Class Striper
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct STRIPERCREATE{
|
||||
STRIPERCREATE()
|
||||
{
|
||||
DFaces = 0;
|
||||
WFaces = 0;
|
||||
NbFaces = 0;
|
||||
AskForWords = true;
|
||||
OneSided = true;
|
||||
SGIAlgorithm = true;
|
||||
ConnectAllStrips = false;
|
||||
}
|
||||
u32 NbFaces; // #faces in source topo
|
||||
u32* DFaces; // list of faces (dwords) or 0
|
||||
u16* WFaces; // list of faces (words) or 0
|
||||
bool AskForWords; // true => results are in words (else dwords)
|
||||
bool OneSided; // true => create one-sided strips
|
||||
bool SGIAlgorithm; // true => use the SGI algorithm, pick least connected faces first
|
||||
bool ConnectAllStrips; // true => create a single strip with void faces
|
||||
};
|
||||
|
||||
struct STRIPERRESULT{
|
||||
u32 NbStrips; // #strips created
|
||||
u32* StripLengths; // Lengths of the strips (NbStrips values)
|
||||
void* StripRuns; // The strips in words or dwords, depends on AskForWords
|
||||
bool AskForWords; // true => results are in words (else dwords)
|
||||
};
|
||||
|
||||
class Striper
|
||||
{
|
||||
private:
|
||||
Striper& FreeUsedRam();
|
||||
u32 ComputeBestStrip(u32 face);
|
||||
u32 TrackStrip(u32 face, u32 oldest, u32 middle, u32* strip, u32* faces, bool* tags);
|
||||
bool ConnectAllStrips(STRIPERRESULT& result);
|
||||
|
||||
Adjacencies* mAdj; // Adjacency structures
|
||||
bool* mTags; // Face markers
|
||||
|
||||
u32 mNbStrips; // The number of strips created for the mesh
|
||||
CustomArray* mStripLengths; // Array to store strip lengths
|
||||
CustomArray* mStripRuns; // Array to store strip indices
|
||||
|
||||
u32 mTotalLength; // The length of the single strip
|
||||
CustomArray* mSingleStrip; // Array to store the single strip
|
||||
|
||||
// Flags
|
||||
bool mAskForWords;
|
||||
bool mOneSided;
|
||||
bool mSGIAlgorithm;
|
||||
bool mConnectAllStrips;
|
||||
|
||||
public:
|
||||
Striper();
|
||||
~Striper();
|
||||
|
||||
bool Init(STRIPERCREATE& create);
|
||||
bool Compute(STRIPERRESULT& result);
|
||||
};
|
||||
|
||||
#endif // __STRIPER_H__
|
||||
46
DSMeshConvert/cets-pterdiman/Strips.cpp
Normal file
46
DSMeshConvert/cets-pterdiman/Strips.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
//#include "Stdafx.h"
|
||||
//
|
||||
//int main(int argc, char* argv[])
|
||||
//{
|
||||
// // Dumb test
|
||||
//
|
||||
// u32 Topology[] = {
|
||||
// 0,1,2,
|
||||
// 1,2,3,
|
||||
// 2,3,4,
|
||||
// 3,4,5,
|
||||
// 4,5,6,
|
||||
// 5,6,7,
|
||||
// 6,7,8,
|
||||
// 7,8,9
|
||||
// };
|
||||
//
|
||||
// STRIPERCREATE sc;
|
||||
// sc.DFaces = Topology;
|
||||
// sc.NbFaces = 8;
|
||||
// sc.AskForWords = true;
|
||||
// sc.ConnectAllStrips = false;
|
||||
// sc.OneSided = false;
|
||||
// sc.SGIAlgorithm = true;
|
||||
//
|
||||
// Striper Strip;
|
||||
// Strip.Init(sc);
|
||||
//
|
||||
// STRIPERRESULT sr;
|
||||
// Strip.Compute(sr);
|
||||
//
|
||||
// fprintf(stdout, "Number of strips: %d\n", sr.NbStrips);
|
||||
// u16* Refs = (u16*)sr.StripRuns;
|
||||
// for(u32 i=0;i<sr.NbStrips;i++)
|
||||
// {
|
||||
// fprintf(stdout, "Strip %d: ", i);
|
||||
// u32 NbRefs = sr.StripLengths[i];
|
||||
// for(u32 j=0;j<NbRefs;j++)
|
||||
// {
|
||||
// fprintf(stdout, "%d ", *Refs++);
|
||||
// }
|
||||
// fprintf(stdout, "\n");
|
||||
// }
|
||||
//
|
||||
// return 0;
|
||||
//}
|
||||
1
DSMeshConvert/help.txt
Normal file
1
DSMeshConvert/help.txt
Normal file
@@ -0,0 +1 @@
|
||||
you need to add assimp 1.1.700 to the directory assimp--1.1.700-sdk for this to compile.
|
||||
381
DSMeshConvert/main.cpp
Normal file
381
DSMeshConvert/main.cpp
Normal file
@@ -0,0 +1,381 @@
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include <assimp.hpp>
|
||||
#include <aiPostProcess.h>
|
||||
#include <aiConfig.h>
|
||||
#include <aiMesh.h>
|
||||
#include <aiScene.h>
|
||||
|
||||
#include <aiVector3D.inl>
|
||||
|
||||
//#define NVTRISTRIP // buggy?!!
|
||||
//#define CETS_PTERDIMAN // http://www.codercorner.com/Strips.htm // memory corruption...
|
||||
#define ACTC // http://plunk.org/~grantham/public/actc/
|
||||
#include "NvTriStrip.h"
|
||||
#include "cets-pterdiman/Striper.h"
|
||||
#include "ac/tc.h"
|
||||
|
||||
#include "stripping.h"
|
||||
|
||||
#include "types.h"
|
||||
|
||||
struct Box
|
||||
{
|
||||
aiVector3D min, max;
|
||||
};
|
||||
|
||||
Box ComputeBoundingBox(aiVector3D* vertices, u32 nbVertices)
|
||||
{
|
||||
Box aabb = { aiVector3D(100000000.0f), aiVector3D(-100000000.0f) };
|
||||
|
||||
for ( u32 i = nbVertices ; i > 0 ; i-- )
|
||||
{
|
||||
if ( vertices->x < aabb.min.x ) aabb.min.x = vertices->x;
|
||||
if ( vertices->y < aabb.min.y ) aabb.min.y = vertices->y;
|
||||
if ( vertices->z < aabb.min.z ) aabb.min.z = vertices->z;
|
||||
if ( vertices->x > aabb.max.x ) aabb.max.x = vertices->x;
|
||||
if ( vertices->y > aabb.max.y ) aabb.max.y = vertices->y;
|
||||
if ( vertices->z > aabb.max.z ) aabb.max.z = vertices->z;
|
||||
vertices++;
|
||||
}
|
||||
|
||||
return aabb;
|
||||
}
|
||||
|
||||
aiMatrix4x4 operator+(aiMatrix4x4& a, aiMatrix4x4& b)
|
||||
{
|
||||
return aiMatrix4x4(
|
||||
a.a1 + b.a1, a.a2 + b.a2, a.a3 + b.a3, a.a4 + b.a4,
|
||||
a.b1 + b.b1, a.b2 + b.b2, a.b3 + b.b3, a.b4 + b.b4,
|
||||
a.c1 + b.c1, a.c2 + b.c2, a.c3 + b.c3, a.c4 + b.c4,
|
||||
a.d1 + b.d1, a.d2 + b.d2, a.d3 + b.d3, a.d4 + b.d4);
|
||||
}
|
||||
|
||||
template <typename t>
|
||||
t map(t x, t a, t b, t c, t d)
|
||||
{
|
||||
t s = b - a;
|
||||
t t = (b * c - a * d) / s;
|
||||
s = (d - c) / s;
|
||||
return x * s + t;
|
||||
}
|
||||
|
||||
void PushValue(std::vector<u32>& list, u32& cmdOffset, u32& cmdIndex, u32 cmd, u32 value)
|
||||
{
|
||||
list[cmdOffset] |= cmd << (cmdIndex * 8); // color
|
||||
cmdIndex = (cmdIndex + 1) % 4;
|
||||
list.push_back(value);
|
||||
if ( cmdIndex == 0 )
|
||||
{
|
||||
list.push_back(0);
|
||||
cmdOffset = list.size() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
int Convert(const char* input, const char* output)
|
||||
{
|
||||
#ifdef NVTRISTRIP
|
||||
// Configure NVTriStrip
|
||||
SetStitchStrips(false);
|
||||
SetCacheSize(64); // ds has no cache, give me longest strips possible ffs !
|
||||
#endif
|
||||
|
||||
// Configure Assimp
|
||||
Assimp::Importer importer;
|
||||
importer.SetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE,
|
||||
aiPrimitiveType_POINT
|
||||
| aiPrimitiveType_LINE);
|
||||
importer.SetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS,
|
||||
aiComponent_TANGENTS_AND_BITANGENTS
|
||||
//| aiComponent_COLORS
|
||||
| aiComponent_COLORSn(1)
|
||||
| aiComponent_COLORSn(2)
|
||||
| aiComponent_COLORSn(3)
|
||||
| aiComponent_TEXCOORDSn(1)
|
||||
| aiComponent_TEXCOORDSn(2)
|
||||
| aiComponent_TEXCOORDSn(3)
|
||||
| aiComponent_BONEWEIGHTS
|
||||
| aiComponent_ANIMATIONS
|
||||
| aiComponent_TEXTURES
|
||||
| aiComponent_LIGHTS
|
||||
| aiComponent_CAMERAS
|
||||
| aiComponent_MATERIALS);
|
||||
|
||||
// Import file
|
||||
const aiScene* scene = importer.ReadFile(input,
|
||||
aiProcess_FixInfacingNormals
|
||||
| aiProcess_GenUVCoords
|
||||
| aiProcess_TransformUVCoords
|
||||
| aiProcess_JoinIdenticalVertices
|
||||
| aiProcess_Triangulate
|
||||
| aiProcess_PreTransformVertices
|
||||
| aiProcess_FindDegenerates
|
||||
| aiProcess_SortByPType
|
||||
| aiProcess_FindInstances
|
||||
| aiProcess_OptimizeMeshes
|
||||
| aiProcess_ImproveCacheLocality
|
||||
| aiProcess_RemoveComponent);
|
||||
|
||||
if ( scene == 0 )
|
||||
{
|
||||
fprintf(stderr, "Could not import %s\n", input);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// TODO: collapse all meshes into one, with warning output
|
||||
if ( scene->mNumMeshes > 1 )
|
||||
{
|
||||
fprintf(stderr, "%s has multiple meshes, not exporting\n", input);
|
||||
return 2;
|
||||
}
|
||||
|
||||
aiMesh* mesh = scene->mMeshes[0];
|
||||
|
||||
if ( mesh->mFaces->mNumIndices > 65535 )
|
||||
{
|
||||
fprintf(stderr, "Model is too complex, not exporting\n");
|
||||
return 3;
|
||||
}
|
||||
|
||||
//std::vector<u32> indices;
|
||||
//for ( u32 i = 0 ; i < mesh->mNumFaces ; i++ )
|
||||
//{
|
||||
// ai_assert(mesh->mFaces[i].mNumIndices == 3);
|
||||
// indices.push_back(mesh->mFaces[i].mIndices[0]);
|
||||
// indices.push_back(mesh->mFaces[i].mIndices[1]);
|
||||
// indices.push_back(mesh->mFaces[i].mIndices[2]);
|
||||
//}
|
||||
|
||||
//BuildDualGraph(indices);
|
||||
|
||||
// Generate triangle strips
|
||||
#ifdef NVTRISTRIP
|
||||
u32 nbIndices = mesh->mNumFaces * 3;
|
||||
u16* indices = new u16[nbIndices];
|
||||
u16* pIndices = indices;
|
||||
for ( u32 i = 0 ; i < nbIndices / 3 ; i++ )
|
||||
{
|
||||
ai_assert(mesh->mFaces[i].mNumIndices == 3);
|
||||
*pIndices++ = mesh->mFaces[i].mIndices[0];
|
||||
*pIndices++ = mesh->mFaces[i].mIndices[1];
|
||||
*pIndices++ = mesh->mFaces[i].mIndices[2];
|
||||
}
|
||||
u16 nbStrips = 0;
|
||||
PrimitiveGroup* strips = 0;
|
||||
if ( ! GenerateStrips(indices, nbIndices, &strips, &nbStrips) )
|
||||
{
|
||||
fprintf(stderr, "Couldn't generate triangle strips, aborting\n");
|
||||
delete[] indices;
|
||||
return 4;
|
||||
}
|
||||
#endif
|
||||
#ifdef CETS_PTERDIMAN
|
||||
u32 nbIndices = mesh->mNumFaces * 3;
|
||||
u32* indices = new u32[nbIndices];
|
||||
u32* pIndices = indices;
|
||||
for ( u32 i = 0 ; i < nbIndices / 3 ; i++ )
|
||||
{
|
||||
*pIndices++ = mesh->mFaces[i].mIndices[0];
|
||||
*pIndices++ = mesh->mFaces[i].mIndices[1];
|
||||
*pIndices++ = mesh->mFaces[i].mIndices[2];
|
||||
}
|
||||
STRIPERCREATE sc;
|
||||
sc.DFaces = indices;
|
||||
sc.NbFaces = mesh->mNumFaces;
|
||||
sc.AskForWords = true;
|
||||
sc.ConnectAllStrips = false;
|
||||
sc.OneSided = false;
|
||||
sc.SGIAlgorithm = false;
|
||||
|
||||
Striper Strip;
|
||||
Strip.Init(sc);
|
||||
|
||||
STRIPERRESULT sr;
|
||||
Strip.Compute(sr);
|
||||
u32 nbStrips = sr.NbStrips;
|
||||
#endif
|
||||
#ifdef ACTC
|
||||
ACTCData *tc;
|
||||
tc = actcNew();
|
||||
actcParami(tc, ACTC_OUT_MIN_FAN_VERTS, INT_MAX);
|
||||
actcBeginInput(tc);
|
||||
for ( u32 i = 0 ; i < mesh->mNumFaces ; i++ )
|
||||
actcAddTriangle(tc,
|
||||
mesh->mFaces[i].mIndices[0],
|
||||
mesh->mFaces[i].mIndices[1],
|
||||
mesh->mFaces[i].mIndices[2]);
|
||||
actcEndInput(tc);
|
||||
actcBeginOutput(tc);
|
||||
u32 prim;
|
||||
u32 v1, v2, v3;
|
||||
u32 nbStrips = 0;
|
||||
std::vector<u32> stripLengths;
|
||||
std::vector<u16> stripIndices;
|
||||
while ( (prim = actcStartNextPrim(tc, &v1, &v2)) != ACTC_DATABASE_EMPTY )
|
||||
{
|
||||
nbStrips++;
|
||||
stripIndices.push_back(v1);
|
||||
stripIndices.push_back(v2);
|
||||
u32 len = 2;
|
||||
while ( actcGetNextVert(tc, &v3) != ACTC_PRIM_COMPLETE )
|
||||
{
|
||||
len++;
|
||||
stripIndices.push_back(v3);
|
||||
}
|
||||
stripLengths.push_back(len);
|
||||
}
|
||||
actcEndOutput(tc);
|
||||
#endif
|
||||
printf("%d strips generated for %d triangles\n", nbStrips, mesh->mNumFaces);
|
||||
|
||||
// TODO: AABB => OBB, for higher precision
|
||||
Box box = ComputeBoundingBox(mesh->mVertices, mesh->mNumVertices);
|
||||
aiVector3D minDS(-7.99f);
|
||||
aiVector3D maxDS(7.99f);
|
||||
aiVector3D scale = box.max - box.min;
|
||||
aiVector3D translate = aiVector3D(
|
||||
box.max.x * minDS.x - box.min.x * maxDS.x,
|
||||
box.max.y * minDS.y - box.min.y * maxDS.y,
|
||||
box.max.z * minDS.z - box.min.z * maxDS.z);
|
||||
translate = translate / scale;
|
||||
scale = (maxDS - minDS) / scale;
|
||||
|
||||
// Generate display list
|
||||
std::vector<u32> list;
|
||||
|
||||
aiMatrix4x4 transform;
|
||||
aiMatrix4x4::Scaling(1.0f / scale, transform);
|
||||
aiMatrix4x4 tmp;
|
||||
aiMatrix4x4::Translation(-translate, tmp);
|
||||
tmp.a1 = 0; tmp.b2 = 0; tmp.c3 = 0;
|
||||
transform = transform + tmp;
|
||||
list.push_back(0x19); // mult matrix 4x3 command
|
||||
float* mtx = transform[0];
|
||||
for ( u32 i = 0 ; i < 4 ; i++ )
|
||||
{
|
||||
for ( u32 j = 0 ; j < 3 ; j++ )
|
||||
{
|
||||
list.push_back(s32(mtx[i + j * 4] * float(1 << 12)));
|
||||
}
|
||||
}
|
||||
|
||||
u32 cmdindex = 1;
|
||||
u32 command = 0;
|
||||
|
||||
u16* idx = 0;
|
||||
#ifdef CETS_PTERDIMAN
|
||||
idx = (u16*)sr.StripRuns;
|
||||
#endif
|
||||
#ifdef ACTC
|
||||
idx = &stripIndices[0];
|
||||
#endif
|
||||
for ( u32 i = 0 ; i < nbStrips ; i++ )
|
||||
{
|
||||
#ifdef NVTRISTRIP
|
||||
idx = strips[i].indices;
|
||||
u32 idxLen = strips[i].numIndices;
|
||||
if ( strips[i].type == PT_STRIP )
|
||||
{
|
||||
PushValue(list, command, cmdindex, 0x40, 2); // begin triangle strip
|
||||
printf("begin strip\n");
|
||||
}
|
||||
else if ( strips[i].type == PT_LIST )
|
||||
{
|
||||
PushValue(list, command, cmdindex, 0x40, 0); // begin triangle list
|
||||
//printf("begin list\n");
|
||||
}
|
||||
else // if ( strips[i]->type == PT_FAN )
|
||||
{
|
||||
fprintf(stderr, "Export failed, fan list generated\n");
|
||||
return 42;
|
||||
}
|
||||
#endif
|
||||
#ifdef CETS_PTERDIMAN
|
||||
PushValue(list, command, cmdindex, 0x40, 2); // begin triangle strip
|
||||
//printf("begin strip\n");
|
||||
u32 idxLen = sr.StripLengths[i];
|
||||
#endif
|
||||
#ifdef ACTC
|
||||
u32 idxLen = stripLengths[i];
|
||||
PushValue(list, command, cmdindex, 0x40, 2); // begin triangle strip
|
||||
//printf("begin strip\n");
|
||||
#endif
|
||||
|
||||
for ( u32 j = idxLen ; j > 0 ; j--, idx++ )
|
||||
{
|
||||
if ( mesh->HasTextureCoords(0) )
|
||||
{
|
||||
aiVector3D t = mesh->mTextureCoords[0][*idx];
|
||||
//printf("texcoord %f %f\n", t.x, t.y);
|
||||
t *= 1024.0f * float(1 << 4);//float(1 << 15);
|
||||
PushValue(list, command, cmdindex, 0x22, (s32(t.x) & 0xFFFF) | ((s32(t.y) & 0xFFFF) << 16));
|
||||
}
|
||||
|
||||
if ( mesh->HasNormals() )
|
||||
{
|
||||
// remove this ?
|
||||
if ( mesh->HasVertexColors(0) )
|
||||
{
|
||||
u32 ar = 0; u32 ag = 0; u32 ab = 0; // ambiant color, TODO: add command line parameter to set it
|
||||
s32 r = (s32)(mesh->mColors[*idx][0].r * 31); if ( r < 0 ) r = 0; if ( r > 31 ) r = 31;
|
||||
s32 g = (s32)(mesh->mColors[*idx][0].g * 31); if ( g < 0 ) g = 0; if ( g > 31 ) g = 31;
|
||||
s32 b = (s32)(mesh->mColors[*idx][0].b * 31); if ( b < 0 ) b = 0; if ( b > 31 ) b = 31;
|
||||
PushValue(list, command, cmdindex, 0x30, r | (g << 5) | (b << 10) | (ar << 16) | (ag << 21) | (ab << 26)); // material diffuse + ambiant
|
||||
}
|
||||
|
||||
aiVector3D n = mesh->mNormals[*idx];
|
||||
n.Normalize();
|
||||
//printf("normal %f %f %f\n", n.x, n.y, n.z);
|
||||
n *= float(1 << 9);
|
||||
PushValue(list, command, cmdindex, 0x21, (s32(n.x) & 0x3FF | ((s32(n.y) & 0x3FF) << 10) | ((s32(n.z) & 0x3FF) << 20)));
|
||||
}
|
||||
else if ( mesh->HasVertexColors(0) )
|
||||
{
|
||||
s32 r = (s32)(mesh->mColors[*idx][0].r * 31); if ( r < 0 ) r = 0; if ( r > 31 ) r = 31;
|
||||
s32 g = (s32)(mesh->mColors[*idx][0].g * 31); if ( g < 0 ) g = 0; if ( g > 31 ) g = 31;
|
||||
s32 b = (s32)(mesh->mColors[*idx][0].b * 31); if ( b < 0 ) b = 0; if ( b > 31 ) b = 31;
|
||||
PushValue(list, command, cmdindex, 0x20, r | (g << 5) | (b << 10) | (1 << 15)); // color
|
||||
}
|
||||
|
||||
aiVector3D p = mesh->mVertices[*idx];
|
||||
//printf("vtx10 %f %f %f\n", p.x, p.y, p.z);
|
||||
p.x *= scale.x; p.y *= scale.y; p.z *= scale.z;
|
||||
p += translate;
|
||||
p *= float(1 << 6);
|
||||
s32 px = (s32)p.x;
|
||||
s32 py = (s32)p.y;
|
||||
s32 pz = (s32)p.z;
|
||||
PushValue(list, command, cmdindex, 0x24, ((px) & 0x3FF) | (((py) & 0x3FF) << 10) | (((pz) & 0x3FF) << 20));
|
||||
}
|
||||
}
|
||||
|
||||
// Output file
|
||||
FILE* f = fopen(output, "wb");
|
||||
fwrite(&list[0], sizeof(list[0]), list.size(), f);
|
||||
fclose(f);
|
||||
|
||||
#ifdef NVTRISTRIP
|
||||
delete[] strips;
|
||||
delete[] indices;
|
||||
#endif
|
||||
#ifdef CETS_PTERDIMAN
|
||||
delete[] indices;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if ( argc < 3 )
|
||||
{
|
||||
fprintf(stderr, "Usage: %s <input> <output>\n", argv[0]);
|
||||
return 42;
|
||||
}
|
||||
|
||||
return Convert(argv[1], argv[2]);
|
||||
}
|
||||
216
DSMeshConvert/stripping.cpp
Normal file
216
DSMeshConvert/stripping.cpp
Normal file
@@ -0,0 +1,216 @@
|
||||
#include "stripping.h"
|
||||
#include <map>
|
||||
#include <set>
|
||||
#define AI_WONT_RETURN
|
||||
#include <aiAssert.h>
|
||||
|
||||
u32 GetNodeFromSet(std::set<u32> (&unconnected)[4], std::set<u32> (&connected)[2], u32& settype, u32& setid)
|
||||
{
|
||||
u32 node;
|
||||
|
||||
if ( unconnected[0].size() > 0 )
|
||||
{
|
||||
node = *unconnected[0].begin();
|
||||
unconnected[0].erase(node);
|
||||
settype = 0;
|
||||
setid = 0;
|
||||
}
|
||||
else if ( unconnected[1].size() > 0 )
|
||||
{
|
||||
node = *unconnected[1].begin();
|
||||
unconnected[1].erase(node);
|
||||
settype = 0;
|
||||
setid = 1;
|
||||
}
|
||||
else if ( connected[0].size() > 0 )
|
||||
{
|
||||
node = *connected[1].begin();
|
||||
connected[1].erase(node);
|
||||
settype = 1;
|
||||
setid = 0;
|
||||
}
|
||||
else if ( unconnected[2].size() > 0 )
|
||||
{
|
||||
node = *unconnected[2].begin();
|
||||
unconnected[2].erase(node);
|
||||
settype = 0;
|
||||
setid = 2;
|
||||
}
|
||||
else if ( connected[1].size() > 0 )
|
||||
{
|
||||
node = *connected[2].begin();
|
||||
connected[0].erase(node);
|
||||
settype = 1;
|
||||
setid = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
node = *unconnected[3].begin();
|
||||
unconnected[3].erase(node);
|
||||
settype = 0;
|
||||
setid = 3;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void Find(u32 node, std::set<u32> (&unconnected)[4], std::set<u32> (&connected)[2], u32& settype, u32& setid)
|
||||
{
|
||||
for ( u32 i = 0 ; i < 4 ; i++ )
|
||||
{
|
||||
std::set<u32>::iterator it = unconnected[i].find(node);
|
||||
if ( it != unconnected[i].end() )
|
||||
{
|
||||
settype = 0;
|
||||
setid = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for ( u32 i = 0 ; i < 2 ; i++ )
|
||||
{
|
||||
std::set<u32>::iterator it = connected[i].find(node);
|
||||
if ( it != connected[i].end() )
|
||||
{
|
||||
settype = 1;
|
||||
setid = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MoveNodeToSet(u32 node, u32 nodeSetID, u32 nodeSetType, std::set<u32> (&connected)[2], std::set<u32> &fullyConnected)
|
||||
{
|
||||
if ( nodeSetType == 0 && nodeSetID > 0 )
|
||||
{
|
||||
if ( nodeSetID == 1 )
|
||||
{
|
||||
connected[0].insert(node);
|
||||
}
|
||||
else
|
||||
{
|
||||
connected[nodeSetID - 2].insert(node);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fullyConnected.insert(node);
|
||||
}
|
||||
}
|
||||
|
||||
// Multi-Path Algorithm for Triangle Strips
|
||||
// Petr Vanecek, Ivana Kolingerova
|
||||
// From the draft of September 16, 2004
|
||||
std::vector<u32> BuildTriangleStrips(std::vector<u32> indices)
|
||||
{
|
||||
u32 nbTriangles = indices.size() / 3;
|
||||
|
||||
// build edge map
|
||||
std::map<std::pair<u32, u32>, std::vector<u32> > connections;
|
||||
u32 triangle = 0;
|
||||
for ( u32 i = 0 ; i < indices.size() ; i += 3, triangle++ )
|
||||
{
|
||||
for ( u32 j = 0 ; j < 3 ; j++ )
|
||||
{
|
||||
static u32 a[] = { 0, 0, 1 };
|
||||
static u32 b[] = { 1, 2, 2 };
|
||||
std::pair<u32, u32> edge(indices[i + a[j]], indices[i + b[j]]);
|
||||
if ( edge.first > edge.second )
|
||||
{
|
||||
std::swap(edge.first, edge.second);
|
||||
}
|
||||
|
||||
std::map<std::pair<u32, u32>, std::vector<u32> >::iterator it = connections.find(edge);
|
||||
if ( it == connections.end() )
|
||||
{
|
||||
std::pair<std::pair<u32, u32>, std::vector<u32> > entry;
|
||||
entry.first = edge;
|
||||
entry.second.push_back(triangle);
|
||||
connections.insert(entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
it->second.push_back(triangle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// build dual graph
|
||||
std::vector<std::set<u32> > graph(nbTriangles);
|
||||
for ( u32 i = 0, triangle = 0 ; i < indices.size() ; i += 3, triangle++ )
|
||||
{
|
||||
for ( u32 j = 0 ; j < 3 ; j++ )
|
||||
{
|
||||
static u32 a[] = { 0, 0, 1 };
|
||||
static u32 b[] = { 1, 2, 2 };
|
||||
std::pair<u32, u32> edge(indices[i + a[j]], indices[i + b[j]]);
|
||||
if ( edge.first > edge.second )
|
||||
{
|
||||
std::swap(edge.first, edge.second);
|
||||
}
|
||||
|
||||
std::map<std::pair<u32, u32>, std::vector<u32> >::iterator it = connections.find(edge);
|
||||
if ( it != connections.end() )
|
||||
{
|
||||
graph[triangle].insert(it->second.begin(), it->second.end());
|
||||
}
|
||||
}
|
||||
graph[triangle].erase(triangle);
|
||||
}
|
||||
|
||||
// build sets
|
||||
std::set<u32> unconnected[4];
|
||||
for ( u32 i = 0 ; i < nbTriangles ; i++ )
|
||||
{
|
||||
ai_assert(graph[i].size() < 4);
|
||||
unconnected[graph[i].size()].insert(i);
|
||||
}
|
||||
|
||||
std::set<u32> connected[2];
|
||||
std::set<u32> fullyConnected;
|
||||
|
||||
while ( fullyConnected.size() < nbTriangles )
|
||||
{
|
||||
u32 nodeSetID, nodeSetType;
|
||||
u32 node = GetNodeFromSet(unconnected, connected, nodeSetType, nodeSetID);
|
||||
u32 node2 = *graph[node].begin();
|
||||
u32 node2SetID, node2SetType;
|
||||
Find(node2, unconnected, connected, node2SetType, node2SetID);
|
||||
if ( node2SetType == 0 )
|
||||
{
|
||||
unconnected[node2SetID].erase(node2);
|
||||
}
|
||||
else
|
||||
{
|
||||
connected[node2SetID].erase(node2);
|
||||
}
|
||||
|
||||
// Create strip
|
||||
std::vector<u32> strip;
|
||||
strip.push_back(node);
|
||||
strip.push_back(node2);
|
||||
|
||||
// Remove edge from graph
|
||||
graph[node].erase(node2);
|
||||
graph[node2].erase(node);
|
||||
|
||||
//strip = ConcatenateStrips(strip);
|
||||
|
||||
MoveNodeToSet(node, nodeSetID, nodeSetType, connected, fullyConnected);
|
||||
MoveNodeToSet(node2, node2SetID, node2SetType, connected, fullyConnected);
|
||||
|
||||
//UpdateNeighbors(node);
|
||||
//UpdateNeighbors(node2);
|
||||
|
||||
//RemoveLoop(strip);
|
||||
|
||||
//UpdateNeighbors(*strip.begin());
|
||||
if ( strip.begin() != strip.end() )
|
||||
{
|
||||
//UpdateNeighbors(*(strip.end() - 1));
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<u32> strips;
|
||||
return strips;
|
||||
}
|
||||
9
DSMeshConvert/stripping.h
Normal file
9
DSMeshConvert/stripping.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef _STRIPPING_H_
|
||||
#define _STRIPPING_H_
|
||||
|
||||
#include <vector>
|
||||
#include "types.h"
|
||||
|
||||
std::vector<u32> BuildTriangleStrips(std::vector<u32> indices);
|
||||
|
||||
#endif // _STRIPPING_H_
|
||||
86
DSMeshLoad/DSMeshLoad.vcxproj
Normal file
86
DSMeshLoad/DSMeshLoad.vcxproj
Normal file
@@ -0,0 +1,86 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{F97FBD13-23BC-42C4-A1DC-FA263214ED05}</ProjectGuid>
|
||||
<RootNamespace>DSMeshLoad</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<TargetMachine>MachineX86</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
121
DSMeshLoad/main.cpp
Normal file
121
DSMeshLoad/main.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#define AI_WONT_RETURN
|
||||
#include "../DSMeshConvert/assimp--1.1.700-sdk/include/aiVector3D.h"
|
||||
#include "../DSMeshConvert/assimp--1.1.700-sdk/include/aiMatrix4x4.h"
|
||||
#include "../DSMeshConvert/assimp--1.1.700-sdk/include/aiMatrix4x4.inl"
|
||||
|
||||
typedef unsigned int u32;
|
||||
typedef signed int s32;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if ( argc != 2 )
|
||||
{
|
||||
fprintf(stderr, "Usage: %s <file.msh>\n", argv[0]);
|
||||
return 42;
|
||||
}
|
||||
|
||||
FILE* f = fopen(argv[1], "rb");
|
||||
if ( ! f )
|
||||
{
|
||||
fprintf(stderr, "Could not open %s\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
u32 len = ftell(f) / 4;
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
u32* list = new u32[len];
|
||||
u32* start = list;
|
||||
u32* end = list + len;
|
||||
|
||||
fread(list, 4, len, f);
|
||||
|
||||
aiMatrix4x4 mtx;
|
||||
float* pMtx = (float*)(&mtx);
|
||||
|
||||
u32 index = 0;
|
||||
u32 command = *list++;
|
||||
while ( list < end )
|
||||
{
|
||||
u32 c = (command >> index) & 0xFF;
|
||||
switch ( c )
|
||||
{
|
||||
case 0x19: // mul mtx 4x3
|
||||
{
|
||||
printf("mul4x3 ");
|
||||
for ( u32 i = 0 ; i < 4 ; i++ )
|
||||
{
|
||||
for ( u32 j = 0 ; j < 3 ; j++ )
|
||||
{
|
||||
s32 v = *list++;
|
||||
float value = v / float(1 << 12);
|
||||
pMtx[i*4+j] = value;
|
||||
printf("%f ", value);
|
||||
}
|
||||
printf("%f ", 0);
|
||||
}
|
||||
printf("\n");
|
||||
break;
|
||||
}
|
||||
case 0x21: // normal
|
||||
{
|
||||
s32 n = *list;
|
||||
s32 nx = n & 0x3FF; if ( nx > 0x200 ) nx -= 0x200;
|
||||
s32 ny = (n >> 10) & 0x3FF; if ( ny >= 0x200 ) ny -= 0x400;
|
||||
s32 nz = (n >> 20) & 0x3FF; if ( nz >= 0x200 ) nz -= 0x400;
|
||||
printf("normal %f %f %f\n",
|
||||
nx / float(1 << 9),
|
||||
ny / float(1 << 9),
|
||||
nz / float(1 << 9));
|
||||
break;
|
||||
}
|
||||
case 0x22: // tex coord
|
||||
{
|
||||
s32 t = *list++;
|
||||
s32 tx = t & 0xFFFF;
|
||||
s32 ty = (t >> 16) & 0xFFFF;
|
||||
printf("texcoord %f %f\n", tx / float(1 << 15), ty / float(1 << 15));
|
||||
break;
|
||||
}
|
||||
case 0x24: // vtx 10
|
||||
{
|
||||
s32 v = *list++;
|
||||
s32 vx = v & 0x3FF; if ( vx > 0x200 ) vx -= 0x200;
|
||||
s32 vy = (v >> 10) & 0x3FF; if ( vy >= 0x200 ) vy -= 0x400;
|
||||
s32 vz = (v >> 20) & 0x3FF; if ( vz >= 0x200 ) vz -= 0x400;
|
||||
//printf("vtx10 %f %f %f\n",
|
||||
// vx / float(1 << 6),
|
||||
// vy / float(1 << 6),
|
||||
// vz / float(1 << 6));
|
||||
aiVector3D vec(vx / float(1 << 6), vy / float(1 << 6), vz / float(1 << 6));
|
||||
vec *= mtx;
|
||||
printf("vtx10 %f %f %f\n", vec.x, vec.y, vec.z);
|
||||
printf("");
|
||||
break;
|
||||
}
|
||||
case 0x40: // begin
|
||||
{
|
||||
printf("begin %s\n", *list++ ? "strip" : "list");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
printf("Unknown command %x\n", c);
|
||||
}
|
||||
}
|
||||
|
||||
index += 8;
|
||||
if ( index == 32 )
|
||||
{
|
||||
index = 0;
|
||||
command = *list++;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] start;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual Studio 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DSTexCompress", "DSTexCompress\DSTexCompress.vcproj", "{126B132C-BACE-403D-A643-CF31C47672C8}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{126B132C-BACE-403D-A643-CF31C47672C8}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{126B132C-BACE-403D-A643-CF31C47672C8}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{126B132C-BACE-403D-A643-CF31C47672C8}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{126B132C-BACE-403D-A643-CF31C47672C8}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -1,214 +0,0 @@
|
||||
// ==========================================================
|
||||
// Batch loader
|
||||
//
|
||||
// Design and implementation by
|
||||
// - Floris van den Berg
|
||||
// - Herv<72> Drolon
|
||||
//
|
||||
// This file is part of FreeImage 3
|
||||
//
|
||||
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
|
||||
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
|
||||
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
|
||||
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
|
||||
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
|
||||
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
|
||||
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
|
||||
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
|
||||
// THIS DISCLAIMER.
|
||||
//
|
||||
// Use at own risk!
|
||||
// ==========================================================
|
||||
|
||||
//
|
||||
// This example shows how to easily batch load a directory
|
||||
// full of images. Because not all formats can be identified
|
||||
// by their header (some images don't have a header or one
|
||||
// at the end of the file) we make use of the
|
||||
// FreeImage_GetFIFFromFilename function. This function
|
||||
// receives a file name, for example 'myfile.bmp', and returns
|
||||
// a FREE_IMAGE_TYPE enum which identifies that bitmap.
|
||||
//
|
||||
// Functions used in this sample :
|
||||
// FreeImage_GetFileType, FreeImage_GetFIFFromFilename, FreeImage_FIFSupportsReading,
|
||||
// FreeImage_Load, FreeImage_GetBPP, FreeImage_FIFSupportsWriting, FreeImage_GetFormatFromFIF
|
||||
// FreeImage_FIFSupportsExportBPP, FreeImage_Save, FreeImage_Unload,
|
||||
// FreeImage_SetOutputMessage, FreeImage_GetVersion, FreeImage_GetCopyrightMessage
|
||||
//
|
||||
// ==========================================================
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <io.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "FreeImage.h"
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
/** Generic image loader
|
||||
@param lpszPathName Pointer to the full file name
|
||||
@param flag Optional load flag constant
|
||||
@return Returns the loaded dib if successful, returns NULL otherwise
|
||||
*/
|
||||
FIBITMAP* GenericLoader(const char* lpszPathName, int flag) {
|
||||
FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
|
||||
|
||||
// check the file signature and deduce its format
|
||||
// (the second argument is currently not used by FreeImage)
|
||||
fif = FreeImage_GetFileType(lpszPathName, 0);
|
||||
if(fif == FIF_UNKNOWN) {
|
||||
// no signature ?
|
||||
// try to guess the file format from the file extension
|
||||
fif = FreeImage_GetFIFFromFilename(lpszPathName);
|
||||
}
|
||||
// check that the plugin has reading capabilities ...
|
||||
if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
|
||||
// ok, let's load the file
|
||||
FIBITMAP *dib = FreeImage_Load(fif, lpszPathName, flag);
|
||||
// unless a bad file format, we are done !
|
||||
return dib;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Generic image writer
|
||||
@param dib Pointer to the dib to be saved
|
||||
@param lpszPathName Pointer to the full file name
|
||||
@param flag Optional save flag constant
|
||||
@return Returns true if successful, returns false otherwise
|
||||
*/
|
||||
bool GenericWriter(FIBITMAP* dib, const char* lpszPathName, int flag) {
|
||||
FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
|
||||
BOOL bSuccess = FALSE;
|
||||
|
||||
if(dib) {
|
||||
// try to guess the file format from the file extension
|
||||
fif = FreeImage_GetFIFFromFilename(lpszPathName);
|
||||
if(fif != FIF_UNKNOWN ) {
|
||||
// check that the plugin has sufficient writing and export capabilities ...
|
||||
WORD bpp = FreeImage_GetBPP(dib);
|
||||
if(FreeImage_FIFSupportsWriting(fif) && FreeImage_FIFSupportsExportBPP(fif, bpp)) {
|
||||
// ok, we can save the file
|
||||
bSuccess = FreeImage_Save(fif, dib, lpszPathName, flag);
|
||||
// unless an abnormal bug, we are done !
|
||||
}
|
||||
}
|
||||
}
|
||||
return (bSuccess == TRUE) ? true : false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
FreeImage error handler
|
||||
@param fif Format / Plugin responsible for the error
|
||||
@param message Error message
|
||||
*/
|
||||
void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message) {
|
||||
printf("\n*** ");
|
||||
if(fif != FIF_UNKNOWN) {
|
||||
printf("%s Format\n", FreeImage_GetFormatFromFIF(fif));
|
||||
}
|
||||
printf(message);
|
||||
printf(" ***\n");
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
#ifndef MAX_PATH
|
||||
#define MAX_PATH 260
|
||||
#endif
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
|
||||
const char *input_dir = "d:\\images\\";
|
||||
FIBITMAP *dib = NULL;
|
||||
int id = 1;
|
||||
|
||||
// call this ONLY when linking with FreeImage as a static library
|
||||
#ifdef FREEIMAGE_LIB
|
||||
FreeImage_Initialise();
|
||||
#endif // FREEIMAGE_LIB
|
||||
|
||||
// initialize your own FreeImage error handler
|
||||
|
||||
FreeImage_SetOutputMessage(FreeImageErrorHandler);
|
||||
|
||||
// print version & copyright infos
|
||||
|
||||
printf(FreeImage_GetVersion());
|
||||
printf("\n");
|
||||
printf(FreeImage_GetCopyrightMessage());
|
||||
printf("\n");
|
||||
|
||||
// open the log file
|
||||
|
||||
FILE *log_file = fopen("log_file.txt", "w");
|
||||
|
||||
// batch convert all supported bitmaps
|
||||
|
||||
_finddata_t finddata;
|
||||
long handle;
|
||||
char image_path[MAX_PATH];
|
||||
|
||||
// scan all files
|
||||
strcpy(image_path, input_dir);
|
||||
strcat(image_path, "*.*");
|
||||
|
||||
if ((handle = _findfirst(image_path, &finddata)) != -1) {
|
||||
do {
|
||||
// make a path to a directory
|
||||
|
||||
char *directory = new char[MAX_PATH];
|
||||
strcpy(directory, input_dir);
|
||||
strcat(directory, finddata.name);
|
||||
|
||||
// make a unique filename
|
||||
|
||||
char *unique = new char[128];
|
||||
itoa(id, unique, 10);
|
||||
strcat(unique, ".png");
|
||||
|
||||
// open and load the file using the default load option
|
||||
dib = GenericLoader(directory, 0);
|
||||
|
||||
if (dib != NULL) {
|
||||
// save the file as PNG
|
||||
bool bSuccess = GenericWriter(dib, unique, PNG_DEFAULT);
|
||||
|
||||
// free the dib
|
||||
FreeImage_Unload(dib);
|
||||
|
||||
if(bSuccess) {
|
||||
fwrite(unique, strlen(unique), 1, log_file);
|
||||
} else {
|
||||
strcpy(unique, "FAILED");
|
||||
fwrite(unique, strlen(unique), 1, log_file);
|
||||
}
|
||||
fwrite(" >> ", 4, 1, log_file);
|
||||
fwrite(directory, strlen(directory), 1, log_file);
|
||||
fwrite("\n", 1, 1, log_file);
|
||||
|
||||
id++;
|
||||
}
|
||||
|
||||
delete [] unique;
|
||||
delete [] directory;
|
||||
|
||||
} while (_findnext(handle, &finddata) == 0);
|
||||
|
||||
_findclose(handle);
|
||||
}
|
||||
|
||||
fclose(log_file);
|
||||
|
||||
// call this ONLY when linking with FreeImage as a static library
|
||||
#ifdef FREEIMAGE_LIB
|
||||
FreeImage_DeInitialise();
|
||||
#endif // FREEIMAGE_LIB
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
// ==========================================================
|
||||
// Multipage functions demonstration
|
||||
//
|
||||
// Design and implementation by
|
||||
// - Herv<72> Drolon
|
||||
//
|
||||
// This file is part of FreeImage 3
|
||||
//
|
||||
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
|
||||
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
|
||||
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
|
||||
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
|
||||
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
|
||||
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
|
||||
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
|
||||
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
|
||||
// THIS DISCLAIMER.
|
||||
//
|
||||
// Use at own risk!
|
||||
// ==========================================================
|
||||
|
||||
// This sample shows how to clone a multipage TIFF
|
||||
//
|
||||
// Functions used in this sample :
|
||||
// FreeImage_OpenMultiBitmap, FreeImage_GetPageCount, FreeImage_LockPage,
|
||||
// FreeImage_AppendPage, FreeImage_UnlockPage, FreeImage_CloseMultiBitmap;
|
||||
// FreeImage_SetOutputMessage
|
||||
//
|
||||
// ==========================================================
|
||||
|
||||
#include <iostream.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "FreeImage.h"
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
FreeImage error handler
|
||||
*/
|
||||
void MyMessageFunc(FREE_IMAGE_FORMAT fif, const char *message) {
|
||||
cout << "\n*** " << message << " ***\n";
|
||||
cout.flush();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
bool CloneMultiPage(FREE_IMAGE_FORMAT fif, char *input, char *output, int output_flag) {
|
||||
|
||||
BOOL bMemoryCache = TRUE;
|
||||
|
||||
// Open src file (read-only, use memory cache)
|
||||
FIMULTIBITMAP *src = FreeImage_OpenMultiBitmap(fif, input, FALSE, TRUE, bMemoryCache);
|
||||
|
||||
if(src) {
|
||||
// Open dst file (creation, use memory cache)
|
||||
FIMULTIBITMAP *dst = FreeImage_OpenMultiBitmap(fif, output, TRUE, FALSE, bMemoryCache);
|
||||
|
||||
// Get src page count
|
||||
int count = FreeImage_GetPageCount(src);
|
||||
|
||||
// Clone src to dst
|
||||
for(int page = 0; page < count; page++) {
|
||||
// Load the bitmap at position 'page'
|
||||
FIBITMAP *dib = FreeImage_LockPage(src, page);
|
||||
if(dib) {
|
||||
// add a new bitmap to dst
|
||||
FreeImage_AppendPage(dst, dib);
|
||||
// Unload the bitmap (do not apply any change to src)
|
||||
FreeImage_UnlockPage(src, dib, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
// Close src
|
||||
FreeImage_CloseMultiBitmap(src, 0);
|
||||
// Save and close dst
|
||||
FreeImage_CloseMultiBitmap(dst, output_flag);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
|
||||
char *input_filename = "images\\input.tif";
|
||||
char *output_filename = "images\\clone.tif";
|
||||
|
||||
// call this ONLY when linking with FreeImage as a static library
|
||||
#ifdef FREEIMAGE_LIB
|
||||
FreeImage_Initialise();
|
||||
#endif // FREEIMAGE_LIB
|
||||
|
||||
// initialize our own FreeImage error handler
|
||||
|
||||
FreeImage_SetOutputMessage(MyMessageFunc);
|
||||
|
||||
// Copy 'input.tif' to 'clone.tif'
|
||||
|
||||
CloneMultiPage(FIF_TIFF, input_filename, output_filename, 0);
|
||||
|
||||
// call this ONLY when linking with FreeImage as a static library
|
||||
#ifdef FREEIMAGE_LIB
|
||||
FreeImage_DeInitialise();
|
||||
#endif // FREEIMAGE_LIB
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,181 +0,0 @@
|
||||
// ==========================================================
|
||||
// Alpha channel manipulation example
|
||||
//
|
||||
// Design and implementation by
|
||||
// - Herv<72> Drolon
|
||||
//
|
||||
// This file is part of FreeImage 3
|
||||
//
|
||||
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
|
||||
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
|
||||
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
|
||||
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
|
||||
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
|
||||
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
|
||||
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
|
||||
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
|
||||
// THIS DISCLAIMER.
|
||||
//
|
||||
// Use at own risk!
|
||||
// ==========================================================
|
||||
|
||||
// This example shows how to create a transparent image from any input image
|
||||
// using the greyscale version of the input image as the alpha channel mask.
|
||||
// The alpha channel is set using the FreeImage_SetChannel function.
|
||||
//
|
||||
//
|
||||
// ==========================================================
|
||||
|
||||
#include <stdio.h>
|
||||
#include "FreeImage.h"
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
/** Generic image loader
|
||||
@param lpszPathName Pointer to the full file name
|
||||
@param flag Optional load flag constant
|
||||
@return Returns the loaded dib if successful, returns NULL otherwise
|
||||
*/
|
||||
FIBITMAP* GenericLoader(const char* lpszPathName, int flag) {
|
||||
FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
|
||||
|
||||
// check the file signature and deduce its format
|
||||
// (the second argument is currently not used by FreeImage)
|
||||
fif = FreeImage_GetFileType(lpszPathName, 0);
|
||||
if(fif == FIF_UNKNOWN) {
|
||||
// no signature ?
|
||||
// try to guess the file format from the file extension
|
||||
fif = FreeImage_GetFIFFromFilename(lpszPathName);
|
||||
}
|
||||
// check that the plugin has reading capabilities ...
|
||||
if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
|
||||
// ok, let's load the file
|
||||
FIBITMAP *dib = FreeImage_Load(fif, lpszPathName, flag);
|
||||
// unless a bad file format, we are done !
|
||||
return dib;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Generic image writer
|
||||
@param dib Pointer to the dib to be saved
|
||||
@param lpszPathName Pointer to the full file name
|
||||
@param flag Optional save flag constant
|
||||
@return Returns true if successful, returns false otherwise
|
||||
*/
|
||||
bool GenericWriter(FIBITMAP* dib, const char* lpszPathName, int flag) {
|
||||
FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
|
||||
BOOL bSuccess = FALSE;
|
||||
|
||||
if(dib) {
|
||||
// try to guess the file format from the file extension
|
||||
fif = FreeImage_GetFIFFromFilename(lpszPathName);
|
||||
if(fif != FIF_UNKNOWN ) {
|
||||
// check that the plugin has sufficient writing and export capabilities ...
|
||||
WORD bpp = FreeImage_GetBPP(dib);
|
||||
if(FreeImage_FIFSupportsWriting(fif) && FreeImage_FIFSupportsExportBPP(fif, bpp)) {
|
||||
// ok, we can save the file
|
||||
bSuccess = FreeImage_Save(fif, dib, lpszPathName, flag);
|
||||
// unless an abnormal bug, we are done !
|
||||
}
|
||||
}
|
||||
}
|
||||
return (bSuccess == TRUE) ? true : false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
FreeImage error handler
|
||||
@param fif Format / Plugin responsible for the error
|
||||
@param message Error message
|
||||
*/
|
||||
void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message) {
|
||||
printf("\n*** ");
|
||||
if(fif != FIF_UNKNOWN) {
|
||||
printf("%s Format\n", FreeImage_GetFormatFromFIF(fif));
|
||||
}
|
||||
printf(message);
|
||||
printf(" ***\n");
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
Creates a 32-bit transparent image using the black channel of the source image
|
||||
@param src Source image
|
||||
@return Returns a 32-bit transparent image
|
||||
*/
|
||||
FIBITMAP* CreateAlphaFromLightness(FIBITMAP *src) {
|
||||
// create a 32-bit image from the source
|
||||
FIBITMAP *dst = FreeImage_ConvertTo32Bits(src);
|
||||
|
||||
// create a 8-bit mask
|
||||
FreeImage_Invert(src);
|
||||
FIBITMAP *mask = FreeImage_ConvertTo8Bits(src);
|
||||
FreeImage_Invert(src);
|
||||
|
||||
// insert the mask as an alpha channel
|
||||
FreeImage_SetChannel(dst, mask, FICC_ALPHA);
|
||||
|
||||
// free the mask and return
|
||||
FreeImage_Unload(mask);
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
|
||||
// call this ONLY when linking with FreeImage as a static library
|
||||
#ifdef FREEIMAGE_LIB
|
||||
FreeImage_Initialise();
|
||||
#endif // FREEIMAGE_LIB
|
||||
|
||||
// initialize your own FreeImage error handler
|
||||
|
||||
FreeImage_SetOutputMessage(FreeImageErrorHandler);
|
||||
|
||||
// print version & copyright infos
|
||||
|
||||
printf("FreeImage version : %s", FreeImage_GetVersion());
|
||||
printf("\n");
|
||||
printf(FreeImage_GetCopyrightMessage());
|
||||
printf("\n");
|
||||
|
||||
|
||||
if(argc != 3) {
|
||||
printf("Usage : CreateAlpha <input file name> <output file name>\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Load the source image
|
||||
FIBITMAP *src = GenericLoader(argv[1], 0);
|
||||
if(src) {
|
||||
// Create a transparent image from the lightness image of src
|
||||
FIBITMAP *dst = CreateAlphaFromLightness(src);
|
||||
|
||||
if(dst) {
|
||||
// Save the destination image
|
||||
bool bSuccess = GenericWriter(dst, argv[2], 0);
|
||||
if(!bSuccess) {
|
||||
printf("\nUnable to save %s file", argv[2]);
|
||||
printf("\nThis format does not support 32-bit images");
|
||||
}
|
||||
|
||||
// Free dst
|
||||
FreeImage_Unload(dst);
|
||||
}
|
||||
|
||||
// Free src
|
||||
FreeImage_Unload(src);
|
||||
}
|
||||
|
||||
// call this ONLY when linking with FreeImage as a static library
|
||||
#ifdef FREEIMAGE_LIB
|
||||
FreeImage_DeInitialise();
|
||||
#endif // FREEIMAGE_LIB
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
// ==========================================================
|
||||
// Plugin functions demonstration
|
||||
//
|
||||
// Design and implementation by
|
||||
// - Herv<72> Drolon
|
||||
//
|
||||
// This file is part of FreeImage 3
|
||||
//
|
||||
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
|
||||
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
|
||||
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
|
||||
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
|
||||
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
|
||||
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
|
||||
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
|
||||
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
|
||||
// THIS DISCLAIMER.
|
||||
//
|
||||
// Use at own risk!
|
||||
// ==========================================================
|
||||
|
||||
// This example shows how to use Plugin functions to explore FreeImage capabilities.
|
||||
// Whenever an external plugin is added to the library, it is automatically loaded
|
||||
// with FreeImage and can be asked for its capabilities via the plugin functions.
|
||||
//
|
||||
// Functions used in this sample :
|
||||
// FreeImage_FIFSupportsExportBPP, FreeImage_FIFSupportsICCProfiles, FreeImage_FIFSupportsReading,
|
||||
// FreeImage_FIFSupportsWriting, FreeImage_GetFIFCount, FreeImage_GetFIFDescription,
|
||||
// FreeImage_GetFIFExtensionList, FreeImage_GetFormatFromFIF,
|
||||
// FreeImage_GetVersion, FreeImage_GetCopyrightMessage, FreeImage_SetOutputMessage
|
||||
//
|
||||
// ==========================================================
|
||||
|
||||
#include <iostream.h>
|
||||
#include <fstream.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "FreeImage.h"
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
FreeImage error handler
|
||||
*/
|
||||
void MyMessageFunc(FREE_IMAGE_FORMAT fif, const char *message) {
|
||||
cout << "\n*** " << message << " ***\n";
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
Print plugins import capabilities
|
||||
*/
|
||||
void PrintImportFormats(iostream& ios) {
|
||||
int count = FreeImage_GetFIFCount();
|
||||
if(count)
|
||||
ios << "FORMAT;DESCRIPTION;EXTENSIONS;ICC PROFILES\n";
|
||||
for(int i = 0; i < count; i++) {
|
||||
FREE_IMAGE_FORMAT fif = (FREE_IMAGE_FORMAT)i;
|
||||
|
||||
if(FreeImage_FIFSupportsReading(fif)) {
|
||||
const char * format = FreeImage_GetFormatFromFIF(fif);
|
||||
const char * description = FreeImage_GetFIFDescription(fif);
|
||||
const char * ext = FreeImage_GetFIFExtensionList(fif);
|
||||
const char * icc = "*";
|
||||
if(FreeImage_FIFSupportsICCProfiles(fif)) {
|
||||
ios << format << ";" << description << ";" << ext << ";" << icc << "\n";
|
||||
} else {
|
||||
ios << format << ";" << description << ";" << ext << "; \n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Print plugins export capabilities
|
||||
*/
|
||||
void PrintExportFormats(iostream& ios) {
|
||||
int count = FreeImage_GetFIFCount();
|
||||
if(count)
|
||||
ios << "FORMAT;DESCRIPTION;EXTENSIONS;BITDEPTH;ICC PROFILES\n";
|
||||
for(int i = 0; i < count; i++) {
|
||||
FREE_IMAGE_FORMAT fif = (FREE_IMAGE_FORMAT)i;
|
||||
|
||||
if(FreeImage_FIFSupportsWriting(fif)) {
|
||||
const char * format = FreeImage_GetFormatFromFIF(fif);
|
||||
const char * description = FreeImage_GetFIFDescription(fif);
|
||||
const char * ext = FreeImage_GetFIFExtensionList(fif);
|
||||
const char * icc = "*";
|
||||
|
||||
ios << format << ";" << description << ";" << ext << ";";
|
||||
if(FreeImage_FIFSupportsExportBPP(fif, 1))
|
||||
ios << "1 ";
|
||||
if(FreeImage_FIFSupportsExportBPP(fif, 4))
|
||||
ios << "4 ";
|
||||
if(FreeImage_FIFSupportsExportBPP(fif, 8))
|
||||
ios << "8 ";
|
||||
if(FreeImage_FIFSupportsExportBPP(fif, 16))
|
||||
ios << "16 ";
|
||||
if(FreeImage_FIFSupportsExportBPP(fif, 24))
|
||||
ios << "24 ";
|
||||
if(FreeImage_FIFSupportsExportBPP(fif, 32))
|
||||
ios << "32 ";
|
||||
if(FreeImage_FIFSupportsICCProfiles(fif)) {
|
||||
ios << ";" << icc;
|
||||
} else {
|
||||
ios << "; ";
|
||||
}
|
||||
ios << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
// call this ONLY when linking with FreeImage as a static library
|
||||
#ifdef FREEIMAGE_LIB
|
||||
FreeImage_Initialise();
|
||||
#endif // FREEIMAGE_LIB
|
||||
|
||||
// initialize FreeImage error handler
|
||||
|
||||
FreeImage_SetOutputMessage(MyMessageFunc);
|
||||
|
||||
// print version & copyright infos
|
||||
|
||||
cout << "FreeImage " << FreeImage_GetVersion() << "\n";
|
||||
cout << FreeImage_GetCopyrightMessage() << "\n\n";
|
||||
|
||||
// Print input formats (including external plugins) known by the library
|
||||
fstream importFile("fif_import.csv", ios::out);
|
||||
PrintImportFormats(importFile);
|
||||
importFile.close();
|
||||
|
||||
// Print output formats (including plugins) known by the library
|
||||
// for each export format, supported bitdepths are given
|
||||
fstream exportFile("fif_export.csv", ios::out);
|
||||
PrintExportFormats(exportFile);
|
||||
exportFile.close();
|
||||
|
||||
// call this ONLY when linking with FreeImage as a static library
|
||||
#ifdef FREEIMAGE_LIB
|
||||
FreeImage_DeInitialise();
|
||||
#endif // FREEIMAGE_LIB
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
/*--------------------------------------------------------------------------*\
|
||||
|| fiio_mem.cpp by Ryan Rubley <ryan@lostreality.org> ||
|
||||
|| ||
|
||||
|| (v1.02) 4-28-2004 ||
|
||||
|| FreeImageIO to memory ||
|
||||
|| ||
|
||||
\*--------------------------------------------------------------------------*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "fiio_mem.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
FIBITMAP *
|
||||
FreeImage_LoadFromMem(FREE_IMAGE_FORMAT fif, fiio_mem_handle *handle, int flags) {
|
||||
FreeImageIO io;
|
||||
SetMemIO(&io);
|
||||
|
||||
if (handle && handle->data) {
|
||||
handle->curpos = 0;
|
||||
return FreeImage_LoadFromHandle(fif, &io, (fi_handle)handle, flags);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BOOL
|
||||
FreeImage_SaveToMem(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, fiio_mem_handle *handle, int flags) {
|
||||
FreeImageIO io;
|
||||
SetMemIO(&io);
|
||||
|
||||
if (handle) {
|
||||
handle->filelen = 0;
|
||||
handle->curpos = 0;
|
||||
return FreeImage_SaveToHandle(fif, dib, &io, (fi_handle)handle, flags);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
void
|
||||
SetMemIO(FreeImageIO *io) {
|
||||
io->read_proc = fiio_mem_ReadProc;
|
||||
io->seek_proc = fiio_mem_SeekProc;
|
||||
io->tell_proc = fiio_mem_TellProc;
|
||||
io->write_proc = fiio_mem_WriteProc;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
#define FIIOMEM(member) (((fiio_mem_handle *)handle)->member)
|
||||
|
||||
unsigned
|
||||
fiio_mem_ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
|
||||
unsigned x;
|
||||
for( x=0; x<count; x++ ) {
|
||||
//if there isnt size bytes left to read, set pos to eof and return a short count
|
||||
if( FIIOMEM(filelen)-FIIOMEM(curpos) < (long)size ) {
|
||||
FIIOMEM(curpos) = FIIOMEM(filelen);
|
||||
break;
|
||||
}
|
||||
//copy size bytes count times
|
||||
memcpy( buffer, (char *)FIIOMEM(data) + FIIOMEM(curpos), size );
|
||||
FIIOMEM(curpos) += size;
|
||||
buffer = (char *)buffer + size;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
unsigned
|
||||
fiio_mem_WriteProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
|
||||
void *newdata;
|
||||
long newdatalen;
|
||||
//double the data block size if we need to
|
||||
while( FIIOMEM(curpos)+(long)(size*count) >= FIIOMEM(datalen) ) {
|
||||
//if we are at or above 1G, we cant double without going negative
|
||||
if( FIIOMEM(datalen) & 0x40000000 ) {
|
||||
//max 2G
|
||||
if( FIIOMEM(datalen) == 0x7FFFFFFF ) {
|
||||
return 0;
|
||||
}
|
||||
newdatalen = 0x7FFFFFFF;
|
||||
} else if( FIIOMEM(datalen) == 0 ) {
|
||||
//default to 4K if nothing yet
|
||||
newdatalen = 4096;
|
||||
} else {
|
||||
//double size
|
||||
newdatalen = FIIOMEM(datalen) << 1;
|
||||
}
|
||||
newdata = realloc( FIIOMEM(data), newdatalen );
|
||||
if( !newdata ) {
|
||||
return 0;
|
||||
}
|
||||
FIIOMEM(data) = newdata;
|
||||
FIIOMEM(datalen) = newdatalen;
|
||||
}
|
||||
memcpy( (char *)FIIOMEM(data) + FIIOMEM(curpos), buffer, size*count );
|
||||
FIIOMEM(curpos) += size*count;
|
||||
if( FIIOMEM(curpos) > FIIOMEM(filelen) ) {
|
||||
FIIOMEM(filelen) = FIIOMEM(curpos);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int
|
||||
fiio_mem_SeekProc(fi_handle handle, long offset, int origin) {
|
||||
switch(origin) { //0 to filelen-1 are 'inside' the file
|
||||
default:
|
||||
case SEEK_SET: //can fseek() to 0-7FFFFFFF always
|
||||
if( offset >= 0 ) {
|
||||
FIIOMEM(curpos) = offset;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case SEEK_CUR:
|
||||
if( FIIOMEM(curpos)+offset >= 0 ) {
|
||||
FIIOMEM(curpos) += offset;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
if( FIIOMEM(filelen)+offset >= 0 ) {
|
||||
FIIOMEM(curpos) = FIIOMEM(filelen)+offset;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
long
|
||||
fiio_mem_TellProc(fi_handle handle) {
|
||||
return FIIOMEM(curpos);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,74 +0,0 @@
|
||||
/*--------------------------------------------------------------------------*\
|
||||
|| fiio_mem.h by Ryan Rubley <ryan@lostreality.org> ||
|
||||
|| ||
|
||||
|| (v1.02) 4-28-2004 ||
|
||||
|| FreeImageIO to memory ||
|
||||
|| ||
|
||||
\*--------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _FIIO_MEM_H_
|
||||
#define _FIIO_MEM_H_
|
||||
|
||||
#include "freeimage.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct fiio_mem_handle_s {
|
||||
long filelen,datalen,curpos;
|
||||
void *data;
|
||||
} fiio_mem_handle;
|
||||
|
||||
/* it is up to the user to create a fiio_mem_handle and init datalen and data
|
||||
* filelen will be pre-set to 0 by SaveToMem
|
||||
* curpos will be pre-set to 0 by SaveToMem and LoadFromMem
|
||||
* IMPORTANT: data should be set to NULL and datalen to 0,
|
||||
* unless the user wants to manually malloc a larger buffer
|
||||
*/
|
||||
FIBITMAP *FreeImage_LoadFromMem(FREE_IMAGE_FORMAT fif, fiio_mem_handle *handle, int flags);
|
||||
BOOL FreeImage_SaveToMem(FREE_IMAGE_FORMAT fif, FIBITMAP *dib, fiio_mem_handle *handle, int flags);
|
||||
|
||||
void SetMemIO(FreeImageIO *io);
|
||||
unsigned fiio_mem_ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle);
|
||||
unsigned fiio_mem_WriteProc(void *buffer, unsigned size, unsigned count, fi_handle handle);
|
||||
int fiio_mem_SeekProc(fi_handle handle, long offset, int origin);
|
||||
long fiio_mem_TellProc(fi_handle handle);
|
||||
|
||||
/*** Example Usage ***
|
||||
|
||||
//variables
|
||||
FIBITMAP *bitmap, *bitmap2;
|
||||
fiio_mem_handle fmh;
|
||||
|
||||
//important initialization
|
||||
fmh.data = NULL;
|
||||
fmh.datalen = 0;
|
||||
|
||||
//load a regular file
|
||||
bitmap = FreeImage_Load(FIF_PNG, "sample.png");
|
||||
|
||||
//save the file to memory
|
||||
FreeImage_SaveToMem(FIF_PNG, bitmap, &fmh, 0);
|
||||
|
||||
//at this point, fmh.data contains the entire PNG data in memory
|
||||
//fmh.datalen is the amount of space malloc'd for the image in memory,
|
||||
//but only fmh.filelen amount of that space is actually used.
|
||||
|
||||
//its easy load an image from memory as well
|
||||
bitmap2 = FreeImage_LoadFromMem(FIF_PNG, &fmh, 0);
|
||||
//you could also have image data in memory via some other method, and just set
|
||||
//fmh.data to point to it, and set both fmh.datalen and fmh.filelen to the
|
||||
//size of that data, then FreeImage_LoadFromMem could load the image from that
|
||||
//memory
|
||||
|
||||
//make sure to free the data since SaveToMem will cause it to be malloc'd
|
||||
free(fmh.data);
|
||||
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,145 +0,0 @@
|
||||
// ==========================================================
|
||||
// Load From Handle Example
|
||||
//
|
||||
// Design and implementation by
|
||||
// - Herv<72> Drolon
|
||||
//
|
||||
// This file is part of FreeImage 3
|
||||
//
|
||||
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
|
||||
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
|
||||
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
|
||||
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
|
||||
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
|
||||
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
|
||||
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
|
||||
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
|
||||
// THIS DISCLAIMER.
|
||||
//
|
||||
// Use at own risk!
|
||||
// ==========================================================
|
||||
|
||||
// This example shows how to load a bitmap from a
|
||||
// user allocated FILE pointer.
|
||||
//
|
||||
// Functions used in this sample :
|
||||
// FreeImage_GetFormatFromFIF, FreeImage_GetFileTypeFromHandle, FreeImage_LoadFromHandle,
|
||||
// FreeImage_GetFIFFromFilename, FreeImage_Save, FreeImage_Unload
|
||||
// FreeImage_GetVersion, FreeImage_GetCopyrightMessage, FreeImage_SetOutputMessage
|
||||
//
|
||||
// ==========================================================
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "FreeImage.h"
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
FreeImage error handler
|
||||
@param fif Format / Plugin responsible for the error
|
||||
@param message Error message
|
||||
*/
|
||||
void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message) {
|
||||
printf("\n*** ");
|
||||
if(fif != FIF_UNKNOWN) {
|
||||
printf("%s Format\n", FreeImage_GetFormatFromFIF(fif));
|
||||
}
|
||||
printf(message);
|
||||
printf(" ***\n");
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
unsigned DLL_CALLCONV
|
||||
myReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
|
||||
return fread(buffer, size, count, (FILE *)handle);
|
||||
}
|
||||
|
||||
unsigned DLL_CALLCONV
|
||||
myWriteProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
|
||||
return fwrite(buffer, size, count, (FILE *)handle);
|
||||
}
|
||||
|
||||
int DLL_CALLCONV
|
||||
mySeekProc(fi_handle handle, long offset, int origin) {
|
||||
return fseek((FILE *)handle, offset, origin);
|
||||
}
|
||||
|
||||
long DLL_CALLCONV
|
||||
myTellProc(fi_handle handle) {
|
||||
return ftell((FILE *)handle);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
|
||||
// call this ONLY when linking with FreeImage as a static library
|
||||
#ifdef FREEIMAGE_LIB
|
||||
FreeImage_Initialise();
|
||||
#endif // FREEIMAGE_LIB
|
||||
|
||||
// initialize your own FreeImage error handler
|
||||
|
||||
FreeImage_SetOutputMessage(FreeImageErrorHandler);
|
||||
|
||||
// print version & copyright infos
|
||||
|
||||
printf(FreeImage_GetVersion());
|
||||
printf("\n");
|
||||
printf(FreeImage_GetCopyrightMessage());
|
||||
printf("\n");
|
||||
|
||||
|
||||
if(argc != 2) {
|
||||
printf("Usage : LoadFromHandle <input file name>\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// initialize your own IO functions
|
||||
|
||||
FreeImageIO io;
|
||||
|
||||
io.read_proc = myReadProc;
|
||||
io.write_proc = myWriteProc;
|
||||
io.seek_proc = mySeekProc;
|
||||
io.tell_proc = myTellProc;
|
||||
|
||||
FILE *file = fopen(argv[1], "rb");
|
||||
|
||||
if (file != NULL) {
|
||||
// find the buffer format
|
||||
FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromHandle(&io, (fi_handle)file, 0);
|
||||
|
||||
if(fif != FIF_UNKNOWN) {
|
||||
// load from the file handle
|
||||
FIBITMAP *dib = FreeImage_LoadFromHandle(fif, &io, (fi_handle)file, 0);
|
||||
|
||||
// save the bitmap as a PNG ...
|
||||
const char *output_filename = "test.png";
|
||||
|
||||
// first, check the output format from the file name or file extension
|
||||
FREE_IMAGE_FORMAT out_fif = FreeImage_GetFIFFromFilename(output_filename);
|
||||
|
||||
if(out_fif != FIF_UNKNOWN) {
|
||||
// then save the file
|
||||
FreeImage_Save(out_fif, dib, output_filename, 0);
|
||||
}
|
||||
|
||||
// free the loaded FIBITMAP
|
||||
FreeImage_Unload(dib);
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
// call this ONLY when linking with FreeImage as a static library
|
||||
#ifdef FREEIMAGE_LIB
|
||||
FreeImage_DeInitialise();
|
||||
#endif // FREEIMAGE_LIB
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
// ==========================================================
|
||||
// Classified FreeImageIO handler
|
||||
//
|
||||
// Design and implementation by
|
||||
// - schickb (schickb@hotmail.com)
|
||||
//
|
||||
// This file is part of FreeImage 3
|
||||
//
|
||||
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
|
||||
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
|
||||
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
|
||||
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
|
||||
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
|
||||
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
|
||||
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
|
||||
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
|
||||
// THIS DISCLAIMER.
|
||||
//
|
||||
// Use at your own risk!
|
||||
// ==========================================================
|
||||
|
||||
class MemIO : public FreeImageIO {
|
||||
public :
|
||||
MemIO( BYTE *data ) : _start(data), _cp(data) {
|
||||
read_proc = _ReadProc;
|
||||
write_proc = _WriteProc;
|
||||
tell_proc = _TellProc;
|
||||
seek_proc = _SeekProc;
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
_cp = _start;
|
||||
}
|
||||
|
||||
static unsigned _ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle);
|
||||
static unsigned _WriteProc(void *buffer, unsigned size, unsigned count, fi_handle handle);
|
||||
static int _SeekProc(fi_handle handle, long offset, int origin);
|
||||
static long _TellProc(fi_handle handle);
|
||||
|
||||
private:
|
||||
BYTE * const _start;
|
||||
BYTE *_cp;
|
||||
};
|
||||
|
||||
|
||||
unsigned
|
||||
MemIO::_ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
|
||||
MemIO *memIO = (MemIO*)handle;
|
||||
|
||||
BYTE *tmp = (BYTE *)buffer;
|
||||
|
||||
for (unsigned c = 0; c < count; c++) {
|
||||
memcpy(tmp, memIO->_cp, size);
|
||||
|
||||
memIO->_cp = memIO->_cp + size;
|
||||
|
||||
tmp += size;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
unsigned
|
||||
MemIO::_WriteProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
|
||||
ASSERT( false );
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
MemIO::_SeekProc(fi_handle handle, long offset, int origin) {
|
||||
ASSERT(origin != SEEK_END);
|
||||
|
||||
MemIO *memIO = (MemIO*)handle;
|
||||
|
||||
if (origin == SEEK_SET)
|
||||
memIO->_cp = memIO->_start + offset;
|
||||
else
|
||||
memIO->_cp = memIO->_cp + offset;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long
|
||||
MemIO::_TellProc(fi_handle handle) {
|
||||
MemIO *memIO = (MemIO*)handle;
|
||||
|
||||
return memIO->_cp - memIO->_start;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// PSEUDOCODE... HELPS TO UNDERSTAND HOW THE MEMIO CLASS WORKS
|
||||
// ----------------------------------------------------------
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
BYTE *data = loadimagesomehow();
|
||||
|
||||
MemIO memIO(data);
|
||||
|
||||
FIBITMAP *fbmp = FreeImage_LoadFromHandle( fif, &memIO, (fi_handle)&memIO );
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
// ==========================================================
|
||||
// Load From Memory Example
|
||||
//
|
||||
// Design and implementation by Floris van den Berg
|
||||
//
|
||||
// This file is part of FreeImage 3
|
||||
//
|
||||
// Use at own risk!
|
||||
// ==========================================================
|
||||
//
|
||||
// This example shows how to load a bitmap from memory
|
||||
// rather than from a file. To do this we make use of the
|
||||
// FreeImage_LoadFromHandle functions where we override
|
||||
// the i/o functions to simulate FILE* access in memory.
|
||||
//
|
||||
// For seeking purposes the fi_handle passed to the i/o
|
||||
// functions contain the start of the data block where the
|
||||
// bitmap is stored.
|
||||
//
|
||||
// ==========================================================
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "FreeImage.h"
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
fi_handle g_load_address;
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
inline unsigned _stdcall
|
||||
_ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
|
||||
BYTE *tmp = (BYTE *)buffer;
|
||||
|
||||
for (unsigned c = 0; c < count; c++) {
|
||||
memcpy(tmp, g_load_address, size);
|
||||
|
||||
g_load_address = (BYTE *)g_load_address + size;
|
||||
|
||||
tmp += size;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
inline unsigned _stdcall
|
||||
_WriteProc(void *buffer, unsigned size, unsigned count, fi_handle handle) {
|
||||
// there's not much use for saving the bitmap into memory now, is there?
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
inline int _stdcall
|
||||
_SeekProc(fi_handle handle, long offset, int origin) {
|
||||
assert(origin != SEEK_END);
|
||||
|
||||
if (origin == SEEK_SET) {
|
||||
g_load_address = (BYTE *)handle + offset;
|
||||
} else {
|
||||
g_load_address = (BYTE *)g_load_address + offset;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline long _stdcall
|
||||
_TellProc(fi_handle handle) {
|
||||
assert((int)handle > (int)g_load_address);
|
||||
|
||||
return ((int)g_load_address - (int)handle);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
FreeImageIO io;
|
||||
|
||||
io.read_proc = _ReadProc;
|
||||
io.write_proc = _WriteProc;
|
||||
io.tell_proc = _TellProc;
|
||||
io.seek_proc = _SeekProc;
|
||||
|
||||
// allocate some memory for the bitmap
|
||||
|
||||
BYTE *test = new BYTE[159744];
|
||||
|
||||
if (test != NULL) {
|
||||
// load the bitmap into memory. ofcourse you can do this any way you want
|
||||
|
||||
FILE *file = fopen("e:\\projects\\images\\money-256.tif", "rb");
|
||||
fread(test, 159744, 1, file);
|
||||
fclose(file);
|
||||
|
||||
// we store the load address of the bitmap for internal reasons
|
||||
|
||||
g_load_address = test;
|
||||
|
||||
// convert the bitmap
|
||||
|
||||
FIBITMAP *dib = FreeImage_LoadFromHandle(FIF_TIFF, &io, (fi_handle)test);
|
||||
|
||||
// don't forget to free the dib !
|
||||
FreeImage_Unload(dib);
|
||||
|
||||
delete [] test;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,317 +0,0 @@
|
||||
// ==========================================================
|
||||
// Simple metadata reader
|
||||
//
|
||||
// Design and implementation by
|
||||
// - Herv<72> Drolon
|
||||
//
|
||||
// This file is part of FreeImage 3
|
||||
//
|
||||
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
|
||||
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
|
||||
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
|
||||
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
|
||||
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
|
||||
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
|
||||
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
|
||||
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
|
||||
// THIS DISCLAIMER.
|
||||
//
|
||||
// Use at own risk!
|
||||
// ==========================================================
|
||||
|
||||
//
|
||||
// This example shows how to easily parse all metadata
|
||||
// contained in a JPEG, TIFF or PNG image.
|
||||
// Comments, Exif and IPTC/NAA metadata tags are written to a HTML file
|
||||
// for later reading, and Adobe XMP XML packets are written
|
||||
// in a file whose extension is '.xmp'. This file can be later
|
||||
// processed using a XML parser.
|
||||
//
|
||||
// Metadata functions showed in this sample :
|
||||
// FreeImage_GetMetadataCount, FreeImage_FindFirstMetadata, FreeImage_FindNextMetadata,
|
||||
// FreeImage_FindCloseMetadata, FreeImage_TagToString, FreeImage_GetMetadata
|
||||
//
|
||||
// ==========================================================
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#include "FreeImage.h"
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
/** Generic image loader
|
||||
@param lpszPathName Pointer to the full file name
|
||||
@param flag Optional load flag constant
|
||||
@return Returns the loaded dib if successful, returns NULL otherwise
|
||||
*/
|
||||
FIBITMAP* GenericLoader(const char* lpszPathName, int flag) {
|
||||
FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
|
||||
|
||||
// check the file signature and deduce its format
|
||||
// (the second argument is currently not used by FreeImage)
|
||||
fif = FreeImage_GetFileType(lpszPathName, 0);
|
||||
if(fif == FIF_UNKNOWN) {
|
||||
// no signature ?
|
||||
// try to guess the file format from the file extension
|
||||
fif = FreeImage_GetFIFFromFilename(lpszPathName);
|
||||
}
|
||||
// check that the plugin has reading capabilities ...
|
||||
if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
|
||||
// ok, let's load the file
|
||||
FIBITMAP *dib = FreeImage_Load(fif, lpszPathName, flag);
|
||||
// unless a bad file format, we are done !
|
||||
return dib;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** Generic image writer
|
||||
@param dib Pointer to the dib to be saved
|
||||
@param lpszPathName Pointer to the full file name
|
||||
@param flag Optional save flag constant
|
||||
@return Returns true if successful, returns false otherwise
|
||||
*/
|
||||
bool GenericWriter(FIBITMAP* dib, const char* lpszPathName, int flag) {
|
||||
FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
|
||||
BOOL bSuccess = FALSE;
|
||||
|
||||
if(dib) {
|
||||
// try to guess the file format from the file extension
|
||||
fif = FreeImage_GetFIFFromFilename(lpszPathName);
|
||||
if(fif != FIF_UNKNOWN ) {
|
||||
// check that the plugin has sufficient writing and export capabilities ...
|
||||
WORD bpp = FreeImage_GetBPP(dib);
|
||||
if(FreeImage_FIFSupportsWriting(fif) && FreeImage_FIFSupportsExportBPP(fif, bpp)) {
|
||||
// ok, we can save the file
|
||||
bSuccess = FreeImage_Save(fif, dib, lpszPathName, flag);
|
||||
// unless an abnormal bug, we are done !
|
||||
}
|
||||
}
|
||||
}
|
||||
return (bSuccess == TRUE) ? true : false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
FreeImage error handler
|
||||
@param fif Format / Plugin responsible for the error
|
||||
@param message Error message
|
||||
*/
|
||||
void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message) {
|
||||
cout << "\n*** ";
|
||||
if(fif != FIF_UNKNOWN) {
|
||||
cout << FreeImage_GetFormatFromFIF(fif) << " Format\n";
|
||||
}
|
||||
cout << message;
|
||||
cout << " ***\n";
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
Print a basic HTML header
|
||||
*/
|
||||
void PrintHTMLHeader(iostream& ios) {
|
||||
ios << "<HTML>\n<BODY>\n<CENTER>\n";
|
||||
ios << "<FONT FACE = \"Arial\">\n";
|
||||
}
|
||||
|
||||
/**
|
||||
Print a HTML footer
|
||||
*/
|
||||
void PrintHTMLFooter(iostream& ios) {
|
||||
ios << "</CENTER>\n</FONT>\n</BODY>\n</HTML>\n";
|
||||
}
|
||||
|
||||
/**
|
||||
Print a table header
|
||||
*/
|
||||
void PrintTableHeader(iostream& ios, const char *title) {
|
||||
ios << "<TABLE BORDER=\"1\">\n";
|
||||
ios << "<TR><TD ALIGN=CENTER COLSPAN=\"3\" BGCOLOR=\"#CCCCCC\"><B><font face=\"Arial\">" << title << "</font></B></TD></TR>\n";
|
||||
}
|
||||
|
||||
/**
|
||||
Print a table section
|
||||
*/
|
||||
void PrintTableSection(iostream& ios, const char *title) {
|
||||
ios << "<TR><TD ALIGN=CENTER COLSPAN=\"3\" BGCOLOR=\"#FFFFCC\"><B><font face=\"Arial\">" << title << "</font></B></TD></TR>\n";
|
||||
ios << "<TR><TD><B>Tag name</B></TD><TD><B>Tag value</B></TD><TD><B>Description</B></TD></TR>";
|
||||
}
|
||||
|
||||
/**
|
||||
Print a table footer
|
||||
*/
|
||||
void PrintTableFooter(iostream& ios) {
|
||||
ios << "</TABLE>\n";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Print the metadata tags to a HTML file
|
||||
*/
|
||||
void PrintMetadata(iostream& ios, const char *sectionTitle, FIBITMAP *dib, FREE_IMAGE_MDMODEL model) {
|
||||
FITAG *tag = NULL;
|
||||
FIMETADATA *mdhandle = NULL;
|
||||
|
||||
mdhandle = FreeImage_FindFirstMetadata(model, dib, &tag);
|
||||
|
||||
if(mdhandle) {
|
||||
// Print a table section
|
||||
PrintTableSection(ios, sectionTitle);
|
||||
|
||||
do {
|
||||
// convert the tag value to a string
|
||||
const char *value = FreeImage_TagToString(model, tag);
|
||||
|
||||
// print the tag
|
||||
// note that most tags do not have a description,
|
||||
// especially when the metadata specifications are not available
|
||||
if(FreeImage_GetTagDescription(tag)) {
|
||||
ios << "<TR><TD>" << FreeImage_GetTagKey(tag) << "</TD><TD>" << value << "</TD><TD>" << FreeImage_GetTagDescription(tag) << "</TD></TR>\n";
|
||||
} else {
|
||||
ios << "<TR><TD>" << FreeImage_GetTagKey(tag) << "</TD><TD>" << value << "</TD><TD>" << " " << "</TD></TR>\n";
|
||||
}
|
||||
|
||||
} while(FreeImage_FindNextMetadata(mdhandle, &tag));
|
||||
}
|
||||
|
||||
FreeImage_FindCloseMetadata(mdhandle);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
unsigned count;
|
||||
|
||||
// call this ONLY when linking with FreeImage as a static library
|
||||
#ifdef FREEIMAGE_LIB
|
||||
FreeImage_Initialise();
|
||||
#endif // FREEIMAGE_LIB
|
||||
|
||||
// initialize your own FreeImage error handler
|
||||
|
||||
FreeImage_SetOutputMessage(FreeImageErrorHandler);
|
||||
|
||||
// print version & copyright infos
|
||||
|
||||
cout << "FreeImage " << FreeImage_GetVersion() << "\n";
|
||||
cout << FreeImage_GetCopyrightMessage() << "\n\n";
|
||||
|
||||
if(argc != 2) {
|
||||
cout << "Usage : ShowMetadata <input file name>\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Load the bitmap
|
||||
|
||||
FIBITMAP *dib = GenericLoader(argv[1], 0);
|
||||
if(!dib)
|
||||
return 0;
|
||||
|
||||
// Create a HTML file
|
||||
std::string html_file(strtok(argv[1], ".") + std::string(".html"));
|
||||
|
||||
fstream metadataFile(html_file.c_str(), ios::out);
|
||||
|
||||
// Print the header
|
||||
|
||||
PrintHTMLHeader(metadataFile);
|
||||
PrintTableHeader(metadataFile, argv[1]);
|
||||
|
||||
// Parse and print metadata
|
||||
|
||||
if(count = FreeImage_GetMetadataCount(FIMD_COMMENTS, dib)) {
|
||||
cout << "\nFIMD_COMMENTS (" << count << " data)\n-----------------------------------------\n";
|
||||
|
||||
PrintMetadata(metadataFile, "Comments", dib, FIMD_COMMENTS);
|
||||
}
|
||||
if(count = FreeImage_GetMetadataCount(FIMD_EXIF_MAIN, dib)) {
|
||||
cout << "\nFIMD_EXIF_MAIN (" << count << " data)\n-----------------------------------------\n";
|
||||
|
||||
PrintMetadata(metadataFile, "Exif - main info", dib, FIMD_EXIF_MAIN);
|
||||
}
|
||||
if(count = FreeImage_GetMetadataCount(FIMD_EXIF_EXIF, dib)) {
|
||||
cout << "\nFIMD_EXIF_EXIF (" << count << " data)\n-----------------------------------------\n";
|
||||
|
||||
PrintMetadata(metadataFile, "Exif - advanced info", dib, FIMD_EXIF_EXIF);
|
||||
}
|
||||
if(count = FreeImage_GetMetadataCount(FIMD_EXIF_GPS, dib)) {
|
||||
cout << "\nFIMD_EXIF_GPS (" << count << " data)\n-----------------------------------------\n";
|
||||
|
||||
PrintMetadata(metadataFile, "Exif GPS", dib, FIMD_EXIF_GPS);
|
||||
}
|
||||
if(count = FreeImage_GetMetadataCount(FIMD_EXIF_INTEROP, dib)) {
|
||||
cout << "\nFIMD_EXIF_INTEROP (" << count << " data)\n-----------------------------------------\n";
|
||||
|
||||
PrintMetadata(metadataFile, "Exif interoperability", dib, FIMD_EXIF_INTEROP);
|
||||
}
|
||||
if(count = FreeImage_GetMetadataCount(FIMD_EXIF_MAKERNOTE, dib)) {
|
||||
cout << "\nFIMD_EXIF_MAKERNOTE (" << count << " data)\n-----------------------------------------\n";
|
||||
|
||||
// Get the camera model
|
||||
FITAG *tagMake = NULL;
|
||||
FreeImage_GetMetadata(FIMD_EXIF_MAIN, dib, "Make", &tagMake);
|
||||
|
||||
std::string buffer((char*)FreeImage_GetTagValue(tagMake));
|
||||
buffer += " Makernote";
|
||||
|
||||
PrintMetadata(metadataFile, buffer.c_str(), dib, FIMD_EXIF_MAKERNOTE);
|
||||
}
|
||||
if(count = FreeImage_GetMetadataCount(FIMD_IPTC, dib)) {
|
||||
cout << "\nFIMD_IPTC (" << count << " data)\n-----------------------------------------\n";
|
||||
|
||||
PrintMetadata(metadataFile, "IPTC/NAA", dib, FIMD_IPTC);
|
||||
}
|
||||
if(count = FreeImage_GetMetadataCount(FIMD_GEOTIFF, dib)) {
|
||||
cout << "\nFIMD_GEOTIFF (" << count << " data)\n-----------------------------------------\n";
|
||||
|
||||
PrintMetadata(metadataFile, "GEOTIFF", dib, FIMD_GEOTIFF);
|
||||
}
|
||||
|
||||
// Print the footer
|
||||
|
||||
PrintTableFooter(metadataFile);
|
||||
PrintHTMLFooter(metadataFile);
|
||||
|
||||
// close the HTML file
|
||||
|
||||
metadataFile.close();
|
||||
|
||||
// print XMP data
|
||||
|
||||
if(count = FreeImage_GetMetadataCount(FIMD_XMP, dib)) {
|
||||
cout << "\nFIMD_XMP (" << count << " packet)\n-----------------------------------------\n";
|
||||
|
||||
std::string xmp_file(strtok(argv[1], ".") + std::string(".xmp"));
|
||||
metadataFile.open(xmp_file.c_str(), ios::out);
|
||||
|
||||
FITAG *tag = NULL;
|
||||
FreeImage_GetMetadata(FIMD_XMP, dib, "XMLPacket", &tag);
|
||||
if(tag) {
|
||||
metadataFile << (char*)FreeImage_GetTagValue(tag);
|
||||
}
|
||||
|
||||
metadataFile.close();
|
||||
}
|
||||
|
||||
|
||||
// Unload the bitmap
|
||||
|
||||
FreeImage_Unload(dib);
|
||||
|
||||
|
||||
// call this ONLY when linking with FreeImage as a static library
|
||||
#ifdef FREEIMAGE_LIB
|
||||
FreeImage_DeInitialise();
|
||||
#endif // FREEIMAGE_LIB
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
CC = gcc
|
||||
CPP = g++
|
||||
COMPILERFLAGS = -O3
|
||||
INCLUDE = -I../../Dist
|
||||
VGALIBRARIES = -lfreeimage -lvga
|
||||
VGAINCLUDE = -I/usr/include/asm
|
||||
GTKLIBRARIES = -lfreeimage `pkg-config --libs gtk+-2.0`
|
||||
GTKINCLUDE = `pkg-config --cflags gtk+-2.0`
|
||||
CFLAGS = $(COMPILERFLAGS) $(INCLUDE)
|
||||
|
||||
all: default
|
||||
|
||||
default: linux-svgalib linux-gtk
|
||||
|
||||
linux-svgalib: linux-svgalib.c
|
||||
$(CC) $(CFLAGS) $< -o $@ $(VGALIBRARIES) $(VGAINCLUDE)
|
||||
strip $@
|
||||
|
||||
linux-gtk: linux-gtk.c
|
||||
$(CC) $(CFLAGS) $< -o $@ $(GTKLIBRARIES) $(GTKINCLUDE)
|
||||
strip $@
|
||||
|
||||
clean:
|
||||
rm -f core linux-svgalib linux-gtk
|
||||
@@ -1,100 +0,0 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include <FreeImage.h>
|
||||
#include <string.h>
|
||||
|
||||
void destroy(GtkWidget * widget, gpointer data) {
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
GtkWidget *window, *imagebox;
|
||||
GdkVisual *visual;
|
||||
GdkImage *image;
|
||||
FIBITMAP *dib;
|
||||
int y;
|
||||
|
||||
// initialize the FreeImage library
|
||||
FreeImage_Initialise(TRUE);
|
||||
|
||||
dib = FreeImage_Load(FIF_PNG, "freeimage.png", PNG_DEFAULT);
|
||||
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||
|
||||
gtk_signal_connect(GTK_OBJECT(window), "destroy",
|
||||
GTK_SIGNAL_FUNC(destroy), NULL);
|
||||
|
||||
visual = gdk_visual_get_system();
|
||||
|
||||
image = gdk_image_new(GDK_IMAGE_NORMAL,visual,
|
||||
FreeImage_GetWidth(dib),FreeImage_GetHeight(dib));
|
||||
|
||||
g_print("picture: %d bpp\n"
|
||||
"system: %d bpp byteorder: %d\n"
|
||||
" redbits: %d greenbits: %d bluebits: %d\n"
|
||||
"image: %d bpp %d bytes/pixel\n",
|
||||
FreeImage_GetBPP(dib),
|
||||
visual->depth,visual->byte_order,
|
||||
visual->red_prec,visual->green_prec,visual->blue_prec,
|
||||
image->depth,image->bpp );
|
||||
|
||||
if (FreeImage_GetBPP(dib) != (image->bpp << 3)) {
|
||||
FIBITMAP *ptr;
|
||||
|
||||
switch (image->bpp) {
|
||||
case 1:
|
||||
ptr = FreeImage_ConvertTo8Bits(dib);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (image->depth == 15) {
|
||||
ptr = FreeImage_ConvertTo16Bits555(dib);
|
||||
} else {
|
||||
ptr = FreeImage_ConvertTo16Bits565(dib);
|
||||
}
|
||||
|
||||
break;
|
||||
case 3:
|
||||
ptr = FreeImage_ConvertTo24Bits(dib);
|
||||
break;
|
||||
|
||||
default:
|
||||
case 4:
|
||||
ptr = FreeImage_ConvertTo32Bits(dib);
|
||||
break;
|
||||
}
|
||||
|
||||
FreeImage_Unload(dib);
|
||||
dib = ptr;
|
||||
}
|
||||
|
||||
//makes it upside down :(
|
||||
// memcpy(image->mem, FreeImage_GetBits(dib), image->bpl * image->height);
|
||||
|
||||
BYTE *ptr = FreeImage_GetBits(dib);
|
||||
|
||||
for (y = 0; y < image->height; y++) {
|
||||
memcpy(image->mem + (y * image->bpl),
|
||||
ptr + ((image->height - y - 1) * image->bpl),
|
||||
image->bpl);
|
||||
}
|
||||
|
||||
FreeImage_Unload(dib);
|
||||
|
||||
imagebox = gtk_image_new_from_image(image, NULL);
|
||||
gtk_container_add(GTK_CONTAINER(window), imagebox);
|
||||
|
||||
gtk_widget_show(imagebox);
|
||||
gtk_widget_show(window);
|
||||
|
||||
gtk_main();
|
||||
|
||||
// release the FreeImage library
|
||||
FreeImage_DeInitialise();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
#include <vga.h>
|
||||
#include "FreeImage.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
FIBITMAP *dib,*ptr;
|
||||
vga_modeinfo *inf;
|
||||
int length,height,bpp,y;
|
||||
|
||||
// initialize the FreeImage library
|
||||
FreeImage_Initialise();
|
||||
|
||||
dib = FreeImage_Load(FIF_PNG, "freeimage.png", PNG_DEFAULT);
|
||||
|
||||
vga_init();
|
||||
vga_setmode(vga_getdefaultmode());
|
||||
|
||||
inf = vga_getmodeinfo(vga_getcurrentmode());
|
||||
|
||||
switch(inf->colors) {
|
||||
default:
|
||||
printf("Must be at least 256 color mode!\n");
|
||||
return;
|
||||
|
||||
case 1 << 8:
|
||||
bpp = 8;
|
||||
break;
|
||||
|
||||
case 1 << 15:
|
||||
bpp = 15;
|
||||
break;
|
||||
|
||||
case 1 << 16:
|
||||
bpp = 16;
|
||||
break;
|
||||
|
||||
case 1 << 24:
|
||||
if( inf->bytesperpixel == 3 ) {
|
||||
bpp = 24;
|
||||
} else {
|
||||
bpp = 32;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(FreeImage_GetBPP(dib) != bpp) {
|
||||
switch(bpp) {
|
||||
case 8:
|
||||
ptr = FreeImage_ConvertTo8Bits(dib);
|
||||
break;
|
||||
|
||||
case 15:
|
||||
ptr = FreeImage_ConvertTo16Bits555(dib);
|
||||
break;
|
||||
|
||||
case 16:
|
||||
ptr = FreeImage_ConvertTo16Bits565(dib);
|
||||
break;
|
||||
|
||||
case 24:
|
||||
ptr = FreeImage_ConvertTo24Bits(dib);
|
||||
break;
|
||||
|
||||
default:
|
||||
case 32:
|
||||
ptr = FreeImage_ConvertTo32Bits(dib);
|
||||
break;
|
||||
}
|
||||
|
||||
FreeImage_Unload(dib);
|
||||
dib = ptr;
|
||||
}
|
||||
|
||||
length = FreeImage_GetWidth(dib);
|
||||
if( inf->width < length ) {
|
||||
length = inf->width;
|
||||
}
|
||||
height = FreeImage_GetHeight(dib);
|
||||
if( inf->height < height ) {
|
||||
height = inf->height;
|
||||
}
|
||||
|
||||
for(y = 0; y < height; y++) {
|
||||
vga_drawscansegment(FreeImage_GetScanLine(dib, y), 0, y, length);
|
||||
}
|
||||
|
||||
FreeImage_Unload(dib);
|
||||
|
||||
vga_getch();
|
||||
vga_setmode(TEXT);
|
||||
|
||||
// release the FreeImage library
|
||||
FreeImage_DeInitialise();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
//**********************************************
|
||||
//Singleton Texture Manager class
|
||||
//Written by Ben English
|
||||
//benjamin.english@oit.edu
|
||||
//
|
||||
//For use with OpenGL and the FreeImage library
|
||||
//**********************************************
|
||||
|
||||
#include "TextureManager.h"
|
||||
|
||||
TextureManager* TextureManager::m_inst(0);
|
||||
|
||||
TextureManager* TextureManager::Inst()
|
||||
{
|
||||
if(!m_inst)
|
||||
m_inst = new TextureManager();
|
||||
|
||||
return m_inst;
|
||||
}
|
||||
|
||||
TextureManager::TextureManager()
|
||||
{
|
||||
// call this ONLY when linking with FreeImage as a static library
|
||||
#ifdef FREEIMAGE_LIB
|
||||
FreeImage_Initialise();
|
||||
#endif
|
||||
}
|
||||
|
||||
//these should never be called
|
||||
//TextureManager::TextureManager(const TextureManager& tm){}
|
||||
//TextureManager& TextureManager::operator=(const TextureManager& tm){}
|
||||
|
||||
TextureManager::~TextureManager()
|
||||
{
|
||||
// call this ONLY when linking with FreeImage as a static library
|
||||
#ifdef FREEIMAGE_LIB
|
||||
FreeImage_DeInitialise();
|
||||
#endif
|
||||
|
||||
UnloadAllTextures();
|
||||
m_inst = 0;
|
||||
}
|
||||
|
||||
bool TextureManager::LoadTexture(const char* filename, const unsigned int texID, GLenum image_format, GLint internal_format, GLint level, GLint border)
|
||||
{
|
||||
//image format
|
||||
FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
|
||||
//pointer to the image, once loaded
|
||||
FIBITMAP *dib(0);
|
||||
//pointer to the image data
|
||||
BYTE* bits(0);
|
||||
//image width and height
|
||||
unsigned int width(0), height(0);
|
||||
//OpenGL's image ID to map to
|
||||
GLuint gl_texID;
|
||||
|
||||
//check the file signature and deduce its format
|
||||
fif = FreeImage_GetFileType(filename, 0);
|
||||
//if still unknown, try to guess the file format from the file extension
|
||||
if(fif == FIF_UNKNOWN)
|
||||
fif = FreeImage_GetFIFFromFilename(filename);
|
||||
//if still unkown, return failure
|
||||
if(fif == FIF_UNKNOWN)
|
||||
return false;
|
||||
|
||||
//check that the plugin has reading capabilities and load the file
|
||||
if(FreeImage_FIFSupportsReading(fif))
|
||||
dib = FreeImage_Load(fif, filename);
|
||||
//if the image failed to load, return failure
|
||||
if(!dib)
|
||||
return false;
|
||||
|
||||
//retrieve the image data
|
||||
bits = FreeImage_GetBits(dib);
|
||||
//get the image width and height
|
||||
width = FreeImage_GetWidth(dib);
|
||||
height = FreeImage_GetHeight(dib);
|
||||
//if this somehow one of these failed (they shouldn't), return failure
|
||||
if((bits == 0) || (width == 0) || (height == 0))
|
||||
return false;
|
||||
|
||||
//if this texture ID is in use, unload the current texture
|
||||
if(m_texID.find(texID) != m_texID.end())
|
||||
glDeleteTextures(1, &(m_texID[texID]));
|
||||
|
||||
//generate an OpenGL texture ID for this texture
|
||||
glGenTextures(1, &gl_texID);
|
||||
//store the texture ID mapping
|
||||
m_texID[texID] = gl_texID;
|
||||
//bind to the new texture ID
|
||||
glBindTexture(GL_TEXTURE_2D, gl_texID);
|
||||
//store the texture data for OpenGL use
|
||||
glTexImage2D(GL_TEXTURE_2D, level, internal_format, width, height,
|
||||
border, image_format, GL_UNSIGNED_BYTE, bits);
|
||||
|
||||
//Free FreeImage's copy of the data
|
||||
FreeImage_Unload(dib);
|
||||
|
||||
//return success
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TextureManager::UnloadTexture(const unsigned int texID)
|
||||
{
|
||||
bool result(true);
|
||||
//if this texture ID mapped, unload it's texture, and remove it from the map
|
||||
if(m_texID.find(texID) != m_texID.end())
|
||||
{
|
||||
glDeleteTextures(1, &(m_texID[texID]));
|
||||
m_texID.erase(texID);
|
||||
}
|
||||
//otherwise, unload failed
|
||||
else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool TextureManager::BindTexture(const unsigned int texID)
|
||||
{
|
||||
bool result(true);
|
||||
//if this texture ID mapped, bind it's texture as current
|
||||
if(m_texID.find(texID) != m_texID.end())
|
||||
glBindTexture(GL_TEXTURE_2D, m_texID[texID]);
|
||||
//otherwise, binding failed
|
||||
else
|
||||
result = false;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void TextureManager::UnloadAllTextures()
|
||||
{
|
||||
//start at the begginning of the texture map
|
||||
std::map<unsigned int, GLuint>::iterator i = m_texID.begin();
|
||||
|
||||
//Unload the textures untill the end of the texture map is found
|
||||
while(i != m_texID.end())
|
||||
UnloadTexture(i->first);
|
||||
|
||||
//clear the texture map
|
||||
m_texID.clear();
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
//**********************************************
|
||||
//Singleton Texture Manager class
|
||||
//Written by Ben English
|
||||
//benjamin.english@oit.edu
|
||||
//
|
||||
//For use with OpenGL and the FreeImage library
|
||||
//**********************************************
|
||||
|
||||
#ifndef TextureManager_H
|
||||
#define TextureManager_H
|
||||
|
||||
#include <windows.h>
|
||||
#include <gl/gl.h>
|
||||
#include "FreeImage.h"
|
||||
#include <map>
|
||||
|
||||
class TextureManager
|
||||
{
|
||||
public:
|
||||
static TextureManager* Inst();
|
||||
virtual ~TextureManager();
|
||||
|
||||
//load a texture an make it the current texture
|
||||
//if texID is already in use, it will be unloaded and replaced with this texture
|
||||
bool LoadTexture(const char* filename, //where to load the file from
|
||||
const unsigned int texID, //arbitrary id you will reference the texture by
|
||||
//does not have to be generated with glGenTextures
|
||||
GLenum image_format = GL_RGB, //format the image is in
|
||||
GLint internal_format = GL_RGB, //format to store the image in
|
||||
GLint level = 0, //mipmapping level
|
||||
GLint border = 0); //border size
|
||||
|
||||
//free the memory for a texture
|
||||
bool UnloadTexture(const unsigned int texID);
|
||||
|
||||
//set the current texture
|
||||
bool BindTexture(const unsigned int texID);
|
||||
|
||||
//free all texture memory
|
||||
void UnloadAllTextures();
|
||||
|
||||
protected:
|
||||
TextureManager();
|
||||
TextureManager(const TextureManager& tm);
|
||||
TextureManager& operator=(const TextureManager& tm);
|
||||
|
||||
static TextureManager* m_inst;
|
||||
std::map<unsigned int, GLuint> m_texID;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,31 +0,0 @@
|
||||
Hello everyone, this is my 2D texture manager class for OpenGL using the FreeImage Library.
|
||||
|
||||
Requirements:
|
||||
--------------------
|
||||
OpenGL
|
||||
STL map class
|
||||
FreeImage (included)
|
||||
|
||||
|
||||
Usage
|
||||
--------------------
|
||||
To load a texture, simply call the LoadTexture function:
|
||||
|
||||
TextureManager::Inst()->LoadTexture("img\\bg.jpg", BACKGROUND_IMAGE_ID);
|
||||
|
||||
This also binds the loaded texture as the current texture, so after calling it you may make any calls to glTexParameter you may need to specify the properties of the texture.
|
||||
|
||||
When you are rendering, just call the TextureManager's BindImage function instead of glBindImage:
|
||||
|
||||
TextureManager::Inst()->BindImage(BACKGROUND_IMAGE_ID);
|
||||
|
||||
and then do your rendering as normal.
|
||||
--------------------
|
||||
|
||||
|
||||
Feel free to distribute this as you like, but mind the FreeImage licence included in license-fi.txt, and please don't take credit for my code. If you modify it, be sure to mention me (Ben English) somewhere.
|
||||
|
||||
Please send any comments or suggestions to me at benjamin.english@oit.edu
|
||||
|
||||
|
||||
Thanks to Herve Drolon for the FreeImage library, I've found it to be very useful!
|
||||
@@ -1,253 +0,0 @@
|
||||
// ==========================================================
|
||||
// Loader/Saver Plugin Cradle
|
||||
//
|
||||
// Design and implementation by
|
||||
// - Floris van den Berg (flvdberg@wxs.nl)
|
||||
// - Herv<72> Drolon (drolon@infonie.fr)
|
||||
//
|
||||
// This file is part of FreeImage 3
|
||||
//
|
||||
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
|
||||
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
|
||||
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
|
||||
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
|
||||
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
|
||||
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
|
||||
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
|
||||
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
|
||||
// THIS DISCLAIMER.
|
||||
//
|
||||
// Use at your own risk!
|
||||
// ==========================================================
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "FreeImage.h"
|
||||
#include "Utilities.h"
|
||||
|
||||
// ==========================================================
|
||||
|
||||
BOOL APIENTRY
|
||||
DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
|
||||
switch (ul_reason_for_call) {
|
||||
case DLL_PROCESS_ATTACH :
|
||||
case DLL_PROCESS_DETACH :
|
||||
case DLL_THREAD_ATTACH :
|
||||
case DLL_THREAD_DETACH :
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// ==========================================================
|
||||
// Plugin Interface
|
||||
// ==========================================================
|
||||
|
||||
static int s_format_id;
|
||||
|
||||
// ==========================================================
|
||||
// Plugin Implementation
|
||||
// ==========================================================
|
||||
|
||||
/**
|
||||
Returns the format string for the plugin. Each plugin,
|
||||
both internal in the DLL and external in a .fip file, must have
|
||||
a unique format string to be addressable.
|
||||
*/
|
||||
|
||||
static const char * DLL_CALLCONV
|
||||
Format() {
|
||||
return "CRADLE";
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a description string for the plugin. Though a
|
||||
description is not necessary per-se,
|
||||
it is advised to return an unique string in order to tell the
|
||||
user what type of bitmaps this plugin will read and/or write.
|
||||
*/
|
||||
|
||||
static const char * DLL_CALLCONV
|
||||
Description() {
|
||||
return "Here comes the description for your image loader/saver";
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a comma separated list of file extensions indicating
|
||||
what files this plugin can open. no spaces or whatsoever are allowed.
|
||||
The list, being used by FreeImage_GetFIFFromFilename, is usually
|
||||
used as a last resort in finding the type of the bitmap we
|
||||
are dealing with. Best is to check the first few bytes on
|
||||
the low-level bits level first and compare them with a known
|
||||
signature . If this fails, FreeImage_GetFIFFromFilename can be
|
||||
used.
|
||||
*/
|
||||
|
||||
static const char * DLL_CALLCONV
|
||||
Extension() {
|
||||
return "ext1,ext2";
|
||||
}
|
||||
|
||||
/**
|
||||
RegExpr is only needed for the Qt wrapper
|
||||
It allows the Qt mechanism for loading bitmaps to identify the bitmap
|
||||
*/
|
||||
static const char * DLL_CALLCONV
|
||||
RegExpr() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a MIME content type string for that format (MIME stands
|
||||
for Multipurpose Internet Mail Extension).
|
||||
*/
|
||||
static const char * DLL_CALLCONV
|
||||
MimeType() {
|
||||
return "image/myformat";
|
||||
}
|
||||
|
||||
/**
|
||||
FreeImage's internal way of seeing if a bitmap is of the desired type.
|
||||
When the type of a bitmap is to be retrieved, FreeImage runs Validate
|
||||
for each registered plugin until one returns true. If a plugin doesn't
|
||||
have a validate function, a return value of false is assumed.
|
||||
|
||||
You can always force to use a particular plugin by directly specifying
|
||||
it on the command line, but this can result in a dead DLL if the plugin
|
||||
was not made for the bitmap.
|
||||
*/
|
||||
static BOOL DLL_CALLCONV
|
||||
Validate(FreeImageIO &io, fi_handle handle) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
SupportsExportDepth is the first in a possible range of new plugin functions
|
||||
to ask specific information to that plugin. This function returns TRUE if it
|
||||
can save a bitmap in the required bitdepth. If it can't the bitmap has to be
|
||||
converted by the user or another plugin has to be chosen.
|
||||
*/
|
||||
static BOOL DLL_CALLCONV
|
||||
SupportsExportDepth(int depth) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns TRUE if the plugin belonging to the given FREE_IMAGE_FORMAT can save a
|
||||
bitmap in the desired data type, returns FALSE otherwise. Currently, TIFF is the only plugin
|
||||
able to save all non-standard images. The PNG plugin is able to save unsigned 16-bit
|
||||
images.
|
||||
*/
|
||||
static BOOL DLL_CALLCONV
|
||||
SupportsExportType(FREE_IMAGE_TYPE type) {
|
||||
return (type == FIT_BITMAP) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
SupportsICCProfiles informs FreeImage that a plugin supports ICC profiles.
|
||||
This function returns TRUE if the plugin can load and save a profile.
|
||||
ICC profile information is accessed via freeimage->get_icc_profile_proc(dib)
|
||||
*/
|
||||
static BOOL DLL_CALLCONV
|
||||
SupportsICCProfiles() {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
Loads a bitmap into memory. On entry it is assumed that
|
||||
the bitmap to be loaded is of the correct type. If the bitmap
|
||||
is of an incorrect type, the plugin might not gracefully fail but
|
||||
crash or enter an endless loop. It is also assumed that all
|
||||
the bitmap data is available at one time. If the bitmap is not complete,
|
||||
for example because it is being downloaded while loaded, the plugin
|
||||
might also not gracefully fail.
|
||||
|
||||
The Load function has the following parameters:
|
||||
|
||||
The first parameter (FreeImageIO *io) is a structure providing
|
||||
function pointers in order to make use of FreeImage's IO redirection. Using
|
||||
FreeImage's file i/o functions instead of standard ones it is garantueed
|
||||
that all bitmap types, both current and future ones, can be loaded from
|
||||
memory, file cabinets, the internet and more. The second parameter (fi_handle handle)
|
||||
is a companion of FreeImageIO and can be best compared with the standard FILE* type,
|
||||
in a generalized form.
|
||||
|
||||
The third parameter (int page) indicates wether we will be loading a certain page
|
||||
in the bitmap or if we will load the default one. This parameter is only used if
|
||||
the plugin supports multi-paged bitmaps, e.g. cabinet bitmaps that contain a series
|
||||
of images or pages. If the plugin does support multi-paging, the page parameter
|
||||
can contain either a number higher or equal to 0 to load a certain page, or -1 to
|
||||
load the default page. If the plugin does not support multi-paging,
|
||||
the page parameter is always -1.
|
||||
|
||||
The fourth parameter (int flags) manipulates the load function to load a bitmap
|
||||
in a certain way. Every plugin has a different flag parameter with different meanings.
|
||||
|
||||
The last parameter (void *data) can contain a special data block used when
|
||||
the file is read multi-paged. Because not every plugin supports multi-paging
|
||||
not every plugin will use the data parameter and it will be set to NULL.However,
|
||||
when the plugin does support multi-paging the parameter contains a pointer to a
|
||||
block of data allocated by the Open function.
|
||||
*/
|
||||
|
||||
static FIBITMAP * DLL_CALLCONV
|
||||
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static BOOL DLL_CALLCONV
|
||||
Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// ==========================================================
|
||||
// Init
|
||||
// ==========================================================
|
||||
|
||||
/**
|
||||
Initialises the plugin. The first parameter (Plugin *plugin)
|
||||
contains a pointer to a pre-allocated Plugin structure
|
||||
wherein pointers to the available plugin functions
|
||||
has to be stored. The second parameter (int format_id) is an identification
|
||||
number that the plugin may use to show plugin specific warning messages
|
||||
or other information to the user. The plugin number
|
||||
is generated by FreeImage and can differ everytime the plugin is
|
||||
initialised.
|
||||
|
||||
If you want to create your own plugin you have to take some
|
||||
rules into account. Plugin functions have to be compiled
|
||||
__stdcall using the multithreaded c runtime libraries. Throwing
|
||||
exceptions in plugin functions is allowed, as long as those exceptions
|
||||
are being caught inside the same plugin. It is forbidden for a plugin
|
||||
function to directly call FreeImage functions or to allocate memory
|
||||
and pass it to the main DLL. Exception to this rule is the special file data
|
||||
block that may be allocated the Open function. Allocating a FIBITMAP inside a
|
||||
plugin can be using the function allocate_proc in the FreeImage structure,
|
||||
which will allocate the memory using the DLL's c runtime library.
|
||||
*/
|
||||
|
||||
void DLL_CALLCONV
|
||||
Init(Plugin *plugin, int format_id) {
|
||||
s_format_id = format_id;
|
||||
|
||||
plugin->format_proc = Format;
|
||||
plugin->description_proc = Description;
|
||||
plugin->extension_proc = Extension;
|
||||
plugin->regexpr_proc = RegExpr;
|
||||
plugin->open_proc = NULL;
|
||||
plugin->close_proc = NULL;
|
||||
plugin->pagecount_proc = NULL;
|
||||
plugin->pagecapability_proc = NULL;
|
||||
plugin->load_proc = Load;
|
||||
plugin->save_proc = Save;
|
||||
plugin->validate_proc = Validate;
|
||||
plugin->mime_proc = MimeType;
|
||||
plugin->supports_export_bpp_proc = SupportsExportDepth;
|
||||
plugin->supports_export_type_proc = SupportsExportType;
|
||||
plugin->supports_icc_profiles_proc = SupportsICCProfiles;
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
// ==========================================================
|
||||
// JBIG Plugin
|
||||
//
|
||||
// Design and implementation by
|
||||
// - Floris van den Berg (flvdberg@wxs.nl)
|
||||
//
|
||||
// This file is part of FreeImage 3
|
||||
//
|
||||
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
|
||||
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
|
||||
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
|
||||
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
|
||||
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
|
||||
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
|
||||
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
|
||||
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
|
||||
// THIS DISCLAIMER.
|
||||
//
|
||||
// Use at your own risk!
|
||||
// ==========================================================
|
||||
|
||||
#ifndef PLUGINCRADLE_H
|
||||
#define PLUGINCRADLE_H
|
||||
|
||||
#ifdef PLUGINCRADLE_EXPORTS
|
||||
#define PLUGIN_API __declspec(dllexport)
|
||||
#else
|
||||
#define PLUGIN_API __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
struct Plugin;
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
#define DLL_CALLCONV __stdcall
|
||||
|
||||
// ----------------------------------------------------------
|
||||
|
||||
extern "C" {
|
||||
PLUGIN_API void DLL_CALLCONV Init(Plugin *plugin, int format_id);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,236 +0,0 @@
|
||||
=====================================================================
|
||||
Using the FreeImage library with the MinGW Compiler Suite
|
||||
=====================================================================
|
||||
|
||||
This file describes how to use the precompiled FreeImage library
|
||||
FreeImage.dll with the MinGW port of the GNU Compiler Collection
|
||||
(GCC), how to build this library from source using MinGW and how
|
||||
to use this MinGW-built library with Microsoft Visual Studio.
|
||||
|
||||
Contents:
|
||||
|
||||
I. Prerequisites
|
||||
|
||||
1. Using the precompiled FreeImage library with MinGW
|
||||
|
||||
2. Building the FreeImage library with MinGW
|
||||
|
||||
3. Using the MinGW FreeImage library with Microsoft Visual Studio
|
||||
|
||||
4. Useful links
|
||||
|
||||
|
||||
---------------------------------------------------------------------
|
||||
I. Prerequisites
|
||||
=====================================================================
|
||||
|
||||
The procedures described in this document have been developed and
|
||||
tested using the following free tools:
|
||||
|
||||
1. MinGW GCC Version 4.4.0 (Core and C++ including required libs)
|
||||
2. MinGW GNU Binutils Version 2.19.1
|
||||
3. MinGW GNU Make Version 3.81-20080326-3
|
||||
4. MinGW Runtime Version 3.15.2
|
||||
5. MinGW API for MS-Windows Version 3.13
|
||||
6. GnuWin32 Package CoreUtils Version 5.3.0 (only for building)
|
||||
7. GnuWin32 Package Sed Version 4.2 (only for creating the GCC
|
||||
import library)*
|
||||
|
||||
* Sed is only needed to create a GCC-native import library from
|
||||
the MSVC import library FreeImage.lib. However, since MinGW now
|
||||
supports linking against MSVC lib files, this process seems to
|
||||
be obsolete. See section 1.
|
||||
|
||||
Basically, no version dependent capabilities are used so, this
|
||||
should also work with older versions of the tools mentioned above.
|
||||
Similarly, the GnuWin32 packages (which I just prefer over MSYS)
|
||||
could likely be replaced by a properly installed MSYS environment.
|
||||
|
||||
Furthermore, the following preconditions should be met:
|
||||
|
||||
1. The folders 'bin' under both the MinGW and the GnuWin32
|
||||
installation directory should have been added to the PATH
|
||||
environment variable. Likely it is best adding these
|
||||
directories permanently to PATH through the System
|
||||
Properties dialog on the Control Panel.
|
||||
|
||||
2. The MinGW Make package only provides a 'mingw32-make.exe'
|
||||
executable. There is no alias 'make.exe'. However, make is
|
||||
preconfigured to use 'make' as the default $(MAKE) command.
|
||||
This seems to be a bug in the MinGW GNU Make distribution.
|
||||
Thus, a copy of 'mingw32-make.exe' named 'make.exe' should
|
||||
be placed into MinGW's 'bin' directory.
|
||||
|
||||
|
||||
|
||||
---------------------------------------------------------------------
|
||||
1. Using the precompiled FreeImage library with MinGW
|
||||
=====================================================================
|
||||
|
||||
When using functions from C/C++, that reside in a DLL, the linker
|
||||
needs a so called import library, which specifies, how to
|
||||
dynamically link these external functions during runtime. However,
|
||||
different linkers use different types or formats of these import
|
||||
libraries.
|
||||
|
||||
Since the precompiled FreeImage library was build with Microsoft
|
||||
Visual Studio, in the past, some extra work was required to use it
|
||||
from MinGW. An import library, that was compatible with GNU ld,
|
||||
must have been created first.
|
||||
|
||||
However, for several MinGW versions, the GNU linker ld also
|
||||
supports linking against Microsoft Visual C++ import libraries
|
||||
directly. So, this effectively makes any circulating HOWTO's on
|
||||
how to create a GCC-compatible import library from a MSVC lib file
|
||||
more or less obsolete. Additionally, MinGW does not require the
|
||||
GCC/Linux usual lib prefix for libraries, so linking with MinGW
|
||||
against the precompiled FreeImage DLL is as easy as with MSVC:
|
||||
|
||||
1.) Open a DOS shell (run application cmd.exe)
|
||||
|
||||
2.) Ensure, that the 'bin' folder of MinGW is added to the PATH
|
||||
environment variable (see Prerequisites).
|
||||
|
||||
3.) Link directly against the supplied lib file:
|
||||
|
||||
C:\>gcc -oFreeImageTest.exe FreeImageTest.c -lFreeImage
|
||||
|
||||
Nonetheless, for the sake of completeness, the following steps
|
||||
describe how to create a native GCC import library:
|
||||
|
||||
1.) Open a DOS shell (run application cmd.exe)
|
||||
|
||||
2.) Ensure, that the 'bin' folders of both MinGW and GnuWin32 are
|
||||
added to the PATH environment variable (see Prerequisites).
|
||||
|
||||
3.) Create a .def file 'libfreeimage.def', that contains all symbols
|
||||
exported by the FreeImage library:
|
||||
|
||||
C:\>pexports FreeImage.dll | sed "s/^_//" > libfreeimage.def
|
||||
|
||||
4.) Create the GCC compatible import library 'libfreeimage.a':
|
||||
|
||||
C:\>dlltool --add-underscore -d libfreeimage.def -l libfreeimage.a
|
||||
|
||||
5.) Use this library to link against with GCC:
|
||||
|
||||
C:\>gcc -oFreeImageTest.exe FreeImageTest.c -lfreeimage
|
||||
|
||||
|
||||
|
||||
---------------------------------------------------------------------
|
||||
2. Building the FreeImage library with MinGW
|
||||
=====================================================================
|
||||
|
||||
You *do not* need to have any other third party library (like
|
||||
libjpeg, libpng, libtiff, libmng and zlib and others) installed on
|
||||
your system in order to compile and use the library. FreeImage uses
|
||||
its own versions of these libraries. This way, you can be sure that
|
||||
FreeImage will always use the latest and properly tested versions
|
||||
of of these third party libraries.
|
||||
|
||||
In order to build the FreeImage library under Windows with MinGW
|
||||
(GCC), ensure that all the prerequisites mentioned above are met.
|
||||
The MinGW makefile aims to build a Windows DLL, that differs as
|
||||
least as possible from the precompiled library that comes with the
|
||||
FreeImage distribution. Thus, the build process also includes the
|
||||
DLL version resource as well as the __stdcall attribute for all the
|
||||
exported functions, including the MSVC-like function decorations
|
||||
_FuncName@nn.
|
||||
|
||||
When building the FreeImage DLL, of course, an import library is
|
||||
generated, too. However, this input library is not in GCC's native
|
||||
format, but in MSVC lib format, which makes it usable from both
|
||||
MinGW and Microsoft Visual Studio with no further processing.
|
||||
|
||||
The MinGW makefile can also be used to build a static library.
|
||||
However, due to the different function export attributes needed
|
||||
for both the dynamic and the shared library (DLL), this requires
|
||||
a separate invocation of make, which in turn needs to rebuild every
|
||||
source file after switching from dynamic to static and vice versa.
|
||||
So, a 'make clean' is required each time, the library type is
|
||||
changed.
|
||||
|
||||
The type of library to build is specified by a variable named
|
||||
FREEIMAGE_LIBRARY_TYPE, which may either be set directly in the
|
||||
Makefile.mingw near line 18 or may be specified as an environment
|
||||
variable. This variable may either take SHARED or STATIC to build
|
||||
a dynamic link library (DLL) or a static library respectively.
|
||||
Since this value is used to dynamically form the actual make target
|
||||
internally, only uppercase values are valid. Defaults to SHARED.
|
||||
|
||||
The MinGW makefile also supports the 'install' target. However,
|
||||
this only copies the FreeImage dynamic link library (DLL) from the
|
||||
Dist folder into the %SystemRoot%\system32 folder. So, invoking this
|
||||
target only makes sense, if the DLL has been built before.
|
||||
|
||||
Since there is neither a common system wide 'include' nor a 'lib'
|
||||
directory available under Windows, the FreeImage header file
|
||||
FreeImage.h as well as both the static library and the DLL import
|
||||
library FreeImage.lib just remain in the 'Dist' folder.
|
||||
|
||||
The following procedure creates the FreeImage dynamic link library
|
||||
(DLL) from the sources, installs it and also creates a static
|
||||
FreeImage library:
|
||||
|
||||
1.) Open a DOS shell (run application cmd.exe)
|
||||
|
||||
2.) Ensure, that the 'bin' folders of both MinGW and GnuWin32 are
|
||||
added to the PATH environment variable (see Prerequisites).
|
||||
|
||||
3.) Create the FreeImage dynamic link library (DLL):
|
||||
|
||||
C:\>make
|
||||
|
||||
4.) Install the FreeImage dynamic link library (DLL):
|
||||
|
||||
C:\>make install
|
||||
|
||||
5.) Clean all files produced by the recent build process:
|
||||
|
||||
C:\>make clean
|
||||
|
||||
6.) Create a static FreeImage library:
|
||||
|
||||
C:\>set FREEIMAGE_LIBRARY_TYPE=STATIC
|
||||
C:\>make
|
||||
|
||||
You should be able to link progams with the -lFreeImage option
|
||||
after the shared library is compiled and installed. You can also
|
||||
link statically against FreeImage.a from MinGW.
|
||||
|
||||
|
||||
|
||||
---------------------------------------------------------------------
|
||||
3. Using the MinGW FreeImage library with Microsoft Visual Studio
|
||||
=====================================================================
|
||||
|
||||
Since the MinGW makefile creates an import library in MSVC's lib
|
||||
format, the produced shared library (DLL) can be used from both
|
||||
MinGW and Microsoft Visual Studio with no further adaption. Just
|
||||
link to the import library FreeImage.lib from either MinGW or
|
||||
Microsoft Visual Studio.
|
||||
|
||||
|
||||
|
||||
---------------------------------------------------------------------
|
||||
4. Useful links
|
||||
=====================================================================
|
||||
|
||||
- The MinGW homepage:
|
||||
http://www.mingw.org/
|
||||
|
||||
- The GnuWin32 homepage:
|
||||
http://gnuwin32.sourceforge.net/
|
||||
|
||||
- The GCC homepage and online documentation:
|
||||
http://gcc.gnu.org/
|
||||
http://gcc.gnu.org/onlinedocs/
|
||||
|
||||
- The GNU Binutils homepage and online documentation:
|
||||
http://www.gnu.org/software/binutils/
|
||||
http://sourceware.org/binutils/docs-2.19/
|
||||
|
||||
- The GNU Make homepage and online documentation:
|
||||
http://www.gnu.org/software/make/
|
||||
http://www.gnu.org/software/make/manual/make.html
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,92 +0,0 @@
|
||||
What's New for FreeImage Delphi Wrapper
|
||||
|
||||
* : fixed
|
||||
- : removed
|
||||
! : changed
|
||||
+ : added
|
||||
|
||||
July 29, 2010
|
||||
+ [Lorenzo Monti] added Free Pascal / Lazarus 32 bit support
|
||||
|
||||
July 14, 2010
|
||||
+ [Lorenzo Monti] updated wrapper for FreeImage 3.13.1
|
||||
* [Lorenzo Monti] fixed declaration of FreeImageIO functions (FI_ReadProc, FI_WriteProc, FI_SeekProc, FI_TellProc)
|
||||
! [Lorenzo Monti] renamed structure PluginStruct to Plugin, according to FreeImage.h
|
||||
* [Lorenzo Monti] fixed declaration of JPEG_CMYK constant
|
||||
* [Lorenzo Monti] fixed declaration of type FreeImage_OutputMessageFunction
|
||||
* [Lorenzo Monti] fixed declaration of FreeImage_OutputMessageProc
|
||||
+ [Lorenzo Monti] added wrapper for FreeImage_OutputMessageProc for older Delphi compilers (<6) not supporting varargs
|
||||
* [Lorenzo Monti] fixed declaration of FreeImage_LookupX11Color and FreeImage_LookupSVGColor
|
||||
! [Lorenzo Monti] changed declaration of FreeImage_GetPixelIndex, FreeImage_GetPixelColor, FreeImage_SetPixelIndex, FreeImage_SetPixelColor
|
||||
! [Lorenzo Monti] changed declaration of FreeImage_GetInfo
|
||||
! [Lorenzo Monti] changed declaration of FreeImage_GetICCProfile, FreeImage_CreateICCProfile, FreeImage_DestroyICCProfile
|
||||
* [Lorenzo Monti] fixed declaration of FreeImage_SetComplexChannel
|
||||
+ [Lorenzo Monti] added Delphi 2010 support
|
||||
+ [Lorenzo Monti] added Version.inc to determine compiler version
|
||||
! [Lorenzo Monti] moved all "external" definitions to implementation section
|
||||
! [Lorenzo Monti] changed FreeBitmap.pas, FreeUtils.pas and TargaImage.pas to reflect changes in the FreeImage.pas unit
|
||||
|
||||
July 17, 2006
|
||||
+ [Herv<72> Drolon] added FIF_FAXG3 and FIF_SGI definitions, added FreeImage_MakeThumbnail definition.
|
||||
|
||||
January 20, 2006
|
||||
! [Anatoliy Pulyaevskiy] updated WinBitmap demo
|
||||
* [Anatoliy Pulyaevskiy] fixed TFreeBitmap.ConvertToStandartType renamed to TFreeBitmap.ConvertToStandardType
|
||||
* [Anatoliy Pulyaevskiy] fixed using of SetFreeImageMarker (only for HDR dib)
|
||||
|
||||
October 19, 2005
|
||||
+ [Anatoliy Pulyaevskiy] updated wrapper for FreeImage 3.8.0
|
||||
+ [Anatoliy Pulyaevskiy] added Delphi 5 support
|
||||
+ [Anatoliy Pulyaevskiy] added TFreeBitmap.OnChanging event
|
||||
! [Anatoliy Pulyaevskiy] changed declaration of TFreeBitmap.Assign method
|
||||
+ [Anatoliy Pulyaevskiy] added TFreeBitmap.CanSave function
|
||||
! [Anatoliy Pulyaevskiy] property TFreeBitmap.Dib now have read/write access
|
||||
+ [Anatoliy Pulyaevskiy] added TFreeTag class incapsulating FreeImage FITAG type
|
||||
|
||||
August 5, 2005
|
||||
* [kaare-nysite] fixed the prototype of FreeImage_ConvertFromRawBits
|
||||
|
||||
June 21, 2005
|
||||
* [Maarten Veerman] fixed the prototype of FreeImage_OpenMultiBitmap
|
||||
|
||||
February 17, 2005 - Version 1.3.0
|
||||
+ [Anatoliy Pulyaevskiy] updated the wrapper for FreeImage 3.6.0
|
||||
! [Anatoliy Pulyaevskiy] FreeImage.pas unit has been reworked
|
||||
|
||||
January 14, 2005 - Version 1.2.1
|
||||
+ [Anatoliy Pulyaevskiy] updated the wrapper for FreeImage 3.5.3
|
||||
+ [Anatoliy Pulyaevskiy] added TFreeBitmap.SetHorizontalResolution and TFreeBitmap.SetVerticalResolution
|
||||
+ [Anatoliy Pulyaevskiy] added TFreeBitmap.MakeThumbnail procedure ( an adapted version of function given by Enzo Costantini)
|
||||
+ [Enzo Costantini] added FIU_GetFIFType utility function
|
||||
+ [Enzo Costantini] added TFreeWinBitmap.CopyToBitmapH function
|
||||
* [Anatoliy Pulyaevskiy] fixed TFreeBitmap.Rotate (fix from FreeImage CVS)
|
||||
+ [Anatoliy Pulyaevskiy] added TFreeBitmap.ConvertToStandartType
|
||||
|
||||
December 20, 2004 - Version 1.2.0
|
||||
+ [Anatoliy Pulyaevskiy] added MultiBitmap Demo
|
||||
* [Anatoliy Pulyaevskiy] fixed TFreeMultiBitmap.LockPage due to error with Locking/Unlocking pages
|
||||
+ [Anatoliy Pulyaevskiy] added TFreeBitmap.ConvertTo4Bits
|
||||
* [Anatoliy Pulyaevskiy] TFreeBitmap.ConvertToGrayScale fixed converting bitmaps with FIC_MINISWHITE color type
|
||||
* [Anatoliy Pulyaevskiy] fixed TFreeWinBitmap.DrawEx FDisplayDib deleting
|
||||
+ [Anatoliy Pulyaevskiy] updated the wrapper for FreeImage 3.5.2
|
||||
|
||||
November 12, 2004 - Version 1.1.0
|
||||
+ [Anatoliy Pulyaevskiy] added TFreeBitmap.Assign(Source: PFIBITMAP)
|
||||
- [Anatoliy Pulyaevskiy] removed TFreeBitmap.SetDib
|
||||
! [Anatoliy Pulyaevskiy] TFreeBitmap.Dib property now read-only
|
||||
* [Anatoliy Pulyaevskiy] TFreeMultiBitmap.UnlockPage implemented
|
||||
* [Anatoliy Pulyaevskiy] fixed TFreeBitmap.Rescale not applies changes
|
||||
|
||||
November 8, 2004 - Version 1.0.0
|
||||
+ [Anatoliy Pulyaevskiy] added Delphi version of FreeImagePlus
|
||||
+ [Anatoliy Pulyaevskiy] updated the wrapper for FreeImage 3.5.0
|
||||
|
||||
January 7, 2004
|
||||
+ [Tommy] added TargaImage unit
|
||||
|
||||
October 28, 2003
|
||||
+ [Peter Bystr<74>m] updated the wrapper for FreeImage 3.0.2
|
||||
|
||||
August 9, 2003
|
||||
+ [Simon Beavis] added a wrapper for FreeImage 2.6.1
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
del /S *.~*
|
||||
del /S *.dcu
|
||||
del /S *.dsk
|
||||
del /S *.cfg
|
||||
del /S *.dof
|
||||
del /S *.obj
|
||||
del /S *.hpp
|
||||
del /S *.ddp
|
||||
del /S *.mps
|
||||
del /S *.mpt
|
||||
del /S *.bak
|
||||
del /S *.exe
|
||||
del /S *.stat
|
||||
@@ -1,13 +0,0 @@
|
||||
program ImagePreview;
|
||||
|
||||
uses
|
||||
Forms,
|
||||
MainFrm in 'MainFrm.pas' {MainForm};
|
||||
|
||||
{$R *.res}
|
||||
|
||||
begin
|
||||
Application.Initialize;
|
||||
Application.CreateForm(TMainForm, MainForm);
|
||||
Application.Run;
|
||||
end.
|
||||
Binary file not shown.
@@ -1,135 +0,0 @@
|
||||
object MainForm: TMainForm
|
||||
Left = 304
|
||||
Top = 165
|
||||
Width = 467
|
||||
Height = 405
|
||||
Caption = 'Image Preview'
|
||||
Color = clWhite
|
||||
Font.Charset = DEFAULT_CHARSET
|
||||
Font.Color = clWindowText
|
||||
Font.Height = -11
|
||||
Font.Name = 'MS Sans Serif'
|
||||
Font.Style = []
|
||||
KeyPreview = True
|
||||
OldCreateOrder = False
|
||||
Position = poDesktopCenter
|
||||
OnCreate = FormCreate
|
||||
OnDestroy = FormDestroy
|
||||
OnKeyUp = FormKeyUp
|
||||
OnMouseWheel = ScrollBoxMouseWheel
|
||||
OnShow = FormShow
|
||||
PixelsPerInch = 96
|
||||
TextHeight = 13
|
||||
object ImgView32: TImgView32
|
||||
Left = 0
|
||||
Top = 0
|
||||
Width = 459
|
||||
Height = 371
|
||||
Align = alClient
|
||||
ParentShowHint = False
|
||||
PopupMenu = PopupMenu
|
||||
Scale = 1
|
||||
ScrollBars.Color = clScrollBar
|
||||
ScrollBars.ShowHandleGrip = True
|
||||
ScrollBars.Style = rbsDefault
|
||||
ShowHint = True
|
||||
SizeGrip = sgAuto
|
||||
TabOrder = 0
|
||||
OnScroll = ImgView32Scroll
|
||||
object AlphaView: TImgView32
|
||||
Left = 8
|
||||
Top = 8
|
||||
Width = 161
|
||||
Height = 145
|
||||
Scale = 1
|
||||
ScrollBars.Color = clScrollBar
|
||||
ScrollBars.ShowHandleGrip = True
|
||||
ScrollBars.Style = rbsDefault
|
||||
SizeGrip = sgAuto
|
||||
TabOrder = 2
|
||||
Visible = False
|
||||
end
|
||||
end
|
||||
object PopupMenu: TPopupMenu
|
||||
Left = 304
|
||||
Top = 28
|
||||
object ZoomInItem: TMenuItem
|
||||
Caption = 'Zoom In'
|
||||
OnClick = ZoomInItemClick
|
||||
end
|
||||
object ZoomOutItem: TMenuItem
|
||||
Caption = 'Zoom Out'
|
||||
OnClick = ZoomOutItemClick
|
||||
end
|
||||
object ActualSizeItem: TMenuItem
|
||||
Caption = 'Actual Size'
|
||||
OnClick = ActualSizeItemClick
|
||||
end
|
||||
object N1: TMenuItem
|
||||
Caption = '-'
|
||||
end
|
||||
object RotateClockwiseItem: TMenuItem
|
||||
Caption = 'Rotate Clockwise'
|
||||
OnClick = RotateClockwiseItemClick
|
||||
end
|
||||
object RotateAntiClockwiseItem: TMenuItem
|
||||
Caption = 'Rotate Anti-Clockwise'
|
||||
OnClick = RotateAntiClockwiseItemClick
|
||||
end
|
||||
object N4: TMenuItem
|
||||
Caption = '-'
|
||||
end
|
||||
object FlipHorizontalItem: TMenuItem
|
||||
Caption = 'Flip Horizontal'
|
||||
OnClick = FlipHorizontalItemClick
|
||||
end
|
||||
object FilpVerticalItem: TMenuItem
|
||||
Caption = 'Filp Vertical'
|
||||
OnClick = FilpVerticalItemClick
|
||||
end
|
||||
object N3: TMenuItem
|
||||
Caption = '-'
|
||||
end
|
||||
object ShowAlphaItem: TMenuItem
|
||||
Caption = 'Show Just Alpha Channel'
|
||||
OnClick = ShowAlphaItemClick
|
||||
end
|
||||
object ShowWithAlphaItem: TMenuItem
|
||||
Caption = 'Show With Alpha Channel'
|
||||
OnClick = ShowWithAlphaItemClick
|
||||
end
|
||||
object N2: TMenuItem
|
||||
Caption = '-'
|
||||
end
|
||||
object OpenImageItem: TMenuItem
|
||||
Caption = 'Open New Image'
|
||||
OnClick = OpenImageItemClick
|
||||
end
|
||||
end
|
||||
object FilterTimer: TTimer
|
||||
Interval = 500
|
||||
OnTimer = FilterTimerTimer
|
||||
Left = 308
|
||||
Top = 84
|
||||
end
|
||||
object OpenDialog: TOpenDialog
|
||||
Filter =
|
||||
'All image files|*.bmp;*.cut;*.ico;*.iff;*.lbm;*.jng;*.jpg;*.jpeg' +
|
||||
';*.koa;*.mng;*.pbm;*.pcd;*.pcx;*.pgm;*.png;*.ppm;*.psd;*.ras;*.t' +
|
||||
'ga;*.tif;*.tiff;.wbmp;*.xbm;*.xpm)|Windows or OS/2 Bitmap File (' +
|
||||
'*.BMP)|*.BMP|Dr. Halo (*.CUT)|*.CUT|Windows Icon (*.ICO)|*.ICO|A' +
|
||||
'miga IFF (*.IFF, *.LBM)|*.IFF;*.LBM|JPEG Network Graphics (*.JNG' +
|
||||
')|*.JNG|Independent JPEG Group (*.JPG)|*.JPG|Commodore 64 Koala ' +
|
||||
'(*.KOA)|*.KOA|Multiple Network Graphics (*.MNG)|*.MNG|Portable B' +
|
||||
'itmap (*.PBM)|*.PBM|Kodak PhotoCD (*.PCD)|*.PCD|PCX bitmap forma' +
|
||||
't (*.PCX)|*.PCX|Portable Graymap (*.PGM)|*.PGM|Portable Network ' +
|
||||
'Graphics (*.PNG)|*.PNG|Portable Pixelmap (*.PPM)|*.PPM|Photoshop' +
|
||||
' (*.PSD)|*.PSD|Sun Rasterfile (*.RAS)|*.RAS|Targa files (*.TGA)|' +
|
||||
'*.TGA|Tagged Image File Format (*.TIF)|*.TIF;*.TIFF|Wireless Bit' +
|
||||
'map (*.WBMP)|*.WBMP|X11 Bitmap Format (*.XBM)|*.XBM|X11 Pixmap F' +
|
||||
'ormat (*.XPM)|*.XPM'
|
||||
Title = 'Open Image File'
|
||||
Left = 328
|
||||
Top = 228
|
||||
end
|
||||
end
|
||||
@@ -1,518 +0,0 @@
|
||||
unit MainFrm;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
|
||||
Dialogs, Menus, ExtCtrls, Math, GR32, GR32_Image, GR32_Transforms,
|
||||
ExtDlgs;
|
||||
|
||||
type
|
||||
TMainForm = class(TForm)
|
||||
PopupMenu: TPopupMenu;
|
||||
ZoomInItem: TMenuItem;
|
||||
ZoomOutItem: TMenuItem;
|
||||
ActualSizeItem: TMenuItem;
|
||||
ImgView32: TImgView32;
|
||||
N1: TMenuItem;
|
||||
AlphaView: TImgView32;
|
||||
ShowAlphaItem: TMenuItem;
|
||||
RotateClockwiseItem: TMenuItem;
|
||||
RotateAntiClockwiseItem: TMenuItem;
|
||||
N3: TMenuItem;
|
||||
ShowWithAlphaItem: TMenuItem;
|
||||
N4: TMenuItem;
|
||||
FlipHorizontalItem: TMenuItem;
|
||||
FilpVerticalItem: TMenuItem;
|
||||
FilterTimer: TTimer;
|
||||
OpenImageItem: TMenuItem;
|
||||
N2: TMenuItem;
|
||||
OpenDialog: TOpenDialog;
|
||||
procedure FormCreate(Sender: TObject);
|
||||
procedure FormDestroy(Sender: TObject);
|
||||
procedure FormShow(Sender: TObject);
|
||||
procedure ZoomInItemClick(Sender: TObject);
|
||||
procedure ZoomOutItemClick(Sender: TObject);
|
||||
procedure ActualSizeItemClick(Sender: TObject);
|
||||
procedure ScrollBoxMouseWheel(Sender: TObject; Shift: TShiftState;
|
||||
WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
|
||||
procedure FormKeyUp(Sender: TObject; var Key: Word;
|
||||
Shift: TShiftState);
|
||||
procedure ShowAlphaItemClick(Sender: TObject);
|
||||
procedure RotateClockwiseItemClick(Sender: TObject);
|
||||
procedure RotateAntiClockwiseItemClick(Sender: TObject);
|
||||
procedure ShowWithAlphaItemClick(Sender: TObject);
|
||||
procedure FlipHorizontalItemClick(Sender: TObject);
|
||||
procedure FilpVerticalItemClick(Sender: TObject);
|
||||
procedure FilterTimerTimer(Sender: TObject);
|
||||
procedure ImgView32Scroll(Sender: TObject);
|
||||
procedure OpenImageItemClick(Sender: TObject);
|
||||
private
|
||||
{ Private declarations }
|
||||
OrigWidth : integer;
|
||||
OrigHeight : integer;
|
||||
BPP : longword;
|
||||
|
||||
procedure LoadImage( Name : string);
|
||||
procedure RecalcWindowSize;
|
||||
public
|
||||
{ Public declarations }
|
||||
end;
|
||||
|
||||
var
|
||||
MainForm: TMainForm;
|
||||
|
||||
implementation
|
||||
|
||||
{$R *.dfm}
|
||||
|
||||
uses FreeImage;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
procedure TMainForm.FormCreate(Sender: TObject);
|
||||
begin
|
||||
AlphaView.Visible := False;
|
||||
AlphaView.Align := alClient;
|
||||
end;
|
||||
// -----------------------------------------------------------------------------
|
||||
procedure TMainForm.FormDestroy(Sender: TObject);
|
||||
begin
|
||||
// ...
|
||||
end;
|
||||
// -----------------------------------------------------------------------------
|
||||
procedure TMainForm.FormShow(Sender: TObject);
|
||||
begin
|
||||
ImgView32.Bitmap.StretchFilter := sfSPline;
|
||||
if ParamCount = 1 then
|
||||
LoadImage(ParamStr(1));
|
||||
end;
|
||||
// -----------------------------------------------------------------------------
|
||||
procedure TMainForm.LoadImage( Name : string);
|
||||
var
|
||||
dib : PFIBITMAP;
|
||||
PBH : PBITMAPINFOHEADER;
|
||||
PBI : PBITMAPINFO;
|
||||
t : FREE_IMAGE_FORMAT;
|
||||
Ext : string;
|
||||
BM : TBitmap;
|
||||
x, y : integer;
|
||||
BP : PLONGWORD;
|
||||
DC : HDC;
|
||||
begin
|
||||
try
|
||||
t := FreeImage_GetFileType(PChar(Name), 16);
|
||||
|
||||
if t = FIF_UNKNOWN then
|
||||
begin
|
||||
// Check for types not supported by GetFileType
|
||||
Ext := UpperCase(ExtractFileExt(Name));
|
||||
if (Ext = '.TGA') or(Ext = '.TARGA') then
|
||||
t := FIF_TARGA
|
||||
else if Ext = '.MNG' then
|
||||
t := FIF_MNG
|
||||
else if Ext = '.PCD' then
|
||||
t := FIF_PCD
|
||||
else if Ext = '.WBMP' then
|
||||
t := FIF_WBMP
|
||||
else if Ext = '.CUT' then
|
||||
t := FIF_CUT
|
||||
else
|
||||
raise Exception.Create('The file "' + Name + '" cannot be displayed because SFM does not recognise the file type.');
|
||||
end;
|
||||
|
||||
dib := FreeImage_Load(t, PChar(name), 0);
|
||||
if Dib = nil then
|
||||
Close;
|
||||
PBH := FreeImage_GetInfoHeader(dib);
|
||||
PBI := FreeImage_GetInfo(dib^);
|
||||
|
||||
BPP := FreeImage_GetBPP(dib);
|
||||
|
||||
ShowWithAlphaItem.Enabled := BPP = 32;
|
||||
ShowAlphaItem.Enabled := BPP = 32;
|
||||
|
||||
if BPP = 32 then
|
||||
begin
|
||||
ImgView32.Bitmap.SetSize(FreeImage_GetWidth(dib), FreeImage_GetHeight(dib));
|
||||
|
||||
BP := PLONGWORD(FreeImage_GetBits(dib));
|
||||
for y := ImgView32.Bitmap.Height - 1 downto 0 do
|
||||
for x := 0 to ImgView32.Bitmap.Width - 1 do
|
||||
begin
|
||||
ImgView32.Bitmap.Pixel[x, y] := BP^;
|
||||
inc(BP);
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
BM := TBitmap.Create;
|
||||
|
||||
BM.Assign(nil);
|
||||
DC := GetDC(Handle);
|
||||
|
||||
BM.handle := CreateDIBitmap(DC,
|
||||
PBH^,
|
||||
CBM_INIT,
|
||||
PChar(FreeImage_GetBits(dib)),
|
||||
PBI^,
|
||||
DIB_RGB_COLORS);
|
||||
|
||||
ImgView32.Bitmap.Assign(BM);
|
||||
AlphaView.Bitmap.Assign(BM);
|
||||
|
||||
BM.Free;
|
||||
ReleaseDC(Handle, DC);
|
||||
end;
|
||||
FreeImage_Unload(dib);
|
||||
|
||||
OrigWidth := ImgView32.Bitmap.Width;
|
||||
OrigHeight := ImgView32.Bitmap.Height;
|
||||
|
||||
Caption := ExtractFileName( Name ) + ' (' + IntToStr(OrigWidth) +
|
||||
' x ' + IntToStr(OrigHeight) + ')';
|
||||
if BPP = 32 then
|
||||
Caption := Caption + ' + Alpha';
|
||||
|
||||
AlphaView.Bitmap.SetSize(OrigWidth, OrigWidth);
|
||||
|
||||
ImgView32.Hint := 'Name: ' + Name + #13 +
|
||||
'Width: ' + IntToStr(OrigWidth) + #13 +
|
||||
'Height: ' + IntToStr(OrigHeight) + #13 +
|
||||
'BPP: ' + IntToStr(BPP);
|
||||
|
||||
RecalcWindowSize;
|
||||
|
||||
Show;
|
||||
except
|
||||
on e:exception do
|
||||
begin
|
||||
Application.BringToFront;
|
||||
MessageDlg(e.message, mtInformation, [mbOK], 0);
|
||||
Close;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
// -----------------------------------------------------------------------------
|
||||
procedure TMainForm.ZoomInItemClick(Sender: TObject);
|
||||
begin
|
||||
FilterTimer.Enabled := False;
|
||||
if ImgView32.Bitmap.StretchFilter <> sfNearest then
|
||||
ImgView32.Bitmap.StretchFilter := sfNearest;
|
||||
FilterTimer.Enabled := True;
|
||||
|
||||
ImgView32.Scale := ImgView32.Scale * 2.0;
|
||||
RecalcWindowSize;
|
||||
end;
|
||||
// -----------------------------------------------------------------------------
|
||||
procedure TMainForm.ZoomOutItemClick(Sender: TObject);
|
||||
begin
|
||||
FilterTimer.Enabled := False;
|
||||
if ImgView32.Bitmap.StretchFilter <> sfNearest then
|
||||
ImgView32.Bitmap.StretchFilter := sfNearest;
|
||||
FilterTimer.Enabled := True;
|
||||
|
||||
ImgView32.Scale := ImgView32.Scale / 2.0;
|
||||
RecalcWindowSize;
|
||||
end;
|
||||
// -----------------------------------------------------------------------------
|
||||
procedure TMainForm.ActualSizeItemClick(Sender: TObject);
|
||||
begin
|
||||
FilterTimer.Enabled := False;
|
||||
if ImgView32.Bitmap.StretchFilter <> sfNearest then
|
||||
ImgView32.Bitmap.StretchFilter := sfNearest;
|
||||
FilterTimer.Enabled := True;
|
||||
|
||||
ImgView32.Scale := 1.0;
|
||||
|
||||
RecalcWindowSize;
|
||||
end;
|
||||
// -----------------------------------------------------------------------------
|
||||
procedure TMainForm.RecalcWindowSize;
|
||||
var
|
||||
Rect : TRect;
|
||||
CW, CH : integer;
|
||||
WSH, WSW : integer;
|
||||
TitleH : integer;
|
||||
BorderY : integer;
|
||||
BorderX : integer;
|
||||
begin
|
||||
CW := ImgView32.Bitmap.Width + GetSystemMetrics(SM_CXVSCROLL);
|
||||
CH := ImgView32.Bitmap.Height + GetSystemMetrics(SM_CYVSCROLL);
|
||||
|
||||
SystemParametersInfo( SPI_GETWORKAREA, 0, @Rect, 0);
|
||||
|
||||
WSH := Rect.Bottom - Rect.Top;
|
||||
WSW := Rect.Right - Rect.Left;
|
||||
TitleH := GetSystemMetrics(SM_CYCAPTION);
|
||||
BorderY := GetSystemMetrics(SM_CYSIZEFRAME) * 2;
|
||||
BorderX := GetSystemMetrics(SM_CXSIZEFRAME) * 2;
|
||||
|
||||
if (Top + CH + TitleH + BorderY > WSH) or (CH + TitleH + BorderY > WSH) then
|
||||
begin
|
||||
Top := Rect.Bottom - CH - BorderY;
|
||||
if Top < 0 then
|
||||
begin
|
||||
Top := 0;
|
||||
CH := WSH - TitleH - BorderY;
|
||||
CW := CW + GetSystemMetrics(SM_CXVSCROLL);
|
||||
|
||||
if CW + BorderX > WSW then
|
||||
CH := CH - GetSystemMetrics(SM_CYVSCROLL);
|
||||
end;
|
||||
end;
|
||||
|
||||
if (Left + CW + BorderX > WSW) or (CW + BorderX > WSW) then
|
||||
begin
|
||||
Left := Rect.Right - CW - BorderX;
|
||||
if Left < 0 then
|
||||
begin
|
||||
Left := 0;
|
||||
CW := WSW - BorderX;
|
||||
CH := CH + GetSystemMetrics(SM_CYVSCROLL);
|
||||
|
||||
if CH + TitleH + BorderY > WSH then
|
||||
CW := CW + GetSystemMetrics(SM_CXVSCROLL);
|
||||
end
|
||||
end;
|
||||
|
||||
ClientWidth := CW;
|
||||
ClientHeight := CH;
|
||||
end;
|
||||
// -----------------------------------------------------------------------------
|
||||
procedure TMainForm.ScrollBoxMouseWheel(Sender: TObject;
|
||||
Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint;
|
||||
var Handled: Boolean);
|
||||
begin
|
||||
FilterTimer.Enabled := False;
|
||||
if ImgView32.Bitmap.StretchFilter <> sfNearest then
|
||||
ImgView32.Bitmap.StretchFilter := sfNearest;
|
||||
FilterTimer.Enabled := True;
|
||||
|
||||
if WheelDelta < 0 then
|
||||
ImgView32.Scroll(0, 20)
|
||||
else
|
||||
ImgView32.Scroll(0, -20);
|
||||
Handled := True;
|
||||
end;
|
||||
// -----------------------------------------------------------------------------
|
||||
procedure TMainForm.FormKeyUp(Sender: TObject; var Key: Word;
|
||||
Shift: TShiftState);
|
||||
var
|
||||
Amount : integer;
|
||||
begin
|
||||
FilterTimer.Enabled := False;
|
||||
if ImgView32.Bitmap.StretchFilter <> sfNearest then
|
||||
ImgView32.Bitmap.StretchFilter := sfNearest;
|
||||
FilterTimer.Enabled := True;
|
||||
|
||||
if ssShift in Shift then
|
||||
Amount := 20 * 2
|
||||
else
|
||||
Amount := 20;
|
||||
|
||||
case Key of
|
||||
VK_ESCAPE:
|
||||
Close;
|
||||
VK_UP:
|
||||
ImgView32.Scroll(0, -Amount);
|
||||
VK_DOWN:
|
||||
ImgView32.Scroll(0, Amount);
|
||||
VK_LEFT:
|
||||
ImgView32.Scroll(-Amount, 0);
|
||||
VK_RIGHT:
|
||||
ImgView32.Scroll(Amount, 0);
|
||||
VK_HOME:
|
||||
ImgView32.ScrollToCenter(0, 0);
|
||||
VK_END:
|
||||
ImgView32.ScrollToCenter(ImgView32.Bitmap.Width, ImgView32.Bitmap.Height);
|
||||
VK_NEXT:
|
||||
ImgView32.Scroll(0, (Trunc(ImgView32.Bitmap.Height div 4)));
|
||||
VK_PRIOR:
|
||||
ImgView32.Scroll(0, -(Trunc(ImgView32.Bitmap.Height div 4)));
|
||||
end;
|
||||
end;
|
||||
// -----------------------------------------------------------------------------
|
||||
procedure TMainForm.ShowAlphaItemClick(Sender: TObject);
|
||||
var
|
||||
x, y : integer;
|
||||
Col : TColor32;
|
||||
Alpha : TColor;
|
||||
begin
|
||||
if ShowAlphaItem.Checked then
|
||||
begin
|
||||
AlphaView.Visible := False;
|
||||
AlphaView.Bitmap.Delete;
|
||||
end
|
||||
else
|
||||
begin
|
||||
AlphaView.Bitmap.Width := ImgView32.Bitmap.Width;
|
||||
AlphaView.Bitmap.Height := ImgView32.Bitmap.Height;
|
||||
|
||||
for x := 0 to AlphaView.Bitmap.Width - 1 do
|
||||
for y := 0 to AlphaView.Bitmap.Height - 1 do
|
||||
begin
|
||||
Col := ImgView32.Bitmap.Pixel[x, y];
|
||||
Alpha := Col shr 24;
|
||||
AlphaView.Bitmap.Pixel[x, y] := Alpha + (Alpha shl 8) + (Alpha shl 16);
|
||||
end;
|
||||
AlphaView.Visible := True;
|
||||
end;
|
||||
ShowAlphaItem.Checked := not ShowAlphaItem.Checked;
|
||||
end;
|
||||
// -----------------------------------------------------------------------------
|
||||
procedure TMainForm.RotateClockwiseItemClick(Sender: TObject);
|
||||
var
|
||||
x : integer;
|
||||
y : integer;
|
||||
DestX : integer;
|
||||
DestY : integer;
|
||||
C : TColor32;
|
||||
begin
|
||||
AlphaView.Bitmap.Assign(ImgView32.Bitmap);
|
||||
|
||||
ImgView32.BeginUpdate;
|
||||
ImgView32.Bitmap.Width := AlphaView.Bitmap.Height;
|
||||
ImgView32.Bitmap.Height := AlphaView.Bitmap.Width;
|
||||
|
||||
for x := 0 to AlphaView.Bitmap.Width - 1 do
|
||||
for y := 0 to AlphaView.Bitmap.Height - 1 do
|
||||
begin
|
||||
C := AlphaView.Bitmap.Pixel[x, y];
|
||||
|
||||
DestX := (ImgView32.Bitmap.Width - 1) - Y;
|
||||
DestY := X;
|
||||
|
||||
ImgView32.Bitmap.Pixels[DestX, DestY] := C;
|
||||
end;
|
||||
|
||||
ImgView32.EndUpdate;
|
||||
ImgView32.Refresh;
|
||||
end;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
procedure TMainForm.RotateAntiClockwiseItemClick(Sender: TObject);
|
||||
var
|
||||
x : integer;
|
||||
y : integer;
|
||||
DestX : integer;
|
||||
DestY : integer;
|
||||
C : TColor32;
|
||||
begin
|
||||
AlphaView.Bitmap.Assign(ImgView32.Bitmap);
|
||||
|
||||
ImgView32.BeginUpdate;
|
||||
ImgView32.Bitmap.Width := AlphaView.Bitmap.Height;
|
||||
ImgView32.Bitmap.Height := AlphaView.Bitmap.Width;
|
||||
|
||||
for x := 0 to AlphaView.Bitmap.Width - 1 do
|
||||
for y := 0 to AlphaView.Bitmap.Height - 1 do
|
||||
begin
|
||||
C := AlphaView.Bitmap.Pixel[x, y];
|
||||
|
||||
DestX := Y;
|
||||
DestY := (ImgView32.Bitmap.Height - 1) -X;
|
||||
|
||||
ImgView32.Bitmap.Pixels[DestX, DestY] := C;
|
||||
end;
|
||||
|
||||
ImgView32.EndUpdate;
|
||||
ImgView32.Refresh;
|
||||
end;
|
||||
// -----------------------------------------------------------------------------
|
||||
procedure TMainForm.ShowWithAlphaItemClick(Sender: TObject);
|
||||
begin
|
||||
if ShowWithAlphaItem.Checked then
|
||||
ImgView32.Bitmap.DrawMode := dmOpaque
|
||||
else
|
||||
ImgView32.Bitmap.DrawMode := dmBlend;
|
||||
ShowWithAlphaItem.Checked := not ShowWithAlphaItem.Checked;
|
||||
end;
|
||||
// -----------------------------------------------------------------------------
|
||||
procedure TMainForm.FlipHorizontalItemClick(Sender: TObject);
|
||||
var
|
||||
x : integer;
|
||||
y : integer;
|
||||
DestX : integer;
|
||||
DestY : integer;
|
||||
C : TColor32;
|
||||
begin
|
||||
AlphaView.Bitmap.Assign(ImgView32.Bitmap);
|
||||
|
||||
ImgView32.BeginUpdate;
|
||||
ImgView32.Bitmap.Width := AlphaView.Bitmap.Width;
|
||||
ImgView32.Bitmap.Height := AlphaView.Bitmap.Height;
|
||||
|
||||
for x := 0 to AlphaView.Bitmap.Width - 1 do
|
||||
for y := 0 to AlphaView.Bitmap.Height - 1 do
|
||||
begin
|
||||
C := AlphaView.Bitmap.Pixel[x, y];
|
||||
|
||||
DestX := (ImgView32.Bitmap.Width - 1) -X;
|
||||
DestY := Y;
|
||||
|
||||
ImgView32.Bitmap.Pixels[DestX, DestY] := C;
|
||||
end;
|
||||
|
||||
ImgView32.EndUpdate;
|
||||
ImgView32.Refresh;
|
||||
end;
|
||||
// -----------------------------------------------------------------------------
|
||||
procedure TMainForm.FilpVerticalItemClick(Sender: TObject);
|
||||
var
|
||||
x : integer;
|
||||
y : integer;
|
||||
DestX : integer;
|
||||
DestY : integer;
|
||||
C : TColor32;
|
||||
begin
|
||||
AlphaView.Bitmap.Assign(ImgView32.Bitmap);
|
||||
|
||||
ImgView32.BeginUpdate;
|
||||
ImgView32.Bitmap.Width := AlphaView.Bitmap.Width;
|
||||
ImgView32.Bitmap.Height := AlphaView.Bitmap.Height;
|
||||
|
||||
for x := 0 to AlphaView.Bitmap.Width - 1 do
|
||||
for y := 0 to AlphaView.Bitmap.Height - 1 do
|
||||
begin
|
||||
C := AlphaView.Bitmap.Pixel[x, y];
|
||||
|
||||
DestX := X;
|
||||
DestY := (ImgView32.Bitmap.Height - 1) - Y;
|
||||
|
||||
ImgView32.Bitmap.Pixels[DestX, DestY] := C;
|
||||
end;
|
||||
|
||||
ImgView32.EndUpdate;
|
||||
ImgView32.Refresh;
|
||||
end;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
procedure TMainForm.FilterTimerTimer(Sender: TObject);
|
||||
begin
|
||||
FilterTimer.Enabled := False;
|
||||
ImgView32.Bitmap.StretchFilter := sfSPline;
|
||||
end;
|
||||
// -----------------------------------------------------------------------------
|
||||
procedure TMainForm.ImgView32Scroll(Sender: TObject);
|
||||
begin
|
||||
FilterTimer.Enabled := False;
|
||||
if ImgView32.Bitmap.StretchFilter <> sfNearest then
|
||||
ImgView32.Bitmap.StretchFilter := sfNearest;
|
||||
FilterTimer.Enabled := True;
|
||||
end;
|
||||
// -----------------------------------------------------------------------------
|
||||
procedure TMainForm.OpenImageItemClick(Sender: TObject);
|
||||
begin
|
||||
if OpenDialog.Execute then
|
||||
begin
|
||||
try
|
||||
Screen.Cursor := crHourGlass;
|
||||
LoadImage(OpenDialog.FileName);
|
||||
finally
|
||||
Screen.Cursor := crDefault;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
@@ -1,8 +0,0 @@
|
||||
This is a simple image viewing application that uses the FreeImage library to display images in many different formats.
|
||||
|
||||
The app displays the image whose name is passed in as a command line argument.
|
||||
|
||||
|
||||
To compile the app you will also need the Graphics32 library available from www.g32.org. It has been tested with version 1.5.1 of Graphics32.
|
||||
|
||||
SJB.
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 63 KiB |
@@ -1,13 +0,0 @@
|
||||
program MultiBitmap;
|
||||
|
||||
uses
|
||||
Forms,
|
||||
mbMainForm in 'mbMainForm.pas' {MainForm};
|
||||
|
||||
{$R *.res}
|
||||
|
||||
begin
|
||||
Application.Initialize;
|
||||
Application.CreateForm(TMainForm, MainForm);
|
||||
Application.Run;
|
||||
end.
|
||||
Binary file not shown.
@@ -1,10 +0,0 @@
|
||||
[Stats]
|
||||
EditorSecs=82
|
||||
DesignerSecs=5
|
||||
InspectorSecs=1
|
||||
CompileSecs=850
|
||||
OtherSecs=5
|
||||
StartTime=20.12.2004 11:40:22
|
||||
RealKeys=0
|
||||
EffectiveKeys=0
|
||||
DebugSecs=19
|
||||
@@ -1,89 +0,0 @@
|
||||
object MainForm: TMainForm
|
||||
Left = 203
|
||||
Top = 192
|
||||
Width = 696
|
||||
Height = 480
|
||||
Caption = 'MultiBitmap Demo'
|
||||
Color = clBtnFace
|
||||
Font.Charset = DEFAULT_CHARSET
|
||||
Font.Color = clWindowText
|
||||
Font.Height = -11
|
||||
Font.Name = 'MS Shell Dlg 2'
|
||||
Font.Style = []
|
||||
OldCreateOrder = False
|
||||
OnPaint = FormPaint
|
||||
OnResize = FormResize
|
||||
PixelsPerInch = 96
|
||||
TextHeight = 13
|
||||
object ToolBar: TToolBar
|
||||
Left = 0
|
||||
Top = 0
|
||||
Width = 688
|
||||
Height = 25
|
||||
AutoSize = True
|
||||
ButtonHeight = 21
|
||||
ButtonWidth = 33
|
||||
Caption = 'ToolBar'
|
||||
EdgeBorders = [ebLeft, ebTop, ebRight, ebBottom]
|
||||
Flat = True
|
||||
Indent = 3
|
||||
ShowCaptions = True
|
||||
TabOrder = 0
|
||||
object tbLoad: TToolButton
|
||||
Left = 3
|
||||
Top = 0
|
||||
Caption = 'Load'
|
||||
ImageIndex = 0
|
||||
OnClick = tbLoadClick
|
||||
end
|
||||
object ToolButton1: TToolButton
|
||||
Left = 36
|
||||
Top = 0
|
||||
Width = 8
|
||||
Caption = 'ToolButton1'
|
||||
ImageIndex = 1
|
||||
Style = tbsSeparator
|
||||
end
|
||||
object tbClose: TToolButton
|
||||
Left = 44
|
||||
Top = 0
|
||||
Caption = 'Close'
|
||||
ImageIndex = 1
|
||||
OnClick = tbCloseClick
|
||||
end
|
||||
object ToolButton2: TToolButton
|
||||
Left = 77
|
||||
Top = 0
|
||||
Width = 8
|
||||
Caption = 'ToolButton2'
|
||||
ImageIndex = 2
|
||||
Style = tbsSeparator
|
||||
end
|
||||
object Label1: TLabel
|
||||
Left = 85
|
||||
Top = 0
|
||||
Width = 36
|
||||
Height = 21
|
||||
Caption = 'Pages: '
|
||||
Layout = tlCenter
|
||||
end
|
||||
object cbPages: TComboBox
|
||||
Left = 121
|
||||
Top = 0
|
||||
Width = 60
|
||||
Height = 21
|
||||
Style = csDropDownList
|
||||
DropDownCount = 15
|
||||
ItemHeight = 13
|
||||
TabOrder = 0
|
||||
OnChange = cbPagesChange
|
||||
end
|
||||
end
|
||||
object OD: TOpenDialog
|
||||
Filter = 'TIFF multibitmap (*.tiff, *.tif)|*.tiff; *.tif|ICO|*.ico'
|
||||
Options = [ofHideReadOnly, ofPathMustExist, ofFileMustExist, ofEnableSizing]
|
||||
Title = 'Open multibitmap..'
|
||||
Left = 64
|
||||
Top = 96
|
||||
end
|
||||
end
|
||||
@@ -1,150 +0,0 @@
|
||||
unit mbMainForm;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
|
||||
Dialogs, ComCtrls, ToolWin, StdCtrls, FreeBitmap;
|
||||
|
||||
type
|
||||
TMainForm = class(TForm)
|
||||
ToolBar: TToolBar;
|
||||
tbLoad: TToolButton;
|
||||
ToolButton1: TToolButton;
|
||||
tbClose: TToolButton;
|
||||
ToolButton2: TToolButton;
|
||||
cbPages: TComboBox;
|
||||
Label1: TLabel;
|
||||
OD: TOpenDialog;
|
||||
procedure tbLoadClick(Sender: TObject);
|
||||
procedure FormPaint(Sender: TObject);
|
||||
procedure tbCloseClick(Sender: TObject);
|
||||
procedure cbPagesChange(Sender: TObject);
|
||||
procedure FormResize(Sender: TObject);
|
||||
private
|
||||
FMultiBitmap: TFreeMultiBitmap;
|
||||
FPage: TFreeWinBitmap;
|
||||
|
||||
procedure PageBitmapChangeHandler(Sender: TObject);
|
||||
procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
|
||||
public
|
||||
constructor Create(AOwner: TComponent); override;
|
||||
destructor Destroy; override;
|
||||
|
||||
procedure OpenMultiBitmap(const FileName: string);
|
||||
procedure CloseMultiBitmap;
|
||||
procedure OpenPage(Number: Integer);
|
||||
end;
|
||||
|
||||
var
|
||||
MainForm: TMainForm;
|
||||
|
||||
implementation
|
||||
|
||||
{$R *.dfm}
|
||||
|
||||
{ TMainForm }
|
||||
|
||||
procedure TMainForm.CloseMultiBitmap;
|
||||
begin
|
||||
if FPage.IsValid then
|
||||
FMultiBitmap.UnlockPage(Fpage, False);
|
||||
FMultiBitmap.Close;
|
||||
cbPages.Clear;
|
||||
end;
|
||||
|
||||
constructor TMainForm.Create(AOwner: TComponent);
|
||||
begin
|
||||
inherited;
|
||||
FMultiBitmap := TFreeMultiBitmap.Create;
|
||||
FPage := TFreeWinBitmap.Create;
|
||||
FPage.OnChange := PageBitmapChangeHandler;
|
||||
end;
|
||||
|
||||
destructor TMainForm.Destroy;
|
||||
begin
|
||||
if FMultiBitmap.IsValid then
|
||||
CloseMultiBitmap;
|
||||
FMultiBitmap.Free;
|
||||
inherited;
|
||||
end;
|
||||
|
||||
procedure TMainForm.OpenMultiBitmap(const FileName: string);
|
||||
var
|
||||
I, Cnt: Integer;
|
||||
begin
|
||||
if FMultiBitmap.IsValid then CloseMultiBitmap;
|
||||
|
||||
FMultiBitmap.Open(FileName, False, True);
|
||||
|
||||
Cnt := FMultiBitmap.GetPageCount;
|
||||
cbPages.OnChange := nil;
|
||||
cbPages.Clear;
|
||||
for I := 0 to Cnt - 1 do
|
||||
cbPages.Items.Add(IntToStr(I));
|
||||
cbPages.OnChange := cbPagesChange;
|
||||
end;
|
||||
|
||||
procedure TMainForm.OpenPage(Number: Integer);
|
||||
begin
|
||||
if not FMultiBitmap.IsValid then Exit;
|
||||
|
||||
if FPage.IsValid then
|
||||
FMultiBitmap.UnlockPage(FPage, False);
|
||||
|
||||
FMultiBitmap.LockPage(Number, FPage);
|
||||
end;
|
||||
|
||||
procedure TMainForm.PageBitmapChangeHandler(Sender: TObject);
|
||||
begin
|
||||
Invalidate;
|
||||
end;
|
||||
|
||||
procedure TMainForm.tbLoadClick(Sender: TObject);
|
||||
begin
|
||||
if OD.Execute then
|
||||
begin
|
||||
try
|
||||
OpenMultiBitmap(OD.FileName);
|
||||
except
|
||||
raise Exception.CreateFmt('Can not load file %s', [OD.FileName]);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainForm.WMEraseBkgnd(var Message: TWMEraseBkgnd);
|
||||
begin
|
||||
Message.Result := 1;
|
||||
end;
|
||||
|
||||
procedure TMainForm.FormPaint(Sender: TObject);
|
||||
begin
|
||||
if not FPage.IsValid then
|
||||
begin
|
||||
Canvas.Brush.Color := clBtnFace;
|
||||
Canvas.FillRect(ClientRect);
|
||||
end
|
||||
else
|
||||
FPage.Draw(Canvas.Handle, ClientRect);
|
||||
end;
|
||||
|
||||
procedure TMainForm.tbCloseClick(Sender: TObject);
|
||||
begin
|
||||
if FMultiBitmap.IsValid then
|
||||
CloseMultiBitmap;
|
||||
end;
|
||||
|
||||
procedure TMainForm.cbPagesChange(Sender: TObject);
|
||||
var
|
||||
Page: Integer;
|
||||
begin
|
||||
Page := StrToInt(cbPages.Text);
|
||||
OpenPage(Page);
|
||||
end;
|
||||
|
||||
procedure TMainForm.FormResize(Sender: TObject);
|
||||
begin
|
||||
Invalidate;
|
||||
end;
|
||||
|
||||
end.
|
||||
@@ -1,22 +0,0 @@
|
||||
TargaImage.pas is a TGraphic descendant for Delphi. Installing it
|
||||
will allow Delphi TImage and TDBImage components to read Targa files
|
||||
just like BMP & WMF files with no coding on your part.
|
||||
|
||||
It also adds the TGA file type to the Delphi Open/Save Picture dialog
|
||||
boxes.
|
||||
|
||||
To install this unit, place it in your one of your library folders
|
||||
and make it available to all your Delphi projects by using
|
||||
Component>Install Component from the Delphi menus.
|
||||
|
||||
NOTE: any Delphi applications using this *must* have FreeImage.dll
|
||||
installed in your application's folder, or somewhere in the path.
|
||||
|
||||
-----------------------
|
||||
|
||||
Tommy
|
||||
Edinburgh, Scotland
|
||||
LeTene@battlefieldeurope.org
|
||||
|
||||
|
||||
|
||||
@@ -1,212 +0,0 @@
|
||||
unit TargaImage;
|
||||
|
||||
// ==========================================================
|
||||
//
|
||||
// This file is part of FreeImage 3
|
||||
//
|
||||
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
|
||||
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
|
||||
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
|
||||
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
|
||||
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
|
||||
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
|
||||
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
|
||||
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
|
||||
// THIS DISCLAIMER.
|
||||
//
|
||||
// Use at your own risk!
|
||||
//
|
||||
// ==========================================================
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Windows,
|
||||
Classes,
|
||||
FreeImage,
|
||||
Graphics,
|
||||
Types;
|
||||
|
||||
type
|
||||
TTargaImage = class(TGraphic)
|
||||
private
|
||||
fImage: PFIBITMAP;
|
||||
fWidth: Integer;
|
||||
fHeight: Integer;
|
||||
protected
|
||||
procedure Draw(ACanvas: TCanvas; const ARect: TRect); override;
|
||||
function GetEmpty: Boolean; override;
|
||||
function GetHeight: Integer; override;
|
||||
function GetWidth: Integer; override;
|
||||
procedure SetHeight(Value: Integer); override;
|
||||
procedure SetWidth(Value: Integer); override;
|
||||
public
|
||||
constructor Create; override;
|
||||
destructor Destroy; override;
|
||||
procedure Assign(Source: TPersistent); override;
|
||||
procedure LoadFromClipboardFormat(AFormat: Word; AData: THandle; APalette: HPALETTE); override;
|
||||
procedure LoadFromStream(Stream: TStream); override;
|
||||
procedure SaveToClipboardFormat(var AFormat: Word; var AData: THandle; var APalette: HPALETTE); override;
|
||||
procedure SaveToStream(Stream: TStream); override;
|
||||
end;
|
||||
|
||||
procedure Register;
|
||||
|
||||
implementation
|
||||
|
||||
{ Design-time registration }
|
||||
|
||||
procedure Register;
|
||||
begin
|
||||
TPicture.RegisterFileFormat('tga', 'TARGA Files', TTargaImage);
|
||||
end;
|
||||
|
||||
{ IO functions }
|
||||
|
||||
function FI_ReadProc(buffer : pointer; size : Cardinal; count : Cardinal; handle : fi_handle) : UInt; stdcall;
|
||||
var
|
||||
stream: TStream;
|
||||
bytesToRead: Cardinal;
|
||||
begin
|
||||
stream := TStream(handle);
|
||||
bytesToRead := size*count;
|
||||
Result := stream.Read(buffer^, bytesToRead);
|
||||
end;
|
||||
|
||||
function FI_WriteProc(buffer : pointer; size, count : Cardinal; handle : fi_handle) : UInt; stdcall;
|
||||
var
|
||||
stream: TStream;
|
||||
bytesToWrite: Cardinal;
|
||||
begin
|
||||
stream := TStream(handle);
|
||||
bytesToWrite := size*count;
|
||||
Result := stream.Write(buffer^, bytesToWrite);
|
||||
end;
|
||||
|
||||
function FI_SeekProc(handle : fi_handle; offset : longint; origin : integer) : Integer; stdcall;
|
||||
begin
|
||||
TStream(handle).Seek(offset, origin);
|
||||
Result := 0;
|
||||
end;
|
||||
|
||||
function FI_TellProc(handle : fi_handle) : LongInt; stdcall;
|
||||
begin
|
||||
Result := TStream(handle).Position;
|
||||
end;
|
||||
|
||||
{ TTargaImage }
|
||||
|
||||
constructor TTargaImage.Create;
|
||||
begin
|
||||
fImage := nil;
|
||||
fWidth := 0;
|
||||
fHeight := 0;
|
||||
inherited;
|
||||
end;
|
||||
|
||||
destructor TTargaImage.Destroy;
|
||||
begin
|
||||
if Assigned(fImage) then
|
||||
FreeImage_Unload(fImage);
|
||||
inherited;
|
||||
end;
|
||||
|
||||
procedure TTargaImage.Assign(Source: TPersistent);
|
||||
begin
|
||||
if Source is TTargaImage then begin
|
||||
fImage := FreeImage_Clone(TTargaImage(Source).fImage);
|
||||
fWidth := FreeImage_GetWidth(fImage);
|
||||
fHeight := FreeImage_GetHeight(fImage);
|
||||
Changed(Self);
|
||||
end else
|
||||
inherited;
|
||||
end;
|
||||
|
||||
procedure TTargaImage.Draw(ACanvas: TCanvas; const ARect: TRect);
|
||||
var
|
||||
pbi: PBitmapInfo;
|
||||
begin
|
||||
if Assigned(fImage) then begin
|
||||
pbi := FreeImage_GetInfo(fImage);
|
||||
SetStretchBltMode(ACanvas.Handle, COLORONCOLOR);
|
||||
StretchDIBits(ACanvas.Handle, ARect.left, ARect.top,
|
||||
ARect.right-ARect.left, ARect.bottom-ARect.top,
|
||||
0, 0, fWidth, fHeight,
|
||||
FreeImage_GetBits(fImage), pbi^, DIB_RGB_COLORS, SRCCOPY);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TTargaImage.GetEmpty: Boolean;
|
||||
begin
|
||||
Result := Assigned(fImage);
|
||||
end;
|
||||
|
||||
function TTargaImage.GetHeight: Integer;
|
||||
begin
|
||||
Result := fHeight;
|
||||
end;
|
||||
|
||||
function TTargaImage.GetWidth: Integer;
|
||||
begin
|
||||
Result := fWidth;
|
||||
end;
|
||||
|
||||
procedure TTargaImage.LoadFromClipboardFormat(AFormat: Word; AData: THandle; APalette: HPALETTE);
|
||||
begin
|
||||
if Assigned(fImage) then begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TTargaImage.LoadFromStream(Stream: TStream);
|
||||
var
|
||||
io: FreeImageIO;
|
||||
begin
|
||||
with io do begin
|
||||
read_proc := FI_ReadProc;
|
||||
write_proc := FI_WriteProc;
|
||||
seek_proc := FI_SeekProc;
|
||||
tell_proc := FI_TellProc;
|
||||
end;
|
||||
fImage := FreeImage_LoadFromHandle(FIF_TARGA, @io, Stream);
|
||||
if Assigned(fImage) then begin
|
||||
fWidth := FreeImage_GetWidth(fImage);
|
||||
fHeight := FreeImage_GetHeight(fImage);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TTargaImage.SaveToClipboardFormat(var AFormat: Word; var AData: THandle; var APalette: HPALETTE);
|
||||
begin
|
||||
end;
|
||||
|
||||
procedure TTargaImage.SaveToStream(Stream: TStream);
|
||||
var
|
||||
io: FreeImageIO;
|
||||
begin
|
||||
with io do begin
|
||||
read_proc := FI_ReadProc;
|
||||
write_proc := FI_WriteProc;
|
||||
seek_proc := FI_SeekProc;
|
||||
tell_proc := FI_TellProc;
|
||||
end;
|
||||
FreeImage_SaveToHandle(FIF_TARGA, fImage, @io, Stream);
|
||||
end;
|
||||
|
||||
procedure TTargaImage.SetHeight(Value: Integer);
|
||||
begin
|
||||
if Assigned(fImage) then begin
|
||||
fHeight := Value;
|
||||
FreeImage_Rescale(fImage, fWidth, fHeight, FILTER_BICUBIC);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TTargaImage.SetWidth(Value: Integer);
|
||||
begin
|
||||
if Assigned(fImage) then begin
|
||||
fWidth := Value;
|
||||
FreeImage_Rescale(fImage, fWidth, fHeight, FILTER_BICUBIC);
|
||||
end;
|
||||
end;
|
||||
|
||||
initialization
|
||||
TPicture.RegisterFileFormat('tga', 'TARGA Files', TTargaImage);
|
||||
end.
|
||||
@@ -1,13 +0,0 @@
|
||||
program MainDemo;
|
||||
|
||||
uses
|
||||
Forms,
|
||||
MainForm in 'MainForm.pas' {fwbMainForm};
|
||||
|
||||
{$R *.res}
|
||||
|
||||
begin
|
||||
Application.Initialize;
|
||||
Application.CreateForm(TfwbMainForm, fwbMainForm);
|
||||
Application.Run;
|
||||
end.
|
||||
Binary file not shown.
@@ -1,607 +0,0 @@
|
||||
object fwbMainForm: TfwbMainForm
|
||||
Left = 205
|
||||
Top = 206
|
||||
Width = 696
|
||||
Height = 480
|
||||
Caption = 'FreeWinBitmap - MainDemo'
|
||||
Color = clCaptionText
|
||||
Font.Charset = DEFAULT_CHARSET
|
||||
Font.Color = clWindowText
|
||||
Font.Height = -11
|
||||
Font.Name = 'Tahoma'
|
||||
Font.Style = []
|
||||
Menu = MainMenu
|
||||
OldCreateOrder = False
|
||||
ShowHint = True
|
||||
OnCreate = FormCreate
|
||||
OnDestroy = FormDestroy
|
||||
OnPaint = FormPaint
|
||||
OnResize = FormResize
|
||||
PixelsPerInch = 96
|
||||
TextHeight = 13
|
||||
object StatusBar: TStatusBar
|
||||
Left = 0
|
||||
Top = 411
|
||||
Width = 688
|
||||
Height = 23
|
||||
Panels = <
|
||||
item
|
||||
Alignment = taCenter
|
||||
Width = 120
|
||||
end
|
||||
item
|
||||
Alignment = taCenter
|
||||
Width = 80
|
||||
end
|
||||
item
|
||||
Width = 50
|
||||
end>
|
||||
end
|
||||
object tbTools: TToolBar
|
||||
Left = 0
|
||||
Top = 0
|
||||
Width = 688
|
||||
Height = 29
|
||||
Caption = 'ToolBar'
|
||||
Color = clBtnFace
|
||||
EdgeBorders = [ebTop, ebBottom]
|
||||
Flat = True
|
||||
Images = ImageList1
|
||||
ParentColor = False
|
||||
TabOrder = 1
|
||||
object ToolButton1: TToolButton
|
||||
Left = 0
|
||||
Top = 0
|
||||
Width = 8
|
||||
Caption = 'ToolButton1'
|
||||
ImageIndex = 1
|
||||
Style = tbsSeparator
|
||||
end
|
||||
object btnOpen: TToolButton
|
||||
Left = 8
|
||||
Top = 0
|
||||
Hint = 'Open image file...'
|
||||
Caption = 'Open...'
|
||||
ImageIndex = 0
|
||||
OnClick = mnuFileOpenClick
|
||||
end
|
||||
object ToolButton4: TToolButton
|
||||
Left = 31
|
||||
Top = 0
|
||||
Width = 8
|
||||
Caption = 'ToolButton4'
|
||||
ImageIndex = 4
|
||||
Style = tbsSeparator
|
||||
end
|
||||
object btnCopy: TToolButton
|
||||
Left = 39
|
||||
Top = 0
|
||||
Hint = 'Copy to clipboard'
|
||||
Caption = 'Copy'
|
||||
ImageIndex = 1
|
||||
OnClick = btnCopyClick
|
||||
end
|
||||
object btnPaste: TToolButton
|
||||
Left = 62
|
||||
Top = 0
|
||||
Hint = 'Paste from from clipboard'
|
||||
Caption = 'Paste'
|
||||
ImageIndex = 2
|
||||
OnClick = btnPasteClick
|
||||
end
|
||||
object ToolButton3: TToolButton
|
||||
Left = 85
|
||||
Top = 0
|
||||
Width = 8
|
||||
Caption = 'ToolButton3'
|
||||
ImageIndex = 4
|
||||
Style = tbsSeparator
|
||||
end
|
||||
object btnClear: TToolButton
|
||||
Left = 93
|
||||
Top = 0
|
||||
Caption = 'Clear'
|
||||
ImageIndex = 3
|
||||
OnClick = btnClearClick
|
||||
end
|
||||
end
|
||||
object MainMenu: TMainMenu
|
||||
Left = 120
|
||||
Top = 48
|
||||
object mnuFile: TMenuItem
|
||||
Caption = '&File'
|
||||
object mnuFileOpen: TMenuItem
|
||||
Caption = '&Open'
|
||||
OnClick = mnuFileOpenClick
|
||||
end
|
||||
object mnuExit: TMenuItem
|
||||
Caption = 'E&xit'
|
||||
OnClick = mnuExitClick
|
||||
end
|
||||
end
|
||||
object mnuImage: TMenuItem
|
||||
Caption = 'Image'
|
||||
object mnuImageFlip: TMenuItem
|
||||
Caption = 'Flip'
|
||||
object mnuFlipHorz: TMenuItem
|
||||
Caption = 'Horizontal'
|
||||
OnClick = mnuFlipHorzClick
|
||||
end
|
||||
object mnuFlipVert: TMenuItem
|
||||
Caption = 'Vertical'
|
||||
OnClick = mnuFlipHorzClick
|
||||
end
|
||||
end
|
||||
object mnuConvert: TMenuItem
|
||||
Caption = 'Convert'
|
||||
object mnuTo4Bits: TMenuItem
|
||||
Caption = 'To 4 Bits'
|
||||
OnClick = mnuFlipHorzClick
|
||||
end
|
||||
object mnuTo8Bits: TMenuItem
|
||||
Caption = 'To 8 Bits'
|
||||
OnClick = mnuFlipHorzClick
|
||||
end
|
||||
object mnuTo16Bits555: TMenuItem
|
||||
Caption = 'To 16 Bits (555)'
|
||||
OnClick = mnuFlipHorzClick
|
||||
end
|
||||
object mnuTo16Bits565: TMenuItem
|
||||
Caption = 'To 16 Bits (565)'
|
||||
OnClick = mnuFlipHorzClick
|
||||
end
|
||||
object mnuTo24Bits: TMenuItem
|
||||
Caption = 'To 24 Bits'
|
||||
OnClick = mnuFlipHorzClick
|
||||
end
|
||||
object mnuTo32Bits: TMenuItem
|
||||
Caption = 'To 32 Bits'
|
||||
OnClick = mnuFlipHorzClick
|
||||
end
|
||||
object mnuDither: TMenuItem
|
||||
Caption = 'Dither'
|
||||
OnClick = mnuFlipHorzClick
|
||||
end
|
||||
object mnuQuantize: TMenuItem
|
||||
Caption = 'Quantize'
|
||||
OnClick = mnuFlipHorzClick
|
||||
end
|
||||
object mnuGrayScale: TMenuItem
|
||||
Caption = 'GrayScale'
|
||||
OnClick = mnuFlipHorzClick
|
||||
end
|
||||
end
|
||||
object mnuRotate: TMenuItem
|
||||
Caption = 'Rotate'
|
||||
object mnuClockwise: TMenuItem
|
||||
Caption = 'Clockwise'
|
||||
OnClick = mnuFlipHorzClick
|
||||
end
|
||||
object mnuAntiClockwise: TMenuItem
|
||||
Caption = 'AntiClockwise'
|
||||
OnClick = mnuFlipHorzClick
|
||||
end
|
||||
end
|
||||
object mnuInvert: TMenuItem
|
||||
Caption = 'Invert'
|
||||
OnClick = mnuFlipHorzClick
|
||||
end
|
||||
object mnuClear: TMenuItem
|
||||
Caption = 'Clear'
|
||||
OnClick = mnuFlipHorzClick
|
||||
end
|
||||
end
|
||||
end
|
||||
object OD: TOpenDialog
|
||||
Title = 'Open file ...'
|
||||
Left = 152
|
||||
Top = 48
|
||||
end
|
||||
object ImageList1: TImageList
|
||||
Left = 184
|
||||
Top = 48
|
||||
Bitmap = {
|
||||
494C010104000900040010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
|
||||
0000000000003600000028000000400000003000000001002000000000000030
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000007088900060809000607880005070
|
||||
8000506070004058600040485000303840002030300020203000101820001010
|
||||
1000101020000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000080685000203040002030400020304000203040002030
|
||||
4000203040002030400020304000203040000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000DFE2F700EFF0FB0000000000000000007088900090A0B00070B0D0000090
|
||||
D0000090D0000090D0000090C0001088C0001080B0001080B0002078A0002070
|
||||
900020486000B9BEBE0000000000000000000000000000000000000000000000
|
||||
00000000000000000000C0704000B0583000B0583000A0502000A05020009048
|
||||
2000904820009040200080402000000000007086900060809000506070004050
|
||||
6000304050002030400090706000F0E0D000B0A09000B0A09000B0A09000B0A0
|
||||
9000B0A09000B0A09000B0A0900020304000000000000000000000000000EFF1
|
||||
FF001F3BF100EFF1FF000000000000000000000000000000000000000000CFD3
|
||||
F3001F2DB900CFD2F30000000000000000008088900080C0D00090A8B00080E0
|
||||
FF0060D0FF0050C8FF0050C8FF0040C0F00030B0F00030A8F00020A0E0001090
|
||||
D00020688000656A700000000000000000000000000000000000000000000000
|
||||
00000000000000000000C0785000FFF8F000D0B0A000D0B0A000D0B0A000C0B0
|
||||
A000C0A8A000C0A8900090402000000000007080900020B8F0000090D0000090
|
||||
D0000090D0000090D00090786000F0E8E000F0D8D000E0D0C000E0C8C000D0C0
|
||||
B000D0B8B000D0B8B000B0A09000203040000000000000000000F0F2FF00576F
|
||||
FF001030FF001E34FF00EFF1FF00000000000000000000000000DFE2F7003F51
|
||||
CF000018C0000F1EB400DFE2F700000000008090A00080D0F00090A8B00090C0
|
||||
D00070D8FF0060D0FF0060D0FF0050C8FF0050C0FF0040B8F00030B0F00030A8
|
||||
F0001088D00020486000E1E4E500000000000000000000000000000000000000
|
||||
00000000000000000000D0886000FFFFFF00E0906000D0805000D0805000D080
|
||||
5000D0805000C0A8A00090482000000000007088900070C8F00010B8F00010B0
|
||||
F00000A8E0000098D000A0807000F0F0F000C0B0A000C0B0A000C0A8A000B0A0
|
||||
9000D0C0B000B0A09000B0A0900020304000000000000000000000000000F1F2
|
||||
FF002D52FF001030FF000028FF00CFD5FF0000000000CFD3F3001F34C7000018
|
||||
D0000F25C300BFC5EF0000000000000000008090A00080D8F00080C8E00090A8
|
||||
B00080E0FF0070D0FF0060D8FF0060D0FF0060D0FF0050C8FF0040C0F00040B8
|
||||
F00030B0F000206880007897A50000000000B0A0900060483000604830006048
|
||||
30006048300060483000D0907000FFFFFF00FFFFFF00FFF0F000F0E0D000F0D0
|
||||
C000F0C0B000C0B0A00090482000000000008088900070D0F00030C0F00010B8
|
||||
F00000A8F00000A0E000A0888000FFF8FF00F0F0F000F0E8E000F0D8D000E0D0
|
||||
C000705850006050400050484000404040000000000000000000000000000000
|
||||
0000F1F2FF002D52FF001030FF000F2DFF00CFD3F6001F34D5000020E0000F25
|
||||
D200DFE2F7000000000000000000000000008098A00090E0F00090E0FF0090A8
|
||||
B00090B8C00070D8FF0060D8FF0060D8FF0060D8FF0060D0FF0050D0FF0050C8
|
||||
FF0040B8F00030A0E0004B697800DEE1E400B0A09000FFF0F000F0E0D000E0D8
|
||||
D000E0D0C000E0C8C000E0A08000FFFFFF00F0A88000E0987000E0906000D080
|
||||
5000D0805000D0B0A000A0482000000000008090A00080D8F00040C8F00030C0
|
||||
F00010B8F00000A0E000B0908000FFFFFF00C0B0A000C0B0A000C0A8A000F0E0
|
||||
D00080605000D0C8C00060504000000000000000000000000000000000000000
|
||||
000000000000E3E6FF005669FF001038FF000020F0000F2DF0002F42D800DFE2
|
||||
F700000000000000000000000000000000008098A00090E0F000A0E8FF0080C8
|
||||
E00090A8B00080E0FF0080E0FF0080E0FF0080E0FF0080E0FF0080E0FF0080E0
|
||||
FF0070D8FF0070D8FF0050A8D000919BA500B0A09000FFF8F000E0B08000E0A0
|
||||
7000E0A07000D0987000E0A89000FFFFFF00FFFFFF00FFFFFF00FFF8F000F0E8
|
||||
E000F0D0C000D0B0A000A0502000000000008098A00090E0F00060D8F00050C8
|
||||
F00030C0F00010B0F000B0989000FFFFFF00FFFFFF00FFF8FF00F0F0F000F0E8
|
||||
E000806850008060500000000000000000000000000000000000000000000000
|
||||
00000000000000000000C3CAFF002048FF001030FF000F2DF000CFD3F6000000
|
||||
00000000000000000000000000000000000090A0A000A0E8F000A0E8FF00A0E8
|
||||
FF0090B0C00090B0C00090A8B00090A8B00080A0B00080A0B0008098A0008098
|
||||
A0008090A0008090A0008088900070889000C0A89000FFFFFF00FFF8F000F0F0
|
||||
F000F0E8E000F0E0D000E0B8A000FFFFFF00FFB09000FFB09000F0D8D000E090
|
||||
6000B0583000B0583000A0502000000000008098A000A0E8F00080E0F00070D8
|
||||
F00050D0F00010B0F000B0A09000B0989000B0908000A0888000A08070009078
|
||||
6000907060000000000000000000000000000000000000000000000000000000
|
||||
000000000000CFD7FF004060FF003050FF002D4BFF001038FF000020F000DFE3
|
||||
FD000000000000000000000000000000000090A0B000A0E8F000A0F0FF00A0E8
|
||||
FF00A0E8FF0080D8FF0060D8FF0060D8FF0060D8FF0060D8FF0060D8FF0060D8
|
||||
FF0070889000000000000000000000000000C0A8A000FFFFFF00FFC8A000F0B8
|
||||
9000E0B08000E0A07000F0C0A000FFFFFF00FFFFFF00FFFFFF00FFFFFF00F098
|
||||
7000F0C8B000B0583000EBD5CB000000000090A0A000B0F0FF00A0E8FF0090E0
|
||||
F00070D0F00010A0D00010A0D00010A0D0001098D0000090D0000090D0000090
|
||||
D000303840000000000000000000000000000000000000000000000000000000
|
||||
0000DBE1FF004060FF004058FF004B70FF00CFD5FF004B69FF002040FF000020
|
||||
F000CFD5FC0000000000000000000000000090A0B000A0F0F000B0F0F000A0F0
|
||||
FF00A0E8FF00A0E8FF0070D8FF0090A0A0008098A0008098A0008090A0008090
|
||||
900070889000000000000000000000000000C0B0A000FFFFFF00FFFFFF00FFF8
|
||||
FF00FFF0F000F0E8E000F0C8B000FFFFFF00FFFFFF00FFFFFF00FFFFFF00F0A8
|
||||
8000C0683000EFD9CB00000000000000000090A0B000B0F0FF00A0F0FF006080
|
||||
9000607080005070800050687000506870005060700040587000207090000090
|
||||
D00040486000000000000000000000000000000000000000000000000000E7EB
|
||||
FF005070FF005078FF00708AFF00E7EBFF0000000000DBDFFF004B69FF003048
|
||||
FF000020F000CFD5FC00000000000000000090A8B000A0D0E000B0F0F000B0F0
|
||||
F000A0F0FF00A0E8FF0090A0B000B3C7CB000000000000000000000000000000
|
||||
000000000000906850009068500090685000D0B8B000FFFFFF00FFD8C000FFD0
|
||||
B000F0E0D000B0A09000F0C8B000F0C0B000F0C0B000F0B8A000F0B09000F0B0
|
||||
9000F7E3D70000000000000000000000000090A8B000B0F0FF00B0F0FF006088
|
||||
900090C8D00090E8F00080D8E00060C8E0005098B000405860002080A0000090
|
||||
D000505870000000000000000000000000000000000000000000F3F5FF006078
|
||||
FF006078FF00697FFF00F3F5FF00000000000000000000000000E7EAFF004B69
|
||||
FF003050FF000028FF00DFE3FD0000000000DCE3E60090A8B00090A8B00090A8
|
||||
B00090A8B00090A8B000AAB3B400000000000000000000000000000000000000
|
||||
000000000000E1D4D2009068500090685000D0C0B000FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00C0A89000D0C8C00090706000E1DCD80000000000000000000000
|
||||
00000000000000000000000000000000000090A8B000B0F0F000B0F0FF00A0F0
|
||||
F0007098A000A0F0F00060757C0080C8D000507080003060800060C0F00020B8
|
||||
F00050607000000000000000000000000000000000000000000000000000E7EB
|
||||
FF006987FF00F3F5FF000000000000000000000000000000000000000000E7EA
|
||||
FF005773FF00E1E5FF0000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000090786000B7A498000000
|
||||
0000F9F6F600A0908000E1D9D20090786000E0C0B000FFFFFF00FFFFFF00FFFF
|
||||
FF00FFFFFF00C0B0A000A0806000E1DCD8000000000000000000000000000000
|
||||
000000000000000000000000000000000000CED8DC0090A8B00090A8B00090A8
|
||||
B0006090A000A0E8F000A0E8F00090D8E0004068700070889000808890007088
|
||||
9000D7DADC000000000000000000000000000000000000000000000000000000
|
||||
0000F3F5FF000000000000000000000000000000000000000000000000000000
|
||||
0000E7EAFF000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000D1CFC900A0908000A088
|
||||
8000B0988000CFC7BF000000000000000000E0C0B000E0C0B000D0C0B000D0C0
|
||||
B000D0B8B000D0B0A000E6DEDC00000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
00000000000080B0C00080B0C00080A0B000DEE1E40000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
000000000000000000000000000000000000424D3E000000000000003E000000
|
||||
2800000040000000300000000100010000000000800100000000000000000000
|
||||
000000000000000000000000FFFFFF0000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000FFFFFFFFFFFFFFFF0007FFFFFC00FFF3
|
||||
0003FC010000E3E30003FC010000C1C10001FC010000E083000100010000F007
|
||||
000000010001F80F000000010003FC1F000000010007F80F000700010007F007
|
||||
000700030007E08300F800070007C1C101F8007F0007E3E3FF9000FF0007F7F7
|
||||
FF8301FFF87FFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000
|
||||
000000000000}
|
||||
end
|
||||
end
|
||||
@@ -1,227 +0,0 @@
|
||||
unit MainForm;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
|
||||
Dialogs, Menus, FreeBitmap, ComCtrls, ImgList, ToolWin;
|
||||
|
||||
type
|
||||
TfwbMainForm = class(TForm)
|
||||
MainMenu: TMainMenu;
|
||||
mnuFile: TMenuItem;
|
||||
mnuFileOpen: TMenuItem;
|
||||
mnuExit: TMenuItem;
|
||||
OD: TOpenDialog;
|
||||
StatusBar: TStatusBar;
|
||||
mnuImage: TMenuItem;
|
||||
mnuImageFlip: TMenuItem;
|
||||
mnuFlipHorz: TMenuItem;
|
||||
mnuFlipVert: TMenuItem;
|
||||
mnuConvert: TMenuItem;
|
||||
mnuTo8Bits: TMenuItem;
|
||||
mnuTo16Bits555: TMenuItem;
|
||||
mnuTo16Bits565: TMenuItem;
|
||||
mnuTo24Bits: TMenuItem;
|
||||
mnuTo32Bits: TMenuItem;
|
||||
mnuDither: TMenuItem;
|
||||
mnuQuantize: TMenuItem;
|
||||
mnuGrayScale: TMenuItem;
|
||||
mnuRotate: TMenuItem;
|
||||
mnuClockwise: TMenuItem;
|
||||
mnuAntiClockwise: TMenuItem;
|
||||
mnuInvert: TMenuItem;
|
||||
mnuClear: TMenuItem;
|
||||
mnuTo4Bits: TMenuItem;
|
||||
tbTools: TToolBar;
|
||||
btnCopy: TToolButton;
|
||||
ImageList1: TImageList;
|
||||
ToolButton1: TToolButton;
|
||||
btnPaste: TToolButton;
|
||||
btnClear: TToolButton;
|
||||
btnOpen: TToolButton;
|
||||
ToolButton3: TToolButton;
|
||||
ToolButton4: TToolButton;
|
||||
procedure FormDestroy(Sender: TObject);
|
||||
procedure FormPaint(Sender: TObject);
|
||||
procedure FormCreate(Sender: TObject);
|
||||
procedure mnuExitClick(Sender: TObject);
|
||||
procedure mnuFileOpenClick(Sender: TObject);
|
||||
procedure FormResize(Sender: TObject);
|
||||
procedure mnuFlipHorzClick(Sender: TObject);
|
||||
procedure btnCopyClick(Sender: TObject);
|
||||
procedure btnClearClick(Sender: TObject);
|
||||
procedure btnPasteClick(Sender: TObject);
|
||||
private
|
||||
FBitmap: TFreeWinBitmap;
|
||||
procedure WMEraseBkgnd(var Message: TMessage); message WM_ERASEBKGND;
|
||||
public
|
||||
{ Public declarations }
|
||||
end;
|
||||
|
||||
var
|
||||
fwbMainForm: TfwbMainForm;
|
||||
|
||||
implementation
|
||||
|
||||
{$R *.dfm}
|
||||
|
||||
uses
|
||||
FreeUtils, FreeImage, Math;
|
||||
|
||||
procedure TfwbMainForm.FormDestroy(Sender: TObject);
|
||||
begin
|
||||
if Assigned(FBitmap) then
|
||||
FBitmap.Free;
|
||||
end;
|
||||
|
||||
procedure TfwbMainForm.FormPaint(Sender: TObject);
|
||||
var
|
||||
dx, dy, w, h: Integer;
|
||||
r1, r2: Double;
|
||||
R: TRect;
|
||||
begin
|
||||
if FBitmap.IsValid then // draw the bitmap
|
||||
begin
|
||||
// determine paint rect
|
||||
r1 := FBitmap.GetWidth / FBitmap.GetHeight;
|
||||
r2 := ClientWidth / ClientHeight;
|
||||
if r1 > r2 then // fit by width
|
||||
begin
|
||||
w := ClientWidth;
|
||||
h := Floor(w / r1);
|
||||
dx := 0;
|
||||
dy := (ClientHeight - h) div 2;
|
||||
end
|
||||
else // fit by height
|
||||
begin
|
||||
h := ClientHeight;
|
||||
w := Floor(h * r1);
|
||||
dy := 0;
|
||||
dx := (ClientWidth - w) div 2;
|
||||
end;
|
||||
with ClientRect do
|
||||
R := Bounds(Left + dx, Top + dy, w, h);
|
||||
FBitmap.Draw(Canvas.Handle, R);
|
||||
|
||||
// erase area around the image
|
||||
Canvas.Brush.Color := Color;
|
||||
if dx > 0 then
|
||||
begin
|
||||
with ClientRect do
|
||||
R := Bounds(Left, Top, dx, ClientHeight);
|
||||
Canvas.FillRect(R);
|
||||
with ClientRect do
|
||||
R := Bounds(Right - dx, Top, dx, ClientHeight);
|
||||
Canvas.FillRect(R);
|
||||
end else
|
||||
if dy > 0 then
|
||||
begin
|
||||
with ClientRect do
|
||||
R := Bounds(Left, Top, ClientWidth, dy);
|
||||
Canvas.FillRect(R);
|
||||
with ClientRect do
|
||||
R := Bounds(Left, Bottom - dy, ClientWidth, dy);
|
||||
Canvas.FillRect(R);
|
||||
end
|
||||
end
|
||||
else // clear
|
||||
begin
|
||||
Canvas.Brush.Color := Color;
|
||||
Canvas.FillRect(ClientRect);
|
||||
end
|
||||
end;
|
||||
|
||||
procedure TfwbMainForm.FormCreate(Sender: TObject);
|
||||
begin
|
||||
FBitmap := TFreeWinBitmap.Create;
|
||||
|
||||
mnuImage.Enabled := FBitmap.IsValid;
|
||||
OD.Filter := FIU_GetAllFilters;
|
||||
end;
|
||||
|
||||
procedure TfwbMainForm.mnuExitClick(Sender: TObject);
|
||||
begin
|
||||
Close;
|
||||
end;
|
||||
|
||||
procedure TfwbMainForm.mnuFileOpenClick(Sender: TObject);
|
||||
var
|
||||
t: Cardinal;
|
||||
begin
|
||||
if OD.Execute then
|
||||
begin
|
||||
t := GetTickCount;
|
||||
FBitmap.Load(OD.FileName);
|
||||
t := GetTickCount - t;
|
||||
mnuImage.Enabled := FBitmap.IsValid;
|
||||
StatusBar.Panels[0].Text := 'Loaded in ' + IntToStr(t) + ' msec.';
|
||||
StatusBar.Panels[1].Text := Format('%dx%d', [FBitmap.GetWidth, FBitmap.GetHeight]);
|
||||
Invalidate;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TfwbMainForm.FormResize(Sender: TObject);
|
||||
begin
|
||||
Invalidate
|
||||
end;
|
||||
|
||||
procedure TfwbMainForm.WMEraseBkgnd(var Message: TMessage);
|
||||
begin
|
||||
Message.Result := 1;
|
||||
end;
|
||||
|
||||
procedure TfwbMainForm.mnuFlipHorzClick(Sender: TObject);
|
||||
begin
|
||||
with FBitmap do
|
||||
if Sender = mnuFlipHorz then
|
||||
FLipHorizontal else
|
||||
if Sender = mnuFlipVert then
|
||||
FlipVertical else
|
||||
if Sender = mnuTo4Bits then
|
||||
ConvertTo4Bits else
|
||||
if Sender = mnuTo8Bits then
|
||||
ConvertTo8Bits else
|
||||
if Sender = mnuTo16Bits555 then
|
||||
ConvertTo16Bits555 else
|
||||
if Sender = mnuTo16Bits565 then
|
||||
ConvertTo16Bits565 else
|
||||
if Sender = mnuTo24Bits then
|
||||
ConvertTo24Bits else
|
||||
if Sender = mnuTo32Bits then
|
||||
ConvertTo32Bits else
|
||||
if Sender = mnuDither then
|
||||
Dither(FID_FS) else
|
||||
if Sender = mnuQuantize then
|
||||
ColorQuantize(FIQ_WUQUANT) else
|
||||
if Sender = mnuGrayScale then
|
||||
ConvertToGrayscale else
|
||||
if Sender = mnuClockwise then
|
||||
Rotate(-90) else
|
||||
if Sender = mnuAntiClockwise then
|
||||
Rotate(90) else
|
||||
if Sender = mnuInvert then
|
||||
Invert else
|
||||
if Sender = mnuClear then
|
||||
Clear;
|
||||
Invalidate;
|
||||
end;
|
||||
|
||||
procedure TfwbMainForm.btnCopyClick(Sender: TObject);
|
||||
begin
|
||||
if FBitmap.IsValid then FBitmap.CopyToClipBoard(Handle);
|
||||
end;
|
||||
|
||||
procedure TfwbMainForm.btnClearClick(Sender: TObject);
|
||||
begin
|
||||
FBitmap.Clear;
|
||||
Invalidate;
|
||||
end;
|
||||
|
||||
procedure TfwbMainForm.btnPasteClick(Sender: TObject);
|
||||
begin
|
||||
FBitmap.PasteFromClipBoard;
|
||||
Invalidate;
|
||||
end;
|
||||
|
||||
end.
|
||||
@@ -1,3 +0,0 @@
|
||||
The contents of FreeImageDW package are subject to the FreeImage Public License Version 1.0 (the "License"); you may not use this package except in compliance with the License. You may obtain a copy of the License at http://home.wxs.nl/~flvdberg/freeimage-license.txt
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License.
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,186 +0,0 @@
|
||||
unit FreeUtils;
|
||||
|
||||
// ==========================================================
|
||||
//
|
||||
// Delphi wrapper for FreeImage 3
|
||||
//
|
||||
// Design and implementation by
|
||||
// - Anatoliy Pulyaevskiy (xvel84@rambler.ru)
|
||||
//
|
||||
// Contributors:
|
||||
// - Enzo Costantini (enzocostantini@libero.it)
|
||||
// - Armindo (tech1.yxendis@wanadoo.fr)
|
||||
// - Lorenzo Monti (LM) lomo74@gmail.com
|
||||
//
|
||||
// Revision history
|
||||
// When Who What
|
||||
// ----------- ----- -----------------------------------------------------------
|
||||
// 2010-07-14 LM made RAD2010 compliant (unicode)
|
||||
//
|
||||
// This file is part of FreeImage 3
|
||||
//
|
||||
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
|
||||
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
|
||||
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
|
||||
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
|
||||
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
|
||||
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
|
||||
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
|
||||
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
|
||||
// THIS DISCLAIMER.
|
||||
//
|
||||
// Use at your own risk!
|
||||
//
|
||||
// ==========================================================
|
||||
|
||||
interface
|
||||
|
||||
{$I 'Version.inc'}
|
||||
|
||||
uses
|
||||
{$IFDEF DELPHI2010}AnsiStrings,{$ENDIF} SysUtils, Classes, FreeImage;
|
||||
|
||||
function FIU_GetFIFType(filename: AnsiString): FREE_IMAGE_FORMAT;
|
||||
|
||||
// returns FIF (plugin) description string
|
||||
function FIU_GetFIFDescription(fif: FREE_IMAGE_FORMAT): AnsiString;
|
||||
|
||||
procedure FIU_GetAllDescriptions(var Descriptions: TStringList);
|
||||
|
||||
// returns file extentions for FIF (e.g. '*.tif;*.tiff)
|
||||
function FIU_GetFIFExtList(fif: FREE_IMAGE_FORMAT): AnsiString;
|
||||
|
||||
// returns file extentions for all plugins
|
||||
function FIU_GetFullExtList: AnsiString;
|
||||
|
||||
// returns "Description + | + ExtList" for specified FIF
|
||||
function FIU_GetFIFFilter(fif: FREE_IMAGE_FORMAT): AnsiString;
|
||||
|
||||
// All supported formats + Full filter list for FIFs
|
||||
function FIU_GetAllFilters: AnsiString;
|
||||
|
||||
//Filter for OpenDialogs
|
||||
function FIU_GetAllOpenFilters: AnsiString;
|
||||
|
||||
//Filter for SaveDialogs
|
||||
function FIU_GetAllSaveFilters: AnsiString;
|
||||
|
||||
implementation
|
||||
|
||||
const
|
||||
FIF_START = FIF_UNKNOWN;
|
||||
FIF_END = FIF_XPM;
|
||||
|
||||
function FIU_GetFIFType(filename: AnsiString): FREE_IMAGE_FORMAT;
|
||||
begin
|
||||
Result := FreeImage_GetFileType(PAnsiChar(filename), 0);
|
||||
end;
|
||||
|
||||
function FIU_GetFIFDescription(fif: FREE_IMAGE_FORMAT): AnsiString;
|
||||
begin
|
||||
Result := FreeImage_GetFIFDescription(fif)
|
||||
end;
|
||||
|
||||
procedure FIU_GetAllDescriptions(var Descriptions: TStringList);
|
||||
var
|
||||
fif: FREE_IMAGE_FORMAT;
|
||||
begin
|
||||
Descriptions.Clear;
|
||||
for fif := FIF_START to FIF_END do
|
||||
Descriptions.Add(string(FreeImage_GetFIFDescription(fif)) + ' (' +
|
||||
string(FIu_GetFIFExtList(fif)) + ')');
|
||||
end;
|
||||
|
||||
function FIU_GetFIFExtList(fif: FREE_IMAGE_FORMAT): AnsiString;
|
||||
var
|
||||
ExtList: AnsiString;
|
||||
I: Smallint;
|
||||
C: AnsiChar;
|
||||
begin
|
||||
Result := '*.';
|
||||
ExtList := FreeImage_GetFIFExtensionList(fif);
|
||||
for I := 1 to Length(ExtList) do
|
||||
begin
|
||||
C := ExtList[i];
|
||||
if C <> ',' then
|
||||
Result := Result + C
|
||||
else
|
||||
Result := Result + ';*.';
|
||||
end
|
||||
end;
|
||||
|
||||
function FIU_GetFullExtList: AnsiString;
|
||||
var
|
||||
fif: FREE_IMAGE_FORMAT;
|
||||
begin
|
||||
Result := FIU_GetFIFExtList(FIF_START);
|
||||
for fif := FIF_START to FIF_END do
|
||||
Result := Result + ';' + FIU_GetFIFExtList(fif)
|
||||
end;
|
||||
|
||||
function FIU_GetFIFFilter(fif: FREE_IMAGE_FORMAT): AnsiString;
|
||||
var
|
||||
Text, ExtList: AnsiString;
|
||||
begin
|
||||
Result := '';
|
||||
if fif <> FIF_UNKNOWN then
|
||||
begin
|
||||
Text := {$IFDEF DELPHI2010}AnsiStrings.{$ENDIF}Trim(FreeImage_GetFIFDescription(fif));
|
||||
ExtList := FIU_GetFIFExtList(fif);
|
||||
Result := Text + '(' + ExtList + ')' + '|' + ExtList
|
||||
end
|
||||
end;
|
||||
|
||||
function FIU_GetAllFilters: AnsiString;
|
||||
var
|
||||
fif: FREE_IMAGE_FORMAT;
|
||||
begin
|
||||
Result := 'All supported formats|' + FIU_GetFullExtList;
|
||||
for fif := FIF_START to FIF_END do
|
||||
begin
|
||||
Result := Result + '|' + FIU_GetFIFFilter(fif)
|
||||
end;
|
||||
end;
|
||||
|
||||
function FIU_GetAllOpenFilters: AnsiString;
|
||||
var
|
||||
fif: FREE_IMAGE_FORMAT;
|
||||
begin
|
||||
Result := 'All supported formats|' + FIU_GetFullExtList;
|
||||
for fif := FIF_START to FIF_END do
|
||||
if FreeImage_FIFSupportsReading(fif) then
|
||||
begin
|
||||
Result := Result + '|' + FIU_GetFIFFilter(fif)
|
||||
end;
|
||||
end;
|
||||
|
||||
function FIU_GetAllSaveFilters: AnsiString;
|
||||
var
|
||||
ExtList: AnsiString;
|
||||
I: Smallint;
|
||||
C: AnsiChar;
|
||||
fif: FREE_IMAGE_FORMAT;
|
||||
s: AnsiString;
|
||||
begin
|
||||
result := '';
|
||||
for fif := FIF_START to FIF_END do
|
||||
if FreeImage_FIFSupportsWriting(fif) then
|
||||
begin
|
||||
ExtList := FreeImage_GetFIFExtensionList(fif);
|
||||
s := '';
|
||||
for I := 1 to Length(ExtList) do
|
||||
begin
|
||||
C := ExtList[i];
|
||||
if C <> ',' then
|
||||
S := S + C
|
||||
else
|
||||
begin
|
||||
result := Result + FreeImage_GetFIFDescription(fif) + ' (' + UpperCase(s) + ')|*.' + s + '|';
|
||||
s := '';
|
||||
end;
|
||||
end;
|
||||
result := Result + FreeImage_GetFIFDescription(fif) + ' (' + UpperCase(s) + ')|*.' + s + '|';
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
@@ -1,186 +0,0 @@
|
||||
// ==========================================================
|
||||
// Delphi wrapper for FreeImage 3
|
||||
//
|
||||
// Design and implementation by
|
||||
// - Simon Beavis
|
||||
// - Peter Bystr<74>m
|
||||
// - Anatoliy Pulyaevskiy (xvel84@rambler.ru)
|
||||
//
|
||||
// Contributors:
|
||||
// - Lorenzo Monti (LM) lomo74@gmail.com
|
||||
//
|
||||
// Revision history
|
||||
// When Who What
|
||||
// ----------- ----- -----------------------------------------------------------
|
||||
// 2010-07-29 LM Added Free Pascal / Lazarus 32 bit support
|
||||
//
|
||||
// This file is part of FreeImage 3
|
||||
//
|
||||
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
|
||||
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
|
||||
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
|
||||
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
|
||||
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
|
||||
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
|
||||
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
|
||||
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
|
||||
// THIS DISCLAIMER.
|
||||
//
|
||||
// Use at your own risk!
|
||||
// ==========================================================
|
||||
|
||||
//some older Delphi version will define WIN32 but not MSWINDOWS
|
||||
{$IFNDEF MSWINDOWS}
|
||||
{$IFDEF WIN32}
|
||||
{$DEFINE MSWINDOWS}
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
|
||||
//test for compiler
|
||||
{$IFDEF FPC}
|
||||
//Free pascal
|
||||
{$IFNDEF CPU32}
|
||||
{$ERROR "64 bit platforms not tested yet. Remove this line if you feel brave."}
|
||||
{$ENDIF}
|
||||
{$IFNDEF ENDIAN_LITTLE}
|
||||
{$ERROR "Big endian CPUs not tested yet. Remove this line if you feel brave."}
|
||||
{$ENDIF}
|
||||
{$DEFINE DELPHI1}
|
||||
{$DEFINE DELPHI2}
|
||||
{$DEFINE DELPHI3}
|
||||
{$DEFINE DELPHI4}
|
||||
{$DEFINE DELPHI5}
|
||||
{$DEFINE DELPHI6}
|
||||
{$DEFINE DELPHI7}
|
||||
{$ELSE}
|
||||
//Delphi
|
||||
{$IFDEF VER80}
|
||||
{$DEFINE DELPHI1}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF VER90}
|
||||
{$DEFINE DELPHI1}
|
||||
{$DEFINE DELPHI2}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF VER100}
|
||||
{$DEFINE DELPHI1}
|
||||
{$DEFINE DELPHI2}
|
||||
{$DEFINE DELPHI3}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF VER120}
|
||||
{$DEFINE DELPHI1}
|
||||
{$DEFINE DELPHI2}
|
||||
{$DEFINE DELPHI3}
|
||||
{$DEFINE DELPHI4}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF VER130}
|
||||
{$DEFINE DELPHI1}
|
||||
{$DEFINE DELPHI2}
|
||||
{$DEFINE DELPHI3}
|
||||
{$DEFINE DELPHI4}
|
||||
{$DEFINE DELPHI5}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF VER140}
|
||||
{$DEFINE DELPHI1}
|
||||
{$DEFINE DELPHI2}
|
||||
{$DEFINE DELPHI3}
|
||||
{$DEFINE DELPHI4}
|
||||
{$DEFINE DELPHI5}
|
||||
{$DEFINE DELPHI6}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF VER150}
|
||||
{$DEFINE DELPHI1}
|
||||
{$DEFINE DELPHI2}
|
||||
{$DEFINE DELPHI3}
|
||||
{$DEFINE DELPHI4}
|
||||
{$DEFINE DELPHI5}
|
||||
{$DEFINE DELPHI6}
|
||||
{$DEFINE DELPHI7}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF VER160}
|
||||
{$DEFINE DELPHI1}
|
||||
{$DEFINE DELPHI2}
|
||||
{$DEFINE DELPHI3}
|
||||
{$DEFINE DELPHI4}
|
||||
{$DEFINE DELPHI5}
|
||||
{$DEFINE DELPHI6}
|
||||
{$DEFINE DELPHI7}
|
||||
{$DEFINE DELPHI8}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF VER170}
|
||||
{$DEFINE DELPHI1}
|
||||
{$DEFINE DELPHI2}
|
||||
{$DEFINE DELPHI3}
|
||||
{$DEFINE DELPHI4}
|
||||
{$DEFINE DELPHI5}
|
||||
{$DEFINE DELPHI6}
|
||||
{$DEFINE DELPHI7}
|
||||
{$DEFINE DELPHI8}
|
||||
{$DEFINE DELPHI2005}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF VER180}
|
||||
{$DEFINE DELPHI1}
|
||||
{$DEFINE DELPHI2}
|
||||
{$DEFINE DELPHI3}
|
||||
{$DEFINE DELPHI4}
|
||||
{$DEFINE DELPHI5}
|
||||
{$DEFINE DELPHI6}
|
||||
{$DEFINE DELPHI7}
|
||||
{$DEFINE DELPHI8}
|
||||
{$DEFINE DELPHI2005}
|
||||
{$DEFINE DELPHI2006}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF VER185}
|
||||
{$DEFINE DELPHI1}
|
||||
{$DEFINE DELPHI2}
|
||||
{$DEFINE DELPHI3}
|
||||
{$DEFINE DELPHI4}
|
||||
{$DEFINE DELPHI5}
|
||||
{$DEFINE DELPHI6}
|
||||
{$DEFINE DELPHI7}
|
||||
{$DEFINE DELPHI8}
|
||||
{$DEFINE DELPHI2005}
|
||||
{$DEFINE DELPHI2006}
|
||||
{$DEFINE DELPHI2007}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF VER200}
|
||||
{$DEFINE DELPHI1}
|
||||
{$DEFINE DELPHI2}
|
||||
{$DEFINE DELPHI3}
|
||||
{$DEFINE DELPHI4}
|
||||
{$DEFINE DELPHI5}
|
||||
{$DEFINE DELPHI6}
|
||||
{$DEFINE DELPHI7}
|
||||
{$DEFINE DELPHI8}
|
||||
{$DEFINE DELPHI2005}
|
||||
{$DEFINE DELPHI2006}
|
||||
{$DEFINE DELPHI2007}
|
||||
{$DEFINE DELPHI2009}
|
||||
{$ENDIF}
|
||||
|
||||
{$IFDEF VER210}
|
||||
{$DEFINE DELPHI1}
|
||||
{$DEFINE DELPHI2}
|
||||
{$DEFINE DELPHI3}
|
||||
{$DEFINE DELPHI4}
|
||||
{$DEFINE DELPHI5}
|
||||
{$DEFINE DELPHI6}
|
||||
{$DEFINE DELPHI7}
|
||||
{$DEFINE DELPHI8}
|
||||
{$DEFINE DELPHI2005}
|
||||
{$DEFINE DELPHI2006}
|
||||
{$DEFINE DELPHI2007}
|
||||
{$DEFINE DELPHI2009}
|
||||
{$DEFINE DELPHI2010}
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
@@ -1,58 +0,0 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
using namespace System::Reflection;
|
||||
using namespace System::Runtime::CompilerServices;
|
||||
|
||||
//
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
//
|
||||
[assembly:AssemblyTitleAttribute("")];
|
||||
[assembly:AssemblyDescriptionAttribute("")];
|
||||
[assembly:AssemblyConfigurationAttribute("")];
|
||||
[assembly:AssemblyCompanyAttribute("")];
|
||||
[assembly:AssemblyProductAttribute("")];
|
||||
[assembly:AssemblyCopyrightAttribute("")];
|
||||
[assembly:AssemblyTrademarkAttribute("")];
|
||||
[assembly:AssemblyCultureAttribute("")];
|
||||
|
||||
//
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the value or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly:AssemblyVersionAttribute("1.0.*")];
|
||||
|
||||
//
|
||||
// In order to sign your assembly you must specify a key to use. Refer to the
|
||||
// Microsoft .NET Framework documentation for more information on assembly signing.
|
||||
//
|
||||
// Use the attributes below to control which key is used for signing.
|
||||
//
|
||||
// Notes:
|
||||
// (*) If no key is specified, the assembly is not signed.
|
||||
// (*) KeyName refers to a key that has been installed in the Crypto Service
|
||||
// Provider (CSP) on your machine. KeyFile refers to a file which contains
|
||||
// a key.
|
||||
// (*) If the KeyFile and the KeyName values are both specified, the
|
||||
// following processing occurs:
|
||||
// (1) If the KeyName can be found in the CSP, that key is used.
|
||||
// (2) If the KeyName does not exist and the KeyFile does exist, the key
|
||||
// in the KeyFile is installed into the CSP and used.
|
||||
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
|
||||
// When specifying the KeyFile, the location of the KeyFile should be
|
||||
// relative to the project directory.
|
||||
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
|
||||
// documentation for more information on this.
|
||||
//
|
||||
[assembly:AssemblyDelaySignAttribute(false)];
|
||||
[assembly:AssemblyKeyFileAttribute("")];
|
||||
[assembly:AssemblyKeyNameAttribute("")];
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
// ==========================================================
|
||||
// FreeImageIO.Net
|
||||
//
|
||||
// Design and implementation by
|
||||
// - Marcos Pernambuco Motta (marcos.pernambuco@gmail.com)
|
||||
//
|
||||
// This file is part of FreeImage 3
|
||||
//
|
||||
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
|
||||
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
|
||||
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
|
||||
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
|
||||
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
|
||||
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
|
||||
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
|
||||
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
|
||||
// THIS DISCLAIMER.
|
||||
//
|
||||
// Use at your own risk!
|
||||
// ==========================================================
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "FreeImageIO.Net.h"
|
||||
|
||||
|
||||
extern "C" static unsigned __stdcall ReadProc (void *buffer, unsigned size, unsigned count, fi_handle handle)
|
||||
{
|
||||
int total_read = 0;
|
||||
struct UNMANAGED_HANDLER* puh = (struct UNMANAGED_HANDLER*)handle;
|
||||
gcroot<unsigned char __gc []> mbuffer = new unsigned char __gc[size];
|
||||
try
|
||||
{
|
||||
total_read = puh->_stream->Read(mbuffer,0,size);
|
||||
Marshal::Copy(mbuffer,0,buffer,total_read);
|
||||
} __finally {
|
||||
mbuffer=NULL;
|
||||
}
|
||||
return (unsigned)total_read;
|
||||
}
|
||||
|
||||
extern "C" static unsigned __stdcall WriteProc (void *buffer, unsigned size, unsigned count, fi_handle handle)
|
||||
{
|
||||
struct UNMANAGED_HANDLER* puh = (struct UNMANAGED_HANDLER*)handle;
|
||||
gcroot<unsigned char __gc []> mbuffer = new unsigned char __gc[size*count];
|
||||
try
|
||||
{
|
||||
|
||||
unsigned char __pin* pbuffer = &mbuffer[0];
|
||||
memcpy(pbuffer,buffer,size*count);
|
||||
puh->_stream->Write(mbuffer,0,size);
|
||||
} __finally {
|
||||
mbuffer=NULL;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
extern "C" static int __stdcall SeekProc (fi_handle handle, long offset, int origin)
|
||||
{
|
||||
struct UNMANAGED_HANDLER* puh = (struct UNMANAGED_HANDLER*)handle;
|
||||
return (int)puh->_stream->Seek(offset,(SeekOrigin) origin);
|
||||
|
||||
}
|
||||
|
||||
extern "C" static long __stdcall TellProc(fi_handle handle)
|
||||
{
|
||||
struct UNMANAGED_HANDLER* puh = (struct UNMANAGED_HANDLER*)handle;
|
||||
return (long)puh->_stream->Position;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user