* Export cameras and lights.

* Import materials. 
TODO:
Assign materials to objects.
This commit is contained in:
Chingiz Dyussenov
2009-07-01 18:18:53 +00:00
parent d8313b70f3
commit 1bd28c878b
2 changed files with 272 additions and 47 deletions

View File

@@ -5,6 +5,8 @@
#include "DNA_image_types.h"
#include "DNA_material_types.h"
#include "DNA_texture_types.h"
#include "DNA_camera_types.h"
#include "DNA_lamp_types.h"
extern "C"
{
@@ -43,6 +45,11 @@ extern "C"
#include <COLLADASWTexture.h>
#include <COLLADASWLibraryMaterials.h>
#include <COLLADASWBindMaterial.h>
#include <COLLADASWLibraryCameras.h>
#include <COLLADASWLibraryLights.h>
#include <COLLADASWInstanceCamera.h>
#include <COLLADASWInstanceLight.h>
#include <COLLADASWCameraOptic.h>
#include <vector>
#include <algorithm> // std::find
@@ -114,6 +121,34 @@ void forEachMeshObjectInScene(Scene *sce, Functor &f)
}
}
template<class Functor>
void forEachCameraObjectInScene(Scene *sce, Functor &f)
{
Base *base= (Base*) sce->base.first;
while(base) {
Object *ob = base->object;
if (ob->type == OB_CAMERA && ob->data) {
f(ob);
}
base= base->next;
}
}
template<class Functor>
void forEachLampObjectInScene(Scene *sce, Functor &f)
{
Base *base= (Base*) sce->base.first;
while(base) {
Object *ob = base->object;
if (ob->type == OB_LAMP && ob->data) {
f(ob);
}
base= base->next;
}
}
// used in forEachMaterialInScene
template <class MaterialFunctor>
class ForEachMaterialFunctor
@@ -184,10 +219,10 @@ public:
DerivedMesh *dm = mesh_get_derived_final(mScene, ob, CD_MASK_BAREMESH);
Mesh *me = (Mesh*)ob->data;
std::string geom_name(id_name(ob));
// openMesh(geoId, geoName, meshId)
openMesh(geom_name, "", "");
// writes <source> for vertex coords
createVertsSource(geom_name, dm);
@@ -497,6 +532,8 @@ public:
// write <node>s
forEachMeshObjectInScene(sce, *this);
forEachCameraObjectInScene(sce, *this);
forEachLampObjectInScene(sce, *this);
// </visual_scene> </library_visual_scenes>
closeVisualScene();
@@ -507,6 +544,7 @@ public:
// called for each object
void operator()(Object *ob) {
COLLADASW::Node node(mSW);
std::string ob_name(id_name(ob));
node.start();
node.addTranslate(ob->loc[0], ob->loc[1], ob->loc[2]);
@@ -521,37 +559,50 @@ public:
QuatToAxisAngle(quat, axis, &angle);
angle_deg = angle * 180.0f / M_PI;
node.addRotate(axis[0], axis[1], axis[2], angle_deg);
node.addScale(ob->size[0], ob->size[1], ob->size[2]);
COLLADASW::InstanceGeometry instGeom(mSW);
std::string ob_name(id_name(ob));
instGeom.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, ob_name));
for(int a = 0; a < ob->totcol; a++) {
Material *ma = give_current_material(ob, a+1);
COLLADASW::BindMaterial& bm = instGeom.getBindMaterial();
COLLADASW::InstanceMaterialList& iml = bm.getInstanceMaterialList();
std::string matid(id_name(ma));
COLLADASW::InstanceMaterial im(matid, COLLADASW::URI
(COLLADABU::Utils::EMPTY_STRING,
matid));
// create <bind_vertex_input> for each uv layer
Mesh *me = (Mesh*)ob->data;
int totlayer = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
// <instance_geometry>
if (ob->type == OB_MESH) {
COLLADASW::InstanceGeometry instGeom(mSW);
instGeom.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, ob_name));
for (int b = 0; b < totlayer; b++) {
char *name = CustomData_get_layer_name(&me->fdata, CD_MTFACE, b);
im.push_back(COLLADASW::BindVertexInput(name, "TEXCOORD", b));
for(int a = 0; a < ob->totcol; a++) {
Material *ma = give_current_material(ob, a+1);
COLLADASW::BindMaterial& bm = instGeom.getBindMaterial();
COLLADASW::InstanceMaterialList& iml = bm.getInstanceMaterialList();
std::string matid(id_name(ma));
COLLADASW::InstanceMaterial im(matid, COLLADASW::URI
(COLLADABU::Utils::EMPTY_STRING,
matid));
// create <bind_vertex_input> for each uv layer
Mesh *me = (Mesh*)ob->data;
int totlayer = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
for (int b = 0; b < totlayer; b++) {
char *name = CustomData_get_layer_name(&me->fdata, CD_MTFACE, b);
im.push_back(COLLADASW::BindVertexInput(name, "TEXCOORD", b));
}
iml.push_back(im);
}
iml.push_back(im);
instGeom.add();
}
instGeom.add();
// <instance_camera>
else if (ob->type == OB_CAMERA) {
COLLADASW::InstanceCamera instCam(mSW, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, ob_name));
instCam.add();
}
// <instance_light>
else if (ob->type == OB_LAMP) {
COLLADASW::InstanceLight instLa(mSW, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, ob_name));
instLa.add();
}
node.end();
}
@@ -818,6 +869,95 @@ public:
}
};
class CamerasExporter: COLLADASW::LibraryCameras
{
public:
CamerasExporter(COLLADASW::StreamWriter *sw): COLLADASW::LibraryCameras(sw){}
void exportCameras(Scene *sce)
{
openLibrary();
forEachCameraObjectInScene(sce, *this);
closeLibrary();
}
void operator()(Object *ob)
{
// XXX add other params later
Camera *cam = (Camera*)ob->data;
std::string cam_name(id_name(ob));
if (cam->type == CAM_PERSP) {
COLLADASW::PerspectiveOptic persp(mSW);
persp.setXFov(1.0);
//persp.setYFov(1.0);
persp.setAspectRatio(1.0);
persp.setZFar(cam->clipend);
persp.setZNear(cam->clipsta);
COLLADASW::Camera ccam(mSW, &persp, cam_name);
addCamera(ccam);
}
else {
COLLADASW::OrthographicOptic ortho(mSW);
ortho.setXMag(1.0);
//ortho.setYMag(1.0, true);
ortho.setAspectRatio(1.0);
ortho.setZFar(cam->clipend);
ortho.setZNear(cam->clipsta);
COLLADASW::Camera ccam(mSW, &ortho, cam_name);
addCamera(ccam);
}
}
};
class LightsExporter: COLLADASW::LibraryLights
{
public:
LightsExporter(COLLADASW::StreamWriter *sw): COLLADASW::LibraryLights(sw){}
void exportLights(Scene *sce)
{
openLibrary();
forEachLampObjectInScene(sce, *this);
closeLibrary();
}
void operator()(Object *ob)
{
Lamp *la = (Lamp*)ob->data;
std::string la_name(id_name(ob));
COLLADASW::Color col(la->r, la->g, la->b);
// sun
if (la->type == LA_SUN) {
COLLADASW::DirectionalLight cla(mSW, la_name, la->energy);
cla.setColor(col);
addLight(cla);
}
// hemi
else if (la->type == LA_HEMI) {
COLLADASW::AmbientLight cla(mSW, la_name, la->energy);
cla.setColor(col);
addLight(cla);
}
// spot
// XXX add other params later
else if (la->type == LA_SPOT) {
COLLADASW::SpotLight cla(mSW, la_name, la->energy);
cla.setColor(col);
addLight(cla);
}
// lamp
else if (la->type != LA_AREA) {
COLLADASW::PointLight cla(mSW, la_name, la->energy);
cla.setColor(col);
addLight(cla);
}
else {
// XXX write error
return;
}
}
};
void DocumentExporter::exportCurrentScene(Scene *sce, const char* filename)
{
@@ -825,43 +965,51 @@ void DocumentExporter::exportCurrentScene(Scene *sce, const char* filename)
COLLADABU::NativeString(std::string(filename));
COLLADASW::StreamWriter sw(native_filename);
//open <Collada>
// open <Collada>
sw.startDocument();
//<asset>
// <asset>
COLLADASW::Asset asset(&sw);
// XXX ask blender devs about this?
asset.setUnit("meter", 1.0);
asset.setUpAxisType(COLLADASW::Asset::Z_UP);
asset.add();
//<library_images>
// <library_cameras>
CamerasExporter ce(&sw);
ce.exportCameras(sce);
// <library_lights>
LightsExporter le(&sw);
le.exportLights(sce);
// <library_images>
ImagesExporter ie(&sw);
ie.exportImages(sce);
//<library_effects>
// <library_effects>
EffectsExporter ee(&sw);
ee.exportEffects(sce);
//<library_materials>
// <library_materials>
MaterialsExporter me(&sw);
me.exportMaterials(sce);
//<library_geometries>
// <library_geometries>
GeometryExporter ge(&sw);
ge.exportGeom(sce);
//<library_visual_scenes>
// <library_visual_scenes>
SceneExporter se(&sw);
se.exportScene(sce);
//<scene>
// <scene>
std::string scene_name(id_name(sce));
COLLADASW::Scene scene(&sw, COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING,
scene_name));
scene.add();
//close <Collada>
// close <Collada>
sw.endDocument();
}

