15 Commits

Author SHA1 Message Date
MarekKowalski d60a13fa26 Merge branch 'master' of https://github.com/MarekKowalski/LiveScan3D 2017-02-11 15:25:32 +01:00
MarekKowalski a70588497b The manual is now finished. 2017-02-11 15:25:06 +01:00
Marek cda38c1b6a Update README.md 2017-02-11 14:38:57 +01:00
MarekKowalski 2b6b153201 Playing sequences of .ply files now possible with the player. 2017-02-11 14:32:24 +01:00
MarekKowalski a1e8ba5345 Added LiveScanPlayer, as well as some bug fixes and improvements. 2017-02-03 16:31:06 +01:00
Marek Kowalski d15f242aca Added new features in live view window. 2017-01-25 11:36:40 +01:00
Marek Kowalski 64027fc77d Calibration now gets saved and loaded to a file on the client side.
Simplified the calibration data structure on client.
Updated README, LICENSE and gitignore.
2017-01-17 19:04:45 +01:00
Marek 8e15bcf917 Merge pull request #14 from JacekNaruniec/master
Added zstd frame compression option
2017-01-17 17:33:49 +01:00
JacekNaruniec 54ca7888ae FramesFileWriterReader renamed to FrameFileWriterReader. 2017-01-17 16:49:49 +01:00
JacekNaruniec 4b25491c9b Added a full screen toggle during live view ("f" key). 2017-01-17 14:20:13 +01:00
JacekNaruniec e453d927d3 Frames are now saved to the file, added FramesFileWriterReader class. 2017-01-14 18:48:27 +01:00
JacekNaruniec e068058868 Added zstd frame compression option (about 25% less frame size for compression level = 2). 2017-01-13 21:05:01 +01:00
Marek 87f376122d Merge pull request #13 from JacekNaruniec/master
Fixed a memory leak and a warning.
2017-01-13 14:14:46 +01:00
JacekNaruniec 25ef21692f Fixed a memory leak and a warning. 2017-01-13 14:11:16 +01:00
Marek c3c65198ff Merge pull request #12 from MarekKowalski/streaming
Streaming of the merged point cloud to other services.
2016-12-21 12:55:37 +01:00
46 changed files with 2579 additions and 353 deletions
+1
View File
@@ -6,6 +6,7 @@
*.user *.user
*.userosscache *.userosscache
*.sln.docstates *.sln.docstates
*.tlog
# User-specific files (MonoDevelop/Xamarin Studio) # User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs *.userprefs
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2015 Marek Copyright (c) 2015 Marek Kowalski, Jacek Naruniec
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
+9 -37
View File
@@ -12,64 +12,36 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LiveScanServer", "LiveScanS
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ICP", "ICP\ICP.vcxproj", "{973EE923-B423-4BCD-AA08-B03DA40CB51F}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ICP", "ICP\ICP.vcxproj", "{973EE923-B423-4BCD-AA08-B03DA40CB51F}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LiveScanPlayer", "LiveScanPlayer\LiveScanPlayer.csproj", "{E52AB19C-F67D-4932-90BD-CC549C1FEC8B}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|Mixed Platforms = Debug|Mixed Platforms
Debug|Win32 = Debug|Win32 Debug|Win32 = Debug|Win32
Release ICP as exe|Any CPU = Release ICP as exe|Any CPU
Release ICP as exe|Mixed Platforms = Release ICP as exe|Mixed Platforms
Release ICP as exe|Win32 = Release ICP as exe|Win32 Release ICP as exe|Win32 = Release ICP as exe|Win32
Release|Any CPU = Release|Any CPU
Release|Mixed Platforms = Release|Mixed Platforms
Release|Win32 = Release|Win32 Release|Win32 = Release|Win32
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Debug|Any CPU.ActiveCfg = Debug|Win32
{9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Debug|Mixed Platforms.Build.0 = Debug|Win32
{9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Debug|Win32.ActiveCfg = Debug|Win32 {9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Debug|Win32.ActiveCfg = Debug|Win32
{9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Debug|Win32.Build.0 = Debug|Win32 {9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Debug|Win32.Build.0 = Debug|Win32
{9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Release ICP as exe|Any CPU.ActiveCfg = Release|Win32
{9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Release ICP as exe|Mixed Platforms.ActiveCfg = Release|Win32
{9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Release ICP as exe|Mixed Platforms.Build.0 = Release|Win32
{9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Release ICP as exe|Win32.ActiveCfg = Release|Win32 {9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Release ICP as exe|Win32.ActiveCfg = Release|Win32
{9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Release ICP as exe|Win32.Build.0 = Release|Win32
{9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Release|Any CPU.ActiveCfg = Release|Win32
{9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Release|Mixed Platforms.ActiveCfg = Release|Win32
{9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Release|Mixed Platforms.Build.0 = Release|Win32
{9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Release|Win32.ActiveCfg = Release|Win32 {9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Release|Win32.ActiveCfg = Release|Win32
{9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Release|Win32.Build.0 = Release|Win32 {9B550BBA-EAFB-4D12-8B1C-8FDA39361F52}.Release|Win32.Build.0 = Release|Win32
{78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
{78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
{78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Debug|Win32.ActiveCfg = Debug|Any CPU {78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Debug|Win32.ActiveCfg = Debug|Any CPU
{78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Release ICP as exe|Any CPU.ActiveCfg = Release|Any CPU {78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Debug|Win32.Build.0 = Debug|Any CPU
{78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Release ICP as exe|Any CPU.Build.0 = Release|Any CPU
{78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Release ICP as exe|Mixed Platforms.ActiveCfg = Release|Any CPU
{78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Release ICP as exe|Mixed Platforms.Build.0 = Release|Any CPU
{78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Release ICP as exe|Win32.ActiveCfg = Release|Any CPU {78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Release ICP as exe|Win32.ActiveCfg = Release|Any CPU
{78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Release|Any CPU.Build.0 = Release|Any CPU
{78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
{78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Release|Mixed Platforms.Build.0 = Release|Any CPU
{78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Release|Win32.ActiveCfg = Release|Any CPU {78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Release|Win32.ActiveCfg = Release|Any CPU
{973EE923-B423-4BCD-AA08-B03DA40CB51F}.Debug|Any CPU.ActiveCfg = Debug|Win32 {78422B2C-0EF1-4A28-A40E-2A7C4A9204B1}.Release|Win32.Build.0 = Release|Any CPU
{973EE923-B423-4BCD-AA08-B03DA40CB51F}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{973EE923-B423-4BCD-AA08-B03DA40CB51F}.Debug|Mixed Platforms.Build.0 = Debug|Win32
{973EE923-B423-4BCD-AA08-B03DA40CB51F}.Debug|Win32.ActiveCfg = Debug|Win32 {973EE923-B423-4BCD-AA08-B03DA40CB51F}.Debug|Win32.ActiveCfg = Debug|Win32
{973EE923-B423-4BCD-AA08-B03DA40CB51F}.Debug|Win32.Build.0 = Debug|Win32 {973EE923-B423-4BCD-AA08-B03DA40CB51F}.Debug|Win32.Build.0 = Debug|Win32
{973EE923-B423-4BCD-AA08-B03DA40CB51F}.Release ICP as exe|Any CPU.ActiveCfg = Release|Win32
{973EE923-B423-4BCD-AA08-B03DA40CB51F}.Release ICP as exe|Mixed Platforms.ActiveCfg = Release|Win32
{973EE923-B423-4BCD-AA08-B03DA40CB51F}.Release ICP as exe|Mixed Platforms.Build.0 = Release|Win32
{973EE923-B423-4BCD-AA08-B03DA40CB51F}.Release ICP as exe|Win32.ActiveCfg = Release|Win32 {973EE923-B423-4BCD-AA08-B03DA40CB51F}.Release ICP as exe|Win32.ActiveCfg = Release|Win32
{973EE923-B423-4BCD-AA08-B03DA40CB51F}.Release ICP as exe|Win32.Build.0 = Release|Win32 {973EE923-B423-4BCD-AA08-B03DA40CB51F}.Release ICP as exe|Win32.Build.0 = Release|Win32
{973EE923-B423-4BCD-AA08-B03DA40CB51F}.Release|Any CPU.ActiveCfg = Release DLL|Win32
{973EE923-B423-4BCD-AA08-B03DA40CB51F}.Release|Mixed Platforms.ActiveCfg = Release DLL|Win32
{973EE923-B423-4BCD-AA08-B03DA40CB51F}.Release|Mixed Platforms.Build.0 = Release DLL|Win32
{973EE923-B423-4BCD-AA08-B03DA40CB51F}.Release|Win32.ActiveCfg = Release DLL|Win32 {973EE923-B423-4BCD-AA08-B03DA40CB51F}.Release|Win32.ActiveCfg = Release DLL|Win32
{973EE923-B423-4BCD-AA08-B03DA40CB51F}.Release|Win32.Build.0 = Release DLL|Win32 {973EE923-B423-4BCD-AA08-B03DA40CB51F}.Release|Win32.Build.0 = Release DLL|Win32
{E52AB19C-F67D-4932-90BD-CC549C1FEC8B}.Debug|Win32.ActiveCfg = Debug|Any CPU
{E52AB19C-F67D-4932-90BD-CC549C1FEC8B}.Debug|Win32.Build.0 = Debug|Any CPU
{E52AB19C-F67D-4932-90BD-CC549C1FEC8B}.Release ICP as exe|Win32.ActiveCfg = Release|Any CPU
{E52AB19C-F67D-4932-90BD-CC549C1FEC8B}.Release|Win32.ActiveCfg = Release|Any CPU
{E52AB19C-F67D-4932-90BD-CC549C1FEC8B}.Release|Win32.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
+4 -2
View File
@@ -13,6 +13,7 @@
<ItemGroup> <ItemGroup>
<ClInclude Include="..\include\LiveScanClient\calibration.h" /> <ClInclude Include="..\include\LiveScanClient\calibration.h" />
<ClInclude Include="..\include\LiveScanClient\filter.h" /> <ClInclude Include="..\include\LiveScanClient\filter.h" />
<ClInclude Include="..\include\LiveScanClient\frameFileWriterReader.h" />
<ClInclude Include="..\include\LiveScanClient\iCapture.h" /> <ClInclude Include="..\include\LiveScanClient\iCapture.h" />
<ClInclude Include="..\include\LiveScanClient\imageRenderer.h" /> <ClInclude Include="..\include\LiveScanClient\imageRenderer.h" />
<ClInclude Include="..\include\LiveScanClient\iMarker.h" /> <ClInclude Include="..\include\LiveScanClient\iMarker.h" />
@@ -28,6 +29,7 @@
<ItemGroup> <ItemGroup>
<ClCompile Include="..\src\LiveScanClient\calibration.cpp" /> <ClCompile Include="..\src\LiveScanClient\calibration.cpp" />
<ClCompile Include="..\src\LiveScanClient\filter.cpp" /> <ClCompile Include="..\src\LiveScanClient\filter.cpp" />
<ClCompile Include="..\src\LiveScanClient\frameFileWriterReader.cpp" />
<ClCompile Include="..\src\LiveScanClient\iCapture.cpp" /> <ClCompile Include="..\src\LiveScanClient\iCapture.cpp" />
<ClCompile Include="..\src\LiveScanClient\imageRenderer.cpp" /> <ClCompile Include="..\src\LiveScanClient\imageRenderer.cpp" />
<ClCompile Include="..\src\LiveScanClient\iMarker.cpp" /> <ClCompile Include="..\src\LiveScanClient\iMarker.cpp" />
@@ -91,7 +93,7 @@
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>c:\Program Files\Microsoft SDKs\Kinect\v2.0_1409\Lib\x86\;D:\opencv\build\x86\vc12\lib;$(KINECTSDK20_DIR)\lib\x86;$(SolutionDir)lib</AdditionalLibraryDirectories> <AdditionalLibraryDirectories>c:\Program Files\Microsoft SDKs\Kinect\v2.0_1409\Lib\x86\;D:\opencv\build\x86\vc12\lib;$(KINECTSDK20_DIR)\lib\x86;$(SolutionDir)lib</AdditionalLibraryDirectories>
<AdditionalDependencies>opencv_highgui248d.lib;opencv_calib3d248d.lib;opencv_imgproc248d.lib;opencv_core248d.lib;kinect20.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>opencv_highgui248d.lib;opencv_calib3d248d.lib;opencv_imgproc248d.lib;opencv_core248d.lib;kinect20.lib;kernel32.lib;libzstdd.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SubSystem>NotSet</SubSystem> <SubSystem>NotSet</SubSystem>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
@@ -111,7 +113,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>opencv_highgui248.lib;opencv_calib3d248.lib;opencv_imgproc248.lib;opencv_core248.lib;kinect20.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>opencv_highgui248.lib;opencv_calib3d248.lib;opencv_imgproc248.lib;opencv_core248.lib;kinect20.lib;libzstd.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>c:\Program Files\Microsoft SDKs\Kinect\v2.0_1409\Lib\x86\;D:\opencv\build\x86\vc12\lib;$(KINECTSDK20_DIR)\lib\x86;$(SolutionDir)lib</AdditionalLibraryDirectories> <AdditionalLibraryDirectories>c:\Program Files\Microsoft SDKs\Kinect\v2.0_1409\Lib\x86\;D:\opencv\build\x86\vc12\lib;$(KINECTSDK20_DIR)\lib\x86;$(SolutionDir)lib</AdditionalLibraryDirectories>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
@@ -54,6 +54,9 @@
<ClInclude Include="..\include\LiveScanClient\utils.h"> <ClInclude Include="..\include\LiveScanClient\utils.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\include\LiveScanClient\frameFileWriterReader.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="..\src\socketCS.cpp"> <ClCompile Include="..\src\socketCS.cpp">
@@ -86,6 +89,9 @@
<ClCompile Include="..\src\LiveScanClient\utils.cpp"> <ClCompile Include="..\src\LiveScanClient\utils.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\src\LiveScanClient\frameFileWriterReader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Image Include="app.ico"> <Image Include="app.ico">
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>
+117
View File
@@ -0,0 +1,117 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace LiveScanPlayer
{
class FrameFileReaderBin : IFrameFileReader
{
BinaryReader binaryReader;
int currentFrameIdx = 0;
string filename;
public FrameFileReaderBin(string filename)
{
this.filename = filename;
binaryReader = new BinaryReader(File.Open(this.filename, FileMode.Open));
}
~FrameFileReaderBin()
{
binaryReader.Dispose();
}
public int frameIdx
{
get
{
return currentFrameIdx;
}
set
{
JumpToFrame(value);
}
}
public void ReadFrame(List<float> vertices, List<byte> colors)
{
if (binaryReader.BaseStream.Position == binaryReader.BaseStream.Length)
Rewind();
string[] lineParts = ReadLine().Split(' ');
int nPoints = Int32.Parse(lineParts[1]);
lineParts = ReadLine().Split(' ');
int frameTimestamp = Int32.Parse(lineParts[1]);
Console.WriteLine((frameTimestamp / 1000).ToString());
short[] tempVertices = new short[3 * nPoints];
byte[] tempColors = new byte[4 * nPoints];
int bytesPerVertexPoint = 3 * sizeof(short);
int bytesPerColorPoint = 4 * sizeof(byte);
int bytesPerPoint = bytesPerVertexPoint + bytesPerColorPoint;
byte[] frameData = binaryReader.ReadBytes(bytesPerPoint * nPoints);
if (frameData.Length < bytesPerPoint * nPoints)
{
Rewind();
ReadFrame(vertices, colors);
return;
}
int vertexDataSize = nPoints * bytesPerVertexPoint;
int colorDataSize = nPoints * bytesPerColorPoint;
Buffer.BlockCopy(frameData, 0, tempVertices, 0, vertexDataSize);
Buffer.BlockCopy(frameData, vertexDataSize, tempColors, 0, colorDataSize);
for (int i = 0; i < nPoints; i++)
{
for (int j = 0; j < 3; j++)
{
vertices.Add(tempVertices[3 * i + j] / 1000.0f);
colors.Add(tempColors[4 * i + j]);
}
}
binaryReader.ReadByte();
currentFrameIdx++;
}
public void JumpToFrame(int frameIdx)
{
Rewind();
for (int i = 0; i < frameIdx; i++)
{
List<float> vertices = new List<float>();
List<byte> colors = new List<byte>();
ReadFrame(vertices, colors);
}
}
public void Rewind()
{
currentFrameIdx = 0;
binaryReader.BaseStream.Seek(0, SeekOrigin.Begin);
}
public string ReadLine()
{
StringBuilder builder = new StringBuilder();
byte buffer = binaryReader.ReadByte();
while (buffer != '\n')
{
builder.Append((char)buffer);
buffer = binaryReader.ReadByte();
}
return builder.ToString();
}
}
}
+90
View File
@@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace LiveScanPlayer
{
class FrameFileReaderPly : IFrameFileReader
{
string[] filenames;
int currentFrameIdx = 0;
public FrameFileReaderPly(string[] filenames)
{
this.filenames = filenames;
}
public int frameIdx
{
get
{
return currentFrameIdx;
}
set
{
JumpToFrame(value);
}
}
public void ReadFrame(List<float> vertices, List<byte> colors)
{
BinaryReader reader = new BinaryReader(new FileStream(filenames[currentFrameIdx], FileMode.Open));
string line = ReadLine(reader);
while (!line.Contains("element vertex"))
line = ReadLine(reader);
string[] lineElems = line.Split(' ');
int nPoints = Int32.Parse(lineElems[2]);
while (!line.Contains("end_header"))
line = ReadLine(reader);
for (int i = 0; i < nPoints; i++)
{
for (int j = 0; j < 3; j++)
{
vertices.Add(reader.ReadSingle());
}
for (int j = 0; j < 3; j++)
{
colors.Add(reader.ReadByte());
}
}
reader.Dispose();
currentFrameIdx++;
if (currentFrameIdx >= filenames.Length)
currentFrameIdx = 0;
}
public void JumpToFrame(int frameIdx)
{
currentFrameIdx = frameIdx;
if (currentFrameIdx >= filenames.Length)
currentFrameIdx = 0;
}
public void Rewind()
{
currentFrameIdx = 0;
}
public string ReadLine(BinaryReader binaryReader)
{
StringBuilder builder = new StringBuilder();
byte buffer = binaryReader.ReadByte();
while (buffer != '\n')
{
builder.Append((char)buffer);
buffer = binaryReader.ReadByte();
}
return builder.ToString();
}
}
}
+23
View File
@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LiveScanPlayer
{
interface IFrameFileReader
{
int frameIdx
{
get;
set;
}
void ReadFrame(List<float> vertices, List<byte> colors);
void JumpToFrame(int frameIdx);
void Rewind();
}
}
+101
View File
@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{E52AB19C-F67D-4932-90BD-CC549C1FEC8B}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>LiveScanPlayer</RootNamespace>
<AssemblyName>LiveScanPlayer</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="OpenTK, Version=1.1.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\bin\OpenTK.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="FrameFileReaderPly.cs" />
<Compile Include="IFrameFileReader.cs" />
<Compile Include="PlayerWindowForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="PlayerWindowForm.Designer.cs">
<DependentUpon>PlayerWindowForm.cs</DependentUpon>
</Compile>
<Compile Include="FrameFileReaderBin.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="PlayerWindowForm.resx">
<DependentUpon>PlayerWindowForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\LiveScanServer\LiveScanServer.csproj">
<Project>{78422b2c-0ef1-4a28-a40e-2a7c4a9204b1}</Project>
<Name>LiveScanServer</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
+169
View File
@@ -0,0 +1,169 @@
namespace LiveScanPlayer
{
partial class PlayerWindowForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.btSelect = new System.Windows.Forms.Button();
this.btStart = new System.Windows.Forms.Button();
this.btShow = new System.Windows.Forms.Button();
this.updateWorker = new System.ComponentModel.BackgroundWorker();
this.OpenGLWorker = new System.ComponentModel.BackgroundWorker();
this.btRewind = new System.Windows.Forms.Button();
this.btRemove = new System.Windows.Forms.Button();
this.lFrameFilesListView = new System.Windows.Forms.ListView();
this.chSaveFrames = new System.Windows.Forms.CheckBox();
this.btnSelectPly = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// btSelect
//
this.btSelect.Location = new System.Drawing.Point(12, 41);
this.btSelect.Name = "btSelect";
this.btSelect.Size = new System.Drawing.Size(89, 23);
this.btSelect.TabIndex = 0;
this.btSelect.Text = "Select bin files";
this.btSelect.UseVisualStyleBackColor = true;
this.btSelect.Click += new System.EventHandler(this.btSelect_Click);
//
// btStart
//
this.btStart.Location = new System.Drawing.Point(12, 12);
this.btStart.Name = "btStart";
this.btStart.Size = new System.Drawing.Size(89, 23);
this.btStart.TabIndex = 1;
this.btStart.Text = "Start player";
this.btStart.UseVisualStyleBackColor = true;
this.btStart.Click += new System.EventHandler(this.btStart_Click);
//
// btShow
//
this.btShow.Location = new System.Drawing.Point(12, 157);
this.btShow.Name = "btShow";
this.btShow.Size = new System.Drawing.Size(89, 23);
this.btShow.TabIndex = 2;
this.btShow.Text = "Show live";
this.btShow.UseVisualStyleBackColor = true;
this.btShow.Click += new System.EventHandler(this.btShow_Click);
//
// updateWorker
//
this.updateWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(this.updateWorker_DoWork);
//
// OpenGLWorker
//
this.OpenGLWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(this.OpenGLWorker_DoWork);
//
// btRewind
//
this.btRewind.Location = new System.Drawing.Point(12, 128);
this.btRewind.Name = "btRewind";
this.btRewind.Size = new System.Drawing.Size(89, 23);
this.btRewind.TabIndex = 5;
this.btRewind.Text = "Rewind";
this.btRewind.UseVisualStyleBackColor = true;
this.btRewind.Click += new System.EventHandler(this.btRewind_Click);
//
// btRemove
//
this.btRemove.Location = new System.Drawing.Point(12, 99);
this.btRemove.Name = "btRemove";
this.btRemove.Size = new System.Drawing.Size(89, 23);
this.btRemove.TabIndex = 6;
this.btRemove.Text = "Remove file";
this.btRemove.UseVisualStyleBackColor = true;
this.btRemove.Click += new System.EventHandler(this.btRemove_Click);
//
// lFrameFilesListView
//
this.lFrameFilesListView.LabelEdit = true;
this.lFrameFilesListView.Location = new System.Drawing.Point(107, 12);
this.lFrameFilesListView.MultiSelect = false;
this.lFrameFilesListView.Name = "lFrameFilesListView";
this.lFrameFilesListView.Size = new System.Drawing.Size(408, 139);
this.lFrameFilesListView.TabIndex = 7;
this.lFrameFilesListView.UseCompatibleStateImageBehavior = false;
this.lFrameFilesListView.View = System.Windows.Forms.View.Details;
this.lFrameFilesListView.AfterLabelEdit += new System.Windows.Forms.LabelEditEventHandler(this.lFrameFilesListView_AfterLabelEdit);
this.lFrameFilesListView.DoubleClick += new System.EventHandler(this.lFrameFilesListView_DoubleClick);
//
// chSaveFrames
//
this.chSaveFrames.AutoSize = true;
this.chSaveFrames.Location = new System.Drawing.Point(432, 157);
this.chSaveFrames.Name = "chSaveFrames";
this.chSaveFrames.Size = new System.Drawing.Size(83, 17);
this.chSaveFrames.TabIndex = 8;
this.chSaveFrames.Text = "save frames";
this.chSaveFrames.UseVisualStyleBackColor = true;
//
// btnSelectPly
//
this.btnSelectPly.Location = new System.Drawing.Point(12, 70);
this.btnSelectPly.Name = "btnSelectPly";
this.btnSelectPly.Size = new System.Drawing.Size(89, 23);
this.btnSelectPly.TabIndex = 9;
this.btnSelectPly.Text = "Select ply files";
this.btnSelectPly.UseVisualStyleBackColor = true;
this.btnSelectPly.Click += new System.EventHandler(this.btnSelectPly_Click);
//
// PlayerWindowForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(527, 190);
this.Controls.Add(this.btnSelectPly);
this.Controls.Add(this.chSaveFrames);
this.Controls.Add(this.lFrameFilesListView);
this.Controls.Add(this.btRemove);
this.Controls.Add(this.btRewind);
this.Controls.Add(this.btShow);
this.Controls.Add(this.btStart);
this.Controls.Add(this.btSelect);
this.Name = "PlayerWindowForm";
this.Text = "LiveScanPlayer";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.PlayerWindowForm_FormClosing);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button btSelect;
private System.Windows.Forms.Button btStart;
private System.Windows.Forms.Button btShow;
private System.ComponentModel.BackgroundWorker updateWorker;
private System.ComponentModel.BackgroundWorker OpenGLWorker;
private System.Windows.Forms.Button btRewind;
private System.Windows.Forms.Button btRemove;
private System.Windows.Forms.ListView lFrameFilesListView;
private System.Windows.Forms.CheckBox chSaveFrames;
private System.Windows.Forms.Button btnSelectPly;
}
}
+237
View File
@@ -0,0 +1,237 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using KinectServer;
namespace LiveScanPlayer
{
public partial class PlayerWindowForm : Form
{
BindingList<IFrameFileReader> lFrameFiles = new BindingList<IFrameFileReader>();
bool bPlayerRunning = false;
List<float> lAllVertices = new List<float>();
List<byte> lAllColors = new List<byte>();
TransferServer oTransferServer = new TransferServer();
AutoResetEvent eUpdateWorkerFinished = new AutoResetEvent(false);
public PlayerWindowForm()
{
InitializeComponent();
oTransferServer.lVertices = lAllVertices;
oTransferServer.lColors = lAllColors;
lFrameFilesListView.Columns.Add("Current frame", 75);
lFrameFilesListView.Columns.Add("Filename", 300);
}
private void PlayerWindowForm_FormClosing(object sender, FormClosingEventArgs e)
{
bPlayerRunning = false;
oTransferServer.StopServer();
}
private void btSelect_Click(object sender, EventArgs e)
{
OpenFileDialog dialog = new OpenFileDialog();
dialog.Multiselect = true;
dialog.ShowDialog();
lock (lFrameFiles)
{
for (int i = 0; i < dialog.FileNames.Length; i++)
{
lFrameFiles.Add(new FrameFileReaderBin(dialog.FileNames[i]));
var item = new ListViewItem(new [] { "0", dialog.FileNames[i]});
lFrameFilesListView.Items.Add(item);
}
}
}
private void btnSelectPly_Click(object sender, EventArgs e)
{
OpenFileDialog dialog = new OpenFileDialog();
dialog.Multiselect = true;
dialog.ShowDialog();
if (dialog.FileNames.Length == 0)
return;
lock (lFrameFiles)
{
lFrameFiles.Add(new FrameFileReaderPly(dialog.FileNames));
var item = new ListViewItem(new[] { "0", Path.GetDirectoryName(dialog.FileNames[0]) });
lFrameFilesListView.Items.Add(item);
}
}
private void btStart_Click(object sender, EventArgs e)
{
bPlayerRunning = !bPlayerRunning;
if (bPlayerRunning)
{
oTransferServer.StartServer();
updateWorker.RunWorkerAsync();
btStart.Text = "Stop player";
}
else
{
oTransferServer.StopServer();
btStart.Text = "Start player";
eUpdateWorkerFinished.WaitOne();
}
}
private void btRemove_Click(object sender, EventArgs e)
{
if (lFrameFilesListView.SelectedIndices.Count == 0)
return;
lock (lFrameFiles)
{
int idx = lFrameFilesListView.SelectedIndices[0];
lFrameFilesListView.Items.RemoveAt(idx);
lFrameFiles.RemoveAt(idx);
}
}
private void btRewind_Click(object sender, EventArgs e)
{
lock (lFrameFiles)
{
for (int i = 0; i < lFrameFiles.Count; i++)
{
lFrameFiles[i].Rewind();
lFrameFilesListView.Items[i].Text = "0";
}
}
}
private void btShow_Click(object sender, EventArgs e)
{
if (!OpenGLWorker.IsBusy)
OpenGLWorker.RunWorkerAsync();
}
private void updateWorker_DoWork(object sender, DoWorkEventArgs e)
{
int curFrameIdx = 0;
string outDir = "outPlayer\\";
DirectoryInfo di = Directory.CreateDirectory(outDir);
while (bPlayerRunning)
{
Thread.Sleep(50);
List<float> tempAllVertices = new List<float>();
List<byte> tempAllColors = new List<byte>();
lock (lFrameFiles)
{
for (int i = 0; i < lFrameFiles.Count; i++)
{
List<float> vertices = new List<float>();
List<byte> colors = new List<byte>();
lFrameFiles[i].ReadFrame(vertices, colors);
tempAllVertices.AddRange(vertices);
tempAllColors.AddRange(colors);
}
}
Thread frameIdxUpdate = new Thread(() => this.Invoke((MethodInvoker)delegate { this.UpdateDisplayedFrameIndices(); }));
frameIdxUpdate.Start();
lock (lAllVertices)
{
lAllVertices.Clear();
lAllColors.Clear();
lAllVertices.AddRange(tempAllVertices);
lAllColors.AddRange(tempAllColors);
}
if (chSaveFrames.Checked)
SaveCurrentFrameToFile(outDir, curFrameIdx);
curFrameIdx++;
}
eUpdateWorkerFinished.Set();
}
private void OpenGLWorker_DoWork(object sender, DoWorkEventArgs e)
{
OpenGLWindow openGLWindow = new OpenGLWindow();
openGLWindow.vertices = lAllVertices;
openGLWindow.colors = lAllColors;
openGLWindow.Run();
}
private void lFrameFilesListView_DoubleClick(object sender, EventArgs e)
{
lFrameFilesListView.SelectedItems[0].BeginEdit();
}
private void lFrameFilesListView_AfterLabelEdit(object sender, LabelEditEventArgs e)
{
int fileIdx = lFrameFilesListView.SelectedIndices[0];
int frameIdx;
bool res = Int32.TryParse(e.Label, out frameIdx);
if (!res)
{
e.CancelEdit = true;
return;
}
lock (lFrameFiles)
{
lFrameFiles[fileIdx].JumpToFrame(frameIdx);
}
}
private void UpdateDisplayedFrameIndices()
{
lock (lFrameFiles)
{
for (int i = 0; i < lFrameFiles.Count; i++)
{
lFrameFilesListView.Items[i].SubItems[0].Text = lFrameFiles[i].frameIdx.ToString();
}
}
}
private void SaveCurrentFrameToFile(string outDir, int frameIdx)
{
List<float> lVertices = new List<float>();
List<byte> lColors = new List<byte>();
lock (lAllVertices)
{
lVertices.AddRange(lAllVertices);
lColors.AddRange(lAllColors);
}
string outputFilename = outDir + frameIdx.ToString().PadLeft(5, '0') + ".ply";
Utils.saveToPly(outputFilename, lVertices, lColors, true);
}
}
}
+126
View File
@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="updateWorker.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>133, 17</value>
</metadata>
<metadata name="OpenGLWorker.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>263, 17</value>
</metadata>
</root>
+22
View File
@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace LiveScanPlayer
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new PlayerWindowForm());
}
}
}
+36
View File
@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 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: AssemblyTitle("LiveScanPlayer")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LiveScanPlayer")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("b435173f-8157-41c6-b94f-3cc1feb6153e")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
+71
View File
@@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace LiveScanPlayer.Properties
{
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("LiveScanPlayer.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}
+117
View File
@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
+30
View File
@@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace LiveScanPlayer.Properties
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default
{
get
{
return defaultInstance;
}
}
}
}
@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>
+5 -1
View File
@@ -35,10 +35,11 @@ namespace KinectServer
public bool bStreamOnlyBodies = false; public bool bStreamOnlyBodies = false;
public bool bShowSkeletons = true; public bool bShowSkeletons = true;
public int iCompressionLevel = 2; // 0 for no compression, 2 is recommended
public int nNumICPIterations = 10; public int nNumICPIterations = 10;
public int nNumRefineIters = 2; public int nNumRefineIters = 2;
public bool bMergeScansForSave = false; public bool bMergeScansForSave = true;
public bool bSaveAsBinaryPLY = true; public bool bSaveAsBinaryPLY = true;
public KinectSettings() public KinectSettings()
@@ -96,6 +97,9 @@ namespace KinectServer
else else
lData.Add(0); lData.Add(0);
bTemp = BitConverter.GetBytes(iCompressionLevel);
lData.AddRange(bTemp);
return lData; return lData;
} }
} }
+20 -19
View File
@@ -42,7 +42,7 @@ namespace KinectServer
public List<byte> lFrameRGB = new List<byte>(); public List<byte> lFrameRGB = new List<byte>();
public List<Single> lFrameVerts = new List<Single>(); public List<Single> lFrameVerts = new List<Single>();
public List<Body> lBodies = new List<Body>(); public List<Body> lBodies = new List<Body>();
public event SocketChangedHandler eChanged; public event SocketChangedHandler eChanged;
@@ -99,7 +99,7 @@ namespace KinectServer
public void SendCalibrationData() public void SendCalibrationData()
{ {
int size = 1 + 2 * (9 + 3) * sizeof(float); int size = 1 + (9 + 3) * sizeof(float);
byte[] data = new byte[size]; byte[] data = new byte[size];
int i = 0; int i = 0;
@@ -111,12 +111,6 @@ namespace KinectServer
Buffer.BlockCopy(oWorldTransform.t, 0, data, i, 3 * sizeof(float)); Buffer.BlockCopy(oWorldTransform.t, 0, data, i, 3 * sizeof(float));
i += 3 * sizeof(float); i += 3 * sizeof(float);
Buffer.BlockCopy(oCameraPose.R, 0, data, i, 9 * sizeof(float));
i += 9 * sizeof(float);
Buffer.BlockCopy(oCameraPose.t, 0, data, i, 3 * sizeof(float));
i += 3 * sizeof(float);
if (SocketConnected()) if (SocketConnected())
oSocket.Send(data); oSocket.Send(data);
} }
@@ -141,11 +135,15 @@ namespace KinectServer
buffer = Receive(sizeof(float) * 3); buffer = Receive(sizeof(float) * 3);
Buffer.BlockCopy(buffer, 0, oWorldTransform.t, 0, sizeof(float) * 3); Buffer.BlockCopy(buffer, 0, oWorldTransform.t, 0, sizeof(float) * 3);
buffer = Receive(sizeof(float) * 9); oCameraPose.R = oWorldTransform.R;
Buffer.BlockCopy(buffer, 0, oCameraPose.R, 0, sizeof(float) * 9); for (int i = 0; i < 3; i++)
{
buffer = Receive(sizeof(float) * 3); oCameraPose.t[i] = 0.0f;
Buffer.BlockCopy(buffer, 0, oCameraPose.t, 0, sizeof(float) * 3); for (int j = 0; j < 3; j++)
{
oCameraPose.t[i] += oWorldTransform.t[j] * oWorldTransform.R[i, j];
}
}
UpdateSocketState(); UpdateSocketState();
} }
@@ -165,19 +163,16 @@ namespace KinectServer
return; return;
} }
oSocket.Receive(buffer, 4, SocketFlags.None); oSocket.Receive(buffer, 8, SocketFlags.None);
//string result = System.Text.Encoding.UTF8.GetString(buffer);
//n_to_read = Int32.Parse(result);
nToRead = BitConverter.ToInt32(buffer, 0); nToRead = BitConverter.ToInt32(buffer, 0);
int iCompressed = BitConverter.ToInt32(buffer, 4);
if (nToRead == -1) if (nToRead == -1)
{ {
bNoMoreStoredFrames = true; bNoMoreStoredFrames = true;
return; return;
} }
buffer = new byte[nToRead]; buffer = new byte[nToRead];
int nAlreadyRead = 0; int nAlreadyRead = 0;
@@ -192,6 +187,12 @@ namespace KinectServer
nAlreadyRead += oSocket.Receive(buffer, nAlreadyRead, nToRead - nAlreadyRead, SocketFlags.None); nAlreadyRead += oSocket.Receive(buffer, nAlreadyRead, nToRead - nAlreadyRead, SocketFlags.None);
} }
if (iCompressed == 1)
buffer = ZSTDDecompressor.Decompress(buffer);
//Receive depth and color data //Receive depth and color data
int startIdx = 0; int startIdx = 0;
+6 -1
View File
@@ -32,7 +32,10 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="OpenTK, Version=1.1.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL" /> <Reference Include="OpenTK, Version=1.1.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\bin\OpenTK.dll</HintPath>
</Reference>
<Reference Include="OpenTK.Compatibility, Version=1.1.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL" /> <Reference Include="OpenTK.Compatibility, Version=1.1.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL" />
<Reference Include="OpenTK.GLControl, Version=1.1.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL" /> <Reference Include="OpenTK.GLControl, Version=1.1.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL" />
<Reference Include="System" /> <Reference Include="System" />
@@ -68,8 +71,10 @@
<Compile Include="TransferServer.cs" /> <Compile Include="TransferServer.cs" />
<Compile Include="TransferSocket.cs" /> <Compile Include="TransferSocket.cs" />
<Compile Include="Utils.cs" /> <Compile Include="Utils.cs" />
<Compile Include="ZSTDDecompressor.cs" />
<EmbeddedResource Include="MainWindowForm.resx"> <EmbeddedResource Include="MainWindowForm.resx">
<DependentUpon>MainWindowForm.cs</DependentUpon> <DependentUpon>MainWindowForm.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource> </EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx"> <EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator> <Generator>ResXFileCodeGenerator</Generator>
+1
View File
@@ -80,6 +80,7 @@
// lClientListBox // lClientListBox
// //
this.lClientListBox.FormattingEnabled = true; this.lClientListBox.FormattingEnabled = true;
this.lClientListBox.HorizontalScrollbar = true;
this.lClientListBox.Location = new System.Drawing.Point(113, 12); this.lClientListBox.Location = new System.Drawing.Point(113, 12);
this.lClientListBox.Name = "lClientListBox"; this.lClientListBox.Name = "lClientListBox";
this.lClientListBox.Size = new System.Drawing.Size(219, 108); this.lClientListBox.Size = new System.Drawing.Size(219, 108);
+9 -58
View File
@@ -42,7 +42,7 @@ namespace KinectServer
static extern float ICP(IntPtr verts1, IntPtr verts2, int nVerts1, int nVerts2, float[] R, float[] t, int maxIter = 200); static extern float ICP(IntPtr verts1, IntPtr verts2, int nVerts1, int nVerts2, float[] R, float[] t, int maxIter = 200);
KinectServer oServer; KinectServer oServer;
TransferServer oTranfserServer; TransferServer oTransferServer;
//Those three variables are shared with the OpenGLWindow class and are used to exchange data with it. //Those three variables are shared with the OpenGLWindow class and are used to exchange data with it.
//Vertices from all of the sensors //Vertices from all of the sensors
@@ -83,9 +83,9 @@ namespace KinectServer
oServer = new KinectServer(oSettings); oServer = new KinectServer(oSettings);
oServer.eSocketListChanged += new SocketListChangedHandler(UpdateListView); oServer.eSocketListChanged += new SocketListChangedHandler(UpdateListView);
oTranfserServer = new TransferServer(); oTransferServer = new TransferServer();
oTranfserServer.lVertices = lAllVertices; oTransferServer.lVertices = lAllVertices;
oTranfserServer.lColors = lAllColors; oTransferServer.lColors = lAllColors;
InitializeComponent(); InitializeComponent();
} }
@@ -100,7 +100,7 @@ namespace KinectServer
stream.Close(); stream.Close();
oServer.StopServer(); oServer.StopServer();
oTranfserServer.StopServer(); oTransferServer.StopServer();
} }
//Starts the server //Starts the server
@@ -111,13 +111,13 @@ namespace KinectServer
if (bServerRunning) if (bServerRunning)
{ {
oServer.StartServer(); oServer.StartServer();
oTranfserServer.StartServer(); oTransferServer.StartServer();
btStart.Text = "Stop server"; btStart.Text = "Stop server";
} }
else else
{ {
oServer.StopServer(); oServer.StopServer();
oTranfserServer.StopServer(); oTransferServer.StopServer();
btStart.Text = "Start server"; btStart.Text = "Start server";
} }
} }
@@ -224,7 +224,7 @@ namespace KinectServer
if (!oSettings.bMergeScansForSave) if (!oSettings.bMergeScansForSave)
{ {
string outputFilename = outDir + "\\" + nFrames.ToString().PadLeft(5, '0') + i.ToString() + ".ply"; string outputFilename = outDir + "\\" + nFrames.ToString().PadLeft(5, '0') + i.ToString() + ".ply";
saveToPly(outputFilename, lFrameVertsAllDevices[i], lFrameRGBAllDevices[i], oSettings.bSaveAsBinaryPLY); Utils.saveToPly(outputFilename, lFrameVertsAllDevices[i], lFrameRGBAllDevices[i], oSettings.bSaveAsBinaryPLY);
} }
} }
@@ -232,7 +232,7 @@ namespace KinectServer
if (oSettings.bMergeScansForSave) if (oSettings.bMergeScansForSave)
{ {
string outputFilename = outDir + "\\" + nFrames.ToString().PadLeft(5, '0') + ".ply"; string outputFilename = outDir + "\\" + nFrames.ToString().PadLeft(5, '0') + ".ply";
saveToPly(outputFilename, lFrameVerts, lFrameRGB, oSettings.bSaveAsBinaryPLY); Utils.saveToPly(outputFilename, lFrameVerts, lFrameRGB, oSettings.bSaveAsBinaryPLY);
} }
} }
} }
@@ -457,55 +457,6 @@ namespace KinectServer
refineWorker.RunWorkerAsync(); refineWorker.RunWorkerAsync();
} }
private void saveToPly(string filename, List<Single> vertices, List<byte> colors, bool binary)
{
int nVertices = vertices.Count / 3;
FileStream fileStream = File.Open(filename, FileMode.Create);
System.IO.StreamWriter streamWriter = new System.IO.StreamWriter(fileStream);
System.IO.BinaryWriter binaryWriter = new System.IO.BinaryWriter(fileStream);
//PLY file header is written here.
if (binary)
streamWriter.WriteLine("ply\nformat binary_little_endian 1.0");
else
streamWriter.WriteLine("ply\nformat ascii 1.0\n");
streamWriter.Write("element vertex " + nVertices.ToString() + "\n");
streamWriter.Write("property float x\nproperty float y\nproperty float z\nproperty uchar red\nproperty uchar green\nproperty uchar blue\nend_header\n");
streamWriter.Flush();
//Vertex and color data are written here.
if (binary)
{
for (int j = 0; j < vertices.Count / 3; j++)
{
for (int k = 0; k < 3; k++)
binaryWriter.Write(vertices[j * 3 + k]);
for (int k = 0; k < 3; k++)
{
byte temp = colors[j * 3 + k];
binaryWriter.Write(temp);
}
}
}
else
{
for (int j = 0; j < vertices.Count / 3; j++)
{
string s = "";
for (int k = 0; k < 3; k++)
s += vertices[j * 3 + k].ToString(CultureInfo.InvariantCulture) + " ";
for (int k = 0; k < 3; k++)
s += colors[j * 3 + k].ToString(CultureInfo.InvariantCulture) + " ";
streamWriter.WriteLine(s);
}
}
streamWriter.Flush();
binaryWriter.Flush();
fileStream.Close();
}
void RestartUpdateWorker() void RestartUpdateWorker()
{ {
if (!updateWorker.IsBusy) if (!updateWorker.IsBusy)
+89 -49
View File
@@ -18,6 +18,7 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Globalization; using System.Globalization;
using System.Windows.Forms.Layout;
using System.Diagnostics; using System.Diagnostics;
@@ -32,7 +33,7 @@ enum ECameraMode
namespace KinectServer namespace KinectServer
{ {
class OpenGLWindow : GameWindow public class OpenGLWindow : GameWindow
{ {
int PointCount; int PointCount;
int LineCount; int LineCount;
@@ -43,6 +44,8 @@ namespace KinectServer
static float KEYBOARD_MOVE_SPEED = 0.01f; static float KEYBOARD_MOVE_SPEED = 0.01f;
bool IsFullscreen = false;
static float MOUSE_ORBIT_SPEED = 0.30f; // 0 = SLOWEST, 1 = FASTEST static float MOUSE_ORBIT_SPEED = 0.30f; // 0 = SLOWEST, 1 = FASTEST
static float MOUSE_DOLLY_SPEED = 0.2f; // same as above...but much more sensitive static float MOUSE_DOLLY_SPEED = 0.2f; // same as above...but much more sensitive
static float MOUSE_TRACK_SPEED = 0.003f; // same as above...but much more sensitive static float MOUSE_TRACK_SPEED = 0.003f; // same as above...but much more sensitive
@@ -52,6 +55,8 @@ namespace KinectServer
float dx = 0.0f; float dx = 0.0f;
float dy = 0.0f; float dy = 0.0f;
byte brightnessModifier = 0;
Vector2 MousePrevious = new Vector2(); Vector2 MousePrevious = new Vector2();
Vector2 MouseCurrent = new Vector2(); Vector2 MouseCurrent = new Vector2();
float[] cameraPosition = new float[3]; float[] cameraPosition = new float[3];
@@ -66,6 +71,8 @@ namespace KinectServer
DateTime tFPSUpdateTimer = DateTime.Now; DateTime tFPSUpdateTimer = DateTime.Now;
int nTickCounter = 0; int nTickCounter = 0;
bool bDrawMarkings = true;
// this struct is used for drawing // this struct is used for drawing
struct VertexC4ubV3f struct VertexC4ubV3f
{ {
@@ -79,7 +86,7 @@ namespace KinectServer
/// <summary>Creates a 800x600 window with the specified title.</summary> /// <summary>Creates a 800x600 window with the specified title.</summary>
public OpenGLWindow() public OpenGLWindow()
: base(800, 600) : base(800, 600, GraphicsMode.Default, "LiveScan")
{ {
this.VSync = VSyncMode.Off; this.VSync = VSyncMode.Off;
MouseUp += new EventHandler<MouseButtonEventArgs>(OnMouseButtonUp); MouseUp += new EventHandler<MouseButtonEventArgs>(OnMouseButtonUp);
@@ -88,7 +95,7 @@ namespace KinectServer
MouseWheel += new EventHandler<MouseWheelEventArgs>(OnMouseWheelChanged); MouseWheel += new EventHandler<MouseWheelEventArgs>(OnMouseWheelChanged);
KeyDown += new EventHandler<KeyboardKeyEventArgs>(OnKeyDown); KeyDown += new EventHandler<KeyboardKeyEventArgs>(OnKeyDown);
cameraPosition[0] = 0; cameraPosition[0] = 0;
cameraPosition[1] = 0; cameraPosition[1] = 0;
cameraPosition[2] = 1.0f; cameraPosition[2] = 1.0f;
@@ -102,9 +109,59 @@ namespace KinectServer
nTickCounter++; nTickCounter++;
} }
public void ToggleFullscreen()
{
if (IsFullscreen)
{
WindowBorder = WindowBorder.Resizable;
WindowState = WindowState.Normal;
ClientSize = new System.Drawing.Size(800, 600);
CursorVisible = true;
}
else
{
CursorVisible = false;
WindowBorder = WindowBorder.Hidden;
WindowState = WindowState.Fullscreen;
}
IsFullscreen = !IsFullscreen;
}
void OnKeyDown(object sender, KeyboardKeyEventArgs e) void OnKeyDown(object sender, KeyboardKeyEventArgs e)
{ {
// e.Key
var keyboard = e.Keyboard;
if (keyboard[Key.Escape])
{
Exit();
}
if (keyboard[Key.Plus])
{
PointSize += 0.1f;
GL.PointSize(PointSize);
}
if (keyboard[Key.Minus])
{
if (PointSize != 0)
PointSize -= 0.1f;
GL.PointSize(PointSize);
}
if (keyboard[Key.W])
cameraPosition[2] -= KEYBOARD_MOVE_SPEED;
if (keyboard[Key.A])
cameraPosition[0] -= KEYBOARD_MOVE_SPEED;
if (keyboard[Key.S])
cameraPosition[2] += KEYBOARD_MOVE_SPEED;
if (keyboard[Key.D])
cameraPosition[0] += KEYBOARD_MOVE_SPEED;
if (keyboard[Key.F])
ToggleFullscreen();
if (keyboard[Key.M])
bDrawMarkings = !bDrawMarkings;
if (keyboard[Key.O])
brightnessModifier = (byte)Math.Max(0, brightnessModifier - 10);
if (keyboard[Key.P])
brightnessModifier = (byte)Math.Min(255, brightnessModifier + 10);
} }
/// <summary>Load resources here.</summary> /// <summary>Load resources here.</summary>
@@ -265,70 +322,53 @@ namespace KinectServer
nTickCounter = 0; nTickCounter = 0;
} }
var keyboard = OpenTK.Input.Keyboard.GetState();
if (keyboard[Key.Escape])
{
Exit();
}
if (keyboard[Key.Plus])
{
PointSize += 0.1f;
GL.PointSize(PointSize);
}
if (keyboard[Key.Minus])
{
if (PointSize != 0)
PointSize -= 0.1f;
GL.PointSize(PointSize);
}
if (keyboard[Key.W])
cameraPosition[2] -= KEYBOARD_MOVE_SPEED;
if (keyboard[Key.A])
cameraPosition[0] -= KEYBOARD_MOVE_SPEED;
if (keyboard[Key.S])
cameraPosition[2] += KEYBOARD_MOVE_SPEED;
if (keyboard[Key.D])
cameraPosition[0] += KEYBOARD_MOVE_SPEED;
lock (vertices) lock (vertices)
{ {
bool bShowSkeletons = settings.bShowSkeletons; bool bShowSkeletons = settings.bShowSkeletons;
PointCount = vertices.Count / 3; PointCount = vertices.Count / 3;
//bounding box LineCount = 0;
LineCount = 12; if (bDrawMarkings)
//markers {
LineCount += settings.lMarkerPoses.Count * 3; //bounding box
//cameras LineCount += 12;
LineCount += cameraPoses.Count * 3; //markers
if (bShowSkeletons) LineCount += settings.lMarkerPoses.Count * 3;
LineCount += 24 * bodies.Count; //cameras
LineCount += cameraPoses.Count * 3;
if (bShowSkeletons)
LineCount += 24 * bodies.Count;
}
VBO = new VertexC4ubV3f[PointCount + 2 * LineCount]; VBO = new VertexC4ubV3f[PointCount + 2 * LineCount];
for (int i = 0; i < PointCount; i++) for (int i = 0; i < PointCount; i++)
{ {
VBO[i].R = (byte)colors[i * 3]; VBO[i].R = (byte)Math.Max(0, Math.Min(255, (colors[i * 3] + brightnessModifier)));
VBO[i].G = (byte)colors[i * 3 + 1]; VBO[i].G = (byte)Math.Max(0, Math.Min(255, (colors[i * 3 + 1] + brightnessModifier)));
VBO[i].B = (byte)colors[i * 3 + 2]; VBO[i].B = (byte)Math.Max(0, Math.Min(255, (colors[i * 3 + 2] + brightnessModifier)));
VBO[i].A = 255; VBO[i].A = 255;
VBO[i].Position.X = vertices[i * 3]; VBO[i].Position.X = vertices[i * 3];
VBO[i].Position.Y = vertices[i * 3 + 1]; VBO[i].Position.Y = vertices[i * 3 + 1];
VBO[i].Position.Z = vertices[i * 3 + 2]; VBO[i].Position.Z = vertices[i * 3 + 2];
} }
int iCurLineCount = 0; if (bDrawMarkings)
iCurLineCount += AddBoundingBox(PointCount + 2 * iCurLineCount);
for (int i = 0; i < settings.lMarkerPoses.Count; i++)
{ {
iCurLineCount += AddMarker(PointCount + 2 * iCurLineCount, settings.lMarkerPoses[i].pose); int iCurLineCount = 0;
iCurLineCount += AddBoundingBox(PointCount + 2 * iCurLineCount);
for (int i = 0; i < settings.lMarkerPoses.Count; i++)
{
iCurLineCount += AddMarker(PointCount + 2 * iCurLineCount, settings.lMarkerPoses[i].pose);
}
for (int i = 0; i < cameraPoses.Count; i++)
{
iCurLineCount += AddCamera(PointCount + 2 * iCurLineCount, cameraPoses[i]);
}
if (bShowSkeletons)
iCurLineCount += AddBodies(PointCount + 2 * iCurLineCount);
} }
for (int i = 0; i < cameraPoses.Count; i++)
{
iCurLineCount += AddCamera(PointCount + 2 * iCurLineCount, cameraPoses[i]);
}
if (bShowSkeletons)
iCurLineCount += AddBodies(PointCount + 2 * iCurLineCount);
} }
} }
+200 -118
View File
@@ -34,7 +34,7 @@
this.txtICPIters = new System.Windows.Forms.TextBox(); this.txtICPIters = new System.Windows.Forms.TextBox();
this.grClient = new System.Windows.Forms.GroupBox(); this.grClient = new System.Windows.Forms.GroupBox();
this.grBody = new System.Windows.Forms.GroupBox(); this.grBody = new System.Windows.Forms.GroupBox();
this.label1 = new System.Windows.Forms.Label(); this.chSkeletons = new System.Windows.Forms.CheckBox();
this.chBodyData = new System.Windows.Forms.CheckBox(); this.chBodyData = new System.Windows.Forms.CheckBox();
this.grMarkers = new System.Windows.Forms.GroupBox(); this.grMarkers = new System.Windows.Forms.GroupBox();
this.lbX2 = new System.Windows.Forms.Label(); this.lbX2 = new System.Windows.Forms.Label();
@@ -77,7 +77,8 @@
this.rAsciiPly = new System.Windows.Forms.RadioButton(); this.rAsciiPly = new System.Windows.Forms.RadioButton();
this.txtRefinIters = new System.Windows.Forms.TextBox(); this.txtRefinIters = new System.Windows.Forms.TextBox();
this.lbOuterIters = new System.Windows.Forms.Label(); this.lbOuterIters = new System.Windows.Forms.Label();
this.chSkeletons = new System.Windows.Forms.CheckBox(); this.label2 = new System.Windows.Forms.Label();
this.cbCompressionLevel = new System.Windows.Forms.ComboBox();
this.grClient.SuspendLayout(); this.grClient.SuspendLayout();
this.grBody.SuspendLayout(); this.grBody.SuspendLayout();
this.grMarkers.SuspendLayout(); this.grMarkers.SuspendLayout();
@@ -89,18 +90,20 @@
// lbMerge // lbMerge
// //
this.lbMerge.AutoSize = true; this.lbMerge.AutoSize = true;
this.lbMerge.Location = new System.Drawing.Point(6, 49); this.lbMerge.Location = new System.Drawing.Point(7, 69);
this.lbMerge.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.lbMerge.Name = "lbMerge"; this.lbMerge.Name = "lbMerge";
this.lbMerge.Size = new System.Drawing.Size(69, 13); this.lbMerge.Size = new System.Drawing.Size(99, 20);
this.lbMerge.TabIndex = 22; this.lbMerge.TabIndex = 22;
this.lbMerge.Text = "Scan saving:"; this.lbMerge.Text = "Scan saving:";
// //
// chMerge // chMerge
// //
this.chMerge.AutoSize = true; this.chMerge.AutoSize = true;
this.chMerge.Location = new System.Drawing.Point(98, 48); this.chMerge.Location = new System.Drawing.Point(156, 70);
this.chMerge.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.chMerge.Name = "chMerge"; this.chMerge.Name = "chMerge";
this.chMerge.Size = new System.Drawing.Size(86, 17); this.chMerge.Size = new System.Drawing.Size(126, 24);
this.chMerge.TabIndex = 23; this.chMerge.TabIndex = 23;
this.chMerge.Text = "merge scans"; this.chMerge.Text = "merge scans";
this.chMerge.UseVisualStyleBackColor = true; this.chMerge.UseVisualStyleBackColor = true;
@@ -109,17 +112,19 @@
// lbICPIters // lbICPIters
// //
this.lbICPIters.AutoSize = true; this.lbICPIters.AutoSize = true;
this.lbICPIters.Location = new System.Drawing.Point(6, 26); this.lbICPIters.Location = new System.Drawing.Point(7, 34);
this.lbICPIters.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.lbICPIters.Name = "lbICPIters"; this.lbICPIters.Name = "lbICPIters";
this.lbICPIters.Size = new System.Drawing.Size(86, 13); this.lbICPIters.Size = new System.Drawing.Size(128, 20);
this.lbICPIters.TabIndex = 24; this.lbICPIters.TabIndex = 24;
this.lbICPIters.Text = "Num of ICP iters:"; this.lbICPIters.Text = "Num of ICP iters:";
// //
// txtICPIters // txtICPIters
// //
this.txtICPIters.Location = new System.Drawing.Point(98, 23); this.txtICPIters.Location = new System.Drawing.Point(156, 31);
this.txtICPIters.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.txtICPIters.Name = "txtICPIters"; this.txtICPIters.Name = "txtICPIters";
this.txtICPIters.Size = new System.Drawing.Size(38, 20); this.txtICPIters.Size = new System.Drawing.Size(55, 26);
this.txtICPIters.TabIndex = 25; this.txtICPIters.TabIndex = 25;
this.txtICPIters.TextChanged += new System.EventHandler(this.txtICPIters_TextChanged); this.txtICPIters.TextChanged += new System.EventHandler(this.txtICPIters_TextChanged);
// //
@@ -129,9 +134,11 @@
this.grClient.Controls.Add(this.grMarkers); this.grClient.Controls.Add(this.grMarkers);
this.grClient.Controls.Add(this.grBounding); this.grClient.Controls.Add(this.grBounding);
this.grClient.Controls.Add(this.grFiltering); this.grClient.Controls.Add(this.grFiltering);
this.grClient.Location = new System.Drawing.Point(12, 12); this.grClient.Location = new System.Drawing.Point(18, 18);
this.grClient.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.grClient.Name = "grClient"; this.grClient.Name = "grClient";
this.grClient.Size = new System.Drawing.Size(632, 327); this.grClient.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.grClient.Size = new System.Drawing.Size(948, 447);
this.grClient.TabIndex = 43; this.grClient.TabIndex = 43;
this.grClient.TabStop = false; this.grClient.TabStop = false;
this.grClient.Text = "KinectClient settings"; this.grClient.Text = "KinectClient settings";
@@ -139,30 +146,35 @@
// grBody // grBody
// //
this.grBody.Controls.Add(this.chSkeletons); this.grBody.Controls.Add(this.chSkeletons);
this.grBody.Controls.Add(this.label1);
this.grBody.Controls.Add(this.chBodyData); this.grBody.Controls.Add(this.chBodyData);
this.grBody.Location = new System.Drawing.Point(9, 211); this.grBody.Location = new System.Drawing.Point(14, 325);
this.grBody.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.grBody.Name = "grBody"; this.grBody.Name = "grBody";
this.grBody.Size = new System.Drawing.Size(249, 110); this.grBody.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.grBody.Size = new System.Drawing.Size(374, 101);
this.grBody.TabIndex = 47; this.grBody.TabIndex = 47;
this.grBody.TabStop = false; this.grBody.TabStop = false;
this.grBody.Text = "Body data"; this.grBody.Text = "Body data";
// //
// label1 // chSkeletons
// //
this.label1.AutoSize = true; this.chSkeletons.AutoSize = true;
this.label1.Location = new System.Drawing.Point(8, 61); this.chSkeletons.Location = new System.Drawing.Point(16, 63);
this.label1.Name = "label1"; this.chSkeletons.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.label1.Size = new System.Drawing.Size(187, 13); this.chSkeletons.Name = "chSkeletons";
this.label1.TabIndex = 20; this.chSkeletons.Size = new System.Drawing.Size(220, 24);
this.label1.Text = "More features will be added here soon"; this.chSkeletons.TabIndex = 21;
this.chSkeletons.Text = "show skeletons in live view";
this.chSkeletons.UseVisualStyleBackColor = true;
this.chSkeletons.CheckedChanged += new System.EventHandler(this.chSkeletons_CheckedChanged);
// //
// chBodyData // chBodyData
// //
this.chBodyData.AutoSize = true; this.chBodyData.AutoSize = true;
this.chBodyData.Location = new System.Drawing.Point(11, 19); this.chBodyData.Location = new System.Drawing.Point(16, 29);
this.chBodyData.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.chBodyData.Name = "chBodyData"; this.chBodyData.Name = "chBodyData";
this.chBodyData.Size = new System.Drawing.Size(113, 17); this.chBodyData.Size = new System.Drawing.Size(167, 24);
this.chBodyData.TabIndex = 19; this.chBodyData.TabIndex = 19;
this.chBodyData.Text = "stream only bodies"; this.chBodyData.Text = "stream only bodies";
this.chBodyData.UseVisualStyleBackColor = true; this.chBodyData.UseVisualStyleBackColor = true;
@@ -186,9 +198,11 @@
this.grMarkers.Controls.Add(this.txtTranslationX); this.grMarkers.Controls.Add(this.txtTranslationX);
this.grMarkers.Controls.Add(this.lisMarkers); this.grMarkers.Controls.Add(this.lisMarkers);
this.grMarkers.Controls.Add(this.txtTranslationY); this.grMarkers.Controls.Add(this.txtTranslationY);
this.grMarkers.Location = new System.Drawing.Point(271, 19); this.grMarkers.Location = new System.Drawing.Point(406, 29);
this.grMarkers.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.grMarkers.Name = "grMarkers"; this.grMarkers.Name = "grMarkers";
this.grMarkers.Size = new System.Drawing.Size(353, 185); this.grMarkers.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.grMarkers.Size = new System.Drawing.Size(530, 285);
this.grMarkers.TabIndex = 45; this.grMarkers.TabIndex = 45;
this.grMarkers.TabStop = false; this.grMarkers.TabStop = false;
this.grMarkers.Text = "Calibration markers"; this.grMarkers.Text = "Calibration markers";
@@ -196,17 +210,19 @@
// lbX2 // lbX2
// //
this.lbX2.AutoSize = true; this.lbX2.AutoSize = true;
this.lbX2.Location = new System.Drawing.Point(230, 19); this.lbX2.Location = new System.Drawing.Point(345, 29);
this.lbX2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.lbX2.Name = "lbX2"; this.lbX2.Name = "lbX2";
this.lbX2.Size = new System.Drawing.Size(14, 13); this.lbX2.Size = new System.Drawing.Size(20, 20);
this.lbX2.TabIndex = 49; this.lbX2.TabIndex = 49;
this.lbX2.Text = "X"; this.lbX2.Text = "X";
// //
// btRemove // btRemove
// //
this.btRemove.Location = new System.Drawing.Point(233, 127); this.btRemove.Location = new System.Drawing.Point(350, 195);
this.btRemove.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.btRemove.Name = "btRemove"; this.btRemove.Name = "btRemove";
this.btRemove.Size = new System.Drawing.Size(92, 23); this.btRemove.Size = new System.Drawing.Size(138, 35);
this.btRemove.TabIndex = 59; this.btRemove.TabIndex = 59;
this.btRemove.Text = "Remove marker"; this.btRemove.Text = "Remove marker";
this.btRemove.UseVisualStyleBackColor = true; this.btRemove.UseVisualStyleBackColor = true;
@@ -214,68 +230,76 @@
// //
// txtOrientationZ // txtOrientationZ
// //
this.txtOrientationZ.Location = new System.Drawing.Point(305, 38); this.txtOrientationZ.Location = new System.Drawing.Point(458, 58);
this.txtOrientationZ.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.txtOrientationZ.Name = "txtOrientationZ"; this.txtOrientationZ.Name = "txtOrientationZ";
this.txtOrientationZ.Size = new System.Drawing.Size(38, 20); this.txtOrientationZ.Size = new System.Drawing.Size(55, 26);
this.txtOrientationZ.TabIndex = 48; this.txtOrientationZ.TabIndex = 48;
this.txtOrientationZ.TextChanged += new System.EventHandler(this.txtOrientationZ_TextChanged); this.txtOrientationZ.TextChanged += new System.EventHandler(this.txtOrientationZ_TextChanged);
// //
// txtId // txtId
// //
this.txtId.Location = new System.Drawing.Point(217, 93); this.txtId.Location = new System.Drawing.Point(326, 143);
this.txtId.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.txtId.Name = "txtId"; this.txtId.Name = "txtId";
this.txtId.Size = new System.Drawing.Size(38, 20); this.txtId.Size = new System.Drawing.Size(55, 26);
this.txtId.TabIndex = 58; this.txtId.TabIndex = 58;
this.txtId.TextChanged += new System.EventHandler(this.txtId_TextChanged); this.txtId.TextChanged += new System.EventHandler(this.txtId_TextChanged);
// //
// lbY2 // lbY2
// //
this.lbY2.AutoSize = true; this.lbY2.AutoSize = true;
this.lbY2.Location = new System.Drawing.Point(274, 19); this.lbY2.Location = new System.Drawing.Point(411, 29);
this.lbY2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.lbY2.Name = "lbY2"; this.lbY2.Name = "lbY2";
this.lbY2.Size = new System.Drawing.Size(14, 13); this.lbY2.Size = new System.Drawing.Size(20, 20);
this.lbY2.TabIndex = 50; this.lbY2.TabIndex = 50;
this.lbY2.Text = "Y"; this.lbY2.Text = "Y";
// //
// txtOrientationY // txtOrientationY
// //
this.txtOrientationY.Location = new System.Drawing.Point(261, 38); this.txtOrientationY.Location = new System.Drawing.Point(392, 58);
this.txtOrientationY.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.txtOrientationY.Name = "txtOrientationY"; this.txtOrientationY.Name = "txtOrientationY";
this.txtOrientationY.Size = new System.Drawing.Size(38, 20); this.txtOrientationY.Size = new System.Drawing.Size(55, 26);
this.txtOrientationY.TabIndex = 47; this.txtOrientationY.TabIndex = 47;
this.txtOrientationY.TextChanged += new System.EventHandler(this.txtOrientationY_TextChanged); this.txtOrientationY.TextChanged += new System.EventHandler(this.txtOrientationY_TextChanged);
// //
// lbId // lbId
// //
this.lbId.AutoSize = true; this.lbId.AutoSize = true;
this.lbId.Location = new System.Drawing.Point(132, 96); this.lbId.Location = new System.Drawing.Point(198, 148);
this.lbId.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.lbId.Name = "lbId"; this.lbId.Name = "lbId";
this.lbId.Size = new System.Drawing.Size(54, 13); this.lbId.Size = new System.Drawing.Size(78, 20);
this.lbId.TabIndex = 57; this.lbId.TabIndex = 57;
this.lbId.Text = "Marker id:"; this.lbId.Text = "Marker id:";
// //
// lbZ2 // lbZ2
// //
this.lbZ2.AutoSize = true; this.lbZ2.AutoSize = true;
this.lbZ2.Location = new System.Drawing.Point(317, 19); this.lbZ2.Location = new System.Drawing.Point(476, 29);
this.lbZ2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.lbZ2.Name = "lbZ2"; this.lbZ2.Name = "lbZ2";
this.lbZ2.Size = new System.Drawing.Size(14, 13); this.lbZ2.Size = new System.Drawing.Size(19, 20);
this.lbZ2.TabIndex = 51; this.lbZ2.TabIndex = 51;
this.lbZ2.Text = "Z"; this.lbZ2.Text = "Z";
// //
// txtOrientationX // txtOrientationX
// //
this.txtOrientationX.Location = new System.Drawing.Point(217, 38); this.txtOrientationX.Location = new System.Drawing.Point(326, 58);
this.txtOrientationX.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.txtOrientationX.Name = "txtOrientationX"; this.txtOrientationX.Name = "txtOrientationX";
this.txtOrientationX.Size = new System.Drawing.Size(38, 20); this.txtOrientationX.Size = new System.Drawing.Size(55, 26);
this.txtOrientationX.TabIndex = 46; this.txtOrientationX.TabIndex = 46;
this.txtOrientationX.TextChanged += new System.EventHandler(this.txtOrientationX_TextChanged); this.txtOrientationX.TextChanged += new System.EventHandler(this.txtOrientationX_TextChanged);
// //
// btAdd // btAdd
// //
this.btAdd.Location = new System.Drawing.Point(135, 127); this.btAdd.Location = new System.Drawing.Point(202, 195);
this.btAdd.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.btAdd.Name = "btAdd"; this.btAdd.Name = "btAdd";
this.btAdd.Size = new System.Drawing.Size(92, 23); this.btAdd.Size = new System.Drawing.Size(138, 35);
this.btAdd.TabIndex = 56; this.btAdd.TabIndex = 56;
this.btAdd.Text = "Add marker"; this.btAdd.Text = "Add marker";
this.btAdd.UseVisualStyleBackColor = true; this.btAdd.UseVisualStyleBackColor = true;
@@ -284,51 +308,58 @@
// lbTranslation // lbTranslation
// //
this.lbTranslation.AutoSize = true; this.lbTranslation.AutoSize = true;
this.lbTranslation.Location = new System.Drawing.Point(132, 68); this.lbTranslation.Location = new System.Drawing.Point(198, 105);
this.lbTranslation.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.lbTranslation.Name = "lbTranslation"; this.lbTranslation.Name = "lbTranslation";
this.lbTranslation.Size = new System.Drawing.Size(62, 13); this.lbTranslation.Size = new System.Drawing.Size(91, 20);
this.lbTranslation.TabIndex = 52; this.lbTranslation.TabIndex = 52;
this.lbTranslation.Text = "Translation:"; this.lbTranslation.Text = "Translation:";
// //
// lbOrientation // lbOrientation
// //
this.lbOrientation.AutoSize = true; this.lbOrientation.AutoSize = true;
this.lbOrientation.Location = new System.Drawing.Point(132, 41); this.lbOrientation.Location = new System.Drawing.Point(198, 63);
this.lbOrientation.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.lbOrientation.Name = "lbOrientation"; this.lbOrientation.Name = "lbOrientation";
this.lbOrientation.Size = new System.Drawing.Size(61, 13); this.lbOrientation.Size = new System.Drawing.Size(91, 20);
this.lbOrientation.TabIndex = 45; this.lbOrientation.TabIndex = 45;
this.lbOrientation.Text = "Orientation:"; this.lbOrientation.Text = "Orientation:";
// //
// txtTranslationZ // txtTranslationZ
// //
this.txtTranslationZ.Location = new System.Drawing.Point(305, 65); this.txtTranslationZ.Location = new System.Drawing.Point(458, 100);
this.txtTranslationZ.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.txtTranslationZ.Name = "txtTranslationZ"; this.txtTranslationZ.Name = "txtTranslationZ";
this.txtTranslationZ.Size = new System.Drawing.Size(38, 20); this.txtTranslationZ.Size = new System.Drawing.Size(55, 26);
this.txtTranslationZ.TabIndex = 55; this.txtTranslationZ.TabIndex = 55;
this.txtTranslationZ.TextChanged += new System.EventHandler(this.txtTranslationZ_TextChanged); this.txtTranslationZ.TextChanged += new System.EventHandler(this.txtTranslationZ_TextChanged);
// //
// txtTranslationX // txtTranslationX
// //
this.txtTranslationX.Location = new System.Drawing.Point(217, 65); this.txtTranslationX.Location = new System.Drawing.Point(326, 100);
this.txtTranslationX.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.txtTranslationX.Name = "txtTranslationX"; this.txtTranslationX.Name = "txtTranslationX";
this.txtTranslationX.Size = new System.Drawing.Size(38, 20); this.txtTranslationX.Size = new System.Drawing.Size(55, 26);
this.txtTranslationX.TabIndex = 53; this.txtTranslationX.TabIndex = 53;
this.txtTranslationX.TextChanged += new System.EventHandler(this.txtTranslationX_TextChanged); this.txtTranslationX.TextChanged += new System.EventHandler(this.txtTranslationX_TextChanged);
// //
// lisMarkers // lisMarkers
// //
this.lisMarkers.FormattingEnabled = true; this.lisMarkers.FormattingEnabled = true;
this.lisMarkers.Location = new System.Drawing.Point(6, 41); this.lisMarkers.ItemHeight = 20;
this.lisMarkers.Location = new System.Drawing.Point(9, 63);
this.lisMarkers.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.lisMarkers.Name = "lisMarkers"; this.lisMarkers.Name = "lisMarkers";
this.lisMarkers.Size = new System.Drawing.Size(120, 108); this.lisMarkers.Size = new System.Drawing.Size(178, 164);
this.lisMarkers.TabIndex = 43; this.lisMarkers.TabIndex = 43;
this.lisMarkers.SelectedIndexChanged += new System.EventHandler(this.lisMarkers_SelectedIndexChanged); this.lisMarkers.SelectedIndexChanged += new System.EventHandler(this.lisMarkers_SelectedIndexChanged);
// //
// txtTranslationY // txtTranslationY
// //
this.txtTranslationY.Location = new System.Drawing.Point(261, 65); this.txtTranslationY.Location = new System.Drawing.Point(392, 100);
this.txtTranslationY.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.txtTranslationY.Name = "txtTranslationY"; this.txtTranslationY.Name = "txtTranslationY";
this.txtTranslationY.Size = new System.Drawing.Size(38, 20); this.txtTranslationY.Size = new System.Drawing.Size(55, 26);
this.txtTranslationY.TabIndex = 54; this.txtTranslationY.TabIndex = 54;
this.txtTranslationY.TextChanged += new System.EventHandler(this.txtTranslationY_TextChanged); this.txtTranslationY.TextChanged += new System.EventHandler(this.txtTranslationY_TextChanged);
// //
@@ -345,9 +376,11 @@
this.grBounding.Controls.Add(this.lbZ); this.grBounding.Controls.Add(this.lbZ);
this.grBounding.Controls.Add(this.lbY); this.grBounding.Controls.Add(this.lbY);
this.grBounding.Controls.Add(this.lbX); this.grBounding.Controls.Add(this.lbX);
this.grBounding.Location = new System.Drawing.Point(9, 19); this.grBounding.Location = new System.Drawing.Point(14, 29);
this.grBounding.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.grBounding.Name = "grBounding"; this.grBounding.Name = "grBounding";
this.grBounding.Size = new System.Drawing.Size(249, 91); this.grBounding.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.grBounding.Size = new System.Drawing.Size(374, 140);
this.grBounding.TabIndex = 46; this.grBounding.TabIndex = 46;
this.grBounding.TabStop = false; this.grBounding.TabStop = false;
this.grBounding.Text = "Bounding box"; this.grBounding.Text = "Bounding box";
@@ -355,93 +388,104 @@
// lbMin // lbMin
// //
this.lbMin.AutoSize = true; this.lbMin.AutoSize = true;
this.lbMin.Location = new System.Drawing.Point(8, 38); this.lbMin.Location = new System.Drawing.Point(12, 58);
this.lbMin.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.lbMin.Name = "lbMin"; this.lbMin.Name = "lbMin";
this.lbMin.Size = new System.Drawing.Size(65, 13); this.lbMin.Size = new System.Drawing.Size(95, 20);
this.lbMin.TabIndex = 13; this.lbMin.TabIndex = 13;
this.lbMin.Text = "Min bounds:"; this.lbMin.Text = "Min bounds:";
// //
// txtMaxZ // txtMaxZ
// //
this.txtMaxZ.Location = new System.Drawing.Point(181, 62); this.txtMaxZ.Location = new System.Drawing.Point(272, 95);
this.txtMaxZ.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.txtMaxZ.Name = "txtMaxZ"; this.txtMaxZ.Name = "txtMaxZ";
this.txtMaxZ.Size = new System.Drawing.Size(38, 20); this.txtMaxZ.Size = new System.Drawing.Size(55, 26);
this.txtMaxZ.TabIndex = 23; this.txtMaxZ.TabIndex = 23;
this.txtMaxZ.TextChanged += new System.EventHandler(this.txtMaxZ_TextChanged); this.txtMaxZ.TextChanged += new System.EventHandler(this.txtMaxZ_TextChanged);
// //
// txtMaxY // txtMaxY
// //
this.txtMaxY.Location = new System.Drawing.Point(137, 62); this.txtMaxY.Location = new System.Drawing.Point(206, 95);
this.txtMaxY.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.txtMaxY.Name = "txtMaxY"; this.txtMaxY.Name = "txtMaxY";
this.txtMaxY.Size = new System.Drawing.Size(38, 20); this.txtMaxY.Size = new System.Drawing.Size(55, 26);
this.txtMaxY.TabIndex = 22; this.txtMaxY.TabIndex = 22;
this.txtMaxY.TextChanged += new System.EventHandler(this.txtMaxY_TextChanged); this.txtMaxY.TextChanged += new System.EventHandler(this.txtMaxY_TextChanged);
// //
// txtMinX // txtMinX
// //
this.txtMinX.Location = new System.Drawing.Point(93, 35); this.txtMinX.Location = new System.Drawing.Point(140, 54);
this.txtMinX.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.txtMinX.Name = "txtMinX"; this.txtMinX.Name = "txtMinX";
this.txtMinX.Size = new System.Drawing.Size(38, 20); this.txtMinX.Size = new System.Drawing.Size(55, 26);
this.txtMinX.TabIndex = 14; this.txtMinX.TabIndex = 14;
this.txtMinX.TextChanged += new System.EventHandler(this.txtMinX_TextChanged); this.txtMinX.TextChanged += new System.EventHandler(this.txtMinX_TextChanged);
// //
// txtMaxX // txtMaxX
// //
this.txtMaxX.Location = new System.Drawing.Point(93, 62); this.txtMaxX.Location = new System.Drawing.Point(140, 95);
this.txtMaxX.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.txtMaxX.Name = "txtMaxX"; this.txtMaxX.Name = "txtMaxX";
this.txtMaxX.Size = new System.Drawing.Size(38, 20); this.txtMaxX.Size = new System.Drawing.Size(55, 26);
this.txtMaxX.TabIndex = 21; this.txtMaxX.TabIndex = 21;
this.txtMaxX.TextChanged += new System.EventHandler(this.txtMaxX_TextChanged); this.txtMaxX.TextChanged += new System.EventHandler(this.txtMaxX_TextChanged);
// //
// txtMinY // txtMinY
// //
this.txtMinY.Location = new System.Drawing.Point(137, 35); this.txtMinY.Location = new System.Drawing.Point(206, 54);
this.txtMinY.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.txtMinY.Name = "txtMinY"; this.txtMinY.Name = "txtMinY";
this.txtMinY.Size = new System.Drawing.Size(38, 20); this.txtMinY.Size = new System.Drawing.Size(55, 26);
this.txtMinY.TabIndex = 15; this.txtMinY.TabIndex = 15;
this.txtMinY.TextChanged += new System.EventHandler(this.txtMinY_TextChanged); this.txtMinY.TextChanged += new System.EventHandler(this.txtMinY_TextChanged);
// //
// lbMax // lbMax
// //
this.lbMax.AutoSize = true; this.lbMax.AutoSize = true;
this.lbMax.Location = new System.Drawing.Point(8, 65); this.lbMax.Location = new System.Drawing.Point(12, 100);
this.lbMax.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.lbMax.Name = "lbMax"; this.lbMax.Name = "lbMax";
this.lbMax.Size = new System.Drawing.Size(68, 13); this.lbMax.Size = new System.Drawing.Size(99, 20);
this.lbMax.TabIndex = 20; this.lbMax.TabIndex = 20;
this.lbMax.Text = "Max bounds:"; this.lbMax.Text = "Max bounds:";
// //
// txtMinZ // txtMinZ
// //
this.txtMinZ.Location = new System.Drawing.Point(181, 35); this.txtMinZ.Location = new System.Drawing.Point(272, 54);
this.txtMinZ.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.txtMinZ.Name = "txtMinZ"; this.txtMinZ.Name = "txtMinZ";
this.txtMinZ.Size = new System.Drawing.Size(38, 20); this.txtMinZ.Size = new System.Drawing.Size(55, 26);
this.txtMinZ.TabIndex = 16; this.txtMinZ.TabIndex = 16;
this.txtMinZ.TextChanged += new System.EventHandler(this.txtMinZ_TextChanged); this.txtMinZ.TextChanged += new System.EventHandler(this.txtMinZ_TextChanged);
// //
// lbZ // lbZ
// //
this.lbZ.AutoSize = true; this.lbZ.AutoSize = true;
this.lbZ.Location = new System.Drawing.Point(193, 16); this.lbZ.Location = new System.Drawing.Point(290, 25);
this.lbZ.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.lbZ.Name = "lbZ"; this.lbZ.Name = "lbZ";
this.lbZ.Size = new System.Drawing.Size(14, 13); this.lbZ.Size = new System.Drawing.Size(19, 20);
this.lbZ.TabIndex = 19; this.lbZ.TabIndex = 19;
this.lbZ.Text = "Z"; this.lbZ.Text = "Z";
// //
// lbY // lbY
// //
this.lbY.AutoSize = true; this.lbY.AutoSize = true;
this.lbY.Location = new System.Drawing.Point(150, 16); this.lbY.Location = new System.Drawing.Point(225, 25);
this.lbY.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.lbY.Name = "lbY"; this.lbY.Name = "lbY";
this.lbY.Size = new System.Drawing.Size(14, 13); this.lbY.Size = new System.Drawing.Size(20, 20);
this.lbY.TabIndex = 18; this.lbY.TabIndex = 18;
this.lbY.Text = "Y"; this.lbY.Text = "Y";
// //
// lbX // lbX
// //
this.lbX.AutoSize = true; this.lbX.AutoSize = true;
this.lbX.Location = new System.Drawing.Point(106, 16); this.lbX.Location = new System.Drawing.Point(159, 25);
this.lbX.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.lbX.Name = "lbX"; this.lbX.Name = "lbX";
this.lbX.Size = new System.Drawing.Size(14, 13); this.lbX.Size = new System.Drawing.Size(20, 20);
this.lbX.TabIndex = 17; this.lbX.TabIndex = 17;
this.lbX.Text = "X"; this.lbX.Text = "X";
// //
@@ -452,27 +496,31 @@
this.grFiltering.Controls.Add(this.lbFilterNeighbors); this.grFiltering.Controls.Add(this.lbFilterNeighbors);
this.grFiltering.Controls.Add(this.lbFilterDistance); this.grFiltering.Controls.Add(this.lbFilterDistance);
this.grFiltering.Controls.Add(this.txtFilterDistance); this.grFiltering.Controls.Add(this.txtFilterDistance);
this.grFiltering.Location = new System.Drawing.Point(9, 116); this.grFiltering.Location = new System.Drawing.Point(14, 178);
this.grFiltering.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.grFiltering.Name = "grFiltering"; this.grFiltering.Name = "grFiltering";
this.grFiltering.Size = new System.Drawing.Size(249, 88); this.grFiltering.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.grFiltering.Size = new System.Drawing.Size(374, 135);
this.grFiltering.TabIndex = 45; this.grFiltering.TabIndex = 45;
this.grFiltering.TabStop = false; this.grFiltering.TabStop = false;
this.grFiltering.Text = "Filtering"; this.grFiltering.Text = "Filtering";
// //
// txtFilterNeighbors // txtFilterNeighbors
// //
this.txtFilterNeighbors.Location = new System.Drawing.Point(93, 39); this.txtFilterNeighbors.Location = new System.Drawing.Point(140, 60);
this.txtFilterNeighbors.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.txtFilterNeighbors.Name = "txtFilterNeighbors"; this.txtFilterNeighbors.Name = "txtFilterNeighbors";
this.txtFilterNeighbors.Size = new System.Drawing.Size(38, 20); this.txtFilterNeighbors.Size = new System.Drawing.Size(55, 26);
this.txtFilterNeighbors.TabIndex = 20; this.txtFilterNeighbors.TabIndex = 20;
this.txtFilterNeighbors.TextChanged += new System.EventHandler(this.txtFilterNeighbors_TextChanged); this.txtFilterNeighbors.TextChanged += new System.EventHandler(this.txtFilterNeighbors_TextChanged);
// //
// chFilter // chFilter
// //
this.chFilter.AutoSize = true; this.chFilter.AutoSize = true;
this.chFilter.Location = new System.Drawing.Point(93, 16); this.chFilter.Location = new System.Drawing.Point(140, 25);
this.chFilter.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.chFilter.Name = "chFilter"; this.chFilter.Name = "chFilter";
this.chFilter.Size = new System.Drawing.Size(100, 17); this.chFilter.Size = new System.Drawing.Size(147, 24);
this.chFilter.TabIndex = 18; this.chFilter.TabIndex = 18;
this.chFilter.Text = "filtering enabled"; this.chFilter.Text = "filtering enabled";
this.chFilter.UseVisualStyleBackColor = true; this.chFilter.UseVisualStyleBackColor = true;
@@ -481,31 +529,36 @@
// lbFilterNeighbors // lbFilterNeighbors
// //
this.lbFilterNeighbors.AutoSize = true; this.lbFilterNeighbors.AutoSize = true;
this.lbFilterNeighbors.Location = new System.Drawing.Point(8, 42); this.lbFilterNeighbors.Location = new System.Drawing.Point(12, 65);
this.lbFilterNeighbors.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.lbFilterNeighbors.Name = "lbFilterNeighbors"; this.lbFilterNeighbors.Name = "lbFilterNeighbors";
this.lbFilterNeighbors.Size = new System.Drawing.Size(67, 13); this.lbFilterNeighbors.Size = new System.Drawing.Size(98, 20);
this.lbFilterNeighbors.TabIndex = 19; this.lbFilterNeighbors.TabIndex = 19;
this.lbFilterNeighbors.Text = "N neighbors:"; this.lbFilterNeighbors.Text = "N neighbors:";
// //
// lbFilterDistance // lbFilterDistance
// //
this.lbFilterDistance.AutoSize = true; this.lbFilterDistance.AutoSize = true;
this.lbFilterDistance.Location = new System.Drawing.Point(8, 68); this.lbFilterDistance.Location = new System.Drawing.Point(12, 105);
this.lbFilterDistance.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.lbFilterDistance.Name = "lbFilterDistance"; this.lbFilterDistance.Name = "lbFilterDistance";
this.lbFilterDistance.Size = new System.Drawing.Size(73, 13); this.lbFilterDistance.Size = new System.Drawing.Size(106, 20);
this.lbFilterDistance.TabIndex = 21; this.lbFilterDistance.TabIndex = 21;
this.lbFilterDistance.Text = "Max distance:"; this.lbFilterDistance.Text = "Max distance:";
// //
// txtFilterDistance // txtFilterDistance
// //
this.txtFilterDistance.Location = new System.Drawing.Point(93, 65); this.txtFilterDistance.Location = new System.Drawing.Point(140, 100);
this.txtFilterDistance.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.txtFilterDistance.Name = "txtFilterDistance"; this.txtFilterDistance.Name = "txtFilterDistance";
this.txtFilterDistance.Size = new System.Drawing.Size(38, 20); this.txtFilterDistance.Size = new System.Drawing.Size(55, 26);
this.txtFilterDistance.TabIndex = 22; this.txtFilterDistance.TabIndex = 22;
this.txtFilterDistance.TextChanged += new System.EventHandler(this.txtFilterDistance_TextChanged); this.txtFilterDistance.TextChanged += new System.EventHandler(this.txtFilterDistance_TextChanged);
// //
// grServer // grServer
// //
this.grServer.Controls.Add(this.cbCompressionLevel);
this.grServer.Controls.Add(this.label2);
this.grServer.Controls.Add(this.rBinaryPly); this.grServer.Controls.Add(this.rBinaryPly);
this.grServer.Controls.Add(this.lbFormat); this.grServer.Controls.Add(this.lbFormat);
this.grServer.Controls.Add(this.rAsciiPly); this.grServer.Controls.Add(this.rAsciiPly);
@@ -515,9 +568,11 @@
this.grServer.Controls.Add(this.txtICPIters); this.grServer.Controls.Add(this.txtICPIters);
this.grServer.Controls.Add(this.chMerge); this.grServer.Controls.Add(this.chMerge);
this.grServer.Controls.Add(this.lbICPIters); this.grServer.Controls.Add(this.lbICPIters);
this.grServer.Location = new System.Drawing.Point(12, 345); this.grServer.Location = new System.Drawing.Point(18, 478);
this.grServer.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.grServer.Name = "grServer"; this.grServer.Name = "grServer";
this.grServer.Size = new System.Drawing.Size(632, 111); this.grServer.Padding = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.grServer.Size = new System.Drawing.Size(948, 175);
this.grServer.TabIndex = 44; this.grServer.TabIndex = 44;
this.grServer.TabStop = false; this.grServer.TabStop = false;
this.grServer.Text = "KinectServer settings"; this.grServer.Text = "KinectServer settings";
@@ -525,9 +580,10 @@
// rBinaryPly // rBinaryPly
// //
this.rBinaryPly.AutoSize = true; this.rBinaryPly.AutoSize = true;
this.rBinaryPly.Location = new System.Drawing.Point(179, 71); this.rBinaryPly.Location = new System.Drawing.Point(277, 105);
this.rBinaryPly.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.rBinaryPly.Name = "rBinaryPly"; this.rBinaryPly.Name = "rBinaryPly";
this.rBinaryPly.Size = new System.Drawing.Size(76, 17); this.rBinaryPly.Size = new System.Drawing.Size(110, 24);
this.rBinaryPly.TabIndex = 30; this.rBinaryPly.TabIndex = 30;
this.rBinaryPly.TabStop = true; this.rBinaryPly.TabStop = true;
this.rBinaryPly.Text = "binary PLY"; this.rBinaryPly.Text = "binary PLY";
@@ -537,18 +593,20 @@
// lbFormat // lbFormat
// //
this.lbFormat.AutoSize = true; this.lbFormat.AutoSize = true;
this.lbFormat.Location = new System.Drawing.Point(6, 73); this.lbFormat.Location = new System.Drawing.Point(7, 106);
this.lbFormat.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.lbFormat.Name = "lbFormat"; this.lbFormat.Name = "lbFormat";
this.lbFormat.Size = new System.Drawing.Size(58, 13); this.lbFormat.Size = new System.Drawing.Size(88, 20);
this.lbFormat.TabIndex = 29; this.lbFormat.TabIndex = 29;
this.lbFormat.Text = "File format:"; this.lbFormat.Text = "File format:";
// //
// rAsciiPly // rAsciiPly
// //
this.rAsciiPly.AutoSize = true; this.rAsciiPly.AutoSize = true;
this.rAsciiPly.Location = new System.Drawing.Point(98, 71); this.rAsciiPly.Location = new System.Drawing.Point(156, 105);
this.rAsciiPly.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.rAsciiPly.Name = "rAsciiPly"; this.rAsciiPly.Name = "rAsciiPly";
this.rAsciiPly.Size = new System.Drawing.Size(75, 17); this.rAsciiPly.Size = new System.Drawing.Size(111, 24);
this.rAsciiPly.TabIndex = 28; this.rAsciiPly.TabIndex = 28;
this.rAsciiPly.TabStop = true; this.rAsciiPly.TabStop = true;
this.rAsciiPly.Text = "ASCII PLY"; this.rAsciiPly.Text = "ASCII PLY";
@@ -557,40 +615,63 @@
// //
// txtRefinIters // txtRefinIters
// //
this.txtRefinIters.Location = new System.Drawing.Point(266, 23); this.txtRefinIters.Location = new System.Drawing.Point(408, 31);
this.txtRefinIters.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.txtRefinIters.Name = "txtRefinIters"; this.txtRefinIters.Name = "txtRefinIters";
this.txtRefinIters.Size = new System.Drawing.Size(38, 20); this.txtRefinIters.Size = new System.Drawing.Size(55, 26);
this.txtRefinIters.TabIndex = 27; this.txtRefinIters.TabIndex = 27;
this.txtRefinIters.TextChanged += new System.EventHandler(this.txtRefinIters_TextChanged); this.txtRefinIters.TextChanged += new System.EventHandler(this.txtRefinIters_TextChanged);
// //
// lbOuterIters // lbOuterIters
// //
this.lbOuterIters.AutoSize = true; this.lbOuterIters.AutoSize = true;
this.lbOuterIters.Location = new System.Drawing.Point(142, 26); this.lbOuterIters.Location = new System.Drawing.Point(222, 36);
this.lbOuterIters.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
this.lbOuterIters.Name = "lbOuterIters"; this.lbOuterIters.Name = "lbOuterIters";
this.lbOuterIters.Size = new System.Drawing.Size(118, 13); this.lbOuterIters.Size = new System.Drawing.Size(178, 20);
this.lbOuterIters.TabIndex = 26; this.lbOuterIters.TabIndex = 26;
this.lbOuterIters.Text = "Num of refinement iters:"; this.lbOuterIters.Text = "Num of refinement iters:";
// //
// chSkeletons // label2
// //
this.chSkeletons.AutoSize = true; this.label2.AutoSize = true;
this.chSkeletons.Location = new System.Drawing.Point(11, 41); this.label2.Location = new System.Drawing.Point(8, 139);
this.chSkeletons.Name = "chSkeletons"; this.label2.Name = "label2";
this.chSkeletons.Size = new System.Drawing.Size(154, 17); this.label2.Size = new System.Drawing.Size(141, 20);
this.chSkeletons.TabIndex = 21; this.label2.TabIndex = 31;
this.chSkeletons.Text = "show skeletons in live view"; this.label2.Text = "Compression level:";
this.chSkeletons.UseVisualStyleBackColor = true; //
this.chSkeletons.CheckedChanged += new System.EventHandler(this.chSkeletons_CheckedChanged); // cbCompressionLevel
//
this.cbCompressionLevel.FormattingEnabled = true;
this.cbCompressionLevel.Items.AddRange(new object[] {
"0 (no compression)",
"1",
"2 (recommended)",
"3",
"5",
"7",
"9",
"11",
"13",
"15",
"17",
"19"});
this.cbCompressionLevel.Location = new System.Drawing.Point(154, 136);
this.cbCompressionLevel.Name = "cbCompressionLevel";
this.cbCompressionLevel.Size = new System.Drawing.Size(169, 28);
this.cbCompressionLevel.TabIndex = 32;
this.cbCompressionLevel.SelectedIndexChanged += new System.EventHandler(this.cbCompressionLevel_SelectedIndexChanged);
// //
// SettingsForm // SettingsForm
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(656, 468); this.ClientSize = new System.Drawing.Size(984, 663);
this.Controls.Add(this.grServer); this.Controls.Add(this.grServer);
this.Controls.Add(this.grClient); this.Controls.Add(this.grClient);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
this.MaximizeBox = false; this.MaximizeBox = false;
this.Name = "SettingsForm"; this.Name = "SettingsForm";
this.Text = "Settings"; this.Text = "Settings";
@@ -657,11 +738,12 @@
private System.Windows.Forms.Label lbX; private System.Windows.Forms.Label lbX;
private System.Windows.Forms.GroupBox grBody; private System.Windows.Forms.GroupBox grBody;
private System.Windows.Forms.CheckBox chBodyData; private System.Windows.Forms.CheckBox chBodyData;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.RadioButton rBinaryPly; private System.Windows.Forms.RadioButton rBinaryPly;
private System.Windows.Forms.Label lbFormat; private System.Windows.Forms.Label lbFormat;
private System.Windows.Forms.RadioButton rAsciiPly; private System.Windows.Forms.RadioButton rAsciiPly;
private System.Windows.Forms.CheckBox chSkeletons; private System.Windows.Forms.CheckBox chSkeletons;
private System.Windows.Forms.ComboBox cbCompressionLevel;
private System.Windows.Forms.Label label2;
} }
} }
+19
View File
@@ -54,6 +54,8 @@ namespace KinectServer
chBodyData.Checked = oSettings.bStreamOnlyBodies; chBodyData.Checked = oSettings.bStreamOnlyBodies;
chSkeletons.Checked = oSettings.bShowSkeletons; chSkeletons.Checked = oSettings.bShowSkeletons;
cbCompressionLevel.SelectedText = oSettings.iCompressionLevel.ToString();
chMerge.Checked = oSettings.bMergeScansForSave; chMerge.Checked = oSettings.bMergeScansForSave;
txtICPIters.Text = oSettings.nNumICPIterations.ToString(); txtICPIters.Text = oSettings.nNumICPIterations.ToString();
txtRefinIters.Text = oSettings.nNumRefineIters.ToString(); txtRefinIters.Text = oSettings.nNumRefineIters.ToString();
@@ -316,5 +318,22 @@ namespace KinectServer
{ {
oSettings.bShowSkeletons = chSkeletons.Checked; oSettings.bShowSkeletons = chSkeletons.Checked;
} }
private void cbCompressionLevel_SelectedIndexChanged(object sender, EventArgs e)
{
int index = cbCompressionLevel.SelectedIndex;
if (index == 0)
oSettings.iCompressionLevel = 0;
else if (index == 2)
oSettings.iCompressionLevel = 2;
else
{
string value = cbCompressionLevel.SelectedItem.ToString();
bool tryParse = Int32.TryParse(value, out oSettings.iCompressionLevel);
if (!tryParse)
oSettings.iCompressionLevel = 0;
}
UpdateClients();
}
} }
} }
+6 -1
View File
@@ -11,7 +11,7 @@ using System.Net;
namespace KinectServer namespace KinectServer
{ {
class TransferServer public class TransferServer
{ {
public List<float> lVertices = new List<float>(); public List<float> lVertices = new List<float>();
public List<byte> lColors = new List<byte>(); public List<byte> lColors = new List<byte>();
@@ -22,6 +22,11 @@ namespace KinectServer
object oClientSocketLock = new object(); object oClientSocketLock = new object();
bool bServerRunning = false; bool bServerRunning = false;
~TransferServer()
{
StopServer();
}
public void StartServer() public void StartServer()
{ {
if (!bServerRunning) if (!bServerRunning)
+1 -1
View File
@@ -9,7 +9,7 @@ using System.Runtime.Serialization.Formatters.Binary;
namespace KinectServer namespace KinectServer
{ {
class TransferSocket public class TransferSocket
{ {
TcpClient oSocket; TcpClient oSocket;
+54
View File
@@ -14,6 +14,8 @@
// } // }
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Globalization;
namespace KinectServer namespace KinectServer
{ {
@@ -157,4 +159,56 @@ namespace KinectServer
public List<Joint> lJoints; public List<Joint> lJoints;
public List<Point2f> lJointsInColorSpace; public List<Point2f> lJointsInColorSpace;
} }
public class Utils
{
public static void saveToPly(string filename, List<Single> vertices, List<byte> colors, bool binary)
{
int nVertices = vertices.Count / 3;
FileStream fileStream = File.Open(filename, FileMode.Create);
System.IO.StreamWriter streamWriter = new System.IO.StreamWriter(fileStream);
System.IO.BinaryWriter binaryWriter = new System.IO.BinaryWriter(fileStream);
//PLY file header is written here.
if (binary)
streamWriter.WriteLine("ply\nformat binary_little_endian 1.0");
else
streamWriter.WriteLine("ply\nformat ascii 1.0\n");
streamWriter.Write("element vertex " + nVertices.ToString() + "\n");
streamWriter.Write("property float x\nproperty float y\nproperty float z\nproperty uchar red\nproperty uchar green\nproperty uchar blue\nend_header\n");
streamWriter.Flush();
//Vertex and color data are written here.
if (binary)
{
for (int j = 0; j < vertices.Count / 3; j++)
{
for (int k = 0; k < 3; k++)
binaryWriter.Write(vertices[j * 3 + k]);
for (int k = 0; k < 3; k++)
{
byte temp = colors[j * 3 + k];
binaryWriter.Write(temp);
}
}
}
else
{
for (int j = 0; j < vertices.Count / 3; j++)
{
string s = "";
for (int k = 0; k < 3; k++)
s += vertices[j * 3 + k].ToString(CultureInfo.InvariantCulture) + " ";
for (int k = 0; k < 3; k++)
s += colors[j * 3 + k].ToString(CultureInfo.InvariantCulture) + " ";
streamWriter.WriteLine(s);
}
}
streamWriter.Flush();
binaryWriter.Flush();
fileStream.Close();
}
}
} }
+41
View File
@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using size_t = System.UIntPtr;
namespace KinectServer
{
static class ZSTDDecompressor
{
private const string dllName = "libzstd.dll";
[DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
public static extern ulong ZSTD_getDecompressedSize(IntPtr src, size_t srcSize);
[DllImport(dllName, CallingConvention = CallingConvention.Cdecl)]
public static extern size_t ZSTD_decompress(IntPtr dst, size_t dstSize,
IntPtr src, size_t srcSize);
public static byte[] Decompress(byte []array)
{
int size = array.Count();
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.Copy(array, 0, ptr, size);
int outSize = (int)ZSTD_getDecompressedSize(ptr, (size_t)size);
IntPtr outPtr = Marshal.AllocHGlobal(outSize);
ZSTD_decompress(outPtr, (size_t)outSize, ptr, (size_t)size);
byte[] outArray = new byte[outSize];
Marshal.Copy(outPtr, outArray, 0, outSize);
Marshal.FreeHGlobal(ptr);
Marshal.FreeHGlobal(outPtr);
return outArray;
}
}
}
+3 -1
View File
@@ -4,10 +4,11 @@ LiveScan3D is a system designed for real time 3D reconstruction using multiple K
The produced 3D reconstruction is in the form of a coloured point cloud, with points from all of the Kinects placed in the same coordinate system. Possible use scenarios of the system include: The produced 3D reconstruction is in the form of a coloured point cloud, with points from all of the Kinects placed in the same coordinate system. Possible use scenarios of the system include:
* capturing an object’s 3D structure from multiple viewpoints simultaneously, * capturing an object’s 3D structure from multiple viewpoints simultaneously,
* capturing a “panoramic” 3D structure of a scene (extending the field of view of one sensor by using many), * capturing a “panoramic” 3D structure of a scene (extending the field of view of one sensor by using many),
* streaming the reconstructed point cloud to a remote location,
* increasing the density of a point cloud captured by a single sensor, by having multiple sensors capture the same scene. * increasing the density of a point cloud captured by a single sensor, by having multiple sensors capture the same scene.
You will also find a short presentation of LiveScan3D in the video below (click to go to YouTube): You will also find a short presentation of LiveScan3D in the video below (click to go to YouTube):
[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/9y_WglwpJtE/0.jpg)](http://www.youtube.com/watch?v=9y_WglwpJtE) [![YouTube link](http://img.youtube.com/vi/9y_WglwpJtE/0.jpg)](http://www.youtube.com/watch?v=9y_WglwpJtE)
At the moment connecting multiple Kinect v2 devices to a single computer is difficult and only possible under Linux. Also, the number of the devices or capture speed might be low, because of the limitations of the PCI-E bus. At the moment connecting multiple Kinect v2 devices to a single computer is difficult and only possible under Linux. Also, the number of the devices or capture speed might be low, because of the limitations of the PCI-E bus.
@@ -28,6 +29,7 @@ While all of our code is licensed under the MIT license, the 3rd party libraries
* nanoflann - https://github.com/jlblancoc/nanoflann, BSD license * nanoflann - https://github.com/jlblancoc/nanoflann, BSD license
* OpenCV - https://github.com/Itseez/opencv, 3-clause BSD license * OpenCV - https://github.com/Itseez/opencv, 3-clause BSD license
* OpenTK - https://github.com/opentk/opentk, MIT/X11 license * OpenTK - https://github.com/opentk/opentk, MIT/X11 license
* ZSTD - https://github.com/facebook/zstd, BSD license
* SocketCS - http://www.adp-gmbh.ch/win/misc/sockets.html * SocketCS - http://www.adp-gmbh.ch/win/misc/sockets.html
If you use this software in your research, then please use the following citation: If you use this software in your research, then please use the following citation:
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+2 -3
View File
@@ -34,9 +34,6 @@ public:
vector<vector<float>> worldR; vector<vector<float>> worldR;
int iUsedMarkerId; int iUsedMarkerId;
vector<float> cameraT;
vector<vector<float>> cameraR;
vector<MarkerPose> markerPoses; vector<MarkerPose> markerPoses;
bool bCalibrated; bool bCalibrated;
@@ -45,6 +42,8 @@ public:
~Calibration(); ~Calibration();
bool Calibrate(RGB *pBuffer, Point3f *pCameraCoordinates, int cColorWidth, int cColorHeight); bool Calibrate(RGB *pBuffer, Point3f *pCameraCoordinates, int cColorWidth, int cColorHeight);
bool LoadCalibration();
void SaveCalibration();
private: private:
IMarker *pDetector; IMarker *pDetector;
int nSampleCounter; int nSampleCounter;
@@ -0,0 +1,41 @@
#pragma once
#include <stdio.h>
#include <string>
#include <vector>
#include <chrono>
#include "utils.h"
class FrameFileWriterReader
{
public:
FrameFileWriterReader();
void openNewFileForWriting();
void openCurrentFileForReading();
// leave filename blank if you want the filename to be generated from the date
void setCurrentFilename(std::string filename = "");
void writeFrame(std::vector<Point3s> points, std::vector<RGB> colors);
bool readFrame(std::vector<Point3s> &outPoints, std::vector<RGB> &outColors);
bool openedForWriting() { return m_bFileOpenedForWriting; }
bool openedForReading() { return m_bFileOpenedForReading; }
void closeFileIfOpened();
~FrameFileWriterReader();
private:
void resetTimer();
int getRecordingTimeMilliseconds();
FILE *m_pFileHandle = nullptr;
bool m_bFileOpenedForWriting = false;
bool m_bFileOpenedForReading = false;
std::string m_sFilename = "";
std::chrono::steady_clock::time_point recording_start_time;
};
+7 -3
View File
@@ -20,6 +20,7 @@
#include "calibration.h" #include "calibration.h"
#include "utils.h" #include "utils.h"
#include "KinectCapture.h" #include "KinectCapture.h"
#include "frameFileWriterReader.h"
#include <thread> #include <thread>
#include <mutex> #include <mutex>
@@ -52,15 +53,18 @@ private:
bool m_bConfirmCaptured; bool m_bConfirmCaptured;
bool m_bConfirmCalibrated; bool m_bConfirmCalibrated;
bool m_bShowDepth; bool m_bShowDepth;
bool m_bFrameCompression;
int m_iCompressionLevel;
FrameFileWriterReader m_framesFileWriterReader;
SocketClient *m_pClientSocket; SocketClient *m_pClientSocket;
std::vector<float> m_vBounds; std::vector<float> m_vBounds;
std::vector<Point3s> m_vLastFrameVertices; std::vector<Point3s> m_vLastFrameVertices;
std::vector<RGB> m_vLastFrameRGB; std::vector<RGB> m_vLastFrameRGB;
std::vector<Body> m_vLastFrameBody; std::vector<Body> m_vLastFrameBody;
std::vector<std::vector<Point3s>> m_vGatheredVertices;
std::vector<std::vector<RGB>> m_vGatheredRGBPoints;
HWND m_hWnd; HWND m_hWnd;
INT64 m_nLastCounter; INT64 m_nLastCounter;
+692
View File
@@ -0,0 +1,692 @@
/*
* Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#if defined (__cplusplus)
extern "C" {
#endif
#ifndef ZSTD_H_235446
#define ZSTD_H_235446
/* ====== Dependency ======*/
#include <stddef.h> /* size_t */
/* ===== ZSTDLIB_API : control library symbols visibility ===== */
#if defined(__GNUC__) && (__GNUC__ >= 4)
# define ZSTDLIB_VISIBILITY __attribute__ ((visibility ("default")))
#else
# define ZSTDLIB_VISIBILITY
#endif
#if defined(ZSTD_DLL_EXPORT) && (ZSTD_DLL_EXPORT==1)
# define ZSTDLIB_API __declspec(dllexport) ZSTDLIB_VISIBILITY
#elif defined(ZSTD_DLL_IMPORT) && (ZSTD_DLL_IMPORT==1)
# define ZSTDLIB_API __declspec(dllimport) ZSTDLIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
#else
# define ZSTDLIB_API ZSTDLIB_VISIBILITY
#endif
/*******************************************************************************************************
Introduction
zstd, short for Zstandard, is a fast lossless compression algorithm, targeting real-time compression scenarios
at zlib-level and better compression ratios. The zstd compression library provides in-memory compression and
decompression functions. The library supports compression levels from 1 up to ZSTD_maxCLevel() which is 22.
Levels >= 20, labelled `--ultra`, should be used with caution, as they require more memory.
Compression can be done in:
- a single step (described as Simple API)
- a single step, reusing a context (described as Explicit memory management)
- unbounded multiple steps (described as Streaming compression)
The compression ratio achievable on small data can be highly improved using compression with a dictionary in:
- a single step (described as Simple dictionary API)
- a single step, reusing a dictionary (described as Fast dictionary API)
Advanced experimental functions can be accessed using #define ZSTD_STATIC_LINKING_ONLY before including zstd.h.
These APIs shall never be used with a dynamic library.
They are not "stable", their definition may change in the future. Only static linking is allowed.
*********************************************************************************************************/
/*------ Version ------*/
#define ZSTD_VERSION_MAJOR 1
#define ZSTD_VERSION_MINOR 1
#define ZSTD_VERSION_RELEASE 3
#define ZSTD_LIB_VERSION ZSTD_VERSION_MAJOR.ZSTD_VERSION_MINOR.ZSTD_VERSION_RELEASE
#define ZSTD_QUOTE(str) #str
#define ZSTD_EXPAND_AND_QUOTE(str) ZSTD_QUOTE(str)
#define ZSTD_VERSION_STRING ZSTD_EXPAND_AND_QUOTE(ZSTD_LIB_VERSION)
#define ZSTD_VERSION_NUMBER (ZSTD_VERSION_MAJOR *100*100 + ZSTD_VERSION_MINOR *100 + ZSTD_VERSION_RELEASE)
ZSTDLIB_API unsigned ZSTD_versionNumber(void); /**< library version number; to be used when checking dll version */
/***************************************
* Simple API
***************************************/
/*! ZSTD_compress() :
Compresses `src` content as a single zstd compressed frame into already allocated `dst`.
Hint : compression runs faster if `dstCapacity` >= `ZSTD_compressBound(srcSize)`.
@return : compressed size written into `dst` (<= `dstCapacity),
or an error code if it fails (which can be tested using ZSTD_isError()). */
ZSTDLIB_API size_t ZSTD_compress( void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
int compressionLevel);
/*! ZSTD_decompress() :
`compressedSize` : must be the _exact_ size of a single compressed frame.
`dstCapacity` is an upper bound of originalSize.
If user cannot imply a maximum upper bound, it's better to use streaming mode to decompress data.
@return : the number of bytes decompressed into `dst` (<= `dstCapacity`),
or an errorCode if it fails (which can be tested using ZSTD_isError()). */
ZSTDLIB_API size_t ZSTD_decompress( void* dst, size_t dstCapacity,
const void* src, size_t compressedSize);
/*! ZSTD_getDecompressedSize() :
* 'src' is the start of a zstd compressed frame.
* @return : content size to be decompressed, as a 64-bits value _if known_, 0 otherwise.
* note 1 : decompressed size is an optional field, that may not be present, especially in streaming mode.
* When `return==0`, data to decompress could be any size.
* In which case, it's necessary to use streaming mode to decompress data.
* Optionally, application can still use ZSTD_decompress() while relying on implied limits.
* (For example, data may be necessarily cut into blocks <= 16 KB).
* note 2 : decompressed size is always present when compression is done with ZSTD_compress()
* note 3 : decompressed size can be very large (64-bits value),
* potentially larger than what local system can handle as a single memory segment.
* In which case, it's necessary to use streaming mode to decompress data.
* note 4 : If source is untrusted, decompressed size could be wrong or intentionally modified.
* Always ensure result fits within application's authorized limits.
* Each application can set its own limits.
* note 5 : when `return==0`, if precise failure cause is needed, use ZSTD_getFrameParams() to know more. */
ZSTDLIB_API unsigned long long ZSTD_getDecompressedSize(const void* src, size_t srcSize);
/*====== Helper functions ======*/
ZSTDLIB_API int ZSTD_maxCLevel(void); /*!< maximum compression level available */
ZSTDLIB_API size_t ZSTD_compressBound(size_t srcSize); /*!< maximum compressed size in worst case scenario */
ZSTDLIB_API unsigned ZSTD_isError(size_t code); /*!< tells if a `size_t` function result is an error code */
ZSTDLIB_API const char* ZSTD_getErrorName(size_t code); /*!< provides readable string from an error code */
/***************************************
* Explicit memory management
***************************************/
/*= Compression context
* When compressing many times,
* it is recommended to allocate a context just once, and re-use it for each successive compression operation.
* This will make workload friendlier for system's memory.
* Use one context per thread for parallel execution in multi-threaded environments. */
typedef struct ZSTD_CCtx_s ZSTD_CCtx;
ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx(void);
ZSTDLIB_API size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx);
/*! ZSTD_compressCCtx() :
Same as ZSTD_compress(), requires an allocated ZSTD_CCtx (see ZSTD_createCCtx()). */
ZSTDLIB_API size_t ZSTD_compressCCtx(ZSTD_CCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize, int compressionLevel);
/*= Decompression context */
typedef struct ZSTD_DCtx_s ZSTD_DCtx;
ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx(void);
ZSTDLIB_API size_t ZSTD_freeDCtx(ZSTD_DCtx* dctx);
/*! ZSTD_decompressDCtx() :
* Same as ZSTD_decompress(), requires an allocated ZSTD_DCtx (see ZSTD_createDCtx()). */
ZSTDLIB_API size_t ZSTD_decompressDCtx(ZSTD_DCtx* ctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
/**************************
* Simple dictionary API
***************************/
/*! ZSTD_compress_usingDict() :
* Compression using a predefined Dictionary (see dictBuilder/zdict.h).
* Note : This function loads the dictionary, resulting in significant startup delay.
* Note : When `dict == NULL || dictSize < 8` no dictionary is used. */
ZSTDLIB_API size_t ZSTD_compress_usingDict(ZSTD_CCtx* ctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const void* dict,size_t dictSize,
int compressionLevel);
/*! ZSTD_decompress_usingDict() :
* Decompression using a predefined Dictionary (see dictBuilder/zdict.h).
* Dictionary must be identical to the one used during compression.
* Note : This function loads the dictionary, resulting in significant startup delay.
* Note : When `dict == NULL || dictSize < 8` no dictionary is used. */
ZSTDLIB_API size_t ZSTD_decompress_usingDict(ZSTD_DCtx* dctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const void* dict,size_t dictSize);
/****************************
* Fast dictionary API
****************************/
typedef struct ZSTD_CDict_s ZSTD_CDict;
/*! ZSTD_createCDict() :
* When compressing multiple messages / blocks with the same dictionary, it's recommended to load it just once.
* ZSTD_createCDict() will create a digested dictionary, ready to start future compression operations without startup delay.
* ZSTD_CDict can be created once and used by multiple threads concurrently, as its usage is read-only.
* `dictBuffer` can be released after ZSTD_CDict creation, as its content is copied within CDict */
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict(const void* dictBuffer, size_t dictSize, int compressionLevel);
/*! ZSTD_freeCDict() :
* Function frees memory allocated by ZSTD_createCDict(). */
ZSTDLIB_API size_t ZSTD_freeCDict(ZSTD_CDict* CDict);
/*! ZSTD_compress_usingCDict() :
* Compression using a digested Dictionary.
* Faster startup than ZSTD_compress_usingDict(), recommended when same dictionary is used multiple times.
* Note that compression level is decided during dictionary creation. */
ZSTDLIB_API size_t ZSTD_compress_usingCDict(ZSTD_CCtx* cctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const ZSTD_CDict* cdict);
typedef struct ZSTD_DDict_s ZSTD_DDict;
/*! ZSTD_createDDict() :
* Create a digested dictionary, ready to start decompression operation without startup delay.
* dictBuffer can be released after DDict creation, as its content is copied inside DDict */
ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict(const void* dictBuffer, size_t dictSize);
/*! ZSTD_freeDDict() :
* Function frees memory allocated with ZSTD_createDDict() */
ZSTDLIB_API size_t ZSTD_freeDDict(ZSTD_DDict* ddict);
/*! ZSTD_decompress_usingDDict() :
* Decompression using a digested Dictionary.
* Faster startup than ZSTD_decompress_usingDict(), recommended when same dictionary is used multiple times. */
ZSTDLIB_API size_t ZSTD_decompress_usingDDict(ZSTD_DCtx* dctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const ZSTD_DDict* ddict);
/****************************
* Streaming
****************************/
typedef struct ZSTD_inBuffer_s {
const void* src; /**< start of input buffer */
size_t size; /**< size of input buffer */
size_t pos; /**< position where reading stopped. Will be updated. Necessarily 0 <= pos <= size */
} ZSTD_inBuffer;
typedef struct ZSTD_outBuffer_s {
void* dst; /**< start of output buffer */
size_t size; /**< size of output buffer */
size_t pos; /**< position where writing stopped. Will be updated. Necessarily 0 <= pos <= size */
} ZSTD_outBuffer;
/*-***********************************************************************
* Streaming compression - HowTo
*
* A ZSTD_CStream object is required to track streaming operation.
* Use ZSTD_createCStream() and ZSTD_freeCStream() to create/release resources.
* ZSTD_CStream objects can be reused multiple times on consecutive compression operations.
* It is recommended to re-use ZSTD_CStream in situations where many streaming operations will be achieved consecutively,
* since it will play nicer with system's memory, by re-using already allocated memory.
* Use one separate ZSTD_CStream per thread for parallel execution.
*
* Start a new compression by initializing ZSTD_CStream.
* Use ZSTD_initCStream() to start a new compression operation.
* Use ZSTD_initCStream_usingDict() or ZSTD_initCStream_usingCDict() for a compression which requires a dictionary (experimental section)
*
* Use ZSTD_compressStream() repetitively to consume input stream.
* The function will automatically update both `pos` fields.
* Note that it may not consume the entire input, in which case `pos < size`,
* and it's up to the caller to present again remaining data.
* @return : a size hint, preferred nb of bytes to use as input for next function call
* or an error code, which can be tested using ZSTD_isError().
* Note 1 : it's just a hint, to help latency a little, any other value will work fine.
* Note 2 : size hint is guaranteed to be <= ZSTD_CStreamInSize()
*
* At any moment, it's possible to flush whatever data remains within internal buffer, using ZSTD_flushStream().
* `output->pos` will be updated.
* Note that some content might still be left within internal buffer if `output->size` is too small.
* @return : nb of bytes still present within internal buffer (0 if it's empty)
* or an error code, which can be tested using ZSTD_isError().
*
* ZSTD_endStream() instructs to finish a frame.
* It will perform a flush and write frame epilogue.
* The epilogue is required for decoders to consider a frame completed.
* Similar to ZSTD_flushStream(), it may not be able to flush the full content if `output->size` is too small.
* In which case, call again ZSTD_endStream() to complete the flush.
* @return : nb of bytes still present within internal buffer (0 if it's empty, hence compression completed)
* or an error code, which can be tested using ZSTD_isError().
*
* *******************************************************************/
typedef struct ZSTD_CStream_s ZSTD_CStream;
ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream(void);
ZSTDLIB_API size_t ZSTD_freeCStream(ZSTD_CStream* zcs);
ZSTDLIB_API size_t ZSTD_initCStream(ZSTD_CStream* zcs, int compressionLevel);
ZSTDLIB_API size_t ZSTD_compressStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
ZSTDLIB_API size_t ZSTD_flushStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
ZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
ZSTDLIB_API size_t ZSTD_CStreamInSize(void); /**< recommended size for input buffer */
ZSTDLIB_API size_t ZSTD_CStreamOutSize(void); /**< recommended size for output buffer. Guarantee to successfully flush at least one complete compressed block in all circumstances. */
/*-***************************************************************************
* Streaming decompression - HowTo
*
* A ZSTD_DStream object is required to track streaming operations.
* Use ZSTD_createDStream() and ZSTD_freeDStream() to create/release resources.
* ZSTD_DStream objects can be re-used multiple times.
*
* Use ZSTD_initDStream() to start a new decompression operation,
* or ZSTD_initDStream_usingDict() if decompression requires a dictionary.
* @return : recommended first input size
*
* Use ZSTD_decompressStream() repetitively to consume your input.
* The function will update both `pos` fields.
* If `input.pos < input.size`, some input has not been consumed.
* It's up to the caller to present again remaining data.
* If `output.pos < output.size`, decoder has flushed everything it could.
* @return : 0 when a frame is completely decoded and fully flushed,
* an error code, which can be tested using ZSTD_isError(),
* any other value > 0, which means there is still some decoding to do to complete current frame.
* The return value is a suggested next input size (a hint to improve latency) that will never load more than the current frame.
* *******************************************************************************/
typedef struct ZSTD_DStream_s ZSTD_DStream;
ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream(void);
ZSTDLIB_API size_t ZSTD_freeDStream(ZSTD_DStream* zds);
ZSTDLIB_API size_t ZSTD_initDStream(ZSTD_DStream* zds);
ZSTDLIB_API size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inBuffer* input);
ZSTDLIB_API size_t ZSTD_DStreamInSize(void); /*!< recommended size for input buffer */
ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output buffer. Guarantee to successfully flush at least one complete block in all circumstances. */
#endif /* ZSTD_H_235446 */
#if defined(ZSTD_STATIC_LINKING_ONLY) && !defined(ZSTD_H_ZSTD_STATIC_LINKING_ONLY)
#define ZSTD_H_ZSTD_STATIC_LINKING_ONLY
/****************************************************************************************
* START OF ADVANCED AND EXPERIMENTAL FUNCTIONS
* The definitions in this section are considered experimental.
* They should never be used with a dynamic library, as they may change in the future.
* They are provided for advanced usages.
* Use them only in association with static linking.
* ***************************************************************************************/
/* --- Constants ---*/
#define ZSTD_MAGICNUMBER 0xFD2FB528 /* >= v0.8.0 */
#define ZSTD_MAGIC_SKIPPABLE_START 0x184D2A50U
#define ZSTD_WINDOWLOG_MAX_32 25
#define ZSTD_WINDOWLOG_MAX_64 27
#define ZSTD_WINDOWLOG_MAX ((U32)(MEM_32bits() ? ZSTD_WINDOWLOG_MAX_32 : ZSTD_WINDOWLOG_MAX_64))
#define ZSTD_WINDOWLOG_MIN 10
#define ZSTD_HASHLOG_MAX ZSTD_WINDOWLOG_MAX
#define ZSTD_HASHLOG_MIN 6
#define ZSTD_CHAINLOG_MAX (ZSTD_WINDOWLOG_MAX+1)
#define ZSTD_CHAINLOG_MIN ZSTD_HASHLOG_MIN
#define ZSTD_HASHLOG3_MAX 17
#define ZSTD_SEARCHLOG_MAX (ZSTD_WINDOWLOG_MAX-1)
#define ZSTD_SEARCHLOG_MIN 1
#define ZSTD_SEARCHLENGTH_MAX 7 /* only for ZSTD_fast, other strategies are limited to 6 */
#define ZSTD_SEARCHLENGTH_MIN 3 /* only for ZSTD_btopt, other strategies are limited to 4 */
#define ZSTD_TARGETLENGTH_MIN 4
#define ZSTD_TARGETLENGTH_MAX 999
#define ZSTD_FRAMEHEADERSIZE_MAX 18 /* for static allocation */
#define ZSTD_FRAMEHEADERSIZE_MIN 6
static const size_t ZSTD_frameHeaderSize_prefix = 5;
static const size_t ZSTD_frameHeaderSize_min = ZSTD_FRAMEHEADERSIZE_MIN;
static const size_t ZSTD_frameHeaderSize_max = ZSTD_FRAMEHEADERSIZE_MAX;
static const size_t ZSTD_skippableHeaderSize = 8; /* magic number + skippable frame length */
/*--- Advanced types ---*/
typedef enum { ZSTD_fast, ZSTD_dfast, ZSTD_greedy, ZSTD_lazy, ZSTD_lazy2, ZSTD_btlazy2, ZSTD_btopt, ZSTD_btopt2 } ZSTD_strategy; /* from faster to stronger */
typedef struct {
unsigned windowLog; /**< largest match distance : larger == more compression, more memory needed during decompression */
unsigned chainLog; /**< fully searched segment : larger == more compression, slower, more memory (useless for fast) */
unsigned hashLog; /**< dispatch table : larger == faster, more memory */
unsigned searchLog; /**< nb of searches : larger == more compression, slower */
unsigned searchLength; /**< match length searched : larger == faster decompression, sometimes less compression */
unsigned targetLength; /**< acceptable match size for optimal parser (only) : larger == more compression, slower */
ZSTD_strategy strategy;
} ZSTD_compressionParameters;
typedef struct {
unsigned contentSizeFlag; /**< 1: content size will be in frame header (if known). */
unsigned checksumFlag; /**< 1: will generate a 22-bits checksum at end of frame, to be used for error detection by decompressor */
unsigned noDictIDFlag; /**< 1: no dict ID will be saved into frame header (if dictionary compression) */
} ZSTD_frameParameters;
typedef struct {
ZSTD_compressionParameters cParams;
ZSTD_frameParameters fParams;
} ZSTD_parameters;
/*= Custom memory allocation functions */
typedef void* (*ZSTD_allocFunction) (void* opaque, size_t size);
typedef void (*ZSTD_freeFunction) (void* opaque, void* address);
typedef struct { ZSTD_allocFunction customAlloc; ZSTD_freeFunction customFree; void* opaque; } ZSTD_customMem;
/***************************************
* Advanced compression functions
***************************************/
/*! ZSTD_estimateCCtxSize() :
* Gives the amount of memory allocated for a ZSTD_CCtx given a set of compression parameters.
* `frameContentSize` is an optional parameter, provide `0` if unknown */
ZSTDLIB_API size_t ZSTD_estimateCCtxSize(ZSTD_compressionParameters cParams);
/*! ZSTD_createCCtx_advanced() :
* Create a ZSTD compression context using external alloc and free functions */
ZSTDLIB_API ZSTD_CCtx* ZSTD_createCCtx_advanced(ZSTD_customMem customMem);
/*! ZSTD_sizeofCCtx() :
* Gives the amount of memory used by a given ZSTD_CCtx */
ZSTDLIB_API size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);
/*! ZSTD_createCDict_byReference() :
* Create a digested dictionary for compression
* Dictionary content is simply referenced, and therefore stays in dictBuffer.
* It is important that dictBuffer outlives CDict, it must remain read accessible throughout the lifetime of CDict */
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel);
/*! ZSTD_createCDict_advanced() :
* Create a ZSTD_CDict using external alloc and free, and customized compression parameters */
ZSTDLIB_API ZSTD_CDict* ZSTD_createCDict_advanced(const void* dict, size_t dictSize, unsigned byReference,
ZSTD_parameters params, ZSTD_customMem customMem);
/*! ZSTD_sizeof_CDict() :
* Gives the amount of memory used by a given ZSTD_sizeof_CDict */
ZSTDLIB_API size_t ZSTD_sizeof_CDict(const ZSTD_CDict* cdict);
/*! ZSTD_getCParams() :
* @return ZSTD_compressionParameters structure for a selected compression level and estimated srcSize.
* `estimatedSrcSize` value is optional, select 0 if not known */
ZSTDLIB_API ZSTD_compressionParameters ZSTD_getCParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
/*! ZSTD_getParams() :
* same as ZSTD_getCParams(), but @return a full `ZSTD_parameters` object instead of sub-component `ZSTD_compressionParameters`.
* All fields of `ZSTD_frameParameters` are set to default (0) */
ZSTDLIB_API ZSTD_parameters ZSTD_getParams(int compressionLevel, unsigned long long estimatedSrcSize, size_t dictSize);
/*! ZSTD_checkCParams() :
* Ensure param values remain within authorized range */
ZSTDLIB_API size_t ZSTD_checkCParams(ZSTD_compressionParameters params);
/*! ZSTD_adjustCParams() :
* optimize params for a given `srcSize` and `dictSize`.
* both values are optional, select `0` if unknown. */
ZSTDLIB_API ZSTD_compressionParameters ZSTD_adjustCParams(ZSTD_compressionParameters cPar, unsigned long long srcSize, size_t dictSize);
/*! ZSTD_compress_advanced() :
* Same as ZSTD_compress_usingDict(), with fine-tune control of each compression parameter */
ZSTDLIB_API size_t ZSTD_compress_advanced (ZSTD_CCtx* ctx,
void* dst, size_t dstCapacity,
const void* src, size_t srcSize,
const void* dict,size_t dictSize,
ZSTD_parameters params);
/*--- Advanced decompression functions ---*/
/*! ZSTD_isFrame() :
* Tells if the content of `buffer` starts with a valid Frame Identifier.
* Note : Frame Identifier is 4 bytes. If `size < 4`, @return will always be 0.
* Note 2 : Legacy Frame Identifiers are considered valid only if Legacy Support is enabled.
* Note 3 : Skippable Frame Identifiers are considered valid. */
ZSTDLIB_API unsigned ZSTD_isFrame(const void* buffer, size_t size);
/*! ZSTD_estimateDCtxSize() :
* Gives the potential amount of memory allocated to create a ZSTD_DCtx */
ZSTDLIB_API size_t ZSTD_estimateDCtxSize(void);
/*! ZSTD_createDCtx_advanced() :
* Create a ZSTD decompression context using external alloc and free functions */
ZSTDLIB_API ZSTD_DCtx* ZSTD_createDCtx_advanced(ZSTD_customMem customMem);
/*! ZSTD_sizeof_DCtx() :
* Gives the amount of memory used by a given ZSTD_DCtx */
ZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx);
/*! ZSTD_createDDict_byReference() :
* Create a digested dictionary, ready to start decompression operation without startup delay.
* Dictionary content is simply referenced, and therefore stays in dictBuffer.
* It is important that dictBuffer outlives DDict, it must remain read accessible throughout the lifetime of DDict */
ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_byReference(const void* dictBuffer, size_t dictSize);
ZSTDLIB_API ZSTD_DDict* ZSTD_createDDict_advanced(const void* dict, size_t dictSize,
unsigned byReference, ZSTD_customMem customMem);
/*! ZSTD_sizeof_DDict() :
* Gives the amount of memory used by a given ZSTD_DDict */
ZSTDLIB_API size_t ZSTD_sizeof_DDict(const ZSTD_DDict* ddict);
/*! ZSTD_getDictID_fromDict() :
* Provides the dictID stored within dictionary.
* if @return == 0, the dictionary is not conformant with Zstandard specification.
* It can still be loaded, but as a content-only dictionary. */
ZSTDLIB_API unsigned ZSTD_getDictID_fromDict(const void* dict, size_t dictSize);
/*! ZSTD_getDictID_fromDDict() :
* Provides the dictID of the dictionary loaded into `ddict`.
* If @return == 0, the dictionary is not conformant to Zstandard specification, or empty.
* Non-conformant dictionaries can still be loaded, but as content-only dictionaries. */
ZSTDLIB_API unsigned ZSTD_getDictID_fromDDict(const ZSTD_DDict* ddict);
/*! ZSTD_getDictID_fromFrame() :
* Provides the dictID required to decompressed the frame stored within `src`.
* If @return == 0, the dictID could not be decoded.
* This could for one of the following reasons :
* - The frame does not require a dictionary to be decoded (most common case).
* - The frame was built with dictID intentionally removed. Whatever dictionary is necessary is a hidden information.
* Note : this use case also happens when using a non-conformant dictionary.
* - `srcSize` is too small, and as a result, the frame header could not be decoded (only possible if `srcSize < ZSTD_FRAMEHEADERSIZE_MAX`).
* - This is not a Zstandard frame.
* When identifying the exact failure cause, it's possible to used ZSTD_getFrameParams(), which will provide a more precise error code. */
ZSTDLIB_API unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize);
/********************************************************************
* Advanced streaming functions
********************************************************************/
/*===== Advanced Streaming compression functions =====*/
ZSTDLIB_API ZSTD_CStream* ZSTD_createCStream_advanced(ZSTD_customMem customMem);
ZSTDLIB_API size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize); /**< pledgedSrcSize must be correct */
ZSTDLIB_API size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel);
ZSTDLIB_API size_t ZSTD_initCStream_advanced(ZSTD_CStream* zcs, const void* dict, size_t dictSize,
ZSTD_parameters params, unsigned long long pledgedSrcSize); /**< pledgedSrcSize is optional and can be zero == unknown */
ZSTDLIB_API size_t ZSTD_initCStream_usingCDict(ZSTD_CStream* zcs, const ZSTD_CDict* cdict); /**< note : cdict will just be referenced, and must outlive compression session */
ZSTDLIB_API size_t ZSTD_resetCStream(ZSTD_CStream* zcs, unsigned long long pledgedSrcSize); /**< re-use compression parameters from previous init; skip dictionary loading stage; zcs must be init at least once before */
ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);
/*===== Advanced Streaming decompression functions =====*/
typedef enum { ZSTDdsp_maxWindowSize } ZSTD_DStreamParameter_e;
ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem);
ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize);
ZSTDLIB_API size_t ZSTD_setDStreamParameter(ZSTD_DStream* zds, ZSTD_DStreamParameter_e paramType, unsigned paramValue);
ZSTDLIB_API size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict); /**< note : ddict will just be referenced, and must outlive decompression session */
ZSTDLIB_API size_t ZSTD_resetDStream(ZSTD_DStream* zds); /**< re-use decompression parameters from previous init; saves dictionary loading */
ZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds);
/*********************************************************************
* Buffer-less and synchronous inner streaming functions
*
* This is an advanced API, giving full control over buffer management, for users which need direct control over memory.
* But it's also a complex one, with many restrictions (documented below).
* Prefer using normal streaming API for an easier experience
********************************************************************* */
/**
Buffer-less streaming compression (synchronous mode)
A ZSTD_CCtx object is required to track streaming operations.
Use ZSTD_createCCtx() / ZSTD_freeCCtx() to manage resource.
ZSTD_CCtx object can be re-used multiple times within successive compression operations.
Start by initializing a context.
Use ZSTD_compressBegin(), or ZSTD_compressBegin_usingDict() for dictionary compression,
or ZSTD_compressBegin_advanced(), for finer parameter control.
It's also possible to duplicate a reference context which has already been initialized, using ZSTD_copyCCtx()
Then, consume your input using ZSTD_compressContinue().
There are some important considerations to keep in mind when using this advanced function :
- ZSTD_compressContinue() has no internal buffer. It uses externally provided buffer only.
- Interface is synchronous : input is consumed entirely and produce 1+ (or more) compressed blocks.
- Caller must ensure there is enough space in `dst` to store compressed data under worst case scenario.
Worst case evaluation is provided by ZSTD_compressBound().
ZSTD_compressContinue() doesn't guarantee recover after a failed compression.
- ZSTD_compressContinue() presumes prior input ***is still accessible and unmodified*** (up to maximum distance size, see WindowLog).
It remembers all previous contiguous blocks, plus one separated memory segment (which can itself consists of multiple contiguous blocks)
- ZSTD_compressContinue() detects that prior input has been overwritten when `src` buffer overlaps.
In which case, it will "discard" the relevant memory section from its history.
Finish a frame with ZSTD_compressEnd(), which will write the last block(s) and optional checksum.
It's possible to use a NULL,0 src content, in which case, it will write a final empty block to end the frame,
Without last block mark, frames will be considered unfinished (broken) by decoders.
You can then reuse `ZSTD_CCtx` (ZSTD_compressBegin()) to compress some new frame.
*/
/*===== Buffer-less streaming compression functions =====*/
ZSTDLIB_API size_t ZSTD_compressBegin(ZSTD_CCtx* cctx, int compressionLevel);
ZSTDLIB_API size_t ZSTD_compressBegin_usingDict(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, int compressionLevel);
ZSTDLIB_API size_t ZSTD_compressBegin_advanced(ZSTD_CCtx* cctx, const void* dict, size_t dictSize, ZSTD_parameters params, unsigned long long pledgedSrcSize);
ZSTDLIB_API size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize);
ZSTDLIB_API size_t ZSTD_compressContinue(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
ZSTDLIB_API size_t ZSTD_compressEnd(ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
/*-
Buffer-less streaming decompression (synchronous mode)
A ZSTD_DCtx object is required to track streaming operations.
Use ZSTD_createDCtx() / ZSTD_freeDCtx() to manage it.
A ZSTD_DCtx object can be re-used multiple times.
First typical operation is to retrieve frame parameters, using ZSTD_getFrameParams().
It fills a ZSTD_frameParams structure which provide important information to correctly decode the frame,
such as the minimum rolling buffer size to allocate to decompress data (`windowSize`),
and the dictionary ID used.
(Note : content size is optional, it may not be present. 0 means : content size unknown).
Note that these values could be wrong, either because of data malformation, or because an attacker is spoofing deliberate false information.
As a consequence, check that values remain within valid application range, especially `windowSize`, before allocation.
Each application can set its own limit, depending on local restrictions. For extended interoperability, it is recommended to support at least 8 MB.
Frame parameters are extracted from the beginning of the compressed frame.
Data fragment must be large enough to ensure successful decoding, typically `ZSTD_frameHeaderSize_max` bytes.
@result : 0 : successful decoding, the `ZSTD_frameParams` structure is correctly filled.
>0 : `srcSize` is too small, please provide at least @result bytes on next attempt.
errorCode, which can be tested using ZSTD_isError().
Start decompression, with ZSTD_decompressBegin() or ZSTD_decompressBegin_usingDict().
Alternatively, you can copy a prepared context, using ZSTD_copyDCtx().
Then use ZSTD_nextSrcSizeToDecompress() and ZSTD_decompressContinue() alternatively.
ZSTD_nextSrcSizeToDecompress() tells how many bytes to provide as 'srcSize' to ZSTD_decompressContinue().
ZSTD_decompressContinue() requires this _exact_ amount of bytes, or it will fail.
@result of ZSTD_decompressContinue() is the number of bytes regenerated within 'dst' (necessarily <= dstCapacity).
It can be zero, which is not an error; it just means ZSTD_decompressContinue() has decoded some metadata item.
It can also be an error code, which can be tested with ZSTD_isError().
ZSTD_decompressContinue() needs previous data blocks during decompression, up to `windowSize`.
They should preferably be located contiguously, prior to current block.
Alternatively, a round buffer of sufficient size is also possible. Sufficient size is determined by frame parameters.
ZSTD_decompressContinue() is very sensitive to contiguity,
if 2 blocks don't follow each other, make sure that either the compressor breaks contiguity at the same place,
or that previous contiguous segment is large enough to properly handle maximum back-reference.
A frame is fully decoded when ZSTD_nextSrcSizeToDecompress() returns zero.
Context can then be reset to start a new decompression.
Note : it's possible to know if next input to present is a header or a block, using ZSTD_nextInputType().
This information is not required to properly decode a frame.
== Special case : skippable frames ==
Skippable frames allow integration of user-defined data into a flow of concatenated frames.
Skippable frames will be ignored (skipped) by a decompressor. The format of skippable frames is as follows :
a) Skippable frame ID - 4 Bytes, Little endian format, any value from 0x184D2A50 to 0x184D2A5F
b) Frame Size - 4 Bytes, Little endian format, unsigned 32-bits
c) Frame Content - any content (User Data) of length equal to Frame Size
For skippable frames ZSTD_decompressContinue() always returns 0.
For skippable frames ZSTD_getFrameParams() returns fparamsPtr->windowLog==0 what means that a frame is skippable.
It also returns Frame Size as fparamsPtr->frameContentSize.
*/
typedef struct {
unsigned long long frameContentSize;
unsigned windowSize;
unsigned dictID;
unsigned checksumFlag;
} ZSTD_frameParams;
/*===== Buffer-less streaming decompression functions =====*/
ZSTDLIB_API size_t ZSTD_getFrameParams(ZSTD_frameParams* fparamsPtr, const void* src, size_t srcSize); /**< doesn't consume input, see details below */
ZSTDLIB_API size_t ZSTD_decompressBegin(ZSTD_DCtx* dctx);
ZSTDLIB_API size_t ZSTD_decompressBegin_usingDict(ZSTD_DCtx* dctx, const void* dict, size_t dictSize);
ZSTDLIB_API void ZSTD_copyDCtx(ZSTD_DCtx* dctx, const ZSTD_DCtx* preparedDCtx);
ZSTDLIB_API size_t ZSTD_nextSrcSizeToDecompress(ZSTD_DCtx* dctx);
ZSTDLIB_API size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
typedef enum { ZSTDnit_frameHeader, ZSTDnit_blockHeader, ZSTDnit_block, ZSTDnit_lastBlock, ZSTDnit_checksum, ZSTDnit_skippableFrame } ZSTD_nextInputType_e;
ZSTDLIB_API ZSTD_nextInputType_e ZSTD_nextInputType(ZSTD_DCtx* dctx);
/**
Block functions
Block functions produce and decode raw zstd blocks, without frame metadata.
Frame metadata cost is typically ~18 bytes, which can be non-negligible for very small blocks (< 100 bytes).
User will have to take in charge required information to regenerate data, such as compressed and content sizes.
A few rules to respect :
- Compressing and decompressing require a context structure
+ Use ZSTD_createCCtx() and ZSTD_createDCtx()
- It is necessary to init context before starting
+ compression : ZSTD_compressBegin()
+ decompression : ZSTD_decompressBegin()
+ variants _usingDict() are also allowed
+ copyCCtx() and copyDCtx() work too
- Block size is limited, it must be <= ZSTD_getBlockSizeMax()
+ If you need to compress more, cut data into multiple blocks
+ Consider using the regular ZSTD_compress() instead, as frame metadata costs become negligible when source size is large.
- When a block is considered not compressible enough, ZSTD_compressBlock() result will be zero.
In which case, nothing is produced into `dst`.
+ User must test for such outcome and deal directly with uncompressed data
+ ZSTD_decompressBlock() doesn't accept uncompressed data as input !!!
+ In case of multiple successive blocks, decoder must be informed of uncompressed block existence to follow proper history.
Use ZSTD_insertBlock() in such a case.
*/
#define ZSTD_BLOCKSIZE_ABSOLUTEMAX (128 * 1024) /* define, for static allocation */
/*===== Raw zstd block functions =====*/
ZSTDLIB_API size_t ZSTD_getBlockSizeMax(ZSTD_CCtx* cctx);
ZSTDLIB_API size_t ZSTD_compressBlock (ZSTD_CCtx* cctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
ZSTDLIB_API size_t ZSTD_decompressBlock(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, const void* src, size_t srcSize);
ZSTDLIB_API size_t ZSTD_insertBlock(ZSTD_DCtx* dctx, const void* blockStart, size_t blockSize); /**< insert block into `dctx` history. Useful for uncompressed blocks */
#endif /* ZSTD_H_ZSTD_STATIC_LINKING_ONLY */
#if defined (__cplusplus)
}
#endif
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+50 -11
View File
@@ -17,7 +17,7 @@
#include "Kinect.h" #include "Kinect.h"
#include "opencv\cv.h" #include "opencv\cv.h"
#include <fstream>
Calibration::Calibration() Calibration::Calibration()
{ {
@@ -25,6 +25,13 @@ Calibration::Calibration()
nSampleCounter = 0; nSampleCounter = 0;
nRequiredSamples = 20; nRequiredSamples = 20;
worldT = vector<float>(3, 0.0f);
for (int i = 0; i < 3; i++)
{
worldR.push_back(vector<float>(3, 0.0f));
worldR[i][i] = 1.0f;
}
pDetector = new MarkerDetector(); pDetector = new MarkerDetector();
} }
@@ -102,17 +109,10 @@ bool Calibration::Calibrate(RGB *pBuffer, Point3f *pCameraCoordinates, int cColo
} }
} }
cameraR = worldR;
cameraT = RotatePoint(worldT, cameraR);
vector<float> translationIncr(3); vector<float> translationIncr(3);
translationIncr[0] = markerPose.t[0]; translationIncr[0] = markerPose.t[0];
translationIncr[1] = markerPose.t[1]; translationIncr[1] = markerPose.t[1];
translationIncr[2] = markerPose.t[2]; translationIncr[2] = markerPose.t[2];;
cameraT[0] += translationIncr[0];
cameraT[1] += translationIncr[1];
cameraT[2] += translationIncr[2];
translationIncr = InverseRotatePoint(translationIncr, worldR); translationIncr = InverseRotatePoint(translationIncr, worldR);
@@ -125,9 +125,50 @@ bool Calibration::Calibrate(RGB *pBuffer, Point3f *pCameraCoordinates, int cColo
marker3DSamples.clear(); marker3DSamples.clear();
nSampleCounter = 0; nSampleCounter = 0;
SaveCalibration();
return true; return true;
} }
bool Calibration::LoadCalibration()
{
ifstream file;
file.open("calibration.txt");
if (!file.is_open())
return false;
for (int i = 0; i < 3; i++)
file >> worldT[i];
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
file >> worldR[i][j];
}
file >> iUsedMarkerId;
file >> bCalibrated;
return true;
}
void Calibration::SaveCalibration()
{
ofstream file;
file.open("calibration.txt");
for (int i = 0; i < 3; i++)
file << worldT[i] << " ";
file << endl;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
file << worldR[i][j];
file << endl;
}
file << iUsedMarkerId << endl;
file << bCalibrated << endl;
file.close();
}
void Calibration::Procrustes(MarkerInfo &marker, vector<Point3f> &markerInWorld, vector<float> &worldToMarkerT, vector<vector<float>> &worldToMarkerR) void Calibration::Procrustes(MarkerInfo &marker, vector<Point3f> &markerInWorld, vector<float> &worldToMarkerT, vector<vector<float>> &worldToMarkerR)
{ {
int nVertices = marker.points.size(); int nVertices = marker.points.size();
@@ -232,8 +273,6 @@ bool Calibration::GetMarkerCorners3D(vector<Point3f> &marker3D, MarkerInfo &mark
return true; return true;
} }
vector<float> InverseRotatePoint(vector<float> &point, std::vector<std::vector<float>> &R) vector<float> InverseRotatePoint(vector<float> &point, std::vector<std::vector<float>> &R)
{ {
vector<float> res(3); vector<float> res(3);
@@ -0,0 +1,109 @@
#include "frameFileWriterReader.h"
#include <ctime>
FrameFileWriterReader::FrameFileWriterReader()
{
}
void FrameFileWriterReader::closeFileIfOpened()
{
if (m_pFileHandle == nullptr)
return;
fclose(m_pFileHandle);
m_pFileHandle = nullptr;
m_bFileOpenedForReading = false;
m_bFileOpenedForWriting = false;
}
void FrameFileWriterReader::resetTimer()
{
recording_start_time = std::chrono::steady_clock::now();
}
int FrameFileWriterReader::getRecordingTimeMilliseconds()
{
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
return static_cast<int>(std::chrono::duration_cast<std::chrono::milliseconds >(end - recording_start_time).count());
}
void FrameFileWriterReader::openCurrentFileForReading()
{
closeFileIfOpened();
m_pFileHandle = fopen(m_sFilename.c_str(), "rb");
m_bFileOpenedForReading = true;
m_bFileOpenedForWriting = false;
}
void FrameFileWriterReader::openNewFileForWriting()
{
closeFileIfOpened();
char filename[1024];
time_t t = time(0);
struct tm * now = localtime(&t);
sprintf(filename, "recording_%04d_%02d_%02d_%02d_%02d.bin", now->tm_year + 1900, now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec);
m_sFilename = filename;
m_pFileHandle = fopen(filename, "wb");
m_bFileOpenedForReading = false;
m_bFileOpenedForWriting = true;
resetTimer();
}
bool FrameFileWriterReader::readFrame(std::vector<Point3s> &outPoints, std::vector<RGB> &outColors)
{
if (!m_bFileOpenedForReading)
openCurrentFileForReading();
outPoints.clear();
outColors.clear();
FILE *f = m_pFileHandle;
int nPoints, timestamp;
char tmp[1024];
int nread = fscanf_s(f, "%s %d %s %d", tmp, 1024, &nPoints, tmp, 1024, &timestamp);
if (nread < 4)
return false;
if (nPoints == 0)
return true;
fgetc(f); // '\n'
outPoints.resize(nPoints);
outColors.resize(nPoints);
fread((void*)outPoints.data(), sizeof(outPoints[0]), nPoints, f);
fread((void*)outColors.data(), sizeof(outColors[0]), nPoints, f);
fgetc(f); // '\n'
return true;
}
void FrameFileWriterReader::writeFrame(std::vector<Point3s> points, std::vector<RGB> colors)
{
if (!m_bFileOpenedForWriting)
openNewFileForWriting();
FILE *f = m_pFileHandle;
int nPoints = static_cast<int>(points.size());
fprintf(f, "n_points= %d\nframe_timestamp= %d\n", nPoints, getRecordingTimeMilliseconds());
if (nPoints > 0)
{
fwrite((void*)points.data(), sizeof(points[0]), nPoints, f);
fwrite((void*)colors.data(), sizeof(colors[0]), nPoints, f);
}
fprintf(f, "\n");
}
FrameFileWriterReader::~FrameFileWriterReader()
{
closeFileIfOpened();
}
+7 -1
View File
@@ -99,6 +99,7 @@ bool KinectCapture::AcquireFrame()
GetBodyFrame(pMultiFrame); GetBodyFrame(pMultiFrame);
GetBodyIndexFrame(pMultiFrame); GetBodyIndexFrame(pMultiFrame);
SafeRelease(pMultiFrame);
return true; return true;
} }
@@ -202,7 +203,12 @@ void KinectCapture::GetBodyFrame(IMultiSourceFrame* pMultiFrame)
bodies[i]->GetJoints(JointType_Count, joints); bodies[i]->GetJoints(JointType_Count, joints);
vBodies[i].vJoints.assign(joints, joints + JointType_Count); vBodies[i].vJoints.assign(joints, joints + JointType_Count);
vBodies[i].bTracked = isTracked;
if (isTracked == TRUE)
vBodies[i].bTracked = true;
else
vBodies[i].bTracked = false;
vBodies[i].vJointsInColorSpace.resize(JointType_Count); vBodies[i].vJointsInColorSpace.resize(JointType_Count);
for (int j = 0; j < JointType_Count; j++) for (int j = 0; j < JointType_Count; j++)
+44 -46
View File
@@ -19,6 +19,7 @@
#include <chrono> #include <chrono>
#include <strsafe.h> #include <strsafe.h>
#include <fstream> #include <fstream>
#include "zstd.h"
std::mutex m_mSocketThreadMutex; std::mutex m_mSocketThreadMutex;
@@ -57,6 +58,8 @@ LiveScanClient::LiveScanClient() :
m_bConfirmCalibrated(false), m_bConfirmCalibrated(false),
m_bShowDepth(false), m_bShowDepth(false),
m_bSocketThread(true), m_bSocketThread(true),
m_bFrameCompression(true),
m_iCompressionLevel(2),
m_pClientSocket(NULL), m_pClientSocket(NULL),
m_nFilterNeighbors(10), m_nFilterNeighbors(10),
m_fFilterThreshold(0.01f) m_fFilterThreshold(0.01f)
@@ -75,6 +78,8 @@ LiveScanClient::LiveScanClient() :
m_vBounds.push_back(0.5); m_vBounds.push_back(0.5);
m_vBounds.push_back(0.5); m_vBounds.push_back(0.5);
m_vBounds.push_back(0.5); m_vBounds.push_back(0.5);
calibration.LoadCalibration();
} }
LiveScanClient::~LiveScanClient() LiveScanClient::~LiveScanClient()
@@ -130,7 +135,7 @@ int LiveScanClient::Run(HINSTANCE hInstance, int nCmdShow)
MSG msg = {0}; MSG msg = {0};
WNDCLASS wc; WNDCLASS wc;
// Dialog custom window class // Dialog custom window class
ZeroMemory(&wc, sizeof(wc)); ZeroMemory(&wc, sizeof(wc));
wc.style = CS_HREDRAW | CS_VREDRAW; wc.style = CS_HREDRAW | CS_VREDRAW;
wc.cbWndExtra = DLGWINDOWEXTRA; wc.cbWndExtra = DLGWINDOWEXTRA;
@@ -180,6 +185,8 @@ int LiveScanClient::Run(HINSTANCE hInstance, int nCmdShow)
return static_cast<int>(msg.wParam); return static_cast<int>(msg.wParam);
} }
void LiveScanClient::UpdateFrame() void LiveScanClient::UpdateFrame()
{ {
if (!pCapture->bInitialized) if (!pCapture->bInitialized)
@@ -200,8 +207,7 @@ void LiveScanClient::UpdateFrame()
if (m_bCaptureFrame) if (m_bCaptureFrame)
{ {
m_vGatheredVertices.push_back(m_vLastFrameVertices); m_framesFileWriterReader.writeFrame(m_vLastFrameVertices, m_vLastFrameRGB);
m_vGatheredRGBPoints.push_back(m_vLastFrameRGB);
m_bConfirmCaptured = true; m_bConfirmCaptured = true;
m_bCaptureFrame = false; m_bCaptureFrame = false;
} }
@@ -323,8 +329,6 @@ LRESULT CALLBACK LiveScanClient::DlgProc(HWND hWnd, UINT message, WPARAM wParam,
} }
else else
{ {
m_vGatheredVertices.clear();
m_vGatheredRGBPoints.clear();
try try
{ {
char address[20]; char address[20];
@@ -332,6 +336,9 @@ LRESULT CALLBACK LiveScanClient::DlgProc(HWND hWnd, UINT message, WPARAM wParam,
m_pClientSocket = new SocketClient(address, 48001); m_pClientSocket = new SocketClient(address, 48001);
m_bConnected = true; m_bConnected = true;
if (calibration.bCalibrated)
m_bConfirmCalibrated = true;
SetDlgItemTextA(m_hWnd, IDC_BUTTON_CONNECT, "Disconnect"); SetDlgItemTextA(m_hWnd, IDC_BUTTON_CONNECT, "Disconnect");
//Clear the status bar so that the "Failed to connect..." disappears. //Clear the status bar so that the "Failed to connect..." disappears.
SetStatusMessage(L"", 1, true); SetStatusMessage(L"", 1, true);
@@ -499,10 +506,13 @@ void LiveScanClient::HandleSocket()
} }
m_bStreamOnlyBodies = (received[i] != 0); m_bStreamOnlyBodies = (received[i] != 0);
i++; i += 1;
//so that we do not lose the next character in the stream m_iCompressionLevel = *(int*)(received.c_str() + i);
i--; if (m_iCompressionLevel > 0)
m_bFrameCompression = true;
else
m_bFrameCompression = false;
} }
//send stored frame //send stored frame
else if (received[i] == MSG_REQUEST_STORED_FRAME) else if (received[i] == MSG_REQUEST_STORED_FRAME)
@@ -510,18 +520,15 @@ void LiveScanClient::HandleSocket()
byteToSend = MSG_STORED_FRAME; byteToSend = MSG_STORED_FRAME;
m_pClientSocket->SendBytes(&byteToSend, 1); m_pClientSocket->SendBytes(&byteToSend, 1);
if (m_vGatheredRGBPoints.size() > 0) vector<Point3s> points;
{ vector<RGB> colors;
SendFrame(m_vGatheredVertices[0], m_vGatheredRGBPoints[0], m_vLastFrameBody); bool res = m_framesFileWriterReader.readFrame(points, colors);
if (res == false)
m_vGatheredRGBPoints.erase(m_vGatheredRGBPoints.begin(), m_vGatheredRGBPoints.begin() + 1);
m_vGatheredVertices.erase(m_vGatheredVertices.begin(), m_vGatheredVertices.begin() + 1);
}
else
{ {
int size = -1; int size = -1;
m_pClientSocket->SendBytes((char*)&size, 4); m_pClientSocket->SendBytes((char*)&size, 4);
} } else
SendFrame(points, colors, m_vLastFrameBody);
} }
//send last frame //send last frame
else if (received[i] == MSG_REQUEST_LAST_FRAME) else if (received[i] == MSG_REQUEST_LAST_FRAME)
@@ -549,27 +556,12 @@ void LiveScanClient::HandleSocket()
i += sizeof(float); i += sizeof(float);
} }
for (int j = 0; j < 3; j++)
{
for (int k = 0; k < 3; k++)
{
calibration.cameraR[j][k] = *(float*)(received.c_str() + i);
i += sizeof(float);
}
}
for (int j = 0; j < 3; j++)
{
calibration.cameraT[j] = *(float*)(received.c_str() + i);
i += sizeof(float);
}
//so that we do not lose the next character in the stream //so that we do not lose the next character in the stream
i--; i--;
} }
else if (received[i] == MSG_CLEAR_STORED_FRAMES) else if (received[i] == MSG_CLEAR_STORED_FRAMES)
{ {
m_vGatheredVertices.clear(); m_framesFileWriterReader.closeFileIfOpened();
m_vGatheredRGBPoints.clear();
} }
} }
@@ -582,7 +574,7 @@ void LiveScanClient::HandleSocket()
if (m_bConfirmCalibrated) if (m_bConfirmCalibrated)
{ {
int size = 2 * (9 + 3) * sizeof(float) + sizeof(int) + 1; int size = (9 + 3) * sizeof(float) + sizeof(int) + 1;
char *buffer = new char[size]; char *buffer = new char[size];
buffer[0] = MSG_CONFIRM_CALIBRATED; buffer[0] = MSG_CONFIRM_CALIBRATED;
int i = 1; int i = 1;
@@ -598,14 +590,6 @@ void LiveScanClient::HandleSocket()
memcpy(buffer + i, calibration.worldT.data(), 3 * sizeof(float)); memcpy(buffer + i, calibration.worldT.data(), 3 * sizeof(float));
i += 3 * sizeof(float); i += 3 * sizeof(float);
memcpy(buffer + i, calibration.cameraR[0].data(), 3 * sizeof(float));
i += 3 * sizeof(float);
memcpy(buffer + i, calibration.cameraR[1].data(), 3 * sizeof(float));
i += 3 * sizeof(float);
memcpy(buffer + i, calibration.cameraR[2].data(), 3 * sizeof(float));
i += 3 * sizeof(float);
memcpy(buffer + i, calibration.cameraT.data(), 3 * sizeof(float));
m_pClientSocket->SendBytes(buffer, size); m_pClientSocket->SendBytes(buffer, size);
m_bConfirmCalibrated = false; m_bConfirmCalibrated = false;
} }
@@ -629,12 +613,11 @@ void LiveScanClient::SendFrame(vector<Point3s> vertices, vector<RGB> RGB, vector
buffer[pos++] = RGB[i].rgbGreen; buffer[pos++] = RGB[i].rgbGreen;
buffer[pos++] = RGB[i].rgbBlue; buffer[pos++] = RGB[i].rgbBlue;
memcpy(buffer.data() + pos, ptr2, sizeof(short)* 3); memcpy(buffer.data() + pos, ptr2, sizeof(short)* 3);
ptr2 += sizeof(short) * 3; ptr2 += sizeof(short) * 3;
pos += sizeof(short) * 3; pos += sizeof(short) * 3;
} }
int nBodies = body.size(); int nBodies = body.size();
size += sizeof(nBodies); size += sizeof(nBodies);
for (int i = 0; i < nBodies; i++) for (int i = 0; i < nBodies; i++)
@@ -682,9 +665,24 @@ void LiveScanClient::SendFrame(vector<Point3s> vertices, vector<RGB> RGB, vector
} }
} }
m_pClientSocket->SendBytes((char*)&size, sizeof(int)); int iCompression = static_cast<int>(m_bFrameCompression);
m_pClientSocket->SendBytes(buffer.data(), size);
if (m_bFrameCompression)
{
// *2, because according to zstd documentation, increasing the size of the output buffer above a
// bound should speed up the compression.
int cBuffSize = ZSTD_compressBound(size) * 2;
vector<char> compressedBuffer(cBuffSize);
int cSize = ZSTD_compress(compressedBuffer.data(), cBuffSize, buffer.data(), size, m_iCompressionLevel);
size = cSize;
buffer = compressedBuffer;
}
char header[8];
memcpy(header, (char*)&size, sizeof(size));
memcpy(header + 4, (char*)&iCompression, sizeof(iCompression));
m_pClientSocket->SendBytes((char*)&header, sizeof(int) * 2);
m_pClientSocket->SendBytes(buffer.data(), size);
} }
void LiveScanClient::StoreFrame(Point3f *vertices, Point2f *mapping, RGB *color, vector<Body> &bodies, BYTE* bodyIndex) void LiveScanClient::StoreFrame(Point3f *vertices, Point2f *mapping, RGB *color, vector<Body> &bodies, BYTE* bodyIndex)