mirror of
https://github.com/leozide/leocad
synced 2025-01-19 22:26:27 +01:00
POVRay lights - export POV file
This commit is contained in:
parent
d29c5b9323
commit
6b5bfbf99f
4 changed files with 531 additions and 107 deletions
|
@ -85,6 +85,8 @@ static std::vector<lcColor> lcParseColorFile(lcFile& File)
|
||||||
|
|
||||||
Color.Code = ~0U;
|
Color.Code = ~0U;
|
||||||
Color.Translucent = false;
|
Color.Translucent = false;
|
||||||
|
Color.Chrome = false;
|
||||||
|
Color.Rubber = false;
|
||||||
Color.Group = LC_COLORGROUP_SOLID;
|
Color.Group = LC_COLORGROUP_SOLID;
|
||||||
Color.Value[0] = FLT_MAX;
|
Color.Value[0] = FLT_MAX;
|
||||||
Color.Value[1] = FLT_MAX;
|
Color.Value[1] = FLT_MAX;
|
||||||
|
@ -157,8 +159,17 @@ static std::vector<lcColor> lcParseColorFile(lcFile& File)
|
||||||
else if (Value != 0)
|
else if (Value != 0)
|
||||||
Color.Group = LC_COLORGROUP_SPECIAL;
|
Color.Group = LC_COLORGROUP_SPECIAL;
|
||||||
}
|
}
|
||||||
else if (!strcmp(Token, "CHROME") || !strcmp(Token, "PEARLESCENT") || !strcmp(Token, "RUBBER") ||
|
else if (!strcmp(Token, "CHROME"))
|
||||||
!strcmp(Token, "MATTE_METALIC") || !strcmp(Token, "METAL") || !strcmp(Token, "LUMINANCE"))
|
{
|
||||||
|
Color.Chrome = true;
|
||||||
|
Color.Group = LC_COLORGROUP_SPECIAL;
|
||||||
|
}
|
||||||
|
else if (!strcmp(Token, "RUBBER"))
|
||||||
|
{
|
||||||
|
Color.Rubber = true;
|
||||||
|
Color.Group = LC_COLORGROUP_SPECIAL;
|
||||||
|
}
|
||||||
|
else if (!strcmp(Token, "PEARLESCENT") || !strcmp(Token, "MATTE_METALIC") || !strcmp(Token, "METAL") || !strcmp(Token, "LUMINANCE"))
|
||||||
{
|
{
|
||||||
Color.Group = LC_COLORGROUP_SPECIAL;
|
Color.Group = LC_COLORGROUP_SPECIAL;
|
||||||
}
|
}
|
||||||
|
@ -236,6 +247,8 @@ bool lcLoadColorFile(lcFile& File, lcStudStyle StudStyle)
|
||||||
|
|
||||||
MainColor.Code = 16;
|
MainColor.Code = 16;
|
||||||
MainColor.Translucent = false;
|
MainColor.Translucent = false;
|
||||||
|
MainColor.Chrome = false;
|
||||||
|
MainColor.Rubber = false;
|
||||||
MainColor.Group = LC_COLORGROUP_SOLID;
|
MainColor.Group = LC_COLORGROUP_SOLID;
|
||||||
MainColor.Value[0] = 1.0f;
|
MainColor.Value[0] = 1.0f;
|
||||||
MainColor.Value[1] = 1.0f;
|
MainColor.Value[1] = 1.0f;
|
||||||
|
@ -257,6 +270,8 @@ bool lcLoadColorFile(lcFile& File, lcStudStyle StudStyle)
|
||||||
|
|
||||||
EdgeColor.Code = 24;
|
EdgeColor.Code = 24;
|
||||||
EdgeColor.Translucent = false;
|
EdgeColor.Translucent = false;
|
||||||
|
EdgeColor.Chrome = false;
|
||||||
|
EdgeColor.Rubber = false;
|
||||||
EdgeColor.Group = LC_NUM_COLORGROUPS;
|
EdgeColor.Group = LC_NUM_COLORGROUPS;
|
||||||
EdgeColor.Value[0] = 0.5f;
|
EdgeColor.Value[0] = 0.5f;
|
||||||
EdgeColor.Value[1] = 0.5f;
|
EdgeColor.Value[1] = 0.5f;
|
||||||
|
@ -279,6 +294,8 @@ bool lcLoadColorFile(lcFile& File, lcStudStyle StudStyle)
|
||||||
|
|
||||||
StudCylinderColor.Code = LC_STUD_CYLINDER_COLOR_CODE;
|
StudCylinderColor.Code = LC_STUD_CYLINDER_COLOR_CODE;
|
||||||
StudCylinderColor.Translucent = false;
|
StudCylinderColor.Translucent = false;
|
||||||
|
StudCylinderColor.Chrome = false;
|
||||||
|
StudCylinderColor.Rubber = false;
|
||||||
StudCylinderColor.Group = LC_NUM_COLORGROUPS;
|
StudCylinderColor.Group = LC_NUM_COLORGROUPS;
|
||||||
StudCylinderColor.Value = lcVector4FromColor(Preferences.mStudCylinderColor);
|
StudCylinderColor.Value = lcVector4FromColor(Preferences.mStudCylinderColor);
|
||||||
StudCylinderColor.Edge = lcVector4FromColor(Preferences.mPartEdgeColor);
|
StudCylinderColor.Edge = lcVector4FromColor(Preferences.mPartEdgeColor);
|
||||||
|
@ -294,6 +311,8 @@ bool lcLoadColorFile(lcFile& File, lcStudStyle StudStyle)
|
||||||
|
|
||||||
NoColor.Code = LC_COLOR_NOCOLOR;
|
NoColor.Code = LC_COLOR_NOCOLOR;
|
||||||
NoColor.Translucent = false;
|
NoColor.Translucent = false;
|
||||||
|
NoColor.Chrome = false;
|
||||||
|
NoColor.Rubber = false;
|
||||||
NoColor.Group = LC_NUM_COLORGROUPS;
|
NoColor.Group = LC_NUM_COLORGROUPS;
|
||||||
NoColor.Value[0] = 0.5f;
|
NoColor.Value[0] = 0.5f;
|
||||||
NoColor.Value[1] = 0.5f;
|
NoColor.Value[1] = 0.5f;
|
||||||
|
@ -362,6 +381,8 @@ int lcGetColorIndex(quint32 ColorCode)
|
||||||
|
|
||||||
Color.Code = ColorCode;
|
Color.Code = ColorCode;
|
||||||
Color.Translucent = false;
|
Color.Translucent = false;
|
||||||
|
Color.Chrome = false;
|
||||||
|
Color.Rubber = false;
|
||||||
Color.Edge[0] = 0.2f;
|
Color.Edge[0] = 0.2f;
|
||||||
Color.Edge[1] = 0.2f;
|
Color.Edge[1] = 0.2f;
|
||||||
Color.Edge[2] = 0.2f;
|
Color.Edge[2] = 0.2f;
|
||||||
|
|
|
@ -13,6 +13,8 @@ struct lcColor
|
||||||
quint32 Code;
|
quint32 Code;
|
||||||
int Group;
|
int Group;
|
||||||
bool Translucent = false;
|
bool Translucent = false;
|
||||||
|
bool Chrome = false;
|
||||||
|
bool Rubber = false;
|
||||||
bool Adjusted = false;
|
bool Adjusted = false;
|
||||||
lcVector4 Value;
|
lcVector4 Value;
|
||||||
lcVector4 Edge;
|
lcVector4 Edge;
|
||||||
|
@ -64,3 +66,13 @@ inline bool lcIsColorTranslucent(size_t ColorIndex)
|
||||||
{
|
{
|
||||||
return gColorList[ColorIndex].Translucent;
|
return gColorList[ColorIndex].Translucent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool lcIsColorChrome(size_t ColorIndex)
|
||||||
|
{
|
||||||
|
return gColorList[ColorIndex].Chrome;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool lcIsColorRubber(size_t ColorIndex)
|
||||||
|
{
|
||||||
|
return gColorList[ColorIndex].Rubber;
|
||||||
|
}
|
||||||
|
|
|
@ -305,14 +305,14 @@ void lcMesh::ExportPOVRay(lcFile& File, const char* MeshName, const char** Color
|
||||||
const lcVector3 n2 = lcUnpackNormal(Verts[Indices[Idx + 1]].Normal);
|
const lcVector3 n2 = lcUnpackNormal(Verts[Indices[Idx + 1]].Normal);
|
||||||
const lcVector3 n3 = lcUnpackNormal(Verts[Indices[Idx + 2]].Normal);
|
const lcVector3 n3 = lcUnpackNormal(Verts[Indices[Idx + 2]].Normal);
|
||||||
|
|
||||||
sprintf(Line, " smooth_triangle { <%.2f, %.2f, %.2f>, <%.2f, %.2f, %.2f>, <%.2f, %.2f, %.2f>, <%.2f, %.2f, %.2f>, <%.2f, %.2f, %.2f>, <%.2f, %.2f, %.2f> }\n",
|
sprintf(Line, " smooth_triangle { <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g> }\n",
|
||||||
-v1.y, -v1.x, v1.z, -n1.y, -n1.x, n1.z, -v2.y, -v2.x, v2.z, -n2.y, -n2.x, n2.z, -v3.y, -v3.x, v3.z, -n3.y, -n3.x, n3.z);
|
-v1.y, -v1.x, v1.z, -n1.y, -n1.x, n1.z, -v2.y, -v2.x, v2.z, -n2.y, -n2.x, n2.z, -v3.y, -v3.x, v3.z, -n3.y, -n3.x, n3.z);
|
||||||
File.WriteLine(Line);
|
File.WriteLine(Line);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Section->ColorIndex != gDefaultColor)
|
if (Section->ColorIndex != gDefaultColor)
|
||||||
{
|
{
|
||||||
sprintf(Line, "material { texture { %s normal { bumps 0.1 scale 2 } } }", ColorTable[Section->ColorIndex]);
|
sprintf(Line, " material { texture { %s normal { bumps 0.1 scale 2 } } }", ColorTable[Section->ColorIndex]);
|
||||||
File.WriteLine(Line);
|
File.WriteLine(Line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "project.h"
|
#include "project.h"
|
||||||
#include "lc_instructions.h"
|
#include "lc_instructions.h"
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
|
#include "light.h"
|
||||||
#include "lc_mainwindow.h"
|
#include "lc_mainwindow.h"
|
||||||
#include "lc_view.h"
|
#include "lc_view.h"
|
||||||
#include "lc_library.h"
|
#include "lc_library.h"
|
||||||
|
@ -1828,15 +1829,6 @@ bool Project::ExportPOVRay(const QString& FileName)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
POVFile.WriteLine("#version 3.7;\n\nglobal_settings {\n assumed_gamma 1.0\n}\n\n");
|
|
||||||
|
|
||||||
char Line[1024];
|
|
||||||
|
|
||||||
lcPiecesLibrary* Library = lcGetPiecesLibrary();
|
|
||||||
std::map<const PieceInfo*, std::pair<char[LC_PIECE_NAME_LEN + 1], int>> PieceTable;
|
|
||||||
size_t NumColors = gColorList.size();
|
|
||||||
std::vector<std::array<char, LC_MAX_COLOR_NAME>> ColorTable(NumColors);
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
LGEO_PIECE_LGEO = 0x01,
|
LGEO_PIECE_LGEO = 0x01,
|
||||||
|
@ -1855,10 +1847,386 @@ bool Project::ExportPOVRay(const QString& FileName)
|
||||||
LGEO_COLOR_GLITTER = 0x40
|
LGEO_COLOR_GLITTER = 0x40
|
||||||
};
|
};
|
||||||
|
|
||||||
QString LGEOPath; // todo: load lgeo from registry and make sure it still works
|
char Line[1024];
|
||||||
|
|
||||||
if (!LGEOPath.isEmpty())
|
sprintf(Line, "// Generated By: LeoCAD %s\n// LDraw File: %s\n// Date: %s\n\n",
|
||||||
|
LC_VERSION_TEXT,
|
||||||
|
mModels[0]->GetProperties().mFileName.toLatin1().constData(),
|
||||||
|
QDateTime::currentDateTime().toString(Qt::ISODate).toLatin1().constData());
|
||||||
|
POVFile.WriteLine(Line);
|
||||||
|
|
||||||
|
POVFile.WriteLine("#version 3.7;\n\n");
|
||||||
|
|
||||||
|
POVFile.WriteLine("global_settings { assumed_gamma 1.0 }\n\n");
|
||||||
|
|
||||||
|
/* POV-Ray uses a left-handed coordinate system
|
||||||
|
* - positive x-axis pointing right
|
||||||
|
* - positive y-axis pointing up
|
||||||
|
* - positive z-axis pointing away from you
|
||||||
|
* POVRay [0]x,[1]y,[2]z = LeoCAD [1]y,[0]x,[2]z */
|
||||||
|
|
||||||
|
lcPiecesLibrary* Library = lcGetPiecesLibrary();
|
||||||
|
std::map<const PieceInfo*, std::pair<char[LC_PIECE_NAME_LEN + 1], int>> PieceTable;
|
||||||
|
size_t NumColors = gColorList.size();
|
||||||
|
std::vector<std::array<char, LC_MAX_COLOR_NAME>> LgeoColorTable(NumColors);
|
||||||
|
std::vector<std::array<char, LC_MAX_COLOR_NAME>> ColorTable(NumColors);
|
||||||
|
|
||||||
|
const lcArray<lcLight*> Lights = gMainWindow->GetActiveModel()->GetLights();
|
||||||
|
const lcCamera* Camera = gMainWindow->GetActiveView()->GetCamera();
|
||||||
|
const QString CameraName = QString(Camera->GetName()).replace(" ","_");
|
||||||
|
const lcVector3& Position = Camera->mPosition;
|
||||||
|
const lcVector3& Target = Camera->mTargetPosition;
|
||||||
|
const lcVector3& Up = Camera->mUpVector;
|
||||||
|
const lcVector3 BackgroundColor = lcVector3FromColor(lcGetPreferences().mBackgroundSolidColor);
|
||||||
|
const lcPOVRayOptions& POVRayOptions = mModels[0]->GetPOVRayOptions();
|
||||||
|
const QString TopModelName = QString("LC_%1").arg(QString(mModels[0]->GetFileName()).replace(" ","_").replace(".","_dot_"));
|
||||||
|
const QString LGEOPath = lcGetProfileString(LC_PROFILE_POVRAY_LGEO_PATH);
|
||||||
|
const bool UseLGEO = POVRayOptions.UseLGEO && !LGEOPath.isEmpty();
|
||||||
|
const int TopModelColorCode = 7;
|
||||||
|
QStringList ColorMacros, MaterialColors;
|
||||||
|
|
||||||
|
lcVector3 Min(FLT_MAX, FLT_MAX, FLT_MAX);
|
||||||
|
lcVector3 Max(-FLT_MAX, -FLT_MAX, -FLT_MAX);
|
||||||
|
|
||||||
|
for (const lcModelPartsEntry& ModelPart : ModelParts)
|
||||||
{
|
{
|
||||||
|
lcVector3 Points[8];
|
||||||
|
|
||||||
|
lcGetBoxCorners(ModelPart.Info->GetBoundingBox(), Points);
|
||||||
|
|
||||||
|
for (int PointIdx = 0; PointIdx < 8; PointIdx++)
|
||||||
|
{
|
||||||
|
lcVector3 Point = lcMul31(Points[PointIdx], ModelPart.WorldMatrix);
|
||||||
|
|
||||||
|
Min = lcMin(Point, Min);
|
||||||
|
Max = lcMax(Point, Max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lcVector3 Center = (Min + Max) / 2.0f;
|
||||||
|
float Radius = (Max - Center).Length() / 25.0f;
|
||||||
|
Center = lcVector3(Center[1], Center[0], Center[2]) / 25.0f;
|
||||||
|
|
||||||
|
lcVector3 FloorColor = POVRayOptions.FloorColor;
|
||||||
|
float FloorAmbient = POVRayOptions.FloorAmbient;
|
||||||
|
float FloorDiffuse = POVRayOptions.FloorDiffuse;
|
||||||
|
char FloorLocation[32];
|
||||||
|
char FloorAxis[16];
|
||||||
|
if (POVRayOptions.FloorAxis == 0)
|
||||||
|
{
|
||||||
|
sprintf(FloorAxis, "x");
|
||||||
|
sprintf(FloorLocation, "MaxX");
|
||||||
|
}
|
||||||
|
else if (POVRayOptions.FloorAxis == 1)
|
||||||
|
{
|
||||||
|
sprintf(FloorAxis, "y");
|
||||||
|
sprintf(FloorLocation, "MaxY");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprintf(FloorAxis, "z");
|
||||||
|
sprintf(FloorLocation, "MaxZ");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const lcLight* Light : Lights)
|
||||||
|
{
|
||||||
|
if (Light->mLightType == LC_AREALIGHT)
|
||||||
|
{
|
||||||
|
if (FloorColor == lcVector3(0.8f,0.8f,0.8f))
|
||||||
|
FloorColor = {1.0f,1.0f,1.0f};
|
||||||
|
if (FloorAmbient == 0.4f)
|
||||||
|
FloorAmbient = 0.0f;
|
||||||
|
if (FloorDiffuse == 0.4f)
|
||||||
|
FloorDiffuse = 0.9f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!POVRayOptions.HeaderIncludeFile.isEmpty())
|
||||||
|
{
|
||||||
|
sprintf(Line, "#include \"%s\"\n\n", POVRayOptions.HeaderIncludeFile.toLatin1().constData());
|
||||||
|
POVFile.WriteLine(Line);
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(Line,
|
||||||
|
"#ifndef (MinX) #declare MinX = %g; #end\n"
|
||||||
|
"#ifndef (MinY) #declare MinY = %g; #end\n"
|
||||||
|
"#ifndef (MinZ) #declare MinZ = %g; #end\n"
|
||||||
|
"#ifndef (MaxX) #declare MaxX = %g; #end\n"
|
||||||
|
"#ifndef (MaxY) #declare MaxY = %g; #end\n"
|
||||||
|
"#ifndef (MaxZ) #declare MaxZ = %g; #end\n"
|
||||||
|
"#ifndef (CenterX) #declare CenterX = %g; #end\n"
|
||||||
|
"#ifndef (CenterY) #declare CenterY = %g; #end\n"
|
||||||
|
"#ifndef (CenterZ) #declare CenterZ = %g; #end\n"
|
||||||
|
"#ifndef (Center) #declare Center = <CenterX,CenterY,CenterZ>; #end\n"
|
||||||
|
"#ifndef (Radius) #declare Radius = %g; #end\n",
|
||||||
|
Min[0], Min[1], Min[2], Max[0], -Max[1], Max[2], Center[0], Center[1], Center[2], Radius);
|
||||||
|
POVFile.WriteLine(Line);
|
||||||
|
sprintf(Line,
|
||||||
|
"#ifndef (CameraSky) #declare CameraSky = <%g,%g,%g>; #end\n"
|
||||||
|
"#ifndef (CameraLocation) #declare CameraLocation = <%g, %g, %g>; #end\n"
|
||||||
|
"#ifndef (CameraTarget) #declare CameraTarget = <%g, %g, %g>; #end\n"
|
||||||
|
"#ifndef (CameraAngle) #declare CameraAngle = %g; #end\n",
|
||||||
|
Up[1], Up[0], Up[2], Position[1] / 25.0f, Position[0] / 25.0f, Position[2] / 25.0f, Target[1] / 25.0f, Target[0] / 25.0f, Target[2] / 25.0f, Camera->m_fovy);
|
||||||
|
POVFile.WriteLine(Line);
|
||||||
|
sprintf(Line,
|
||||||
|
"#ifndef (BackgroundColor) #declare BackgroundColor = <%1g, %1g, %1g>; #end\n"
|
||||||
|
"#ifndef (Background) #declare Background = %s; #end\n",
|
||||||
|
BackgroundColor[0], BackgroundColor[1], BackgroundColor[2], (POVRayOptions.ExcludeBackground ? "false" : "true"));
|
||||||
|
POVFile.WriteLine(Line);
|
||||||
|
sprintf(Line,
|
||||||
|
"#ifndef (FloorAxis) #declare FloorAxis = %s; #end\n"
|
||||||
|
"#ifndef (FloorLocation) #declare FloorLocation = %s; #end\n"
|
||||||
|
"#ifndef (FloorColor) #declare FloorColor = <%1g, %1g, %1g>; #end\n"
|
||||||
|
"#ifndef (FloorAmbient) #declare FloorAmbient = %1g; #end\n"
|
||||||
|
"#ifndef (FloorDiffuse) #declare FloorDiffuse = %1g; #end\n"
|
||||||
|
"#ifndef (Floor) #declare Floor = %s; #end\n",
|
||||||
|
FloorAxis, FloorLocation, FloorColor[0], FloorColor[1], FloorColor[2], FloorAmbient, FloorDiffuse, (POVRayOptions.ExcludeFloor ? "false" : "true"));
|
||||||
|
POVFile.WriteLine(Line);
|
||||||
|
sprintf(Line,
|
||||||
|
"#ifndef (Ambient) #declare Ambient = 0.4; #end\n"
|
||||||
|
"#ifndef (Diffuse) #declare Diffuse = 0.4; #end\n"
|
||||||
|
"#ifndef (Reflection) #declare Reflection = 0.08; #end\n"
|
||||||
|
"#ifndef (Phong) #declare Phong = 0.5; #end\n"
|
||||||
|
"#ifndef (PhongSize) #declare PhongSize = 40; #end\n"
|
||||||
|
"#ifndef (TransReflection) #declare TransReflection = 0.2; #end\n"
|
||||||
|
"#ifndef (TransFilter) #declare TransFilter = 0.85; #end\n"
|
||||||
|
"#ifndef (TransIoR) #declare TransIoR = 1.25; #end\n"
|
||||||
|
"#ifndef (RubberReflection) #declare RubberReflection = 0; #end\n"
|
||||||
|
"#ifndef (RubberPhong) #declare RubberPhong = 0.1; #end\n"
|
||||||
|
"#ifndef (RubberPhongS) #declare RubberPhongS = 10; #end\n"
|
||||||
|
"#ifndef (ChromeReflection) #declare ChromeReflection = 0.85; #end\n"
|
||||||
|
"#ifndef (ChromeBrilliance) #declare ChromeBrilliance = 5; #end\n"
|
||||||
|
"#ifndef (ChromeSpecular) #declare ChromeSpecular = 0.8; #end\n"
|
||||||
|
"#ifndef (ChromeRough) #declare ChromeRough = 0.01; #end\n"
|
||||||
|
"#ifndef (OpaqueNormal) #declare OpaqueNormal = normal { bumps 0.001 scale 0.5 }; #end\n"
|
||||||
|
"#ifndef (TransNormal) #declare TransNormal = normal { bumps 0.001 scale 0.5 }; #end\n");
|
||||||
|
POVFile.WriteLine(Line);
|
||||||
|
sprintf(Line,
|
||||||
|
"#ifndef (Quality) #declare Quality = 3; #end\n"
|
||||||
|
"#ifndef (Studs) #declare Studs = 1; #end\n"
|
||||||
|
"#ifndef (LgeoLibrary) #declare LgeoLibrary = %s; #end\n"
|
||||||
|
"#ifndef (ModelReflection) #declare ModelReflection = %i; #end\n"
|
||||||
|
"#ifndef (ModelShadow) #declare ModelShadow = %i; #end\n\n",
|
||||||
|
(POVRayOptions.UseLGEO ? "true" : "false"), (POVRayOptions.NoReflection ? 0 : 1), (POVRayOptions.NoShadow ? 0 : 1));
|
||||||
|
POVFile.WriteLine(Line);
|
||||||
|
|
||||||
|
sprintf(Line,
|
||||||
|
"#ifndef (SkipWriteLightMacro)\n"
|
||||||
|
"#macro WriteLight(Type, Shadowless, Location, Target, Color, Power, SpotRadius, SpotFalloff, SpotTightness, AreaCircle, AreaWidth, AreaHeight, AreaRows, AreaColumns)\n"
|
||||||
|
" #local PointLight = %i;\n"
|
||||||
|
" #local AreaLight = %i;\n"
|
||||||
|
" #local SunLight = %i;\n"
|
||||||
|
" #local SpotLight = %i;\n"
|
||||||
|
" light_source {\n"
|
||||||
|
" Location\n"
|
||||||
|
" color rgb Color*Power\n"
|
||||||
|
" #if (Shadowless > 0)\n"
|
||||||
|
" shadowless\n"
|
||||||
|
" #end\n"
|
||||||
|
" #if (Type = AreaLight)\n"
|
||||||
|
" area_light AreaWidth, AreaHeight, AreaRows, AreaColumns\n"
|
||||||
|
" jitter\n"
|
||||||
|
" #if (AreaCircle > 0 & AreaWidth > 2 & AreaHeight > 2 & AreaRows > 1 & AreaColumns > 1 )\n"
|
||||||
|
" circular \n"
|
||||||
|
" #if (AreaWidth = AreaHeight & AreaRows = AreaColumns)\n"
|
||||||
|
" orient\n"
|
||||||
|
" #end\n"
|
||||||
|
" #end\n"
|
||||||
|
" #elseif (Type = SunLight)\n"
|
||||||
|
" parallel\n"
|
||||||
|
" point_at Target\n"
|
||||||
|
" #elseif (Type = SpotLight)\n"
|
||||||
|
" spotlight\n"
|
||||||
|
" radius SpotRadius\n"
|
||||||
|
" falloff SpotFalloff\n"
|
||||||
|
" tightness SpotTightness\n"
|
||||||
|
" point_at Target\n"
|
||||||
|
" #end\n"
|
||||||
|
" }\n"
|
||||||
|
"#end\n"
|
||||||
|
"#end\n\n",
|
||||||
|
LC_POINTLIGHT, LC_AREALIGHT, LC_SUNLIGHT, LC_SPOTLIGHT);
|
||||||
|
POVFile.WriteLine(Line);
|
||||||
|
|
||||||
|
for (const lcModelPartsEntry& ModelPart : ModelParts)
|
||||||
|
{
|
||||||
|
int ColorIdx = ModelPart.ColorIndex;
|
||||||
|
|
||||||
|
if (lcIsColorTranslucent(ColorIdx))
|
||||||
|
{
|
||||||
|
if (!ColorMacros.contains("TranslucentColor"))
|
||||||
|
{
|
||||||
|
sprintf(Line,
|
||||||
|
"#ifndef (SkipTranslucentColorMacro)\n"
|
||||||
|
"#macro TranslucentColor(r, g, b, f)\n"
|
||||||
|
" material {\n"
|
||||||
|
" texture {\n"
|
||||||
|
" pigment { srgbf <r,g,b,f> }\n"
|
||||||
|
" finish { emission 0 ambient Ambient diffuse Diffuse }\n"
|
||||||
|
" finish { phong Phong phong_size PhongSize reflection TransReflection }\n"
|
||||||
|
" normal { TransNormal }\n"
|
||||||
|
" }\n"
|
||||||
|
" interior { ior TransIoR }\n"
|
||||||
|
" }\n"
|
||||||
|
"#end\n"
|
||||||
|
"#end\n\n");
|
||||||
|
POVFile.WriteLine(Line);
|
||||||
|
ColorMacros.append("TranslucentColor");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (lcIsColorChrome(ColorIdx))
|
||||||
|
{
|
||||||
|
if (!ColorMacros.contains("ChromeColor"))
|
||||||
|
{
|
||||||
|
sprintf(Line,
|
||||||
|
"#ifndef (SkipChromeColorMacro)\n"
|
||||||
|
"#macro ChromeColor(r, g, b)\n"
|
||||||
|
"#if (LgeoLibrary) material { #end\n"
|
||||||
|
" texture {\n"
|
||||||
|
" pigment { srgbf <r,g,b,0> }\n"
|
||||||
|
" finish { emission 0 ambient Ambient diffuse Diffuse }\n"
|
||||||
|
" finish { phong Phong phong_size PhongSize reflection ChromeReflection brilliance ChromeBrilliance metallic specular ChromeSpecular roughness ChromeRough }\n"
|
||||||
|
" }\n"
|
||||||
|
"#if (LgeoLibrary) } #end\n"
|
||||||
|
"#end\n"
|
||||||
|
"#end\n\n");
|
||||||
|
POVFile.WriteLine(Line);
|
||||||
|
ColorMacros.append("ChromeColor");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (lcIsColorRubber(ColorIdx))
|
||||||
|
{
|
||||||
|
if (!ColorMacros.contains("RubberColor"))
|
||||||
|
{
|
||||||
|
sprintf(Line,
|
||||||
|
"#ifndef (SkipRubberColorMacro)\n"
|
||||||
|
"#macro RubberColor(r, g, b)\n"
|
||||||
|
"#if (LgeoLibrary) material { #end\n"
|
||||||
|
" texture {\n"
|
||||||
|
" pigment { srgbf <r,g,b,0> }\n"
|
||||||
|
" finish { emission 0 ambient Ambient diffuse Diffuse }\n"
|
||||||
|
" finish { phong RubberPhong phong_size RubberPhongS reflection RubberReflection }\n"
|
||||||
|
" }\n"
|
||||||
|
"#if (LgeoLibrary) } #end\n"
|
||||||
|
"#end\n"
|
||||||
|
"#end\n\n");
|
||||||
|
POVFile.WriteLine(Line);
|
||||||
|
ColorMacros.append("RubberColor");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!ColorMacros.contains("OpaqueColor"))
|
||||||
|
{
|
||||||
|
sprintf(Line,
|
||||||
|
"#ifndef (SkipOpaqueColorMacro)\n"
|
||||||
|
"#macro OpaqueColor(r, g, b)\n"
|
||||||
|
"#if (LgeoLibrary) material { #end\n"
|
||||||
|
" texture {\n"
|
||||||
|
" pigment { srgbf <r,g,b,0> }\n"
|
||||||
|
" finish { emission 0 ambient Ambient diffuse Diffuse }\n"
|
||||||
|
" finish { phong Phong phong_size PhongSize reflection Reflection }\n"
|
||||||
|
" normal { OpaqueNormal }\n"
|
||||||
|
" }\n"
|
||||||
|
"#if (LgeoLibrary) } #end\n"
|
||||||
|
"#end\n"
|
||||||
|
"#end\n\n");
|
||||||
|
POVFile.WriteLine(Line);
|
||||||
|
ColorMacros.append("OpaqueColor");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(Line, "#if (Background)\n background {\n color rgb BackgroundColor\n }\n#end\n\n");
|
||||||
|
POVFile.WriteLine(Line);
|
||||||
|
|
||||||
|
sprintf(Line, "#ifndef (Skip%s)\n camera {\n perspective\n right x * image_width / image_height\n sky CameraSky\n location CameraLocation\n look_at CameraTarget\n angle CameraAngle * image_width / image_height\n }\n#end\n\n",
|
||||||
|
(CameraName.isEmpty() ? "Camera" : CameraName.toLatin1().constData()));
|
||||||
|
POVFile.WriteLine(Line);
|
||||||
|
|
||||||
|
lcVector3 LightTarget(0.0f, 0.0f, 0.0f), LightColor(1.0f, 1.0f, 1.0f);
|
||||||
|
lcVector2 AreaSize(200.0f, 200.0f), AreaGrid(10.0f, 10.0f);
|
||||||
|
int AreaCircle = 0, Shadowless = 0, LightType = LC_AREALIGHT;
|
||||||
|
float Power = 0, SpotRadius = 0, SpotFalloff = 0, SpotTightness = 0;
|
||||||
|
if (Lights.IsEmpty())
|
||||||
|
{
|
||||||
|
lcVector3 Location[4];
|
||||||
|
Location[0] = {0.0f * Radius + Center[0], -1.5f * Radius + Center[1], -1.5f * Radius + Center[2]};
|
||||||
|
Location[1] = {1.5f * Radius + Center[0], -1.0f * Radius + Center[1], 0.866026f * Radius + Center[2]};
|
||||||
|
Location[2] = {0.0f * Radius + Center[0], -2.0f * Radius + Center[1], 0.0f * Radius + Center[2]};
|
||||||
|
Location[3] = {2.0f * Radius + Center[0], 0.0f * Radius + Center[1], -2.0f * Radius + Center[2]};
|
||||||
|
for (int Idx = 0; Idx < 4; Idx++)
|
||||||
|
{
|
||||||
|
Power = Idx < 2 ? 0.75f : 0.5f;
|
||||||
|
sprintf(Line,"#ifndef (SkipLight%i)\nWriteLight(%i, %i, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, %g, %g, %g, %g, %i, %i, %i, %i, %i)\n#end\n\n",
|
||||||
|
Idx,
|
||||||
|
LightType,
|
||||||
|
Shadowless,
|
||||||
|
Location[Idx][0], Location[Idx][1], Location[Idx][2],
|
||||||
|
LightTarget[0], LightTarget[1], LightTarget[2],
|
||||||
|
LightColor[0], LightColor[1], LightColor[2],
|
||||||
|
Power,
|
||||||
|
SpotRadius, SpotFalloff, SpotTightness,
|
||||||
|
AreaCircle, (int)AreaSize[0], (int)AreaSize[1], (int)AreaGrid[0], (int)AreaGrid[1]);
|
||||||
|
POVFile.WriteLine(Line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (const lcLight* Light : Lights)
|
||||||
|
{
|
||||||
|
const lcVector3& Location = Light->mPosition;
|
||||||
|
const QString LightName = QString(Light->mName).replace(" ","_");
|
||||||
|
LightType = Light->mLightType;
|
||||||
|
Shadowless = static_cast<int>(Light->mShadowless);
|
||||||
|
LightColor = Light->mLightColor;
|
||||||
|
Power = Light->mPOVRayExponent;
|
||||||
|
switch(LightType)
|
||||||
|
{
|
||||||
|
case LC_AREALIGHT:
|
||||||
|
AreaCircle = Light->mLightShape == LC_LIGHT_SHAPE_DISK ? 1 : 0;
|
||||||
|
AreaSize = Light->mAreaSize;
|
||||||
|
AreaGrid = Light->mAreaGrid;
|
||||||
|
break;
|
||||||
|
case LC_SUNLIGHT:
|
||||||
|
LightTarget = Light->mTargetPosition;
|
||||||
|
break;
|
||||||
|
case LC_SPOTLIGHT:
|
||||||
|
LightTarget = Light->mTargetPosition;
|
||||||
|
SpotFalloff = Light->mSpotFalloff;
|
||||||
|
SpotRadius = Light->mSpotSize - SpotFalloff;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(Line,"#ifndef (Skip%s)\n WriteLight(%i, %i, <%g, %g, %g>, <%g, %g, %g>, <%g, %g, %g>, %g, %g, %g, %g, %i, %i, %i, %i, %i)\n#end\n\n",
|
||||||
|
LightName.toLatin1().constData(),
|
||||||
|
LightType,
|
||||||
|
Shadowless,
|
||||||
|
Location[1], Location[0], Location[2],
|
||||||
|
LightTarget[1], LightTarget[0], LightTarget[2],
|
||||||
|
LightColor[0], LightColor[1], LightColor[2],
|
||||||
|
Power,
|
||||||
|
SpotRadius, SpotFalloff, SpotTightness,
|
||||||
|
AreaCircle, (int)AreaSize[0], (int)AreaSize[1], (int)AreaGrid[0], (int)AreaGrid[1]);
|
||||||
|
POVFile.WriteLine(Line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
POVFile.WriteLine("#ifndef (lg_quality) #declare lg_quality = Quality; #end\n\n");
|
||||||
|
|
||||||
|
if (UseLGEO)
|
||||||
|
{
|
||||||
|
memset(Line, 0, 1024);
|
||||||
|
|
||||||
|
POVFile.WriteLine("#ifndef (lg_studs) #declare lg_studs = Studs; #end\n\n");
|
||||||
|
|
||||||
|
POVFile.WriteLine("#if (lg_quality = 3) #declare lg_quality = 4; #end\n\n");
|
||||||
|
|
||||||
|
POVFile.WriteLine("#include \"lg_defs.inc\"\n\n#include \"lg_color.inc\"\n\n");
|
||||||
|
|
||||||
lcDiskFile TableFile(QFileInfo(QDir(LGEOPath), QLatin1String("lg_elements.lst")).absoluteFilePath());
|
lcDiskFile TableFile(QFileInfo(QDir(LGEOPath), QLatin1String("lg_elements.lst")).absoluteFilePath());
|
||||||
|
|
||||||
if (!TableFile.Open(QIODevice::ReadOnly))
|
if (!TableFile.Open(QIODevice::ReadOnly))
|
||||||
|
@ -1869,6 +2237,7 @@ bool Project::ExportPOVRay(const QString& FileName)
|
||||||
|
|
||||||
while (TableFile.ReadLine(Line, sizeof(Line)))
|
while (TableFile.ReadLine(Line, sizeof(Line)))
|
||||||
{
|
{
|
||||||
|
|
||||||
char Src[129], Dst[129], Flags[11];
|
char Src[129], Dst[129], Flags[11];
|
||||||
|
|
||||||
if (*Line == ';')
|
if (*Line == ';')
|
||||||
|
@ -1877,20 +2246,22 @@ bool Project::ExportPOVRay(const QString& FileName)
|
||||||
if (sscanf(Line,"%128s%128s%10s", Src, Dst, Flags) != 3)
|
if (sscanf(Line,"%128s%128s%10s", Src, Dst, Flags) != 3)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
strcat(Src, ".dat");
|
strncat(Src, ".dat", 4);
|
||||||
|
|
||||||
PieceInfo* Info = Library->FindPiece(Src, nullptr, false, false);
|
PieceInfo* Info = Library->FindPiece(Src, nullptr, false, false);
|
||||||
if (!Info)
|
if (!Info)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (strchr(Flags, 'L'))
|
bool LgeoPartFound = false;
|
||||||
|
|
||||||
|
if ((LgeoPartFound = strchr(Flags, 'L')))
|
||||||
{
|
{
|
||||||
std::pair<char[LC_PIECE_NAME_LEN + 1], int>& Entry = PieceTable[Info];
|
std::pair<char[LC_PIECE_NAME_LEN + 1], int>& Entry = PieceTable[Info];
|
||||||
Entry.second |= LGEO_PIECE_LGEO;
|
Entry.second |= LGEO_PIECE_LGEO;
|
||||||
sprintf(Entry.first, "lg_%s", Dst);
|
sprintf(Entry.first, "lg_%s", Dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strchr(Flags, 'A'))
|
if (strchr(Flags, 'A') && !LgeoPartFound)
|
||||||
{
|
{
|
||||||
std::pair<char[LC_PIECE_NAME_LEN + 1], int>& Entry = PieceTable[Info];
|
std::pair<char[LC_PIECE_NAME_LEN + 1], int>& Entry = PieceTable[Info];
|
||||||
Entry.second |= LGEO_PIECE_AR;
|
Entry.second |= LGEO_PIECE_AR;
|
||||||
|
@ -1905,15 +2276,15 @@ bool Project::ExportPOVRay(const QString& FileName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lcDiskFile ColorFile(QFileInfo(QDir(LGEOPath), QLatin1String("lg_colors.lst")).absoluteFilePath());
|
lcDiskFile LgeoColorFile(QFileInfo(QDir(LGEOPath), QLatin1String("lg_colors.lst")).absoluteFilePath());
|
||||||
|
|
||||||
if (!ColorFile.Open(QIODevice::ReadOnly))
|
if (!LgeoColorFile.Open(QIODevice::ReadOnly))
|
||||||
{
|
{
|
||||||
QMessageBox::information(gMainWindow, tr("LeoCAD"), tr("Could not find LGEO files in folder '%1'.").arg(LGEOPath));
|
QMessageBox::information(gMainWindow, tr("LeoCAD"), tr("Could not find LGEO files in folder '%1'.").arg(LGEOPath));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (ColorFile.ReadLine(Line, sizeof(Line)))
|
while (LgeoColorFile.ReadLine(Line, sizeof(Line)))
|
||||||
{
|
{
|
||||||
char Name[1024], Flags[1024];
|
char Name[1024], Flags[1024];
|
||||||
int Code;
|
int Code;
|
||||||
|
@ -1924,20 +2295,82 @@ bool Project::ExportPOVRay(const QString& FileName)
|
||||||
if (sscanf(Line,"%d%s%s", &Code, Name, Flags) != 3)
|
if (sscanf(Line,"%d%s%s", &Code, Name, Flags) != 3)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
size_t Color = lcGetColorIndex(Code);
|
size_t ColorIdx = lcGetColorIndex(Code);
|
||||||
if (Color >= NumColors)
|
if (ColorIdx >= NumColors)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
strcpy(ColorTable[Color].data(), Name);
|
strncpy(LgeoColorTable[ColorIdx].data(), Name, LC_MAX_COLOR_NAME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const lcModelPartsEntry& ModelPart : ModelParts)
|
||||||
|
{
|
||||||
|
size_t ColorIdx = ModelPart.ColorIndex;
|
||||||
|
|
||||||
|
if (!ColorTable[ColorIdx][0])
|
||||||
|
{
|
||||||
|
lcColor* Color = &gColorList[ColorIdx];
|
||||||
|
|
||||||
|
if (!LgeoColorTable[ColorIdx][0])
|
||||||
|
{
|
||||||
|
sprintf(ColorTable[ColorIdx].data(), "lc_%s", Color->SafeName);
|
||||||
|
|
||||||
|
if (lcIsColorTranslucent(ColorIdx))
|
||||||
|
{
|
||||||
|
if (!UseLGEO && !MaterialColors.contains(ColorTable[ColorIdx].data()))
|
||||||
|
MaterialColors.append(ColorTable[ColorIdx].data());
|
||||||
|
|
||||||
|
sprintf(Line, "#ifndef (lc_%s)\n#declare lc_%s = TranslucentColor(%g, %g, %g, TransFilter)\n#end\n\n",
|
||||||
|
Color->SafeName, Color->SafeName, Color->Value[0], Color->Value[1], Color->Value[2]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char MacroName[LC_MAX_COLOR_NAME];
|
||||||
|
if (lcIsColorChrome(ColorIdx))
|
||||||
|
sprintf(MacroName, "Chrome");
|
||||||
|
else if (lcIsColorRubber(ColorIdx))
|
||||||
|
sprintf(MacroName, "Rubber");
|
||||||
|
else
|
||||||
|
sprintf(MacroName, "Opaque");
|
||||||
|
|
||||||
|
sprintf(Line, "#ifndef (lc_%s)\n#declare lc_%s = %sColor(%g, %g, %g)\n#end\n\n",
|
||||||
|
Color->SafeName, Color->SafeName, MacroName, Color->Value[0], Color->Value[1], Color->Value[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sprintf(ColorTable[ColorIdx].data(), "LDXColor%i", Color->Code);
|
||||||
|
|
||||||
|
sprintf(Line,"#ifndef (LDXColor%i) // %s\n#declare LDXColor%i = material { texture { %s } }\n#end\n\n",
|
||||||
|
Color->Code, Color->Name, Color->Code, LgeoColorTable[ColorIdx].data());
|
||||||
|
}
|
||||||
|
|
||||||
|
POVFile.WriteLine(Line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ColorTable[lcGetColorIndex(TopModelColorCode)][0])
|
||||||
|
{
|
||||||
|
size_t ColorIdx = lcGetColorIndex(TopModelColorCode);
|
||||||
|
|
||||||
|
lcColor* Color = &gColorList[ColorIdx];
|
||||||
|
|
||||||
|
sprintf(ColorTable[ColorIdx].data(), "LDXColor%i", Color->Code);
|
||||||
|
|
||||||
|
if (!LgeoColorTable[ColorIdx][0])
|
||||||
|
sprintf(Line, "#ifndef (lc_%s)\n#declare lc_%s = OpaqueColor(%g, %g, %g)\n#end\n\n",
|
||||||
|
Color->SafeName, Color->SafeName, Color->Value[0], Color->Value[1], Color->Value[2]);
|
||||||
|
else
|
||||||
|
sprintf(Line,"#ifndef (LDXColor%i) // %s\n#declare LDXColor%i = material { texture { %s } }\n#end\n\n",
|
||||||
|
Color->Code, Color->Name, Color->Code, LgeoColorTable[ColorIdx].data());
|
||||||
|
|
||||||
|
POVFile.WriteLine(Line);
|
||||||
|
}
|
||||||
|
|
||||||
std::set<lcMesh*> AddedMeshes;
|
std::set<lcMesh*> AddedMeshes;
|
||||||
|
|
||||||
if (!LGEOPath.isEmpty())
|
if (UseLGEO)
|
||||||
{
|
{
|
||||||
POVFile.WriteLine("#include \"lg_defs.inc\"\n#include \"lg_color.inc\"\n\n");
|
|
||||||
|
|
||||||
for (const lcModelPartsEntry& ModelPart : ModelParts)
|
for (const lcModelPartsEntry& ModelPart : ModelParts)
|
||||||
{
|
{
|
||||||
if (ModelPart.Mesh)
|
if (ModelPart.Mesh)
|
||||||
|
@ -1958,7 +2391,7 @@ bool Project::ExportPOVRay(const QString& FileName)
|
||||||
const std::pair<char[LC_PIECE_NAME_LEN + 1], int>& Entry = Search->second;
|
const std::pair<char[LC_PIECE_NAME_LEN + 1], int>& Entry = Search->second;
|
||||||
if (Entry.first[0])
|
if (Entry.first[0])
|
||||||
{
|
{
|
||||||
sprintf(Line, "#include \"%s.inc\"\n", Entry.first);
|
sprintf(Line, "#include \"%s.inc\" // %s\n", Entry.first, ModelPart.Info->m_strDescription);
|
||||||
POVFile.WriteLine(Line);
|
POVFile.WriteLine(Line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1966,29 +2399,6 @@ bool Project::ExportPOVRay(const QString& FileName)
|
||||||
POVFile.WriteLine("\n");
|
POVFile.WriteLine("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t ColorIdx = 0; ColorIdx < gColorList.size(); ColorIdx++)
|
|
||||||
{
|
|
||||||
lcColor* Color = &gColorList[ColorIdx];
|
|
||||||
|
|
||||||
if (lcIsColorTranslucent(ColorIdx))
|
|
||||||
{
|
|
||||||
sprintf(Line, "#declare lc_%s = texture { pigment { rgb <%f, %f, %f> filter 0.9 } finish { ambient 0.3 diffuse 0.2 reflection 0.25 phong 0.3 phong_size 60 } }\n",
|
|
||||||
Color->SafeName, Color->Value[0], Color->Value[1], Color->Value[2]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sprintf(Line, "#declare lc_%s = texture { pigment { rgb <%f, %f, %f> } finish { ambient 0.1 phong 0.2 phong_size 20 } }\n",
|
|
||||||
Color->SafeName, Color->Value[0], Color->Value[1], Color->Value[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
POVFile.WriteLine(Line);
|
|
||||||
|
|
||||||
if (!ColorTable[ColorIdx][0])
|
|
||||||
sprintf(ColorTable[ColorIdx].data(), "lc_%s", Color->SafeName);
|
|
||||||
}
|
|
||||||
|
|
||||||
POVFile.WriteLine("\n");
|
|
||||||
|
|
||||||
std::vector<const char*> ColorTablePointer;
|
std::vector<const char*> ColorTablePointer;
|
||||||
ColorTablePointer.resize(NumColors);
|
ColorTablePointer.resize(NumColors);
|
||||||
for (size_t ColorIdx = 0; ColorIdx < NumColors; ColorIdx++)
|
for (size_t ColorIdx = 0; ColorIdx < NumColors; ColorIdx++)
|
||||||
|
@ -1996,7 +2406,7 @@ bool Project::ExportPOVRay(const QString& FileName)
|
||||||
|
|
||||||
auto GetMeshName = [](const lcModelPartsEntry& ModelPart, char (&Name)[LC_PIECE_NAME_LEN])
|
auto GetMeshName = [](const lcModelPartsEntry& ModelPart, char (&Name)[LC_PIECE_NAME_LEN])
|
||||||
{
|
{
|
||||||
strcpy(Name, ModelPart.Info->mFileName);
|
strncpy(Name, ModelPart.Info->mFileName, sizeof(Name));
|
||||||
|
|
||||||
for (char* c = Name; *c; c++)
|
for (char* c = Name; *c; c++)
|
||||||
if (*c == '-' || *c == '.')
|
if (*c == '-' || *c == '.')
|
||||||
|
@ -2006,7 +2416,7 @@ bool Project::ExportPOVRay(const QString& FileName)
|
||||||
{
|
{
|
||||||
char Suffix[32];
|
char Suffix[32];
|
||||||
sprintf(Suffix, "_%p", ModelPart.Mesh);
|
sprintf(Suffix, "_%p", ModelPart.Mesh);
|
||||||
strncat(Name, Suffix, sizeof(Name) - 1);
|
strncat(Name, Suffix, sizeof(Name) - strlen(Name) - 1);
|
||||||
Name[sizeof(Name) - 1] = 0;
|
Name[sizeof(Name) - 1] = 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -2027,7 +2437,7 @@ bool Project::ExportPOVRay(const QString& FileName)
|
||||||
if (!ModelPart.Mesh)
|
if (!ModelPart.Mesh)
|
||||||
{
|
{
|
||||||
std::pair<char[LC_PIECE_NAME_LEN + 1], int>& Entry = PieceTable[ModelPart.Info];
|
std::pair<char[LC_PIECE_NAME_LEN + 1], int>& Entry = PieceTable[ModelPart.Info];
|
||||||
strcpy(Entry.first, "lc_");
|
strncpy(Entry.first, "lc_", 3);
|
||||||
strncat(Entry.first, Name, sizeof(Entry.first) - 1);
|
strncat(Entry.first, Name, sizeof(Entry.first) - 1);
|
||||||
Entry.first[sizeof(Entry.first) - 1] = 0;
|
Entry.first[sizeof(Entry.first) - 1] = 0;
|
||||||
}
|
}
|
||||||
|
@ -2038,65 +2448,30 @@ bool Project::ExportPOVRay(const QString& FileName)
|
||||||
POVFile.WriteLine(Line);
|
POVFile.WriteLine(Line);
|
||||||
}
|
}
|
||||||
|
|
||||||
const lcCamera* Camera = gMainWindow->GetActiveView()->GetCamera();
|
sprintf(Line, "#declare %s = union {\n", TopModelName.toLatin1().constData());
|
||||||
const lcVector3& Position = Camera->mPosition;
|
|
||||||
const lcVector3& Target = Camera->mTargetPosition;
|
|
||||||
const lcVector3& Up = Camera->mUpVector;
|
|
||||||
|
|
||||||
sprintf(Line, "camera {\n perspective\n right x * image_width / image_height\n sky<%1g,%1g,%1g>\n location <%1g, %1g, %1g>\n look_at <%1g, %1g, %1g>\n angle %.0f * image_width / image_height\n}\n\n",
|
|
||||||
Up[1], Up[0], Up[2], Position[1] / 25.0f, Position[0] / 25.0f, Position[2] / 25.0f, Target[1] / 25.0f, Target[0] / 25.0f, Target[2] / 25.0f, Camera->m_fovy);
|
|
||||||
POVFile.WriteLine(Line);
|
|
||||||
lcVector3 BackgroundColor = lcVector3FromColor(lcGetPreferences().mBackgroundSolidColor);
|
|
||||||
sprintf(Line, "background { color rgb <%1g, %1g, %1g> }\n\n", BackgroundColor[0], BackgroundColor[1], BackgroundColor[2]);
|
|
||||||
POVFile.WriteLine(Line);
|
|
||||||
|
|
||||||
lcVector3 Min(FLT_MAX, FLT_MAX, FLT_MAX);
|
|
||||||
lcVector3 Max(-FLT_MAX, -FLT_MAX, -FLT_MAX);
|
|
||||||
|
|
||||||
for (const lcModelPartsEntry& ModelPart : ModelParts)
|
|
||||||
{
|
|
||||||
lcVector3 Points[8];
|
|
||||||
|
|
||||||
lcGetBoxCorners(ModelPart.Info->GetBoundingBox(), Points);
|
|
||||||
|
|
||||||
for (int PointIdx = 0; PointIdx < 8; PointIdx++)
|
|
||||||
{
|
|
||||||
lcVector3 Point = lcMul31(Points[PointIdx], ModelPart.WorldMatrix);
|
|
||||||
|
|
||||||
Min = lcMin(Point, Min);
|
|
||||||
Max = lcMax(Point, Max);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lcVector3 Center = (Min + Max) / 2.0f;
|
|
||||||
float Radius = (Max - Center).Length() / 25.0f;
|
|
||||||
Center = lcVector3(Center[1], Center[0], Center[2]) / 25.0f;
|
|
||||||
|
|
||||||
sprintf(Line, "light_source{ <%f, %f, %f>\n color rgb 0.75\n area_light 200, 200, 10, 10\n jitter\n}\n\n", 0.0f * Radius + Center.x, -1.5f * Radius + Center.y, -1.5f * Radius + Center.z);
|
|
||||||
POVFile.WriteLine(Line);
|
|
||||||
sprintf(Line, "light_source{ <%f, %f, %f>\n color rgb 0.75\n area_light 200, 200, 10, 10\n jitter\n}\n\n", 1.5f * Radius + Center.x, -1.0f * Radius + Center.y, 0.866026f * Radius + Center.z);
|
|
||||||
POVFile.WriteLine(Line);
|
|
||||||
sprintf(Line, "light_source{ <%f, %f, %f>\n color rgb 0.5\n area_light 200, 200, 10, 10\n jitter\n}\n\n", 0.0f * Radius + Center.x, -2.0f * Radius + Center.y, 0.0f * Radius + Center.z);
|
|
||||||
POVFile.WriteLine(Line);
|
|
||||||
sprintf(Line, "light_source{ <%f, %f, %f>\n color rgb 0.5\n area_light 200, 200, 10, 10\n jitter\n}\n\n", 2.0f * Radius + Center.x, 0.0f * Radius + Center.y, -2.0f * Radius + Center.z);
|
|
||||||
POVFile.WriteLine(Line);
|
POVFile.WriteLine(Line);
|
||||||
|
|
||||||
for (const lcModelPartsEntry& ModelPart : ModelParts)
|
for (const lcModelPartsEntry& ModelPart : ModelParts)
|
||||||
{
|
{
|
||||||
int Color = ModelPart.ColorIndex;
|
int ColorIdx = ModelPart.ColorIndex;
|
||||||
const char* Suffix = lcIsColorTranslucent(Color) ? "_clear" : "";
|
const char* Suffix = lcIsColorTranslucent(ColorIdx) ? "_clear" : "";
|
||||||
const float* f = ModelPart.WorldMatrix;
|
const float* f = ModelPart.WorldMatrix;
|
||||||
|
char Modifier[32];
|
||||||
|
if (UseLGEO || MaterialColors.contains(ColorTable[ColorIdx].data()))
|
||||||
|
sprintf(Modifier, "material");
|
||||||
|
else
|
||||||
|
sprintf(Modifier, "texture");
|
||||||
if (!ModelPart.Mesh)
|
if (!ModelPart.Mesh)
|
||||||
{
|
{
|
||||||
std::pair<char[LC_PIECE_NAME_LEN + 1], int>& Entry = PieceTable[ModelPart.Info];
|
std::pair<char[LC_PIECE_NAME_LEN + 1], int>& Entry = PieceTable[ModelPart.Info];
|
||||||
|
|
||||||
if (Entry.second & LGEO_PIECE_SLOPE)
|
if (Entry.second & LGEO_PIECE_SLOPE)
|
||||||
{
|
{
|
||||||
sprintf(Line, "merge {\n object {\n %s%s\n texture { %s }\n }\n"
|
sprintf(Line,
|
||||||
" object {\n %s_slope\n texture { %s normal { bumps 0.3 scale 0.02 } }\n }\n"
|
" merge {\n object {\n %s%s\n %s { %s }\n }\n"
|
||||||
" matrix <%.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f>\n}\n",
|
" object {\n %s_slope\n texture {\n %s normal { bumps 0.3 scale 0.02 }\n }\n }\n"
|
||||||
Entry.first, Suffix, ColorTable[Color].data(), Entry.first, ColorTable[Color].data(),
|
" matrix <%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g>\n }\n",
|
||||||
|
Entry.first, Suffix, Modifier, ColorTable[ColorIdx].data(), Entry.first, ColorTable[ColorIdx].data(),
|
||||||
-f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f);
|
-f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2104,8 +2479,8 @@ bool Project::ExportPOVRay(const QString& FileName)
|
||||||
if (!ModelPart.Info || !ModelPart.Info->GetMesh())
|
if (!ModelPart.Info || !ModelPart.Info->GetMesh())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
sprintf(Line, "object {\n %s%s\n texture { %s }\n matrix <%.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f>\n}\n",
|
sprintf(Line, " object {\n %s%s\n %s { %s }\n matrix <%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g>\n }\n",
|
||||||
Entry.first, Suffix, ColorTable[Color].data(), -f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f);
|
Entry.first, Suffix, Modifier, ColorTable[ColorIdx].data(), -f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2114,13 +2489,29 @@ bool Project::ExportPOVRay(const QString& FileName)
|
||||||
char Name[LC_PIECE_NAME_LEN];
|
char Name[LC_PIECE_NAME_LEN];
|
||||||
GetMeshName(ModelPart, Name);
|
GetMeshName(ModelPart, Name);
|
||||||
|
|
||||||
sprintf(Line, "object {\n lc_%s%s\n texture { %s }\n matrix <%.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f>\n}\n",
|
sprintf(Line, " object {\n lc_%s%s\n %s { %s }\n matrix <%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g>\n }\n",
|
||||||
Name, Suffix, ColorTable[Color].data(), -f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f);
|
Name, Suffix, Modifier, ColorTable[ColorIdx].data(), -f[5], -f[4], -f[6], -f[1], -f[0], -f[2], f[9], f[8], f[10], f[13] / 25.0f, f[12] / 25.0f, f[14] / 25.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
POVFile.WriteLine(Line);
|
POVFile.WriteLine(Line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sprintf(Line, "\n #if (ModelReflection = 0)\n no_reflection\n #end\n #if (ModelShadow = 0)\n no_shadow\n #end\n}\n\n");
|
||||||
|
POVFile.WriteLine(Line);
|
||||||
|
|
||||||
|
sprintf(Line, "object {\n %s\n %s { %s }\n}\n\n",
|
||||||
|
TopModelName.toLatin1().constData(), (UseLGEO ? "material" : "texture"), ColorTable[lcGetColorIndex(TopModelColorCode)].data());
|
||||||
|
POVFile.WriteLine(Line);
|
||||||
|
|
||||||
|
sprintf(Line, "#if (Floor)\n object {\n plane { FloorAxis, FloorLocation hollow }\n texture {\n pigment { color srgb FloorColor }\n finish { emission 0 ambient FloorAmbient diffuse FloorDiffuse }\n }\n }\n#end\n");
|
||||||
|
POVFile.WriteLine(Line);
|
||||||
|
|
||||||
|
if (!POVRayOptions.FooterIncludeFile.isEmpty())
|
||||||
|
{
|
||||||
|
sprintf(Line, "\n#include \"%s\"\n", POVRayOptions.FooterIncludeFile.toLatin1().constData());
|
||||||
|
POVFile.WriteLine(Line);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2239,7 +2630,7 @@ void Project::SaveImage()
|
||||||
|
|
||||||
if (Dialog.exec() != QDialog::Accepted)
|
if (Dialog.exec() != QDialog::Accepted)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QString Extension = QFileInfo(Dialog.mFileName).suffix();
|
QString Extension = QFileInfo(Dialog.mFileName).suffix();
|
||||||
|
|
||||||
if (!Extension.isEmpty())
|
if (!Extension.isEmpty())
|
||||||
|
|
Loading…
Reference in a new issue