Commit 0cd35c70 authored by David Llewellyn-Jones's avatar David Llewellyn-Jones

Added ASCII STL export code.

parent 0df2049d
......@@ -164,31 +164,55 @@
</object>
</child>
<child>
<object class="GtkMenuItem" id="MenuExport">
<object class="GtkMenuItem" id="MenuExportModel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_action_appearance">False</property>
<property name="label" translatable="yes">Export</property>
<property name="label" translatable="yes">Export Model</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu" id="menu2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkMenuItem" id="MenuExportModel">
<object class="GtkMenuItem" id="MenuExportModelPLY">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_action_appearance">False</property>
<property name="label" translatable="yes">Model</property>
<property name="label" translatable="yes">PLY</property>
<property name="use_underline">True</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="MenuExportAnim">
<object class="GtkMenuItem" id="MenuExportModelSTL">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_action_appearance">False</property>
<property name="label" translatable="yes">Animation</property>
<property name="label" translatable="yes">STL</property>
<property name="use_underline">True</property>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem" id="MenuExportAnim">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_action_appearance">False</property>
<property name="label" translatable="yes">Export Animation</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu" id="menu8">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkMenuItem" id="MenuExportAnimPLY">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_action_appearance">False</property>
<property name="label" translatable="yes">PLY</property>
<property name="use_underline">True</property>
</object>
</child>
......@@ -533,7 +557,7 @@
</packing>
</child>
<child>
<object class="GtkToolButton" id="ExportModel">
<object class="GtkToolButton" id="ExportModelPLY">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_action_appearance">False</property>
......@@ -547,7 +571,7 @@
</packing>
</child>
<child>
<object class="GtkToolButton" id="ExportAnim">
<object class="GtkToolButton" id="ExportAnimPLY">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="use_action_appearance">False</property>
......
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 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 recall.c recall.h controlvar.c controlvar.h shadow.c shadow.h
___functy_LDADD = -lm @FUNCTY_LIBS@
......
......@@ -53,6 +53,7 @@ struct _CartesianPersist {
void CartesianPopulateVerticesColour (FuncPersist * psFuncData);
void CartesianPopulateVerticesNoColour (FuncPersist * psFuncData);
void CartesianResetVertices (FuncPersist * psFuncData);
void CartesianVertex (Vector3 * pvVertex, Vector3 * pvNormal, double fXFunc, double fYFunc, bool boScreenCoords, double fMultiplier, double fScale, FuncPersist const * psFuncData);
///////////////////////////////////////////////////////////////////
// Function definitions
......@@ -876,6 +877,131 @@ int CartesianCountStoredFaces (double fMultiplier, FuncPersist const * psFuncDat
return nFaces;
}
void CartesianVertex (Vector3 * pvVertex, Vector3 * pvNormal, double fXFunc, double fYFunc, bool boScreenCoords, double fMultiplier, double fScale, FuncPersist const * psFuncData) {
CartesianPersist * psCartesianData = psFuncData->Func.psCartesianData;
double fZFunc;
double fXScreen;
double fYScreen;
double fZScreen;
Vector3 vX;
Vector3 vY;
Vector3 vN;
Vector3 vVertex;
if ((pvVertex != NULL) || (pvNormal != NULL)) {
if (psCartesianData->psVariableX) {
SetVariable (psCartesianData->psVariableX, fXFunc);
}
if (psCartesianData->psVariableY) {
SetVariable (psCartesianData->psVariableY, fYFunc);
}
fZFunc = ApproximateOperation (psFuncData->psFunction);
vX.fX = 1.0f;
vX.fY = 0.0f;
vX.fZ = ApproximateOperation (psCartesianData->psDiffWrtX);
vY.fX = 0.0f;
vY.fY = 1.0f;
vY.fZ = ApproximateOperation (psCartesianData->psDiffWrtY);
vN = Normal (& vX, & vY);
fXScreen = (((fXFunc - psFuncData->fXMin) / psFuncData->fXWidth) * AXIS_XSIZE) - AXIS_XHSIZE;
fYScreen = (((fYFunc - psFuncData->fYMin) / psFuncData->fYWidth) * AXIS_YSIZE) - AXIS_YHSIZE;
fZScreen = (((fZFunc - psFuncData->fZMin) / psFuncData->fZWidth) * AXIS_ZSIZE) - AXIS_ZHSIZE;
if (psCartesianData->psVariableZ) {
SetVariable (psCartesianData->psVariableZ, fZFunc);
}
// Output the vertex to file
if (boScreenCoords) {
SetVector3 (vVertex, fXScreen, fYScreen, fZScreen);
}
else {
SetVector3 (vVertex, fXFunc, fYFunc, fZFunc);
}
ScaleVectorDirect (& vVertex, fScale);
if (pvVertex) {
*pvVertex = vVertex;
}
if (pvNormal) {
*pvNormal = vN;
}
}
}
void CartesianOutputStoredVerticesSTL (Recall * hFile, bool boBinary, bool boScreenCoords, double fMultiplier, double fScale, FuncPersist const * psFuncData) {
//CartesianPersist * psCartesianData = psFuncData->Func.psCartesianData;
int nX;
int nY;
double fXFunc;
double fYFunc;
int nXVertices;
int nYVertices;
Vector3 avPos[4];
int nVertex;
Vector3 vX;
Vector3 vY;
Vector3 vN;
double fAccuracy;
if (fMultiplier > 0.0) {
fAccuracy = psFuncData->fAccuracy / fMultiplier;
}
else {
fAccuracy = 0.5;
}
if (fAccuracy < ACCURACY_MIN) {
fAccuracy = ACCURACY_MIN;
}
nXVertices = floor (1.0 / fAccuracy) + 1;
nYVertices = floor (1.0 / fAccuracy) + 1;
for (nX = 0; nX < (nXVertices - 1); nX++) {
for (nY = 0; nY < (nYVertices - 1); nY++) {
for (nVertex = 0; nVertex < 4; nVertex++) {
fXFunc = ((((double)((nX + (int)(nVertex / 2)) % nXVertices)) * fAccuracy) * psFuncData->fXWidth) + psFuncData->fXMin;
fYFunc = ((((double)((nY + (nVertex % 2)) % nYVertices)) * fAccuracy) * psFuncData->fYWidth) + psFuncData->fYMin;
CartesianVertex (& avPos[nVertex], NULL, fXFunc, fYFunc, boScreenCoords, fMultiplier, fScale, psFuncData);
}
// Calculate the normals
// Based on the triangles rather than the curves to avoid messy results
vX = SubtractVectors (& avPos[1], & avPos[0]);
vY = SubtractVectors (& avPos[2], & avPos[0]);
vN = Normal (& vX, & vY);
// Output the triangles
recprintf (hFile, "facet normal %e %e %e\n", vN.fX, vN.fY, vN.fZ);
recprintf (hFile, "outer loop\n");
recprintf (hFile, "\tvertex %e %e %e\n", avPos[0].fX, avPos[0].fY, avPos[0].fZ);
recprintf (hFile, "\tvertex %e %e %e\n", avPos[2].fX, avPos[2].fY, avPos[2].fZ);
recprintf (hFile, "\tvertex %e %e %e\n", avPos[1].fX, avPos[1].fY, avPos[1].fZ);
recprintf (hFile, "endloop\n");
recprintf (hFile, "endfacet\n");
// Calculate the normals
// Based on the triangles rather than the curves to avoid messy results
vX = SubtractVectors (& avPos[3], & avPos[1]);
vY = SubtractVectors (& avPos[2], & avPos[1]);
vN = Normal (& vX, & vY);
recprintf (hFile, "facet normal %e %e %e\n", vN.fX, vN.fY, vN.fZ);
recprintf (hFile, "outer loop\n");
recprintf (hFile, "\tvertex %e %e %e\n", avPos[1].fX, avPos[1].fY, avPos[1].fZ);
recprintf (hFile, "\tvertex %e %e %e\n", avPos[2].fX, avPos[2].fY, avPos[2].fZ);
recprintf (hFile, "\tvertex %e %e %e\n", avPos[3].fX, avPos[3].fY, avPos[3].fZ);
recprintf (hFile, "endloop\n");
recprintf (hFile, "endfacet\n");
}
}
}
bool CartesianAssignControlVarsToFunction (FnControlPersist * psFnControlData, FuncPersist * psFuncData) {
// Do nothing
return FALSE;
......
......@@ -56,6 +56,7 @@ int CartesianOutputStoredVertices (Recall * hFile, bool boBinary, bool boScreenC
int CartesianOutputStoredIndices (Recall * hFile, bool boBinary, double fMultiplier, int nOffset, FuncPersist const * psFuncData);
int CartesianCountStoredVertices (double fMultiplier, FuncPersist const * psFuncData);
int CartesianCountStoredFaces (double fMultiplier, FuncPersist const * psFuncData);
void CartesianOutputStoredVerticesSTL (Recall * hFile, bool boBinary, bool boScreenCoords, double fMultiplier, double fScale, FuncPersist const * psFuncData);
bool CartesianAssignControlVarsToFunction (FnControlPersist * psFnControlData, FuncPersist * psFuncData);
///////////////////////////////////////////////////////////////////
......
......@@ -88,6 +88,7 @@ void CurvePopulateVerticesColour (FuncPersist * psFuncData);
void CurvePopulateVerticesNoColour (FuncPersist * psFuncData);
void CurveResetVertices (FuncPersist * psFuncData);
void CurveRecalculateCentre (CurvePersist * psCurveData);
void CurveVertex (Vector3 * pvVertex, Vector3 * pvNormal, double fStep, double fTheta, bool boScreenCoords, double fMultiplier, double fScale, FuncPersist const * psFuncData);
///////////////////////////////////////////////////////////////////
// Function definitions
......@@ -1465,6 +1466,206 @@ int CurveCountStoredFaces (double fMultiplier, FuncPersist const * psFuncData) {
return nFaces;
}
void CurveVertex (Vector3 * pvVertex, Vector3 * pvNormal, double fStep, double fTheta, bool boScreenCoords, double fMultiplier, double fScale, FuncPersist const * psFuncData) {
CurvePersist * psCurveData = psFuncData->Func.psCurveData;
double fXFunc;
double fYFunc;
double fZFunc;
double fXScreen;
double fYScreen;
double fZScreen;
Vector3 vA;
Vector3 vP;
Vector3 vN;
Vector3 vVertex;
Vector3 vPos;
Vector3 vOffset;
Vector3 vTangent;
Vector3 vNormal;
Vector3 vBinormal;
Vector3 vSecondDeriv;
Vector3 vTwist1;
Vector3 vTwist2;
Vector3 vUp;
float fSin;
float fCos;
Variable * psA;
Variable * psP;
float fRadius;
float fRadiusDerivA;
float fRadiusDerivP;
float fCurveLength;
Vector3 vNormalOut;
if ((pvVertex != NULL) || (pvNormal != NULL)) {
SetVector3 (vUp, 0.01f, 0.1f, 1.0f);
Normalise (& vUp);
// Create the parametric functions
psA = FindVariable (psFuncData->psVariables, "a");
psP = FindVariable (psFuncData->psVariables, "p");
if (psA) {
SetVariable (psA, fStep);
}
vPos = ApproximateVecSym (psCurveData->pvCurve);
// Calculate the tangent vector
vTangent = ApproximateVecSym (psCurveData->pvCurveDeriv);
// Calculate the second derivative for the binormal calculation
vSecondDeriv = ApproximateVecSym (psCurveData->pvCurveDeriv2);
// Normalise the tangent vector
fCurveLength = Length (& vTangent);
Normalise (& vTangent);
// Calculate the Frenet frame binormal vector
vBinormal = CrossProduct (& vTangent, & vSecondDeriv);
// Tackle inflection points and straight lines
if (Length (& vBinormal) < INFLECTION_ZEROCHECK) {
vBinormal = CrossProduct (& vTangent, & vUp);
}
Normalise (& vBinormal);
// Calculate the Frenet frame normal vector
vNormal = CrossProduct (& vTangent, & vBinormal);
if (psP) {
SetVariable (psP, fTheta);
}
fSin = sin (fTheta);
fCos = cos (fTheta);
// Transform the position in relation to the Frenet frame
// vOffset = (vNormal * fSin) + (fBinormal * fCos);
vTwist1 = ScaleVector (& vNormal, fCos);
vTwist2 = ScaleVector (& vBinormal, fSin);
vOffset = AddVectors (& vTwist1, & vTwist2);
fRadius = ApproximateOperation (psFuncData->psFunction);
fRadiusDerivA = ApproximateOperation (psCurveData->psRadiusDerivA);
fRadiusDerivP = ApproximateOperation (psCurveData->psRadiusDerivP);
// Set the curve position
fXFunc = (vPos.fX + (fRadius * vOffset.fX));
fYFunc = (vPos.fY + (fRadius * vOffset.fY));
fZFunc = (vPos.fZ + (fRadius * vOffset.fZ));
// Translate the function
fXFunc += psCurveData->fXCentre;
fYFunc += psCurveData->fYCentre;
fZFunc += psCurveData->fZCentre;
// Scale and translate to screen coordinates
fXScreen = (((fXFunc - psFuncData->fXMin) / psFuncData->fXWidth) * AXIS_XSIZE) - AXIS_XHSIZE;
fYScreen = (((fYFunc - psFuncData->fYMin) / psFuncData->fYWidth) * AXIS_YSIZE) - AXIS_YHSIZE;
fZScreen = (((fZFunc - psFuncData->fXMin) / psFuncData->fZWidth) * AXIS_ZSIZE) - AXIS_ZHSIZE;
// Calculate two perpendicular tangents to the curve
vA.fX = fRadiusDerivA * fCos;
vA.fY = fRadiusDerivA * fSin;
vA.fZ = fCurveLength;
vP.fX = ((fRadiusDerivP * fCos) - (fRadius * fSin));
vP.fY = ((fRadiusDerivP * fSin) + (fRadius * fCos));
vP.fZ = 0.0f;
// Calculate the normal to the untransformed curve
vN = Normal (& vP, & vA);
// Set the curve normal transformed in relation to the Frenet frame
vNormalOut.fX = (vNormal.fX * vN.fX) + (vBinormal.fX * vN.fY) + (vTangent.fX * vN.fZ);
vNormalOut.fY = (vNormal.fY * vN.fX) + (vBinormal.fY * vN.fY) + (vTangent.fY * vN.fZ);
vNormalOut.fZ = (vNormal.fZ * vN.fX) + (vBinormal.fZ * vN.fY) + (vTangent.fZ * vN.fZ);
// Output the vertex to file
if (boScreenCoords) {
SetVector3 (vVertex, fXScreen, fYScreen, fZScreen);
}
else {
SetVector3 (vVertex, fXFunc, fYFunc, fZFunc);
}
ScaleVectorDirect (& vVertex, fScale);
if (pvVertex) {
*pvVertex = vVertex;
}
if (pvNormal) {
*pvNormal = vNormalOut;
}
}
}
void CurveOutputStoredVerticesSTL (Recall * hFile, bool boBinary, bool boScreenCoords, double fMultiplier, double fScale, FuncPersist const * psFuncData) {
CurvePersist * psCurveData = psFuncData->Func.psCurveData;
int nPiece;
int nPieces;
int nSegments;
int nSegment;
double fStep;
double fTheta;
double fTexTheta;
Vector3 avPos[4];
int nVertex;
Vector3 vP;
Vector3 vS;
Vector3 vN;
nPieces = (int)((float)psCurveData->nPieces * fMultiplier);
if (nPieces < 2) {
nPieces = 2;
}
nSegments = (int)((float)psCurveData->nSegments * fMultiplier);
if (nSegments < 3) {
nSegments = 3;
}
for (nPiece = 0; nPiece < (nPieces - 1); nPiece++) {
for (nSegment = 0; nSegment < (nSegments - 1); nSegment++) {
for (nVertex = 0; nVertex < 4; nVertex++) {
fStep = ((double)(((nPiece + (int)(nVertex / 2)) % nPieces))) / ((double)(nPieces - 1.0f));
fTexTheta = ((double)(((nSegment + (nVertex % 2)) % nPieces))) / ((double)nSegments - 1.0f);
fTheta = fTexTheta * (2.0 * M_PI);
CurveVertex (& avPos[nVertex], NULL, fStep, fTheta, boScreenCoords, fMultiplier, fScale, psFuncData);
}
// Calculate the normals
// Based on the triangles rather than the curves to avoid messy results
vP = SubtractVectors (& avPos[1], & avPos[0]);
vS = SubtractVectors (& avPos[2], & avPos[0]);
vN = Normal (& vP, & vS);
// Output the triangles
recprintf (hFile, "facet normal %e %e %e\n", vN.fX, vN.fY, vN.fZ);
recprintf (hFile, "outer loop\n");
recprintf (hFile, "\tvertex %e %e %e\n", avPos[0].fX, avPos[0].fY, avPos[0].fZ);
recprintf (hFile, "\tvertex %e %e %e\n", avPos[2].fX, avPos[2].fY, avPos[2].fZ);
recprintf (hFile, "\tvertex %e %e %e\n", avPos[1].fX, avPos[1].fY, avPos[1].fZ);
recprintf (hFile, "endloop\n");
recprintf (hFile, "endfacet\n");
// Calculate the normals
// Based on the triangles rather than the curves to avoid messy results
vP = SubtractVectors (& avPos[3], & avPos[1]);
vS = SubtractVectors (& avPos[2], & avPos[1]);
vN = Normal (& vP, & vS);
recprintf (hFile, "facet normal %e %e %e\n", vN.fX, vN.fY, vN.fZ);
recprintf (hFile, "outer loop\n");
recprintf (hFile, "\tvertex %e %e %e\n", avPos[1].fX, avPos[1].fY, avPos[1].fZ);
recprintf (hFile, "\tvertex %e %e %e\n", avPos[2].fX, avPos[2].fY, avPos[2].fZ);
recprintf (hFile, "\tvertex %e %e %e\n", avPos[3].fX, avPos[3].fY, avPos[3].fZ);
recprintf (hFile, "endloop\n");
recprintf (hFile, "endfacet\n");
}
}
}
bool CurveAssignControlVarsToFunction (FnControlPersist * psFnControlData, FuncPersist * psFuncData) {
CurvePersist * psCurveData = psFuncData->Func.psCurveData;
bool boFound;
......
......@@ -65,6 +65,7 @@ int CurveOutputStoredVertices (Recall * hFile, bool boBinary, bool boScreenCoord
int CurveOutputStoredIndices (Recall * hFile, bool boBinary, double fMultiplier, int nOffset, FuncPersist const * psFuncData);
int CurveCountStoredVertices (double fMultiplier, FuncPersist const * psFuncData);
int CurveCountStoredFaces (double fMultiplier, FuncPersist const * psFuncData);
void CurveOutputStoredVerticesSTL (Recall * hFile, bool boBinary, bool boScreenCoords, double fMultiplier, double fScale, FuncPersist const * psFuncData);
bool CurveAssignControlVarsToFunction (FnControlPersist * psFnControlData, FuncPersist * psFuncData);
///////////////////////////////////////////////////////////////////
......
......@@ -39,12 +39,12 @@
///////////////////////////////////////////////////////////////////
// Function prototypes
void ExportModelRecall (Recall * hFile, bool boBinary, bool boScreenCoords, bool boExportAlpha, double fMultiplier, double fScale, GSList const * const psFunctions);
void ExportModelRecallPLY (Recall * hFile, bool boBinary, bool boScreenCoords, bool boExportAlpha, double fMultiplier, double fScale, GSList const * const psFunctions);
///////////////////////////////////////////////////////////////////
// Function definitions
bool ExportModel (char const * szFilename, bool boBinary, bool boScreenCoords, bool boExportAlpha, double fMultiplier, double fScale, GSList const * const psFunctions) {
bool ExportModelPLY (char const * szFilename, bool boBinary, bool boScreenCoords, bool boExportAlpha, double fMultiplier, double fScale, GSList const * const psFunctions) {
Recall * hFile;
bool boResult;
......@@ -53,7 +53,7 @@ bool ExportModel (char const * szFilename, bool boBinary, bool boScreenCoords, b
hFile = recopen (szFilename, "m");
if (hFile) {
ExportModelRecall (hFile, boBinary, boScreenCoords, boExportAlpha, fMultiplier, fScale, psFunctions);
ExportModelRecallPLY (hFile, boBinary, boScreenCoords, boExportAlpha, fMultiplier, fScale, psFunctions);
recclose (hFile);
boResult = TRUE;
......@@ -62,7 +62,7 @@ bool ExportModel (char const * szFilename, bool boBinary, bool boScreenCoords, b
return boResult;
}
void ExportModelRecall (Recall * hFile, bool boBinary, bool boScreenCoords, bool boExportAlpha, double fMultiplier, double fScale, GSList const * const psFunctions) {
void ExportModelRecallPLY (Recall * hFile, bool boBinary, bool boScreenCoords, bool boExportAlpha, double fMultiplier, double fScale, GSList const * const psFunctions) {
int nVertices;
int nFaces;
int nOffset;
......@@ -140,7 +140,7 @@ void ExportModelRecall (Recall * hFile, bool boBinary, bool boScreenCoords, bool
RestoreLocale (psRestore);
}
bool ExportModelAnimated (char const * szFilename, bool boBinary, bool boScreenCoords, bool boExportAlpha, float fMultiplier, double fScale, double fTimeStart, double fTimeEnd, int nFrames, GSList const * const psFunctions) {
bool ExportModelAnimatedPLY (char const * szFilename, bool boBinary, bool boScreenCoords, bool boExportAlpha, float fMultiplier, double fScale, double fTimeStart, double fTimeEnd, int nFrames, GSList const * const psFunctions) {
bool boSuccess;
GSList const * psFuncList;
double fTime;
......@@ -226,7 +226,7 @@ bool ExportModelAnimated (char const * szFilename, bool boBinary, bool boScreenC
hFile = recopen (NULL, "m");
if (hFile) {
ExportModelRecall (hFile, boBinary, boScreenCoords, boExportAlpha, fMultiplier, fScale, psFunctions);
ExportModelRecallPLY (hFile, boBinary, boScreenCoords, boExportAlpha, fMultiplier, fScale, psFunctions);
uSize = MemoryGetSize (hFile);
pData = MemoryDetachData (hFile);
......
......@@ -31,8 +31,8 @@
///////////////////////////////////////////////////////////////////
// Function prototypes
bool ExportModel (char const * szFilename, bool boBinary, bool boScreenCoords, bool boExportAlpha, double fMultiplier, double fScale, GSList const * const psFunctions);
bool ExportModelAnimated (char const * szFilename, bool boBinary, bool boScreenCoords, bool boExportAlpha, float fMultiplier, double fScale, double fTimeStart, double fTimeEnd, int nFrames, GSList const * const psFunctions);
bool ExportModelPLY (char const * szFilename, bool boBinary, bool boScreenCoords, bool boExportAlpha, double fMultiplier, double fScale, GSList const * const psFunctions);
bool ExportModelAnimatedPLY (char const * szFilename, bool boBinary, bool boScreenCoords, bool boExportAlpha, float fMultiplier, double fScale, double fTimeStart, double fTimeEnd, int nFrames, GSList const * const psFunctions);
///////////////////////////////////////////////////////////////////
// Function definitions
......
......@@ -1036,6 +1036,23 @@ int CountStoredFaces (double fMultiplier, FuncPersist const * psFuncData) {
return nFaces;
}
void OutputStoredVerticesSTL (Recall * hFile, bool boBinary, bool boScreenCoords, double fMultiplier, double fScale, FuncPersist const * psFuncData) {
switch (psFuncData->eType) {
case FUNCTYPE_CARTESIAN:
CartesianOutputStoredVerticesSTL (hFile, boBinary, boScreenCoords, fMultiplier, fScale, psFuncData);
break;
case FUNCTYPE_SPHERICAL:
SphericalOutputStoredVerticesSTL (hFile, boBinary, boScreenCoords, fMultiplier, fScale, psFuncData);
break;
case FUNCTYPE_CURVE:
CurveOutputStoredVerticesSTL (hFile, boBinary, boScreenCoords, fMultiplier, fScale, psFuncData);
break;
default:
// Do nothing
break;
}
}
void DrawGraph (FuncPersist * psFuncData) {
int nXIndex;
GLfloat * afVertices;
......
......@@ -100,6 +100,7 @@ int OutputStoredVertices (Recall * hFile, bool boBinary, bool boScreenCoords, bo
int OutputStoredIndices (Recall * hFile, bool boBinary, double fMultiplier, int nOffset, FuncPersist const * psFuncData);
int CountStoredVertices (double fMultiplier, FuncPersist const * psFuncData);
int CountStoredFaces (double fMultiplier, FuncPersist const * psFuncData);
void OutputStoredVerticesSTL (Recall * hFile, bool boBinary, bool boScreenCoords, double fMultiplier, double fScale, FuncPersist const * psFuncData);
void RecentreGraph (FuncPersist * psFuncData);
void DrawGraph (FuncPersist * psFuncData);
void DrawGraphShadow (FuncPersist * psFuncData);
......
This diff is collapsed.
......@@ -52,9 +52,11 @@ struct _FunctyPersist {
GString * szFilename;
bool boFolderSet;
bool boFolderSetAnim;
bool boExportedModel;
bool boExportedModelPLY;
bool boExportedModelSTL;
bool boExportedAnim;
GString * szExportModelName;
GString * szExportModelNamePLY;
GString * szExportModelNameSTL;
GString * szExportAnimName;
bool boBinary;
double fExportMultiplier;
......
......@@ -70,6 +70,7 @@ void SphericalPopulateVerticesColour (FuncPersist * psFuncData);
void SphericalPopulateVerticesNoColour (FuncPersist * psFuncData);
void SphericalResetVertices (FuncPersist * psFuncData);
void SphericalRecalculateCentre (SphericalPersist * psSphericalData);
void SphericalVertex (Vector3 * pvVertex, Vector3 * pvNormal, double fAFunc, double fPFunc, bool boScreenCoords, double fMultiplier, double fScale, FuncPersist const * psFuncData);
///////////////////////////////////////////////////////////////////
// Function definitions
......@@ -1067,6 +1068,163 @@ int SphericalCountStoredFaces (double fMultiplier, FuncPersist const * psFuncDat
return nFaces;
}
void SphericalVertex (Vector3 * pvVertex, Vector3 * pvNormal, double fAFunc, double fPFunc, bool boScreenCoords, double fMultiplier, double fScale, FuncPersist const * psFuncData) {
SphericalPersist * psSphericalData = psFuncData->Func.psSphericalData;
double fRFunc;
double fXFunc;
double fYFunc;
double fZFunc;
double fDiff;
double fXScreen;
double fYScreen;
double fZScreen;
Vector3 vA;
Vector3 vP;
Vector3 vN;
Vector3 vVertex;
if ((pvVertex != NULL) || (pvNormal != NULL)) {
if (psSphericalData->psVariableA) {
SetVariable (psSphericalData->psVariableA, fAFunc);
}
if (psSphericalData->psVariableP) {
SetVariable (psSphericalData->psVariableP, fPFunc);
}
fRFunc = ApproximateOperation (psFuncData->psFunction);
// Calculate the normal
fDiff = ApproximateOperation (psSphericalData->psDiffWrtA);
vA.fX = sin (fPFunc) * ((fDiff * cos (fAFunc)) - (fRFunc * sin (fAFunc)));
vA.fY = sin (fPFunc) * ((fDiff * sin (fAFunc)) + (fRFunc * cos (fAFunc)));
vA.fZ = fDiff * cos (fPFunc);
fDiff = ApproximateOperation (psSphericalData->psDiffWrtP);
vP.fX = cos (fAFunc) * ((fDiff * sin (fPFunc)) + (fRFunc * cos (fPFunc)));
vP.fY = sin (fAFunc) * ((fDiff * sin (fPFunc)) + (fRFunc * cos (fPFunc)));
vP.fZ = (fDiff * cos (fPFunc)) - (fRFunc * sin (fPFunc));
vN = Normal (& vA, & vP);
// Since sin(p) is zero when p is zero, we need to fix the normal
if (fPFunc == 0.0f) {
vN.fX = 0.0;
vN.fY = 0.0;
vN.fZ = -1.0;
}
// Calculate the cartesian position
fXFunc = (fRFunc * cos (fAFunc) * sin (fPFunc));
fYFunc = (fRFunc * sin (fAFunc) * sin (fPFunc));
fZFunc = (fRFunc * cos (fPFunc));
// Translate the function
fXFunc += psSphericalData->fXCentre;
fYFunc += psSphericalData->fYCentre;
fZFunc += psSphericalData->fZCentre;
// Scale and translate to screen coordinates
fXScreen = (((fXFunc - psFuncData->fXMin) / psFuncData->fXWidth) * AXIS_XSIZE) - AXIS_XHSIZE;
fYScreen = (((fYFunc - psFuncData->fYMin) / psFuncData->fYWidth) * AXIS_YSIZE) - AXIS_YHSIZE;
fZScreen = (((fZFunc - psFuncData->fZMin) / psFuncData->fZWidth) * AXIS_ZSIZE) - AXIS_ZHSIZE;
if (psSphericalData->psVariableR) {
SetVariable (psSphericalData->psVariableR, fRFunc);
}
// Return the correct vertex position
if (boScreenCoords) {
SetVector3 (vVertex, fXScreen, fYScreen, fZScreen);
}
else {
SetVector3 (vVertex, fXFunc, fYFunc, fZFunc);
}
ScaleVectorDirect (& vVertex, fScale);
vN.fX = -vN.fX;
vN.fY = -vN.fY;
vN.fZ = -vN.fZ;
if (pvVertex) {
*pvVertex = vVertex;
}
if (pvNormal) {
*pvNormal = vN;
}
}
}
void SphericalOutputStoredVerticesSTL (Recall * hFile, bool boBinary, bool boScreenCoords, double fMultiplier, double fScale, FuncPersist const * psFuncData) {
//SphericalPersist * psSphericalData = psFuncData->Func.psSphericalData;
int nA;
int nP;
double fAFunc;
double fPFunc;
int nAVertices;
int nPVertices;
Vector3 avPos[4];
int nVertex;
Vector3 vA;
Vector3 vP;
Vector3 vN;
double fAccuracy;
if (fMultiplier > 0.0) {
fAccuracy = psFuncData->fAccuracy / fMultiplier;
}
else {
fAccuracy = 0.5;
}
if (fAccuracy < ACCURACY_MIN) {
fAccuracy = ACCURACY_MIN;
}
nAVertices = floor (1.0 / fAccuracy) + 1;
nPVertices = floor (1.0 / fAccuracy) + 1;
for (nA = 0; nA < (nAVertices - 1); nA++) {
for (nP = 0; nP < (nPVertices - 1); nP++) {
for (nVertex = 0; nVertex < 4; nVertex++) {