490 lines
17 KiB
C++
490 lines
17 KiB
C++
/***************************************************************************
|
|
* Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2005 *
|
|
* *
|
|
* This file is part of the FreeCAD CAx development system. *
|
|
* *
|
|
* This library is free software; you can redistribute it and/or *
|
|
* modify it under the terms of the GNU Library General Public *
|
|
* License as published by the Free Software Foundation; either *
|
|
* version 2 of the License, or (at your option) any later version. *
|
|
* *
|
|
* This library is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU Library General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU Library General Public *
|
|
* License along with this library; see the file COPYING.LIB. If not, *
|
|
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
|
* Suite 330, Boston, MA 02111-1307, USA *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "PreCompiled.h"
|
|
|
|
#ifndef _PreComp_
|
|
# include <BRep_Tool.hxx>
|
|
# include <BRepMesh_IncrementalMesh.hxx>
|
|
# include <GeomAPI_ProjectPointOnSurf.hxx>
|
|
# include <GeomLProp_SLProps.hxx>
|
|
# include <Poly_Triangulation.hxx>
|
|
# include <TopExp_Explorer.hxx>
|
|
# include <TopoDS.hxx>
|
|
# include <TopoDS_Face.hxx>
|
|
# include <sstream>
|
|
#endif
|
|
|
|
#include <Base/Console.h>
|
|
#include <Base/Exception.h>
|
|
#include <Base/Sequencer.h>
|
|
#include <App/ComplexGeoData.h>
|
|
|
|
|
|
#include "PovTools.h"
|
|
|
|
using Base::Console;
|
|
|
|
using namespace Raytracing;
|
|
using namespace std;
|
|
|
|
#include "PovTools.h"
|
|
|
|
//#include "TempCamera.inc"
|
|
//camera {
|
|
// location CamPos
|
|
// look_at LookAt
|
|
// sky Up
|
|
// angle 45
|
|
//}
|
|
|
|
std::string PovTools::getCamera(const CamDef& Cam, int width, int height)
|
|
{
|
|
std::stringstream out;
|
|
out << "// declares positon and view direction\n" << endl
|
|
<< "// Generated by FreeCAD (http://www.freecadweb.org/)" << endl
|
|
|
|
// writing Camera positions
|
|
<< "#declare cam_location = <" << Cam.CamPos.X() <<"," << Cam.CamPos.Z() <<"," << Cam.CamPos.Y()<<">;" << endl
|
|
|
|
// writing lookat
|
|
<< "#declare cam_look_at = <" << Cam.LookAt.X() <<"," << Cam.LookAt.Z() <<"," << Cam.LookAt.Y() <<">;"<< endl
|
|
|
|
// writing the Up Vector
|
|
<< "#declare cam_sky = <" << Cam.Up.X() <<"," << Cam.Up.Z() <<"," << Cam.Up.Y() <<">;"<< endl
|
|
|
|
// array of zoom factors
|
|
<< "#declare cam_angle = 45; " << endl
|
|
// instance of the camera
|
|
<< "camera {" << endl
|
|
<< " location cam_location" << endl
|
|
<< " look_at cam_look_at" << endl
|
|
<< " sky cam_sky" << endl
|
|
<< " angle cam_angle " << endl
|
|
<< " right x*" << width << "/" << height << endl
|
|
<< "}"<< endl;
|
|
return out.str();
|
|
}
|
|
|
|
void PovTools::writeCamera(const char* FileName, const CamDef& Cam)
|
|
{
|
|
std::vector<CamDef> vCam;
|
|
vCam.push_back(Cam);
|
|
writeCameraVec(FileName,vCam);
|
|
}
|
|
|
|
|
|
void PovTools::writeCameraVec(const char* FileName, const std::vector<CamDef>& CamVec)
|
|
{
|
|
std::stringstream out;
|
|
std::vector<CamDef>::const_iterator It;
|
|
out << "// declares positon and view directions\n"
|
|
<< "// Generated by FreeCAD (http://www.freecadweb.org/)\n\n"
|
|
<< "// Total number of camera positions\n"
|
|
<< "#declare nCamPos = " << CamVec.size() << ";\n\n";
|
|
|
|
// writing Camera positions
|
|
out << "// Array of positions\n"
|
|
<< "#declare CamPos = array[" << CamVec.size() << "] {\n";
|
|
for (It = CamVec.begin(); It != CamVec.end(); It++)
|
|
out << " <" << It->CamPos.X() <<"," << It->CamPos.Z() <<"," << It->CamPos.Y() <<">,\n";
|
|
out << "};\n"
|
|
// writing Camera Direction vector
|
|
<< "// Array of Directions (only for special calculations)\n"
|
|
<< "#declare CamDir = array[" << CamVec.size() << "] {\n";
|
|
|
|
for (It = CamVec.begin(); It != CamVec.end(); It++)
|
|
out << " <" << It->CamDir.X() <<"," << It->CamDir.Z() <<"," << It->CamDir.Y() <<">,\n";
|
|
out << "};\n"
|
|
// writing lookat
|
|
<< "// Array of Look At positions\n"
|
|
<< "#declare LookAt = array[" << CamVec.size() << "] {\n";
|
|
|
|
for (It = CamVec.begin(); It != CamVec.end(); It++)
|
|
out << " <" << It->LookAt.X() <<"," << It->LookAt.Z() <<"," << It->LookAt.Y() <<">,\n";
|
|
out << "};\n"
|
|
// writing the Up Vector
|
|
<< "// // Array of up vectors\n"
|
|
<< "#declare Up = array[" << CamVec.size() << "] {\n";
|
|
|
|
for (It = CamVec.begin(); It != CamVec.end(); It++)
|
|
out << " <" << It->Up.X() <<"," << It->Up.Z() <<"," << It->Up.Y() <<">,\n";
|
|
out << "};\n"
|
|
// array of zoom factors
|
|
<< "// // Array of up vectors\n"
|
|
<< "#declare CamZoom = array[" << CamVec.size() << "] {\n";
|
|
|
|
for (It = CamVec.begin(); It != CamVec.end(); It++)
|
|
out << " 45,\n";
|
|
out << "};\n";
|
|
|
|
|
|
// open the file and write
|
|
Base::ofstream fout(FileName);
|
|
fout << out.str() << endl;
|
|
fout.close();
|
|
}
|
|
|
|
void PovTools::writeData(const char *FileName, const char *PartName,
|
|
const Data::ComplexGeoData* data, float fMeshDeviation)
|
|
{
|
|
// open the file and write
|
|
Base::ofstream fout(FileName);
|
|
// write the file
|
|
fout << "// Written by FreeCAD http://www.freecadweb.org/" << endl;
|
|
|
|
unsigned long count = data->countSubElements("Face");
|
|
for (unsigned long i=0; i<count; i++) {
|
|
std::vector<Base::Vector3d> points;
|
|
std::vector<Base::Vector3d> normals;
|
|
std::vector<Data::ComplexGeoData::Facet> facets;
|
|
Data::Segment* segm = data->getSubElement("Face", i);
|
|
data->getFacesFromSubelement(segm, points, normals, facets);
|
|
delete segm;
|
|
|
|
// writing per face header
|
|
fout << "// element number" << i << " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl
|
|
<< "#declare " << PartName << i << " = mesh2{" << endl
|
|
<< " vertex_vectors {" << endl
|
|
<< " " << points.size() << "," << endl;
|
|
|
|
// writing vertices
|
|
for (std::vector<Base::Vector3d>::iterator it = points.begin(); it != points.end(); ++it) {
|
|
fout << " <"
|
|
<< it->x << ","
|
|
<< it->y << ","
|
|
<< it->z << ">,"
|
|
<< endl;
|
|
}
|
|
|
|
// writing per vertex normals
|
|
fout << " }" << endl
|
|
<< " normal_vectors {" << endl
|
|
<< " " << normals.size() << "," << endl;
|
|
|
|
for (std::vector<Base::Vector3d>::iterator it = normals.begin(); it != normals.end(); ++it) {
|
|
fout << " <"
|
|
<< it->x << ","
|
|
<< it->y << ","
|
|
<< it->z << ">,"
|
|
<< endl;
|
|
}
|
|
|
|
// writing triangle indices
|
|
fout << " }" << endl
|
|
<< " face_indices {" << endl
|
|
<< " " << facets.size() << "," << endl;
|
|
for (std::vector<Data::ComplexGeoData::Facet>::iterator it = facets.begin(); it != facets.end(); ++it) {
|
|
fout << " <" << it->I1 << ","<< it->I3 << ","<< it->I2 << ">," << endl;
|
|
}
|
|
|
|
// end of face
|
|
fout << " }" << endl
|
|
<< "} // end of element" << i << endl << endl;
|
|
}
|
|
|
|
fout << endl << endl << "// Declare all together +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl
|
|
<< "#declare " << PartName << " = union {" << endl;
|
|
for (unsigned long i=1; i < count; i++) {
|
|
fout << "mesh2{ " << PartName << i << "}" << endl;
|
|
}
|
|
fout << "}" << endl;
|
|
fout.close();
|
|
}
|
|
|
|
void PovTools::writeShape(const char *FileName, const char *PartName,
|
|
const TopoDS_Shape& Shape, float fMeshDeviation)
|
|
{
|
|
// open the file and write
|
|
Base::ofstream fout(FileName);
|
|
writeShape(fout,PartName,Shape,fMeshDeviation);
|
|
fout.close();
|
|
}
|
|
|
|
void PovTools::writeShape(std::ostream &out, const char *PartName,
|
|
const TopoDS_Shape& Shape, float fMeshDeviation)
|
|
{
|
|
Base::Console().Log("Meshing with Deviation: %f\n",fMeshDeviation);
|
|
|
|
TopExp_Explorer ex;
|
|
BRepMesh_IncrementalMesh MESH(Shape,fMeshDeviation);
|
|
|
|
|
|
// counting faces and start sequencer
|
|
int l = 1;
|
|
for (ex.Init(Shape, TopAbs_FACE); ex.More(); ex.Next(),l++) {}
|
|
Base::SequencerLauncher seq("Writing file", l);
|
|
|
|
// write the file
|
|
out << "// Written by FreeCAD http://www.freecadweb.org/" << endl;
|
|
l = 1;
|
|
for (ex.Init(Shape, TopAbs_FACE); ex.More(); ex.Next(),l++) {
|
|
|
|
// get the shape and mesh it
|
|
const TopoDS_Face& aFace = TopoDS::Face(ex.Current());
|
|
|
|
// this block mesh the face and transfers it in a C array of vertices and face indexes
|
|
Standard_Integer nbNodesInFace,nbTriInFace;
|
|
gp_Vec* vertices=0;
|
|
gp_Vec* vertexnormals=0;
|
|
long* cons=0;
|
|
|
|
transferToArray(aFace,&vertices,&vertexnormals,&cons,nbNodesInFace,nbTriInFace);
|
|
|
|
if (!vertices) break;
|
|
// writing per face header
|
|
out << "// face number" << l << " +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl
|
|
<< "#declare " << PartName << l << " = mesh2{" << endl
|
|
<< " vertex_vectors {" << endl
|
|
<< " " << nbNodesInFace << "," << endl;
|
|
// writing vertices
|
|
for (int i=0; i < nbNodesInFace; i++) {
|
|
out << " <" << vertices[i].X() << ","
|
|
<< vertices[i].Z() << ","
|
|
<< vertices[i].Y() << ">,"
|
|
<< endl;
|
|
}
|
|
out << " }" << endl
|
|
// writing per vertex normals
|
|
<< " normal_vectors {" << endl
|
|
<< " " << nbNodesInFace << "," << endl;
|
|
for (int j=0; j < nbNodesInFace; j++) {
|
|
out << " <" << vertexnormals[j].X() << ","
|
|
<< vertexnormals[j].Z() << ","
|
|
<< vertexnormals[j].Y() << ">,"
|
|
<< endl;
|
|
}
|
|
|
|
out << " }" << endl
|
|
// writing triangle indices
|
|
<< " face_indices {" << endl
|
|
<< " " << nbTriInFace << "," << endl;
|
|
for (int k=0; k < nbTriInFace; k++) {
|
|
out << " <" << cons[3*k] << ","<< cons[3*k+2] << ","<< cons[3*k+1] << ">," << endl;
|
|
}
|
|
// end of face
|
|
out << " }" << endl
|
|
<< "} // end of Face"<< l << endl << endl;
|
|
|
|
delete [] vertexnormals;
|
|
delete [] vertices;
|
|
delete [] cons;
|
|
|
|
seq.next();
|
|
|
|
} // end of face loop
|
|
|
|
|
|
out << endl << endl << "// Declare all together +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl
|
|
<< "#declare " << PartName << " = union {" << endl;
|
|
for (int i=1; i < l; i++) {
|
|
out << "mesh2{ " << PartName << i << "}" << endl;
|
|
}
|
|
out << "}" << endl;
|
|
}
|
|
|
|
void PovTools::writeShapeCSV(const char *FileName,
|
|
const TopoDS_Shape& Shape,
|
|
float fMeshDeviation,
|
|
float fLength)
|
|
{
|
|
const char cSeperator = ',';
|
|
|
|
Base::Console().Log("Meshing with Deviation: %f\n",fMeshDeviation);
|
|
|
|
TopExp_Explorer ex;
|
|
BRepMesh_IncrementalMesh MESH(Shape,fMeshDeviation);
|
|
|
|
// open the file and write
|
|
std::ofstream fout(FileName);
|
|
|
|
// counting faces and start sequencer
|
|
int l = 1;
|
|
for (ex.Init(Shape, TopAbs_FACE); ex.More(); ex.Next(),l++) {}
|
|
Base::SequencerLauncher seq("Writing file", l);
|
|
|
|
// write the file
|
|
l = 1;
|
|
for (ex.Init(Shape, TopAbs_FACE); ex.More(); ex.Next(),l++) {
|
|
|
|
// get the shape and mesh it
|
|
const TopoDS_Face& aFace = TopoDS::Face(ex.Current());
|
|
|
|
// this block mesh the face and transfers it in a C array of vertices and face indexes
|
|
Standard_Integer nbNodesInFace,nbTriInFace;
|
|
gp_Vec* vertices=0;
|
|
gp_Vec* vertexnormals=0;
|
|
long* cons=0;
|
|
|
|
transferToArray(aFace,&vertices,&vertexnormals,&cons,nbNodesInFace,nbTriInFace);
|
|
|
|
if (!vertices) break;
|
|
// writing per face header
|
|
// writing vertices
|
|
for (int i=0; i < nbNodesInFace; i++) {
|
|
fout << vertices[i].X() << cSeperator
|
|
<< vertices[i].Z() << cSeperator
|
|
<< vertices[i].Y() << cSeperator
|
|
<< vertexnormals[i].X() * fLength <<cSeperator
|
|
<< vertexnormals[i].Z() * fLength <<cSeperator
|
|
<< vertexnormals[i].Y() * fLength <<cSeperator
|
|
<< endl;
|
|
}
|
|
|
|
delete [] vertexnormals;
|
|
delete [] vertices;
|
|
delete [] cons;
|
|
|
|
seq.next();
|
|
|
|
} // end of face loop
|
|
|
|
fout.close();
|
|
}
|
|
|
|
void PovTools::transferToArray(const TopoDS_Face& aFace,gp_Vec** vertices,gp_Vec** vertexnormals, long** cons,int &nbNodesInFace,int &nbTriInFace )
|
|
{
|
|
TopLoc_Location aLoc;
|
|
|
|
// doing the meshing and checking the result
|
|
//BRepMesh_IncrementalMesh MESH(aFace,fDeflection);
|
|
Handle(Poly_Triangulation) aPoly = BRep_Tool::Triangulation(aFace,aLoc);
|
|
if (aPoly.IsNull()) {
|
|
Base::Console().Log("Empty face trianglutaion\n");
|
|
nbNodesInFace =0;
|
|
nbTriInFace = 0;
|
|
vertices = 0l;
|
|
cons = 0l;
|
|
return;
|
|
}
|
|
|
|
// geting the transformation of the shape/face
|
|
gp_Trsf myTransf;
|
|
Standard_Boolean identity = true;
|
|
if (!aLoc.IsIdentity()) {
|
|
identity = false;
|
|
myTransf = aLoc.Transformation();
|
|
}
|
|
|
|
Standard_Integer i;
|
|
// geting size and create the array
|
|
nbNodesInFace = aPoly->NbNodes();
|
|
nbTriInFace = aPoly->NbTriangles();
|
|
*vertices = new gp_Vec[nbNodesInFace];
|
|
*vertexnormals = new gp_Vec[nbNodesInFace];
|
|
for (i=0; i < nbNodesInFace; i++) {
|
|
(*vertexnormals)[i]= gp_Vec(0.0,0.0,0.0);
|
|
}
|
|
|
|
*cons = new long[3*(nbTriInFace)+1];
|
|
|
|
// check orientation
|
|
TopAbs_Orientation orient = aFace.Orientation();
|
|
|
|
// cycling through the poly mesh
|
|
const Poly_Array1OfTriangle& Triangles = aPoly->Triangles();
|
|
const TColgp_Array1OfPnt& Nodes = aPoly->Nodes();
|
|
for (i=1; i<=nbTriInFace; i++) {
|
|
// Get the triangle
|
|
Standard_Integer N1,N2,N3;
|
|
Triangles(i).Get(N1,N2,N3);
|
|
|
|
// change orientation of the triangles
|
|
if ( orient != TopAbs_FORWARD )
|
|
{
|
|
Standard_Integer tmp = N1;
|
|
N1 = N2;
|
|
N2 = tmp;
|
|
}
|
|
|
|
gp_Pnt V1 = Nodes(N1);
|
|
gp_Pnt V2 = Nodes(N2);
|
|
gp_Pnt V3 = Nodes(N3);
|
|
|
|
// transform the vertices to the place of the face
|
|
if (!identity) {
|
|
V1.Transform(myTransf);
|
|
V2.Transform(myTransf);
|
|
V3.Transform(myTransf);
|
|
}
|
|
|
|
// Calculate triangle normal
|
|
gp_Vec v1(V1.X(),V1.Y(),V1.Z()),v2(V2.X(),V2.Y(),V2.Z()),v3(V3.X(),V3.Y(),V3.Z());
|
|
gp_Vec Normal = (v2-v1)^(v3-v1);
|
|
|
|
//Standard_Real Area = 0.5 * Normal.Magnitude();
|
|
|
|
// add the triangle normal to the vertex normal for all points of this triangle
|
|
(*vertexnormals)[N1-1] += gp_Vec(Normal.X(),Normal.Y(),Normal.Z());
|
|
(*vertexnormals)[N2-1] += gp_Vec(Normal.X(),Normal.Y(),Normal.Z());
|
|
(*vertexnormals)[N3-1] += gp_Vec(Normal.X(),Normal.Y(),Normal.Z());
|
|
|
|
(*vertices)[N1-1].SetX((float)(V1.X()));
|
|
(*vertices)[N1-1].SetY((float)(V1.Y()));
|
|
(*vertices)[N1-1].SetZ((float)(V1.Z()));
|
|
(*vertices)[N2-1].SetX((float)(V2.X()));
|
|
(*vertices)[N2-1].SetY((float)(V2.Y()));
|
|
(*vertices)[N2-1].SetZ((float)(V2.Z()));
|
|
(*vertices)[N3-1].SetX((float)(V3.X()));
|
|
(*vertices)[N3-1].SetY((float)(V3.Y()));
|
|
(*vertices)[N3-1].SetZ((float)(V3.Z()));
|
|
|
|
int j = i - 1;
|
|
N1--;
|
|
N2--;
|
|
N3--;
|
|
(*cons)[3*j] = N1;
|
|
(*cons)[3*j+1] = N2;
|
|
(*cons)[3*j+2] = N3;
|
|
}
|
|
|
|
// normalize all vertex normals
|
|
for (i=0; i < nbNodesInFace; i++) {
|
|
|
|
gp_Dir clNormal;
|
|
|
|
try {
|
|
Handle_Geom_Surface Surface = BRep_Tool::Surface(aFace);
|
|
|
|
gp_Pnt vertex((*vertices)[i].XYZ());
|
|
// gp_Pnt vertex((*vertices)[i][0], (*vertices)[i][1], (*vertices)[i][2]);
|
|
GeomAPI_ProjectPointOnSurf ProPntSrf(vertex, Surface);
|
|
Standard_Real fU, fV;
|
|
ProPntSrf.Parameters(1, fU, fV);
|
|
|
|
GeomLProp_SLProps clPropOfFace(Surface, fU, fV, 2, gp::Resolution());
|
|
|
|
clNormal = clPropOfFace.Normal();
|
|
gp_Vec temp = clNormal;
|
|
//Base::Console().Log("unterschied:%.2f",temp.dot((*vertexnormals)[i]));
|
|
if ( temp * (*vertexnormals)[i] < 0 )
|
|
temp = -temp;
|
|
(*vertexnormals)[i] = temp;
|
|
|
|
}
|
|
catch (...) {
|
|
}
|
|
|
|
(*vertexnormals)[i].Normalize();
|
|
}
|
|
}
|