JtReader: allow to open JT files using TKJT

This commit is contained in:
wmayer
2023-11-08 23:20:57 +01:00
committed by wwmayer
parent ba95a534d5
commit 640018bfa7
4 changed files with 401 additions and 10 deletions

View File

@@ -24,6 +24,7 @@
#include <App/Application.h>
#include <App/Document.h>
#include <App/InventorObject.h>
#include <Base/Console.h>
#include <Base/FileInfo.h>
#include <Base/Interpreter.h>
@@ -34,6 +35,7 @@
#include <CXX/Extensions.hxx>
#include "TestJtReader.h"
#include "TKJtReader.h"
using std::vector;
@@ -64,9 +66,10 @@ public:
}
private:
// NOLINTBEGIN
Py::Object read(const Py::Tuple& args)
{
char* Name;
char* Name {};
if (!PyArg_ParseTuple(args.ptr(), "et", "utf-8", &Name)) {
throw Py::Exception();
}
@@ -77,7 +80,7 @@ private:
}
Py::Object open(const Py::Tuple& args)
{
char* Name;
char* Name {};
if (!PyArg_ParseTuple(args.ptr(), "et", "utf-8", &Name)) {
throw Py::Exception();
}
@@ -87,11 +90,24 @@ private:
// Base::Console().Log("Open in Mesh with %s",Name);
Base::FileInfo file(EncodedName.c_str());
Base::FileInfo file(EncodedName);
if (file.hasExtension("jt")) {
TestJtReader reader;
reader.setFile(EncodedName.c_str());
reader.setFile(EncodedName);
reader.read();
#ifdef JTREADER_HAVE_TKJT
JtReaderNS::TKJtReader jtReader;
jtReader.open(EncodedName);
App::Document* doc = App::GetApplication().newDocument();
std::string objname = file.fileNamePure();
auto iv = dynamic_cast<App::InventorObject*>(
doc->addObject("App::InventorObject", objname.c_str()));
iv->Buffer.setValue(jtReader.getOutput());
iv->purgeTouched();
#endif
return Py::None();
}
@@ -99,8 +115,8 @@ private:
}
Py::Object importer(const Py::Tuple& args)
{
char* Name;
const char* DocName;
char* Name {};
const char* DocName {};
if (!PyArg_ParseTuple(args.ptr(), "ets", "utf-8", &Name, &DocName)) {
throw Py::Exception();
}
@@ -112,21 +128,33 @@ private:
if (file.hasExtension("jt")) {
// add Import feature
App::Document* pcDoc = App::GetApplication().getDocument(DocName);
if (!pcDoc) {
pcDoc = App::GetApplication().newDocument(DocName);
App::Document* doc = App::GetApplication().getDocument(DocName);
if (!doc) {
doc = App::GetApplication().newDocument(DocName);
}
#ifdef JTREADER_HAVE_TKJT
JtReaderNS::TKJtReader jtReader;
jtReader.open(EncodedName);
std::string objname = file.fileNamePure();
auto iv = dynamic_cast<App::InventorObject*>(
doc->addObject("App::InventorObject", objname.c_str()));
iv->Buffer.setValue(jtReader.getOutput());
iv->purgeTouched();
#endif
return Py::None();
}
throw Py::RuntimeError("unknown file ending");
}
// NOLINTEND
};
PyObject* initModule()
{
return Base::Interpreter().addModule(new Module);
return Base::Interpreter().addModule(new Module); // NOLINT
}
} // namespace JtReaderNS

View File