View File

@@ -19,6 +19,7 @@
#include "COLLADAFWTranslate.h"
#include "COLLADAFWScale.h"
#include "COLLADAFWRotate.h"
#include "COLLADAFWEffect.h"
#include "COLLADASaxFWLLoader.h"
@@ -40,6 +41,7 @@ extern "C"
#include "DNA_object_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_mesh_types.h"
#include "DNA_material_types.h"
#include "DocumentImporter.h"
@@ -97,6 +99,7 @@ private:
bContext *mContext;
std::map<COLLADAFW::UniqueId, Mesh*> uid_mesh_map; // geometry unique id-to-mesh map
std::map<COLLADAFW::UniqueId, Material*> uid_material_map;
class UnitConverter
{
@@ -221,12 +224,12 @@ public:
for (i = 0; i < visualScene->getRootNodes().getCount(); i++) {
COLLADAFW::Node *node = visualScene->getRootNodes()[i];
// TODO: check node type
if (node->getType() != COLLADAFW::Node::NODE) {
continue;
}
Object *ob = add_object(sce, OB_MESH);
const std::string& id = node->getOriginalId();
@@ -239,13 +242,13 @@ public:
// though a node may have more of them...
// TODO: join multiple <instance_geometry> meshes into 1, and link object with it
COLLADAFW::InstanceGeometryPointerArray &geom = node->getInstanceGeometries();
if (geom.getCount() < 1) {
fprintf(stderr, "Node hasn't got any geometry.\n");
continue;
}
const COLLADAFW::UniqueId& uid = geom[0]->getInstanciatedObjectId();
if (uid_mesh_map.find(uid) == uid_mesh_map.end()) {
// XXX report to user
@@ -254,9 +257,9 @@ public:
fprintf(stderr, "Couldn't find a mesh by UID.\n");
continue;
}
set_mesh(ob, uid_mesh_map[uid]);
float rot[3][3];
Mat3One(rot);
@@ -287,7 +290,7 @@ public:
float rot_copy[3][3];
float mat[3][3];
AxisAngleToQuat(quat, axis, angle);
QuatToMat3(quat, mat);
Mat3CpyMat3(rot_copy, rot);
Mat3MulMat3(rot, rot_copy, mat);
@@ -312,7 +315,7 @@ public:
break;
}
}
Mat3ToEul(rot, ob->rot);
}
@@ -496,8 +499,9 @@ public:
{
// TODO: create and store a material.
// Let it have 0 users for now.
/*std::string name = material->getOriginalId();
add_material(name);*/
const std::string& str_mat_id = material->getOriginalId();
Material *ma = add_material((char*)str_mat_id.c_str());
this->uid_material_map[material->getInstantiatedEffect()] = ma;
return true;
}
@@ -505,6 +509,79 @@ public:
@return The writer should return true, if writing succeeded, false otherwise.*/
virtual bool writeEffect( const COLLADAFW::Effect* effect )
{
const COLLADAFW::UniqueId& uid = effect->getUniqueId();
if (uid_material_map.find(uid) == uid_material_map.end()) {
// XXX report to user
// this could happen if a mesh was not created
// (e.g. if it contains unsupported geometry)
fprintf(stderr, "Couldn't find a material by UID.\n");
return true;
}
Material *ma = uid_material_map[uid];
COLLADAFW::CommonEffectPointerArray ef_array = effect->getCommonEffects();
if (ef_array.getCount() < 1) {
fprintf(stderr, "Effect hasn't got any common effects.\n");
}
COLLADAFW::EffectCommon *ef = ef_array[0];
COLLADAFW::EffectCommon::ShaderType shader = ef->getShaderType();
// blinn
if (shader == COLLADAFW::EffectCommon::SHADER_BLINN) {
ma->spec_shader = MA_SPEC_BLINN;
ma->spec = ef->getShininess().getFloatValue();
}
// phong
else if (shader == COLLADAFW::EffectCommon::SHADER_PHONG) {
ma->spec_shader = MA_SPEC_PHONG;
ma->spec = ef->getShininess().getFloatValue();
}
// lambert
else if (shader == COLLADAFW::EffectCommon::SHADER_LAMBERT) {
ma->diff_shader = MA_DIFF_LAMBERT;
}
// default - lambert
else {
ma->diff_shader = MA_DIFF_LAMBERT;
fprintf(stderr, "Current shader type is not supported.\n");
}
// reflectivity
ma->ray_mirror = ef->getReflectivity().getFloatValue();
// index of refraction
ma->ang = ef->getIndexOfRefraction().getFloatValue();
COLLADAFW::Color col;
// diffuse
if (ef->getDiffuse().isColor()) {
col = ef->getDiffuse().getColor();
ma->r = col.getRed();
ma->g = col.getGreen();
ma->b = col.getBlue();
}
// ambient
if (ef->getAmbient().isColor()) {
col = ef->getAmbient().getColor();
ma->ambr = col.getRed();
ma->ambg = col.getGreen();
ma->ambb = col.getBlue();
}
// specular
if (ef->getSpecular().isColor()) {
col = ef->getSpecular().getColor();
ma->specr = col.getRed();
ma->specg = col.getGreen();
ma->specb = col.getBlue();
}
// reflective
if (ef->getReflective().isColor()) {
col = ef->getReflective().getColor();
ma->mirr = col.getRed();
ma->mirg = col.getGreen();
ma->mirb = col.getBlue();
}
return true;
}