diff --git a/code/AssxmlExporter.cpp b/code/AssxmlExporter.cpp index bcf805501..8ddbf8abc 100644 --- a/code/AssxmlExporter.cpp +++ b/code/AssxmlExporter.cpp @@ -179,7 +179,7 @@ static std::string encodeXML(const std::string& data) { // ----------------------------------------------------------------------------------- // Write a text model dump -static +static void WriteDump(const aiScene* scene, IOStream* io, bool shortened) { time_t tt = ::time( NULL ); tm* p = ::gmtime( &tt ); diff --git a/code/BlenderLoader.cpp b/code/BlenderLoader.cpp index 574cdce9f..c5071cc26 100644 --- a/code/BlenderLoader.cpp +++ b/code/BlenderLoader.cpp @@ -1049,7 +1049,24 @@ aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, c // blender orients directional lights as facing toward -z out->mDirection = aiVector3D(0.f, 0.f, -1.f); + out->mUp = aiVector3D(0.f, 1.f, 0.f); break; + + case Lamp::Type_Area: + out->mType = aiLightSource_AREA; + + if (lamp->area_shape == 0) { + out->mSize = aiVector2D(lamp->area_size, lamp->area_size); + } + else { + out->mSize = aiVector2D(lamp->area_size, lamp->area_sizey); + } + + // blender orients directional lights as facing toward -z + out->mDirection = aiVector3D(0.f, 0.f, -1.f); + out->mUp = aiVector3D(0.f, 1.f, 0.f); + break; + default: break; } diff --git a/code/BlenderScene.cpp b/code/BlenderScene.cpp index 0addd013b..cb0245fce 100644 --- a/code/BlenderScene.cpp +++ b/code/BlenderScene.cpp @@ -206,6 +206,10 @@ template <> void Structure :: Convert ( ReadField(dest.att2,"att2",db); ReadField((int&)dest.falloff_type,"falloff_type",db); ReadField(dest.sun_brightness,"sun_brightness",db); + ReadField(dest.area_size,"area_size",db); + ReadField(dest.area_sizey,"area_sizey",db); + ReadField(dest.area_sizez,"area_sizez",db); + ReadField(dest.area_shape,"area_shape",db); db.reader->IncPtr(size); } diff --git a/code/BlenderScene.h b/code/BlenderScene.h index 051b54ed3..5305789b7 100644 --- a/code/BlenderScene.h +++ b/code/BlenderScene.h @@ -371,8 +371,8 @@ struct Lamp : ElemBase { //short ray_samp, ray_sampy, ray_sampz; //short ray_samp_type; - //short area_shape; - //float area_size, area_sizey, area_sizez; + short area_shape; + float area_size, area_sizey, area_sizez; //float adapt_thresh; //short ray_samp_method; diff --git a/code/PretransformVertices.cpp b/code/PretransformVertices.cpp index d37bfd599..8158bdd6f 100644 --- a/code/PretransformVertices.cpp +++ b/code/PretransformVertices.cpp @@ -618,6 +618,7 @@ void PretransformVertices::Execute( aiScene* pScene) // transformation of the corresponding node l->mPosition = nd->mTransformation * l->mPosition; l->mDirection = aiMatrix3x3( nd->mTransformation ) * l->mDirection; + l->mUp = aiMatrix3x3( nd->mTransformation ) * l->mUp; } if( !configKeepHierarchy ) { diff --git a/include/assimp/light.h b/include/assimp/light.h index cc53a18f4..939d5b6cd 100644 --- a/include/assimp/light.h +++ b/include/assimp/light.h @@ -82,6 +82,10 @@ enum aiLightSourceType //! other properties, just a color. aiLightSource_AMBIENT = 0x4, + //! An area light is a rectangle with predefined size that uniformly + //! emits light from one of its sides. The position is center of the + //! rectangle and direction is its normal vector. + aiLightSource_AREA = 0x5, /** This value is not used. It is just there to force the * compiler to map this enum to a 32 Bit integer. @@ -135,6 +139,14 @@ struct aiLight */ C_STRUCT aiVector3D mDirection; + /** Up direction of the light source in space. Relative to the + * transformation of the node corresponding to the light. + * + * The direction is undefined for point lights. The vector + * may be normalized, but it needn't. + */ + C_STRUCT aiVector3D mUp; + /** Constant light attenuation factor. * * The intensity of the light source at a given distance 'd' from @@ -217,6 +229,9 @@ struct aiLight */ float mAngleOuterCone; + /** Size of area light source. */ + C_STRUCT aiVector2D mSize; + #ifdef __cplusplus aiLight() @@ -226,6 +241,7 @@ struct aiLight , mAttenuationQuadratic (0.f) , mAngleInnerCone ((float)AI_MATH_TWO_PI) , mAngleOuterCone ((float)AI_MATH_TWO_PI) + , mSize (0.f, 0.f) { } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a6c00dde1..0a9e10e40 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -54,6 +54,7 @@ SOURCE_GROUP( unit FILES SET( TEST_SRCS unit/AssimpAPITest.cpp + unit/utBlendImportAreaLight.cpp unit/utFastAtof.cpp unit/utFindDegenerates.cpp unit/utFindInvalidData.cpp diff --git a/test/models/BLEND/AreaLight_269.blend b/test/models/BLEND/AreaLight_269.blend new file mode 100644 index 000000000..9337d5799 Binary files /dev/null and b/test/models/BLEND/AreaLight_269.blend differ diff --git a/test/unit/utBlendImportAreaLight.cpp b/test/unit/utBlendImportAreaLight.cpp new file mode 100644 index 000000000..603a5e513 --- /dev/null +++ b/test/unit/utBlendImportAreaLight.cpp @@ -0,0 +1,113 @@ +/* +--------------------------------------------------------------------------- +Open Asset Import Library (assimp) +--------------------------------------------------------------------------- + +Copyright (c) 2006-2016, assimp team + +All rights reserved. + +Redistribution and use of this software in source and binary forms, +with or without modification, are permitted provided that the following +conditions are met: + +* Redistributions of source code must retain the above +copyright notice, this list of conditions and the +following disclaimer. + +* Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the +following disclaimer in the documentation and/or other +materials provided with the distribution. + +* Neither the name of the assimp team, nor the names of its +contributors may be used to endorse or promote products +derived from this software without specific prior +written permission of the assimp team. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--------------------------------------------------------------------------- +*/ +#include "UnitTestPCH.h" + +#include +#include +#include +#include + +class BlendImportAreaLight : public ::testing::Test { +public: + + virtual void SetUp() + { + im = new Assimp::Importer(); + } + + virtual void TearDown() + { + delete im; + } + +protected: + + Assimp::Importer* im; +}; + +// ------------------------------------------------------------------------------------------------ +TEST_F(BlendImportAreaLight, testImportLight) +{ + const aiScene* pTest = im->ReadFile(ASSIMP_TEST_MODELS_DIR "/BLEND/AreaLight_269.blend",0); + ASSERT_TRUE(pTest != NULL); + ASSERT_TRUE(pTest->HasLights()); + + std::vector< std::pair > lightNames; + + for (size_t i = 0; i < pTest->mNumLights; i++) { + lightNames.push_back(std::make_pair(pTest->mLights[i]->mName.C_Str(), i)); + } + + std::sort(lightNames.begin(), lightNames.end()); + + std::vector lights; + + for (size_t i = 0; i < pTest->mNumLights; ++i) { + lights.push_back(*pTest->mLights[lightNames[i].second]); + } + + ASSERT_STREQ(lights[0].mName.C_Str(), "Bar"); + ASSERT_STREQ(lights[1].mName.C_Str(), "Baz"); + ASSERT_STREQ(lights[2].mName.C_Str(), "Foo"); + + ASSERT_EQ(lights[0].mType, aiLightSource_AREA); + ASSERT_EQ(lights[1].mType, aiLightSource_POINT); + ASSERT_EQ(lights[2].mType, aiLightSource_AREA); + + EXPECT_FLOAT_EQ(lights[0].mSize.x, 0.5f); + EXPECT_FLOAT_EQ(lights[0].mSize.y, 2.0f); + EXPECT_FLOAT_EQ(lights[2].mSize.x, 1.0f); + EXPECT_FLOAT_EQ(lights[2].mSize.y, 1.0f); + + EXPECT_FLOAT_EQ(lights[0].mColorDiffuse.r, 42.0f); + EXPECT_FLOAT_EQ(lights[0].mColorDiffuse.g, 42.0f); + EXPECT_FLOAT_EQ(lights[0].mColorDiffuse.b, 42.0f); + EXPECT_FLOAT_EQ(lights[2].mColorDiffuse.r, 1.0f); + EXPECT_FLOAT_EQ(lights[2].mColorDiffuse.g, 1.0f); + EXPECT_FLOAT_EQ(lights[2].mColorDiffuse.b, 1.0f); + + EXPECT_FLOAT_EQ(lights[0].mDirection.x, 0.0f); + EXPECT_FLOAT_EQ(lights[0].mDirection.y, 0.0f); + EXPECT_FLOAT_EQ(lights[0].mDirection.z, -1.0f); + EXPECT_FLOAT_EQ(lights[2].mDirection.x, 0.0f); + EXPECT_FLOAT_EQ(lights[2].mDirection.y, 0.0f); + EXPECT_FLOAT_EQ(lights[2].mDirection.z, -1.0f); +}