@@ -1,3 +1,6 @@
set(JTREADER_TKJT_INCLUDE_DIRS CACHE PATH "Include directory of TKJT headers")
set(JTREADER_TKJT_LIBRARIES CACHE FILEPATH "File path to TKJT library")
include_directories(
${CMAKE_BINARY_DIR}
${CMAKE_CURRENT_BINARY_DIR}
@@ -12,6 +15,7 @@ link_directories(${OCC_LIBRARY_DIR})
set(JtReader_LIBS
Mesh
${OCC_LIBRARIES}
#${OCC_OCAF_LIBRARIES}
#${OCC_OCAF_DEBUG_LIBRARIES}
)
@@ -27,6 +31,19 @@ SET(JtReader_SRCS
FcLodHandler.cpp
)
if (EXISTS "${JTREADER_TKJT_INCLUDE_DIRS}/JtData_Object.hxx")
add_definitions(-DJTREADER_HAVE_TKJT)
include_directories(${JTREADER_TKJT_INCLUDE_DIRS})
list (APPEND JtReader_LIBS
${JTREADER_TKJT_LIBRARIES}
)
list (APPEND JtReader_SRCS
TKJtReader.cpp
TKJtReader.h
)
endif ()
set (JtReader_Scripts
../Init.py
)

View File

@@ -0,0 +1,270 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/***************************************************************************
* Copyright (c) 2023 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* This file is part of FreeCAD. *
* *
* FreeCAD is free software: you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 2.1 of the *
* License, or (at your option) any later version. *
* *
* FreeCAD 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 *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with FreeCAD. If not, see *
* <https://www.gnu.org/licenses/>. *
* *
**************************************************************************/
#include "PreCompiled.h"
#include <gp_Trsf.hxx>
#include "TKJtReader.h"
#include <Base/Console.h>
#include <Base/FileInfo.h>
using namespace JtReaderNS;
namespace
{
// clang-format off
const Handle(Standard_Type) Type_JtAttribute_GeometricTransform = STANDARD_TYPE(JtAttribute_GeometricTransform);
const Handle(Standard_Type) Type_JtAttribute_Material = STANDARD_TYPE(JtAttribute_Material);
const Handle(Standard_Type) Type_JtNode_Partition = STANDARD_TYPE(JtNode_Partition);
const Handle(Standard_Type) Type_JtNode_Group = STANDARD_TYPE(JtNode_Group);
const Handle(Standard_Type) Type_JtNode_Instance = STANDARD_TYPE(JtNode_Instance);
const Handle(Standard_Type) Type_JtNode_RangeLOD = STANDARD_TYPE(JtNode_RangeLOD);
const Handle(Standard_Type) Type_JtNode_Shape_Base = STANDARD_TYPE(JtNode_Shape_Base);
const Handle(Standard_Type) Type_JtNode_Shape_Vertex = STANDARD_TYPE(JtNode_Shape_Vertex);
const Handle(Standard_Type) Type_JtNode_Shape_TriStripSet = STANDARD_TYPE(JtNode_Shape_TriStripSet);
// clang-format on
} // namespace
TKJtReader::TKJtReader()
: builder {result}
{}
void TKJtReader::clear()
{
result.str(std::string());
result.clear();
}
void TKJtReader::open(const std::string& filename)
{
clear();
Base::FileInfo file(filename);
jtDir = TCollection_ExtendedString(TCollection_AsciiString((file.dirPath() + '/').c_str()));
TCollection_ExtendedString aFileName(filename.c_str());
Handle(JtData_Model) aModel = new JtData_Model(aFileName);
if (!aModel.IsNull()) {
Handle(JtNode_Partition) aNode = aModel->Init();
if (!aNode.IsNull()) {
rootNode = aNode;
builder.addHeader();
builder.beginSeparator();
Base::ShapeHintsItem shapeHints;
shapeHints.setShapeType(Base::ShapeType::Type::UnknownShapeType);
shapeHints.setVertexOrdering(Base::VertexOrdering::Ordering::CounterClockwise);
builder.addNode(shapeHints);
traverseGraph(aNode);
builder.endSeparator();
rootNode.Nullify();
}
}
}
std::string TKJtReader::getOutput() const
{
return result.str();
}
void TKJtReader::readMaterialAttribute(const Handle(JtAttribute_Material) & aMaterial)
{
const Jt_F32* ambient = aMaterial->AmbientColor();
const Jt_F32* diffuse = aMaterial->DiffuseColor();
const Jt_F32* specular = aMaterial->SpecularColor();
// const Jt_F32* emissive = aMaterial->EmissionColor();
Jt_F32 shininess = aMaterial->Shininess() / 100.0F;
// NOLINTBEGIN
Base::MaterialItem item;
item.setAmbientColor({Base::ColorRGB(ambient[0], ambient[1], ambient[2])});
item.setDiffuseColor({Base::ColorRGB(diffuse[0], diffuse[1], diffuse[2])});
item.setSpecularColor({Base::ColorRGB(specular[0], specular[1], specular[2])});
// Ignore the emissive color as there are sometimes some weird values
// item.setEmissiveColor({Base::ColorRGB(emissive[0], emissive[1], emissive[2])});
item.setShininess({shininess});
// NOLINTEND
builder.addNode(item);
}
void TKJtReader::readTransformAttribute(const Handle(JtAttribute_GeometricTransform) & aTransform)
{
gp_Trsf trsf;
aTransform->GetTrsf(trsf);
gp_Mat mat = trsf.VectorialPart();
gp_XYZ xyz = trsf.TranslationPart();
Base::Matrix4D mtrx;
// NOLINTBEGIN
mtrx[0][0] = mat(1, 1);
mtrx[0][1] = mat(1, 2);
mtrx[0][2] = mat(1, 3);
mtrx[1][0] = mat(2, 1);
mtrx[1][1] = mat(2, 2);
mtrx[1][2] = mat(2, 3);
mtrx[2][0] = mat(3, 1);
mtrx[2][1] = mat(3, 2);
mtrx[2][2] = mat(3, 3);
// set pos vector
mtrx[0][3] = xyz.X();
mtrx[1][3] = xyz.Y();
mtrx[2][3] = xyz.Z();
// NOLINTEND
transformations.push_back(mtrx);
}
void TKJtReader::readShapeVertex(const Handle(JtNode_Shape_Vertex) & aShape)
{
const JtData_Object::VectorOfLateLoads& aLateLoaded = aShape->LateLoads();
for (std::size_t index = 0; index < aLateLoaded.Count(); ++index) {
Handle(JtData_Object) anObject = aLateLoaded[index]->DefferedObject();
if (anObject.IsNull()) {
aLateLoaded[index]->Load();
anObject = aLateLoaded[index]->DefferedObject();
}
if (!anObject.IsNull()) {
Handle(JtElement_ShapeLOD_TriStripSet) aLOD =
Handle(JtElement_ShapeLOD_TriStripSet)::DownCast(anObject);
if (!aLOD.IsNull()) {
getTriangleStripSet(aLOD);
}
}
}
}
void TKJtReader::getTriangleStripSet(const Handle(JtElement_ShapeLOD_TriStripSet) & aLOD)
{
const int pointsPerFace = 3;
std::vector<Base::Vector3f> points;
std::vector<int> faces;
const JtElement_ShapeLOD_Vertex::VertexData& vertices = aLOD->Vertices();
const JtElement_ShapeLOD_Vertex::IndicesVec& indices = aLOD->Indices();
float* data = vertices.Data();
// NOLINTBEGIN
for (int index = 0; index < indices.Count(); index += 3) {
int coordIndex = indices[index] * 3;
points.emplace_back(data[coordIndex], data[coordIndex + 1], data[coordIndex + 2]);
coordIndex = indices[index + 1] * 3;
points.emplace_back(data[coordIndex], data[coordIndex + 1], data[coordIndex + 2]);
coordIndex = indices[index + 2] * 3;
points.emplace_back(data[coordIndex], data[coordIndex + 1], data[coordIndex + 2]);
faces.push_back(pointsPerFace);
}
// NOLINTEND
builder.addNode(Base::Coordinate3Item {points});
builder.addNode(Base::FaceSetItem {faces});
}
void TKJtReader::readPartition(const Handle(JtNode_Partition) & aPart)
{
if (rootNode != aPart) {
TCollection_ExtendedString aFullPath = jtDir + aPart->FileName();
TCollection_AsciiString aFileName(aFullPath);
Handle(JtData_Model) aModel = new JtData_Model(aFullPath);
Handle(JtNode_Partition) aNode = aModel->Init();
if (!aNode.IsNull()) {
builder.addNode(Base::InfoItem(std::string(aFileName.ToCString())));
traverseGraph(aNode);
}
}
}
void TKJtReader::readGroup(const Handle(JtNode_Group) & aGroup)
{
if (!transformations.empty()) {
builder.addNode(Base::TransformItem {transformations.back()});
transformations.pop_back();
}
const auto& aChildren = aGroup->Children();
for (std::size_t aChildIdx = 0; aChildIdx < aChildren.Count(); ++aChildIdx) {
Handle(JtNode_Base) aChild = Handle(JtNode_Base)::DownCast(aChildren[aChildIdx]);
traverseGraph(aChild);
}
}
void TKJtReader::readRangeLOD(const Handle(JtNode_RangeLOD) & aRangeLOD)
{
readGroup(aRangeLOD);
}
void TKJtReader::readInstance(const Handle(JtNode_Instance) & anInstance)
{
Handle(JtNode_Base) aBase = Handle(JtNode_Base)::DownCast(anInstance->Object());
if (!aBase.IsNull()) {
traverseGraph(aBase);
}
}
void TKJtReader::readAttributes(const JtData_Object::VectorOfObjects& attr)
{
for (std::size_t aAttrIdx = 0; aAttrIdx < attr.Count(); ++aAttrIdx) {
Handle(JtData_Object) anAttr = attr[aAttrIdx];
if (anAttr->IsKind(Type_JtAttribute_GeometricTransform)) {
Handle(JtAttribute_GeometricTransform) aTransform =
Handle(JtAttribute_GeometricTransform)::DownCast(anAttr);
readTransformAttribute(aTransform);
}
else if (anAttr->IsKind(Type_JtAttribute_Material)) {
Handle(JtAttribute_Material) aMaterial = Handle(JtAttribute_Material)::DownCast(anAttr);
readMaterialAttribute(aMaterial);
}
}
}
void TKJtReader::traverseGraph(const Handle(JtNode_Base) & aNode)
{
readAttributes(aNode->Attributes());
if (aNode->IsKind(Type_JtNode_Partition)) {
Handle(JtNode_Partition) aPart = Handle(JtNode_Partition)::DownCast(aNode);
builder.beginSeparator();
readPartition(aPart);
readGroup(aPart);
builder.endSeparator();
}
else if (aNode->IsKind(Type_JtNode_RangeLOD)) {
Handle(JtNode_RangeLOD) aRangeLOD = Handle(JtNode_RangeLOD)::DownCast(aNode);
builder.beginSeparator();
readRangeLOD(aRangeLOD);
builder.endSeparator();
}
else if (aNode->IsKind(Type_JtNode_Group)) {
Handle(JtNode_Group) aGroup = Handle(JtNode_Group)::DownCast(aNode);
builder.beginSeparator();
readGroup(aGroup);
builder.endSeparator();
}
else if (aNode->IsKind(Type_JtNode_Instance)) {
Handle(JtNode_Instance) anInstance = Handle(JtNode_Instance)::DownCast(aNode);
readInstance(anInstance);
}
else if (aNode->IsKind(Type_JtNode_Shape_Vertex)) {
Handle(JtNode_Shape_Vertex) aShape = Handle(JtNode_Shape_Vertex)::DownCast(aNode);
readShapeVertex(aShape);
}
}

View File

@@ -0,0 +1,76 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/***************************************************************************
* Copyright (c) 2023 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* This file is part of FreeCAD. *
* *
* FreeCAD is free software: you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 2.1 of the *
* License, or (at your option) any later version. *
* *
* FreeCAD 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 *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with FreeCAD. If not, see *
* <https://www.gnu.org/licenses/>. *
* *
**************************************************************************/
#ifndef JT_READER_TKJTREADER_H
#define JT_READER_TKJTREADER_H
#ifdef JTREADER_HAVE_TKJT
#include <JtAttribute_GeometricTransform.hxx>
#include <JtAttribute_Material.hxx>
#include <JtData_Model.hxx>
#include <JtElement_ShapeLOD_TriStripSet.hxx>
#include <JtNode_Instance.hxx>
#include <JtNode_Partition.hxx>
#include <JtNode_RangeLOD.hxx>
#include <JtNode_Shape_TriStripSet.hxx>
#include <JtNode_Shape_Vertex.hxx>
#include <TCollection_AsciiString.hxx>
#include <TCollection_ExtendedString.hxx>
#include <Base/Builder3D.h>
namespace JtReaderNS
{
class TKJtReader
{
public:
TKJtReader();
void open(const std::string& filename);
void clear();
std::string getOutput() const;
private:
void traverseGraph(const Handle(JtNode_Base) & aNode);
void readMaterialAttribute(const Handle(JtAttribute_Material) & aMaterial);
void readTransformAttribute(const Handle(JtAttribute_GeometricTransform) & aTransform);
void readShapeVertex(const Handle(JtNode_Shape_Vertex) & aShape);
void readPartition(const Handle(JtNode_Partition) & aPart);
void readGroup(const Handle(JtNode_Group) & aGroup);
void readRangeLOD(const Handle(JtNode_RangeLOD) & aRangeLOD);
void readInstance(const Handle(JtNode_Instance) & anInstance);
void readAttributes(const JtData_Object::VectorOfObjects& attr);
void getTriangleStripSet(const Handle(JtElement_ShapeLOD_TriStripSet) & aLOD);
private:
TCollection_ExtendedString jtDir;
Handle(JtNode_Partition) rootNode;
std::stringstream result;
Base::InventorBuilder builder;
std::list<Base::Matrix4D> transformations;
};
}; // namespace JtReaderNS
#endif // JTREADER_HAVE_TKJT
#endif // JT_READER_TKJTREADER_H