fix T39967: Added support for Import/export of vertex color layers
This commit is contained in:
@@ -289,6 +289,12 @@ void GeometryExporter::createLooseEdgeList(Object *ob,
|
||||
|
||||
}
|
||||
|
||||
std::string GeometryExporter::makeVertexColorSourceId(std::string& geom_id, char *layer_name)
|
||||
{
|
||||
std::string result = getIdBySemantics(geom_id, COLLADASW::InputSemantic::COLOR) + "-" + layer_name;
|
||||
return result;
|
||||
}
|
||||
|
||||
// powerful because it handles both cases when there is material and when there's not
|
||||
void GeometryExporter::createPolylist(short material_index,
|
||||
bool has_uvs,
|
||||
@@ -365,9 +371,20 @@ void GeometryExporter::createPolylist(short material_index,
|
||||
}
|
||||
}
|
||||
|
||||
if (has_color) {
|
||||
COLLADASW::Input input4(COLLADASW::InputSemantic::COLOR, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::COLOR), has_uvs ? 3 : 2);
|
||||
til.push_back(input4);
|
||||
int totlayer_mcol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL);
|
||||
if (totlayer_mcol > 0) {
|
||||
int map_index = 0;
|
||||
|
||||
for (int a = 0; a < totlayer_mcol; a++) {
|
||||
char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPCOL, a);
|
||||
COLLADASW::Input input4(COLLADASW::InputSemantic::COLOR,
|
||||
makeUrl(makeVertexColorSourceId(geom_id, layer_name)),
|
||||
(has_uvs) ? 3 : 2, // all color layers have same index order
|
||||
map_index // set number equals color map index
|
||||
);
|
||||
til.push_back(input4);
|
||||
map_index++;
|
||||
}
|
||||
}
|
||||
|
||||
// sets <vcount>
|
||||
@@ -420,6 +437,7 @@ void GeometryExporter::createVertsSource(std::string geom_id, Mesh *me)
|
||||
ARRAY_ID_SUFFIX);
|
||||
source.setAccessorCount(totverts);
|
||||
source.setAccessorStride(3);
|
||||
|
||||
COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
|
||||
param.push_back("X");
|
||||
param.push_back("Y");
|
||||
@@ -437,40 +455,56 @@ void GeometryExporter::createVertsSource(std::string geom_id, Mesh *me)
|
||||
|
||||
}
|
||||
|
||||
|
||||
void GeometryExporter::createVertexColorSource(std::string geom_id, Mesh *me)
|
||||
{
|
||||
MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer(&me->ldata, CD_MLOOPCOL);
|
||||
if (mloopcol == NULL)
|
||||
/* Find number of vertex color layers */
|
||||
int totlayer_mcol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL);
|
||||
if (totlayer_mcol == 0)
|
||||
return;
|
||||
|
||||
int active_vcolor_index = CustomData_get_active_layer_index(&me->ldata, CD_MLOOPCOL);
|
||||
|
||||
COLLADASW::FloatSourceF source(mSW);
|
||||
source.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::COLOR));
|
||||
source.setArrayId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::COLOR) + ARRAY_ID_SUFFIX);
|
||||
source.setAccessorCount(me->totloop);
|
||||
source.setAccessorStride(3);
|
||||
int map_index = 0;
|
||||
for (int a = 0; a < totlayer_mcol; a++) {
|
||||
|
||||
COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
|
||||
param.push_back("R");
|
||||
param.push_back("G");
|
||||
param.push_back("B");
|
||||
map_index++;
|
||||
MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_n(&me->ldata, CD_MLOOPCOL, a);
|
||||
|
||||
source.prepareToAppendValues();
|
||||
COLLADASW::FloatSourceF source(mSW);
|
||||
|
||||
MPoly *mpoly;
|
||||
int i;
|
||||
for (i = 0, mpoly = me->mpoly; i < me->totpoly; i++, mpoly++) {
|
||||
MLoopCol *mlc = mloopcol + mpoly->loopstart;
|
||||
for (int j = 0; j < mpoly->totloop; j++, mlc++) {
|
||||
source.appendValues(
|
||||
mlc->r / 255.0f,
|
||||
mlc->g / 255.0f,
|
||||
mlc->b / 255.0f
|
||||
);
|
||||
char *layer_name = bc_CustomData_get_layer_name(&me->ldata, CD_MLOOPCOL, a);
|
||||
std::string layer_id = makeVertexColorSourceId(geom_id, layer_name);
|
||||
source.setId(layer_id);
|
||||
|
||||
source.setNodeName(layer_name);
|
||||
|
||||
source.setArrayId(layer_id + ARRAY_ID_SUFFIX);
|
||||
source.setAccessorCount(me->totloop);
|
||||
source.setAccessorStride(3);
|
||||
|
||||
COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList();
|
||||
param.push_back("R");
|
||||
param.push_back("G");
|
||||
param.push_back("B");
|
||||
|
||||
source.prepareToAppendValues();
|
||||
|
||||
MPoly *mpoly;
|
||||
int i;
|
||||
for (i = 0, mpoly = me->mpoly; i < me->totpoly; i++, mpoly++) {
|
||||
MLoopCol *mlc = mloopcol + mpoly->loopstart;
|
||||
for (int j = 0; j < mpoly->totloop; j++, mlc++) {
|
||||
source.appendValues(
|
||||
mlc->r / 255.0f,
|
||||
mlc->g / 255.0f,
|
||||
mlc->b / 255.0f
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
source.finish();
|
||||
source.finish();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -100,7 +100,8 @@ public:
|
||||
void create_normals(std::vector<Normal> &nor, std::vector<BCPolygonNormalsIndices> &ind, Mesh *me);
|
||||
|
||||
std::string getIdBySemantics(std::string geom_id, COLLADASW::InputSemantic::Semantics type, std::string other_suffix = "");
|
||||
|
||||
std::string makeVertexColorSourceId(std::string& geom_id, char *layer_name);
|
||||
|
||||
COLLADASW::URI getUrlBySemantics(std::string geom_id, COLLADASW::InputSemantic::Semantics type, std::string other_suffix = "");
|
||||
|
||||
COLLADASW::URI makeUrl(std::string id);
|
||||
|
||||
@@ -173,6 +173,42 @@ void UVDataWrapper::getUV(int uv_index, float *uv)
|
||||
}
|
||||
}
|
||||
|
||||
VCOLDataWrapper::VCOLDataWrapper(COLLADAFW::MeshVertexData& vdata) : mVData(&vdata){
|
||||
}
|
||||
|
||||
void VCOLDataWrapper::get_vcol(int v_index, MLoopCol *mloopcol)
|
||||
{
|
||||
int stride = mVData->getStride(0);
|
||||
if(stride == 0) stride =3;
|
||||
|
||||
switch (mVData->getType()) {
|
||||
case COLLADAFW::MeshVertexData::DATA_TYPE_FLOAT:
|
||||
{
|
||||
COLLADAFW::ArrayPrimitiveType<float> *values = mVData->getFloatValues();
|
||||
if (values->empty()) return;
|
||||
|
||||
mloopcol->r = FTOCHAR((*values)[v_index * stride]);
|
||||
mloopcol->g = FTOCHAR((*values)[v_index * stride + 1]);
|
||||
mloopcol->b = FTOCHAR((*values)[v_index * stride + 2]);
|
||||
}
|
||||
break;
|
||||
|
||||
case COLLADAFW::MeshVertexData::DATA_TYPE_DOUBLE:
|
||||
{
|
||||
COLLADAFW::ArrayPrimitiveType<double> *values = mVData->getDoubleValues();
|
||||
if (values->empty()) return;
|
||||
|
||||
mloopcol->r = FTOCHAR((*values)[v_index * stride]);
|
||||
mloopcol->g = FTOCHAR((*values)[v_index * stride + 1]);
|
||||
mloopcol->b = FTOCHAR((*values)[v_index * stride + 2]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "VCOLDataWrapper.getvcol(): unknown data type\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MeshImporter::MeshImporter(UnitConverter *unitconv, ArmatureImporter *arm, Scene *sce) : unitconverter(unitconv), scene(sce), armature_importer(arm) {
|
||||
}
|
||||
|
||||
@@ -187,6 +223,17 @@ void MeshImporter::set_poly_indices(MPoly *mpoly, MLoop *mloop, int loop_index,
|
||||
}
|
||||
}
|
||||
|
||||
void MeshImporter::set_vcol(MLoopCol *mlc, VCOLDataWrapper &vob, int loop_index, COLLADAFW::IndexList &index_list, int count)
|
||||
{
|
||||
COLLADAFW::UIntValuesArray& indices =index_list.getIndices();
|
||||
int index;
|
||||
for(index = 0; index < count; index++,mlc++)
|
||||
{
|
||||
int v_index = indices[index+loop_index];
|
||||
vob.get_vcol(v_index,mlc);
|
||||
}
|
||||
}
|
||||
|
||||
void MeshImporter::set_face_uv(MLoopUV *mloopuv, UVDataWrapper &uvs,
|
||||
int start_index, COLLADAFW::IndexList& index_list, int count)
|
||||
{
|
||||
@@ -328,6 +375,17 @@ bool MeshImporter::primitive_has_faces(COLLADAFW::MeshPrimitive *mp) {
|
||||
return has_faces;
|
||||
}
|
||||
|
||||
|
||||
static std::string extract_vcolname(const COLLADAFW::String &collada_id) {
|
||||
std::string colname = collada_id;
|
||||
int spos = colname.find("-mesh-colors-");
|
||||
if (spos != std::string::npos) {
|
||||
colname = colname.substr(spos+13);
|
||||
}
|
||||
return colname;
|
||||
}
|
||||
|
||||
|
||||
// =================================================================
|
||||
// Return the number of faces by summing up
|
||||
// the facecounts of the parts.
|
||||
@@ -337,8 +395,9 @@ bool MeshImporter::primitive_has_faces(COLLADAFW::MeshPrimitive *mp) {
|
||||
void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me)
|
||||
{
|
||||
COLLADAFW::MeshPrimitiveArray& prim_arr = collada_mesh->getMeshPrimitives();
|
||||
int total_poly_count = 0;
|
||||
int total_loop_count = 0;
|
||||
int total_poly_count = 0;
|
||||
int total_loop_count = 0;
|
||||
int total_color_count = 0;
|
||||
|
||||
// collect edge_count and face_count from all parts
|
||||
for (int i = 0; i < prim_arr.getCount(); i++) {
|
||||
@@ -360,6 +419,7 @@ void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me)
|
||||
|
||||
total_poly_count += prim_poly_count;
|
||||
total_loop_count += prim_loop_count;
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -394,6 +454,17 @@ void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me)
|
||||
me->mtpoly = (MTexPoly *)CustomData_get_layer_n(&me->pdata, CD_MTEXPOLY, 0);
|
||||
me->mloopuv = (MLoopUV *) CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, 0);
|
||||
}
|
||||
|
||||
int totcolset = collada_mesh->getColors().getInputInfosArray().getCount();
|
||||
if (totcolset > 0) {
|
||||
for (int i = 0; i < totcolset; i++) {
|
||||
COLLADAFW::MeshVertexData::InputInfos *info = collada_mesh->getColors().getInputInfosArray()[i];
|
||||
COLLADAFW::String colname = extract_vcolname(info->mName);
|
||||
CustomData_add_layer_named(&me->ldata,CD_MLOOPCOL,CD_DEFAULT,NULL,me->totloop, colname.c_str());
|
||||
}
|
||||
me->mloopcol = (MLoopCol *) CustomData_get_layer_n(&me->ldata, CD_MLOOPCOL, 0);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -538,6 +609,7 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me)
|
||||
allocate_poly_data(collada_mesh, me);
|
||||
|
||||
UVDataWrapper uvs(collada_mesh->getUVCoords());
|
||||
VCOLDataWrapper vcol(collada_mesh->getColors());
|
||||
|
||||
MPoly *mpoly = me->mpoly;
|
||||
MLoop *mloop = me->mloop;
|
||||
@@ -553,9 +625,9 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me)
|
||||
COLLADAFW::MeshPrimitive *mp = prim_arr[i];
|
||||
|
||||
// faces
|
||||
size_t prim_totpoly = mp->getFaceCount();
|
||||
unsigned int *position_indices = mp->getPositionIndices().getData();
|
||||
unsigned int *normal_indices = mp->getNormalIndices().getData();
|
||||
size_t prim_totpoly = mp->getFaceCount();
|
||||
unsigned int *position_indices = mp->getPositionIndices().getData();
|
||||
unsigned int *normal_indices = mp->getNormalIndices().getData();
|
||||
|
||||
bool mp_has_normals = primitive_has_useable_normals(mp);
|
||||
bool mp_has_faces = primitive_has_faces(mp);
|
||||
@@ -564,7 +636,6 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me)
|
||||
|
||||
// since we cannot set mpoly->mat_nr here, we store a portion of me->mpoly in Primitive
|
||||
Primitive prim = {mpoly, 0};
|
||||
COLLADAFW::IndexListArray& index_list_array = mp->getUVCoordIndicesArray();
|
||||
|
||||
// If MeshPrimitive is TRIANGLE_FANS we split it into triangles
|
||||
// The first trifan vertex will be the first vertex in every triangle
|
||||
@@ -611,6 +682,9 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me)
|
||||
COLLADAFW::Polygons *mpvc = (COLLADAFW::Polygons *)mp;
|
||||
unsigned int start_index = 0;
|
||||
|
||||
COLLADAFW::IndexListArray& index_list_array_uvcoord = mp->getUVCoordIndicesArray();
|
||||
COLLADAFW::IndexListArray& index_list_array_vcolor = mp->getColorIndicesArray();
|
||||
|
||||
for (unsigned int j = 0; j < prim_totpoly; j++) {
|
||||
|
||||
// Vertices in polygon:
|
||||
@@ -618,15 +692,15 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me)
|
||||
set_poly_indices(mpoly, mloop, loop_index, position_indices, vcount);
|
||||
|
||||
|
||||
for (unsigned int uvset_index = 0; uvset_index < index_list_array.getCount(); uvset_index++) {
|
||||
for (unsigned int uvset_index = 0; uvset_index < index_list_array_uvcoord.getCount(); uvset_index++) {
|
||||
// get mtface by face index and uv set index
|
||||
COLLADAFW::IndexList& index_list = *index_list_array[uvset_index];
|
||||
COLLADAFW::IndexList& index_list = *index_list_array_uvcoord[uvset_index];
|
||||
MLoopUV *mloopuv = (MLoopUV *)CustomData_get_layer_named(&me->ldata, CD_MLOOPUV, index_list.getName().c_str());
|
||||
if (mloopuv == NULL) {
|
||||
fprintf(stderr, "Collada import: Mesh [%s] : Unknown reference to TEXCOORD [#%s].", me->id.name, index_list.getName().c_str() );
|
||||
fprintf(stderr, "Collada import: Mesh [%s] : Unknown reference to TEXCOORD [#%s].\n", me->id.name, index_list.getName().c_str() );
|
||||
}
|
||||
else {
|
||||
set_face_uv(mloopuv+loop_index, uvs, start_index, *index_list_array[uvset_index], vcount);
|
||||
set_face_uv(mloopuv+loop_index, uvs, start_index, *index_list_array_uvcoord[uvset_index], vcount);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -634,10 +708,23 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me)
|
||||
if (!is_flat_face(normal_indices, nor, vcount))
|
||||
mpoly->flag |= ME_SMOOTH;
|
||||
}
|
||||
|
||||
|
||||
for(unsigned int vcolor_index = 0 ; vcolor_index < index_list_array_vcolor.getCount();vcolor_index++)
|
||||
{
|
||||
COLLADAFW::IndexList& index_list = *index_list_array_vcolor[vcolor_index];
|
||||
COLLADAFW::String colname = extract_vcolname(index_list.getName());
|
||||
MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_named(&me->ldata, CD_MLOOPCOL, colname.c_str());
|
||||
if (mloopcol == NULL) {
|
||||
fprintf(stderr, "Collada import: Mesh [%s] : Unknown reference to VCOLOR [#%s].\n", me->id.name, index_list.getName().c_str() );
|
||||
}
|
||||
else {
|
||||
set_vcol(mloopcol+loop_index, vcol, start_index, *index_list_array_vcolor[vcolor_index], vcount);
|
||||
}
|
||||
}
|
||||
|
||||
mpoly++;
|
||||
mloop += vcount;
|
||||
loop_index += vcount;
|
||||
mloop += vcount;
|
||||
loop_index += vcount;
|
||||
start_index += vcount;
|
||||
prim.totpoly++;
|
||||
|
||||
@@ -654,6 +741,8 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me)
|
||||
|
||||
if (mp_has_faces)
|
||||
mat_prim_map[mp->getMaterialId()].push_back(prim);
|
||||
|
||||
|
||||
}
|
||||
|
||||
geom_uid_mat_mapping_map[collada_mesh->getUniqueId()] = mat_prim_map;
|
||||
@@ -1114,5 +1203,6 @@ bool MeshImporter::write_geometry(const COLLADAFW::Geometry *geom)
|
||||
// read_lines() must be called after the face edges have been generated.
|
||||
// Oterwise the loose edges will be silently deleted again.
|
||||
read_lines(mesh, me);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -77,6 +77,14 @@ public:
|
||||
void getUV(int uv_index, float *uv);
|
||||
};
|
||||
|
||||
class VCOLDataWrapper
|
||||
{
|
||||
COLLADAFW::MeshVertexData *mVData;
|
||||
public:
|
||||
VCOLDataWrapper(COLLADAFW::MeshVertexData& vdata);
|
||||
void get_vcol(int v_index, MLoopCol *mloopcol);
|
||||
};
|
||||
|
||||
class MeshImporter : public MeshImporterBase
|
||||
{
|
||||
private:
|
||||
@@ -113,6 +121,12 @@ private:
|
||||
COLLADAFW::IndexList& index_list,
|
||||
int count);
|
||||
|
||||
void set_vcol(MLoopCol *mloopcol,
|
||||
VCOLDataWrapper &vob,
|
||||
int loop_index,
|
||||
COLLADAFW::IndexList& index_list,
|
||||
int count);
|
||||
|
||||
#ifdef COLLADA_DEBUG
|
||||
void print_index_list(COLLADAFW::IndexList& index_list);
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user