Commit 8607932e authored by David Llewellyn-Jones's avatar David Llewellyn-Jones

Added code structures for SVX voxel export.

parent aa1ace38
bin_PROGRAMS = ../functy
___functy_SOURCES = function.c function.h function_private.h functy.c functy.h textures.c textures.h utils.c utils.h vis.c vis.h filesave.c filesave.h cartesian.c cartesian.h spherical.c spherical.h shader.c shader.h curve.c curve.h vecsym.c vecsym.h exportply.c exportply.h exportstl.c exportstl.h exportbitmap.c exportbitmap.h recall.c recall.h controlvar.c controlvar.h shadow.c shadow.h
___functy_SOURCES = function.c function.h function_private.h functy.c functy.h textures.c textures.h utils.c utils.h vis.c vis.h filesave.c filesave.h cartesian.c cartesian.h spherical.c spherical.h shader.c shader.h curve.c curve.h vecsym.c vecsym.h exportply.c exportply.h exportstl.c exportstl.h exportbitmap.c exportbitmap.h exportsvx.c exportsvx.h recall.c recall.h controlvar.c controlvar.h shadow.c shadow.h
___functy_LDADD = -lm @FUNCTY_LIBS@
......
......@@ -304,7 +304,7 @@ bool ExportBitmapAnimated (char const * szFilename, char const * szType, int nHe
}
// Close the archive
printf ("Compressing (this mau take some time).\n");
printf ("Compressing (this may take some time).\n");
nError = zip_close (psZipArchive);
if (nError < 0) {
......
......@@ -258,7 +258,7 @@ bool ExportModelAnimatedPLY (char const * szFilename, bool boBinary, bool boScre
}
// Close the archive
printf ("Compressing (this mau take some time).\n");
printf ("Compressing (this may take some time).\n");
nError = zip_close (psZipArchive);
if (nError < 0) {
......
......@@ -238,7 +238,7 @@ bool ExportModelAnimatedSTL (char const * szFilename, bool boBinary, bool boScre
}
// Close the archive
printf ("Compressing (this mau take some time).\n");
printf ("Compressing (this may take some time).\n");
nError = zip_close (psZipArchive);
if (nError < 0) {
......
///////////////////////////////////////////////////////////////////
// Functy
// 3D graph drawing utility
//
// David Llewellyn-Jones
// http://www.flypig.co.uk
//
// Summer 2012
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
// Includes
#include <errno.h>
#include <zip.h>
#include <unistd.h>
#include "exportsvx.h"
#include "filesave.h"
///////////////////////////////////////////////////////////////////
// Defines
///////////////////////////////////////////////////////////////////
// Structures and enumerations
///////////////////////////////////////////////////////////////////
// Global variables
///////////////////////////////////////////////////////////////////
// Function prototypes
void FreePixelBufferSVX (guchar * pixels, gpointer data);
///////////////////////////////////////////////////////////////////
// Function definitions
// Callback for freeing the pixel buffer data
void FreePixelBufferSVX (guchar * pixels, gpointer data) {
// Free the data
g_free (pixels);
}
bool ExportModelSVX (char const * szFilename, int nResolution, VisPersist * psVisData) {
bool boSuccess;
GSList const * psFuncList;
GString * szFileIncrement;
GString * szFileNameFormat;
FuncPersist * psFuncData;
unsigned char * pcData;
unsigned long int uSize;
struct zip * psZipArchive;
int nError = 0;
zip_uint64_t uErrorLength;
char * szError;
struct zip_source * pzZipSource;
zip_int64_t nPosition;
int nResult;
int nSlice;
gchar * pcBuffer;
int nX;
int nY;
int nChannel;
int nChannels;
GdkPixbuf * psImage;
GError * psError = NULL;
boSuccess = TRUE;
nChannels = 3;
// Check whether the file exists and delete it if it does
nResult = access (szFilename, F_OK);
if (nResult == 0) {
nResult = remove (szFilename);
if (nResult != 0) {
printf ("Error deleting existing file.");
boSuccess = FALSE;
}
}
if (boSuccess) {
// Create the archive
//psZipArchive = zip_open (szFilename, (ZIP_CREATE | ZIP_TRUNCATE), & nError);
psZipArchive = zip_open (szFilename, (ZIP_CREATE), & nError);
if (psZipArchive == NULL) {
uErrorLength = zip_error_to_str (NULL, 0, nError, errno);
szError = g_malloc (uErrorLength + 1);
uErrorLength = zip_error_to_str (szError, uErrorLength + 1, nError, errno);
printf ("Error creating archive: %s\n", szError);
g_free (szError);
boSuccess = FALSE;
}
// Create the format for the filename
szFileNameFormat = g_string_new ("");
// Format is a decimal integer with EXPORTVOXEL_SLICE_EXP digits padded with zeros, followed by .extension
g_string_printf (szFileNameFormat, "density/slice%%0%dd.%s", EXPORTVOXEL_SLICE_EXP, "png");
szFileIncrement = g_string_new ("");
for (nSlice = 0; nSlice < nResolution; nSlice++) {
// Set the filename
g_string_printf (szFileIncrement, szFileNameFormat->str, nSlice);
// Create the memory to store the slice
pcData = g_new (unsigned char, (nResolution * nResolution * nChannels));
if (pcData != NULL) {
// Clear the slice
for (nX = 0; nX < nResolution; nX++) {
for (nY = 0; nY < nResolution; nY++) {
for (nChannel = 0; nChannel < nChannels; nChannel++) {
pcData[(((nX + (nY * nResolution)) * nChannels) + nChannel)] = 0;
}
}
}
// Render slices for each function
psFuncList = GetFunctionList (psVisData);
while (psFuncList) {
psFuncData = (FuncPersist *)(psFuncList->data);
// Render the function slice
OutputVoxelSlice (pcData, nResolution, nChannels, nSlice, psFuncData);
psFuncList = g_slist_next (psFuncList);
}
// Create a PNG image from the data
psImage = gdk_pixbuf_new_from_data (pcData, GDK_COLORSPACE_RGB, FALSE, 8, nResolution, nResolution, nResolution * 3, FreePixelBufferSVX, NULL);
if (psImage) {
// Create an in-memory PNG file from the data
psError = NULL;
pcBuffer = NULL;
gdk_pixbuf_save_to_buffer (psImage, & pcBuffer, & uSize, "png", & psError, NULL);
if (psError) {
printf ("%s", psError->message);
boSuccess = FALSE;
}
}
g_object_unref (G_OBJECT (psImage));
if (pcBuffer != NULL) {
// Add memory to the archive as a file
// This will be freed automatically once it's no longer needed
pzZipSource = zip_source_buffer (psZipArchive, pcBuffer, uSize, 1);
nPosition = zip_add (psZipArchive, szFileIncrement->str, pzZipSource);
if (nPosition < 0) {
zip_source_free (pzZipSource);
printf ("Error adding file: %s\n", zip_strerror (psZipArchive));
boSuccess = FALSE;
}
}
else {
printf ("Failed to create PNG voxel slice.\n");
boSuccess = FALSE;
}
printf ("Output slice %d out of %d.\n", (nSlice + 1), nResolution);
}
else {
printf ("Couldn't allocate memory for voxel slice.\n");
boSuccess = FALSE;
}
}
// Close the archive
printf ("Compressing (this may take some time).\n");
nError = zip_close (psZipArchive);
if (nError < 0) {
printf ("Error closing archive: %s\n", zip_strerror (psZipArchive));
}
g_string_free (szFileIncrement, TRUE);
g_string_free (szFileNameFormat, TRUE);
}
return boSuccess;
}
///////////////////////////////////////////////////////////////////
// Functy
// 3D graph drawing utility
//
// David Llewellyn-Jones
// http://www.flypig.co.uk
//
// Summer 2014
///////////////////////////////////////////////////////////////////
#ifndef EXPORTSVX_H
#define EXPORTSVX_H
///////////////////////////////////////////////////////////////////
// Includes
#include "vis.h"
#include "function.h"
///////////////////////////////////////////////////////////////////
// Defines
#define EXPORTVOXEL_SLICE_EXP (4)
///////////////////////////////////////////////////////////////////
// Structures and enumerations
///////////////////////////////////////////////////////////////////
// Global variables
///////////////////////////////////////////////////////////////////
// Function prototypes
bool ExportModelSVX (char const * szFilename, int nResolution, VisPersist * psVisData);
///////////////////////////////////////////////////////////////////
// Function definitions
#endif /* EXPORTSVX_H */
......@@ -1372,6 +1372,20 @@ Matrix4 * GetFunctionTransform (FuncPersist * psFuncData) {
return & psFuncData->mStructureTransform;
}
void OutputVoxelSlice (unsigned char * pcData, int nResolution, int nChannels, int nSlice, FuncPersist * psFuncData) {
// TODO: Actually store something in the slice
switch (psFuncData->eType) {
case FUNCTYPE_CARTESIAN:
break;
case FUNCTYPE_SPHERICAL:
break;
case FUNCTYPE_CURVE:
break;
default:
// Do nothing
break;
}
}
......@@ -110,6 +110,7 @@ void SetFunctionControlVars (FnControlPersist * psFnControlData, FuncPersist * p
void SetFunctionShadowData (ShadowPersist * psShadowData, FuncPersist * psFuncData);
void SetFunctionTransform (Matrix4 const * pmTransform, FuncPersist * psFuncData);
Matrix4 * GetFunctionTransform (FuncPersist * psFuncData);
void OutputVoxelSlice (unsigned char * pcData, int nResolution, int nChannels, int nSlice, FuncPersist * psFuncData);
///////////////////////////////////////////////////////////////////
// Function definitions
......
......@@ -232,6 +232,7 @@ FunctyPersist * NewFunctyPersist (void) {
psFunctyData->fExportTimeStart = 0.0;
psFunctyData->fExportTimeEnd = 1.0;
psFunctyData->nExportFrames = 50;
psFunctyData->nVoxelResolution = 512;
psFunctyData->eNextFunctionType = FUNCTYPE_INVALID;
psFunctyData->eButtonBarStyle = BUTTONBARSTYLE_ICONS;
psFunctyData->boShowPanelLeft = TRUE;
......@@ -3117,21 +3118,18 @@ static gboolean ExportFileSVXPress (GtkWidget * psWidget, gpointer psData) {
char * szFilename;
char * szFolder;
bool boExported;
GtkFileFilter * psFilterSTL;
GtkFileFilter * psFilterSVX;
GtkFileFilter * psFilterAll;
GtkWidget * psBinary;
GtkWidget * psMultiplier;
GtkWidget * psScale;
GtkWidget * psScreenCoords;
GtkWidget * psVoxelResolution;
GtkWidget * psOptionsFile;
GtkWidget * psWidgetAdd;
GtkAdjustment * psAdjustment;
psFilterSTL = gtk_file_filter_new ();
gtk_file_filter_add_pattern (psFilterSTL, "*.svx");
gtk_file_filter_add_mime_type (psFilterSTL, "text/svx");
gtk_file_filter_add_mime_type (psFilterSTL, "application/svx");
gtk_file_filter_set_name (psFilterSTL, "Shapeways Voxel Format");
psFilterSVX = gtk_file_filter_new ();
gtk_file_filter_add_pattern (psFilterSVX, "*.svx");
gtk_file_filter_add_mime_type (psFilterSVX, "text/svx");
gtk_file_filter_add_mime_type (psFilterSVX, "application/svx");
gtk_file_filter_set_name (psFilterSVX, "Shapeways Voxel Format");
psFilterAll = gtk_file_filter_new ();
gtk_file_filter_add_pattern (psFilterAll, "*");
......@@ -3143,7 +3141,7 @@ static gboolean ExportFileSVXPress (GtkWidget * psWidget, gpointer psData) {
gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (psDialogue), TRUE);
g_object_set (G_OBJECT (psDialogue), "local-only", FALSE, NULL);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (psDialogue), psFilterSTL);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (psDialogue), psFilterSVX);
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (psDialogue), psFilterAll);
PauseAnimationModal (TRUE, psFunctyData);
......@@ -3166,48 +3164,24 @@ static gboolean ExportFileSVXPress (GtkWidget * psWidget, gpointer psData) {
gtk_widget_show (psOptionsFile);
// Add file attribute widgets
psWidgetAdd = gtk_label_new ("Scale");
psWidgetAdd = gtk_label_new ("Resolution");
gtk_label_set_justify (GTK_LABEL (psWidgetAdd), GTK_JUSTIFY_RIGHT);
gtk_widget_show (psWidgetAdd);
gtk_box_pack_start (GTK_BOX (psOptionsFile), psWidgetAdd, FALSE, TRUE, 0);
psAdjustment = GTK_ADJUSTMENT (gtk_adjustment_new (psFunctyData->fExportScale, 0.001, 10000.0, 0.1, 10.0, 0.0));
psScale = gtk_spin_button_new (psAdjustment, 0.1, 3);
gtk_widget_show (psScale);
gtk_box_pack_start (GTK_BOX (psOptionsFile), psScale, FALSE, TRUE, 0);
psWidgetAdd = gtk_label_new ("Accuracy");
gtk_label_set_justify (GTK_LABEL (psWidgetAdd), GTK_JUSTIFY_RIGHT);
gtk_widget_show (psWidgetAdd);
gtk_box_pack_start (GTK_BOX (psOptionsFile), psWidgetAdd, FALSE, TRUE, 0);
psAdjustment = GTK_ADJUSTMENT (gtk_adjustment_new (psFunctyData->fExportMultiplier, 0.00, 1000.0, 0.1, 1.0, 0.0));
psMultiplier = gtk_spin_button_new (psAdjustment, 1.0, 3);
gtk_widget_show (psMultiplier);
gtk_box_pack_start (GTK_BOX (psOptionsFile), psMultiplier, FALSE, TRUE, 0);
psBinary = gtk_check_button_new_with_label ("Binary");
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (psBinary), psFunctyData->boBinary);
gtk_widget_show (psBinary);
gtk_box_pack_start (GTK_BOX (psOptionsFile), psBinary, FALSE, TRUE, 0);
psScreenCoords = gtk_check_button_new_with_label ("Screen coords");
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (psScreenCoords), psFunctyData->boExportScreen);
gtk_widget_show (psScreenCoords);
gtk_box_pack_start (GTK_BOX (psOptionsFile), psScreenCoords, FALSE, TRUE, 0);
psAdjustment = GTK_ADJUSTMENT (gtk_adjustment_new (psFunctyData->nVoxelResolution, 1.0, 4096.0, 1.0, 10.0, 0.0));
psVoxelResolution = gtk_spin_button_new (psAdjustment, 1, 0);
gtk_widget_show (psVoxelResolution);
gtk_box_pack_start (GTK_BOX (psOptionsFile), psVoxelResolution, FALSE, TRUE, 0);
gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (psDialogue), psOptionsFile);
if (gtk_dialog_run (GTK_DIALOG (psDialogue)) == GTK_RESPONSE_ACCEPT) {
psFunctyData->boBinary = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (psBinary));
psFunctyData->fExportMultiplier = gtk_spin_button_get_value (GTK_SPIN_BUTTON (psMultiplier));
psFunctyData->fExportScale = gtk_spin_button_get_value (GTK_SPIN_BUTTON (psScale));
psFunctyData->boExportScreen = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (psScreenCoords));
psFunctyData->nVoxelResolution = gtk_spin_button_get_value (GTK_SPIN_BUTTON (psVoxelResolution));
szFilename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (psDialogue));
// Actually perform the model export
boExported = ExportModelFileSVX (szFilename, psFunctyData->boBinary, psFunctyData->boExportScreen, psFunctyData->fExportMultiplier, psFunctyData->fExportScale, psFunctyData->psVisData);
boExported = ExportModelFileSVX (szFilename, psFunctyData->nVoxelResolution, psFunctyData->psVisData);
if (boExported) {
g_string_assign (psFunctyData->szExportModelNameSVX, szFilename);
......
......@@ -68,6 +68,7 @@ struct _FunctyPersist {
double fExportTimeStart;
double fExportTimeEnd;
int nExportFrames;
int nVoxelResolution;
GString * szFolder;
GString * szFolderAnim;
FUNCTYPE eNextFunctionType;
......
......@@ -29,6 +29,7 @@
#include "exportply.h"
#include "exportstl.h"
#include "exportbitmap.h"
#include "exportsvx.h"
#include "shader.h"
#include "shadow.h"
......@@ -2545,10 +2546,10 @@ bool ExportModelFileSTL (char const * szFilename, bool boBinary, bool boScreenCo
return boSuccess;
}
bool ExportModelFileSVX (char const * szFilename, bool boBinary, bool boScreenCoords, double fMultiplier, double fScale, VisPersist * psVisData) {
bool ExportModelFileSVX (char const * szFilename, int nResolution, VisPersist * psVisData) {
bool boSuccess;
//boSuccess = ExportModelSVX (szFilename, boBinary, boScreenCoords, fMultiplier, fScale, psVisData->psFuncList);
boSuccess = ExportModelSVX (szFilename, nResolution, psVisData);
return boSuccess;
}
......
......@@ -116,7 +116,7 @@ void GetView (float * pfViewRadius, float * pfRotation, float * pfElevation, Vis
void ScaleFunctionRange (double fScale, VisPersist * psVisData);
bool ExportModelFilePLY (char const * szFilename, bool boBinary, bool boScreenCoords, bool boExportAlpha, double fMultiplier, double fScale, VisPersist * psVisData);
bool ExportModelFileSTL (char const * szFilename, bool boBinary, bool boScreenCoords, double fMultiplier, double fScale, VisPersist * psVisData);
bool ExportModelFileSVX (char const * szFilename, bool boBinary, bool boScreenCoords, double fMultiplier, double fScale, VisPersist * psVisData);
bool ExportModelFileSVX (char const * szFilename, int nResolution, VisPersist * psVisData);
bool ExportBitmapFilePNG (char const * szFilename, int nHeight, int nWidth, VisPersist * psVisData);
bool ExportModelFileAnimatedPLY (char const * szFilename, bool boBinary, bool boScreenCoords, bool boExportAlpha, double fMultiplier, double fScale, double fTimeStart, double fTimeEnd, int nFrames, VisPersist * psVisData);
bool ExportModelFileAnimatedSTL (char const * szFilename, bool boBinary, bool boScreenCoords, double fMultiplier, double fScale, double fTimeStart, double fTimeEnd, int nFrames, VisPersist * psVisData);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment