Tuesday merger of bf-blender into orange branch.
This commit is contained in:
134
extern/bullet/Bullet/CollisionShapes/BvhTriangleMeshShape.cpp
vendored
Normal file
134
extern/bullet/Bullet/CollisionShapes/BvhTriangleMeshShape.cpp
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (c) 2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies.
|
||||
* Erwin Coumans makes no representations about the suitability
|
||||
* of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
//#define DISABLE_BVH
|
||||
|
||||
|
||||
#include "CollisionShapes/BvhTriangleMeshShape.h"
|
||||
#include "CollisionShapes/OptimizedBvh.h"
|
||||
|
||||
///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization.
|
||||
///Uses an interface to access the triangles to allow for sharing graphics/physics triangles.
|
||||
BvhTriangleMeshShape::BvhTriangleMeshShape(StridingMeshInterface* meshInterface)
|
||||
:TriangleMeshShape(meshInterface)
|
||||
{
|
||||
//construct bvh from meshInterface
|
||||
#ifndef DISABLE_BVH
|
||||
|
||||
m_bvh = new OptimizedBvh();
|
||||
m_bvh->Build(meshInterface);
|
||||
|
||||
#endif //DISABLE_BVH
|
||||
|
||||
}
|
||||
|
||||
BvhTriangleMeshShape::~BvhTriangleMeshShape()
|
||||
{
|
||||
delete m_bvh;
|
||||
}
|
||||
|
||||
//perform bvh tree traversal and report overlapping triangles to 'callback'
|
||||
void BvhTriangleMeshShape::ProcessAllTriangles(TriangleCallback* callback,const SimdVector3& aabbMin,const SimdVector3& aabbMax) const
|
||||
{
|
||||
|
||||
#ifdef DISABLE_BVH
|
||||
//brute force traverse all triangles
|
||||
TriangleMeshShape::ProcessAllTriangles(callback,aabbMin,aabbMax);
|
||||
#else
|
||||
|
||||
//first get all the nodes
|
||||
|
||||
|
||||
struct MyNodeOverlapCallback : public NodeOverlapCallback
|
||||
{
|
||||
StridingMeshInterface* m_meshInterface;
|
||||
TriangleCallback* m_callback;
|
||||
SimdVector3 m_triangle[3];
|
||||
|
||||
|
||||
MyNodeOverlapCallback(TriangleCallback* callback,StridingMeshInterface* meshInterface)
|
||||
:m_callback(callback),
|
||||
m_meshInterface(meshInterface)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void ProcessNode(const OptimizedBvhNode* node)
|
||||
{
|
||||
const unsigned char *vertexbase;
|
||||
int numverts;
|
||||
PHY_ScalarType type;
|
||||
int stride;
|
||||
const unsigned char *indexbase;
|
||||
int indexstride;
|
||||
int numfaces;
|
||||
PHY_ScalarType indicestype;
|
||||
|
||||
|
||||
m_meshInterface->getLockedReadOnlyVertexIndexBase(
|
||||
&vertexbase,
|
||||
numverts,
|
||||
type,
|
||||
stride,
|
||||
&indexbase,
|
||||
indexstride,
|
||||
numfaces,
|
||||
indicestype,
|
||||
node->m_subPart);
|
||||
|
||||
int* gfxbase = (int*)(indexbase+node->m_triangleIndex*indexstride);
|
||||
|
||||
const SimdVector3& meshScaling = m_meshInterface->getScaling();
|
||||
for (int j=2;j>=0;j--)
|
||||
{
|
||||
|
||||
int graphicsindex = gfxbase[j];
|
||||
#ifdef DEBUG_TRIANGLE_MESH
|
||||
printf("%d ,",graphicsindex);
|
||||
#endif //DEBUG_TRIANGLE_MESH
|
||||
float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
|
||||
|
||||
m_triangle[j] = SimdVector3(
|
||||
graphicsbase[0]*meshScaling.getX(),
|
||||
graphicsbase[1]*meshScaling.getY(),
|
||||
graphicsbase[2]*meshScaling.getZ());
|
||||
#ifdef DEBUG_TRIANGLE_MESH
|
||||
printf("triangle vertices:%f,%f,%f\n",triangle[j].x(),triangle[j].y(),triangle[j].z());
|
||||
#endif //DEBUG_TRIANGLE_MESH
|
||||
}
|
||||
|
||||
m_callback->ProcessTriangle(m_triangle);
|
||||
m_meshInterface->unLockReadOnlyVertexBase(node->m_subPart);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
MyNodeOverlapCallback myNodeCallback(callback,m_meshInterface);
|
||||
|
||||
m_bvh->ReportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
|
||||
|
||||
|
||||
#endif//DISABLE_BVH
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void BvhTriangleMeshShape::setLocalScaling(const SimdVector3& scaling)
|
||||
{
|
||||
if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
|
||||
{
|
||||
TriangleMeshShape::setLocalScaling(scaling);
|
||||
delete m_bvh;
|
||||
m_bvh = new OptimizedBvh();
|
||||
m_bvh->Build(m_meshInterface);
|
||||
//rebuild the bvh...
|
||||
}
|
||||
}
|
||||
53
extern/bullet/Bullet/CollisionShapes/BvhTriangleMeshShape.h
vendored
Normal file
53
extern/bullet/Bullet/CollisionShapes/BvhTriangleMeshShape.h
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies.
|
||||
* Erwin Coumans makes no representations about the suitability
|
||||
* of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
#ifndef BVH_TRIANGLE_MESH_SHAPE_H
|
||||
#define BVH_TRIANGLE_MESH_SHAPE_H
|
||||
|
||||
#include "CollisionShapes/TriangleMeshShape.h"
|
||||
#include "CollisionShapes/OptimizedBvh.h"
|
||||
|
||||
///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization.
|
||||
///Uses an interface to access the triangles to allow for sharing graphics/physics triangles.
|
||||
class BvhTriangleMeshShape : public TriangleMeshShape
|
||||
{
|
||||
|
||||
OptimizedBvh* m_bvh;
|
||||
|
||||
|
||||
public:
|
||||
BvhTriangleMeshShape(StridingMeshInterface* meshInterface);
|
||||
|
||||
virtual ~BvhTriangleMeshShape();
|
||||
|
||||
|
||||
/*
|
||||
virtual int GetShapeType() const
|
||||
{
|
||||
return TRIANGLE_MESH_SHAPE_PROXYTYPE;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
virtual void ProcessAllTriangles(TriangleCallback* callback,const SimdVector3& aabbMin,const SimdVector3& aabbMax) const;
|
||||
|
||||
|
||||
//debugging
|
||||
virtual char* GetName()const {return "BVHTRIANGLEMESH";}
|
||||
|
||||
|
||||
virtual void setLocalScaling(const SimdVector3& scaling);
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif //BVH_TRIANGLE_MESH_SHAPE_H
|
||||
11
extern/bullet/Bullet/CollisionShapes/CollisionMargin.h
vendored
Normal file
11
extern/bullet/Bullet/CollisionShapes/CollisionMargin.h
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef COLLISION_MARGIN_H
|
||||
#define COLLISION_MARGIN_H
|
||||
|
||||
//used by Gjk and some other algorithms
|
||||
|
||||
#define CONVEX_DISTANCE_MARGIN 0.04f// 0.1f//;//0.01f
|
||||
|
||||
|
||||
|
||||
#endif //COLLISION_MARGIN_H
|
||||
|
||||
86
extern/bullet/Bullet/CollisionShapes/ConvexTriangleCallback.cpp
vendored
Normal file
86
extern/bullet/Bullet/CollisionShapes/ConvexTriangleCallback.cpp
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
#include "ConvexTriangleCallback.h"
|
||||
#include "NarrowPhaseCollision/PersistentManifold.h"
|
||||
#include "NarrowPhaseCollision/ManifoldContactAddResult.h"
|
||||
#include "NarrowPhaseCollision/GjkPairDetector.h"
|
||||
#include "NarrowPhaseCollision/MinkowskiPenetrationDepthSolver.h"
|
||||
|
||||
|
||||
|
||||
#include "TriangleShape.h"
|
||||
|
||||
//m_manifoldPtr = m_dispatcher->GetNewManifold(proxy0->m_clientObject,proxy1->m_clientObject);
|
||||
//m_dispatcher->ReleaseManifold( m_manifoldPtr );
|
||||
|
||||
ConvexTriangleCallback::ConvexTriangleCallback(PersistentManifold* manifold,ConvexShape* convexShape,const SimdTransform&convexTransform,const SimdTransform& triangleMeshTransform)
|
||||
:m_triangleMeshTransform(triangleMeshTransform),
|
||||
m_convexTransform(convexTransform),
|
||||
m_convexShape(convexShape),
|
||||
m_manifoldPtr(manifold),
|
||||
m_triangleCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
ConvexTriangleCallback::~ConvexTriangleCallback()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ConvexTriangleCallback::ClearCache()
|
||||
{
|
||||
m_manifoldPtr->ClearManifold();
|
||||
};
|
||||
|
||||
|
||||
|
||||
void ConvexTriangleCallback::ProcessTriangle(SimdVector3* triangle)
|
||||
{
|
||||
|
||||
//triangle, convex
|
||||
TriangleShape tm(triangle[0],triangle[1],triangle[2]);
|
||||
tm.SetMargin(m_collisionMarginTriangle);
|
||||
GjkPairDetector::ClosestPointInput input;
|
||||
input.m_transformA = m_triangleMeshTransform;
|
||||
input.m_transformB = m_convexTransform;
|
||||
|
||||
ManifoldContactAddResult output(m_triangleMeshTransform,m_convexTransform,m_manifoldPtr);
|
||||
|
||||
|
||||
VoronoiSimplexSolver simplexSolver;
|
||||
MinkowskiPenetrationDepthSolver penetrationDepthSolver;
|
||||
|
||||
GjkPairDetector gjkDetector(&tm,m_convexShape,&simplexSolver,&penetrationDepthSolver);
|
||||
|
||||
gjkDetector.SetMinkowskiA(&tm);
|
||||
gjkDetector.SetMinkowskiB(m_convexShape);
|
||||
input.m_maximumDistanceSquared = tm.GetMargin()+ m_convexShape->GetMargin() + m_manifoldPtr->GetManifoldMargin();
|
||||
input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared;
|
||||
|
||||
input.m_maximumDistanceSquared = 1e30f;//?
|
||||
|
||||
|
||||
gjkDetector.GetClosestPoints(input,output);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ConvexTriangleCallback::Update(float collisionMarginTriangle)
|
||||
{
|
||||
m_triangleCount = 0;
|
||||
m_collisionMarginTriangle = collisionMarginTriangle;
|
||||
|
||||
SimdTransform boxInTriangleSpace;
|
||||
boxInTriangleSpace = m_triangleMeshTransform.inverse() * m_convexTransform;
|
||||
|
||||
m_convexShape->GetAabb(boxInTriangleSpace,m_aabbMin,m_aabbMax);
|
||||
|
||||
float extraMargin = CONVEX_DISTANCE_MARGIN;
|
||||
|
||||
SimdVector3 extra(extraMargin,extraMargin,extraMargin);
|
||||
|
||||
m_aabbMax += extra;
|
||||
m_aabbMin -= extra;
|
||||
|
||||
}
|
||||
49
extern/bullet/Bullet/CollisionShapes/ConvexTriangleCallback.h
vendored
Normal file
49
extern/bullet/Bullet/CollisionShapes/ConvexTriangleCallback.h
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
#ifndef CONVEX_TRIANGLE_CALLBACK_H
|
||||
#define CONVEX_TRIANGLE_CALLBACK_H
|
||||
|
||||
#include "TriangleCallback.h"
|
||||
class ConvexShape;
|
||||
class PersistentManifold;
|
||||
#include "SimdTransform.h"
|
||||
///ConvexTriangleCallback processes the narrowphase convex-triangle collision detection
|
||||
class ConvexTriangleCallback: public TriangleCallback
|
||||
{
|
||||
SimdVector3 m_aabbMin;
|
||||
SimdVector3 m_aabbMax ;
|
||||
|
||||
SimdTransform m_triangleMeshTransform;
|
||||
SimdTransform m_convexTransform;
|
||||
|
||||
// bool m_useContinuous;
|
||||
float m_collisionMarginTriangle;
|
||||
|
||||
public:
|
||||
int m_triangleCount;
|
||||
|
||||
ConvexShape* m_convexShape;
|
||||
|
||||
PersistentManifold* m_manifoldPtr;
|
||||
|
||||
ConvexTriangleCallback(PersistentManifold* manifold,ConvexShape* convexShape,const SimdTransform&convexTransform,const SimdTransform& triangleMeshTransform);
|
||||
|
||||
void Update(float collisionMarginTriangle);
|
||||
|
||||
virtual ~ConvexTriangleCallback();
|
||||
|
||||
virtual void ProcessTriangle(SimdVector3* triangle);
|
||||
|
||||
void ClearCache();
|
||||
|
||||
inline const SimdVector3& GetAabbMin() const
|
||||
{
|
||||
return m_aabbMin;
|
||||
}
|
||||
inline const SimdVector3& GetAabbMax() const
|
||||
{
|
||||
return m_aabbMax;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif //CONVEX_TRIANGLE_CALLBACK_H
|
||||
45
extern/bullet/Bullet/CollisionShapes/EmptyShape.cpp
vendored
Normal file
45
extern/bullet/Bullet/CollisionShapes/EmptyShape.cpp
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies.
|
||||
* Erwin Coumans makes no representations about the suitability
|
||||
* of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include "EmptyShape.h"
|
||||
|
||||
|
||||
#include "CollisionShape.h"
|
||||
|
||||
|
||||
EmptyShape::EmptyShape()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
EmptyShape::~EmptyShape()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
///GetAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
|
||||
void EmptyShape::GetAabb(const SimdTransform& t,SimdVector3& aabbMin,SimdVector3& aabbMax) const
|
||||
{
|
||||
SimdVector3 margin(GetMargin(),GetMargin(),GetMargin());
|
||||
|
||||
aabbMin = t.getOrigin() - margin;
|
||||
|
||||
aabbMax = t.getOrigin() + margin;
|
||||
|
||||
}
|
||||
|
||||
void EmptyShape::CalculateLocalInertia(SimdScalar mass,SimdVector3& inertia)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
75
extern/bullet/Bullet/CollisionShapes/EmptyShape.h
vendored
Normal file
75
extern/bullet/Bullet/CollisionShapes/EmptyShape.h
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies.
|
||||
* Erwin Coumans makes no representations about the suitability
|
||||
* of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
#ifndef EMPTY_SHAPE_H
|
||||
#define EMPTY_SHAPE_H
|
||||
|
||||
#include "CollisionShape.h"
|
||||
|
||||
#include "SimdVector3.h"
|
||||
#include "SimdTransform.h"
|
||||
#include "SimdMatrix3x3.h"
|
||||
#include <vector>
|
||||
#include "CollisionShapes/CollisionMargin.h"
|
||||
|
||||
|
||||
|
||||
|
||||
/// EmptyShape is a collision shape without actual collision detection. It can be replaced by another shape during runtime
|
||||
class EmptyShape : public CollisionShape
|
||||
{
|
||||
public:
|
||||
EmptyShape();
|
||||
|
||||
virtual ~EmptyShape();
|
||||
|
||||
|
||||
///GetAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
|
||||
void GetAabb(const SimdTransform& t,SimdVector3& aabbMin,SimdVector3& aabbMax) const;
|
||||
|
||||
|
||||
virtual void setLocalScaling(const SimdVector3& scaling)
|
||||
{
|
||||
m_localScaling = scaling;
|
||||
}
|
||||
virtual const SimdVector3& getLocalScaling() const
|
||||
{
|
||||
return m_localScaling;
|
||||
}
|
||||
|
||||
virtual void CalculateLocalInertia(SimdScalar mass,SimdVector3& inertia);
|
||||
|
||||
virtual int GetShapeType() const { return EMPTY_SHAPE_PROXYTYPE;}
|
||||
|
||||
virtual void SetMargin(float margin)
|
||||
{
|
||||
m_collisionMargin = margin;
|
||||
}
|
||||
virtual float GetMargin() const
|
||||
{
|
||||
return m_collisionMargin;
|
||||
}
|
||||
virtual char* GetName()const
|
||||
{
|
||||
return "Empty";
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
SimdScalar m_collisionMargin;
|
||||
protected:
|
||||
SimdVector3 m_localScaling;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif //EMPTY_SHAPE_H
|
||||
268
extern/bullet/Bullet/CollisionShapes/OptimizedBvh.cpp
vendored
Normal file
268
extern/bullet/Bullet/CollisionShapes/OptimizedBvh.cpp
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
* Copyright (c) 2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies.
|
||||
* Erwin Coumans makes no representations about the suitability
|
||||
* of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include "OptimizedBvh.h"
|
||||
#include "StridingMeshInterface.h"
|
||||
#include "AabbUtil2.h"
|
||||
|
||||
|
||||
|
||||
void OptimizedBvh::Build(StridingMeshInterface* triangles)
|
||||
{
|
||||
int countTriangles = 0;
|
||||
|
||||
|
||||
|
||||
// NodeArray triangleNodes;
|
||||
|
||||
struct NodeTriangleCallback : public InternalTriangleIndexCallback
|
||||
{
|
||||
NodeArray& m_triangleNodes;
|
||||
|
||||
NodeTriangleCallback(NodeArray& triangleNodes)
|
||||
:m_triangleNodes(triangleNodes)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
virtual void InternalProcessTriangleIndex(SimdVector3* triangle,int partId,int triangleIndex)
|
||||
{
|
||||
|
||||
OptimizedBvhNode node;
|
||||
node.m_aabbMin = SimdVector3(1e30f,1e30f,1e30f);
|
||||
node.m_aabbMax = SimdVector3(-1e30f,-1e30f,-1e30f);
|
||||
node.m_aabbMin.setMin(triangle[0]);
|
||||
node.m_aabbMax.setMax(triangle[0]);
|
||||
node.m_aabbMin.setMin(triangle[1]);
|
||||
node.m_aabbMax.setMax(triangle[1]);
|
||||
node.m_aabbMin.setMin(triangle[2]);
|
||||
node.m_aabbMax.setMax(triangle[2]);
|
||||
|
||||
node.m_escapeIndex = -1;
|
||||
node.m_leftChild = 0;
|
||||
node.m_rightChild = 0;
|
||||
|
||||
|
||||
//for child nodes
|
||||
node.m_subPart = partId;
|
||||
node.m_triangleIndex = triangleIndex;
|
||||
|
||||
|
||||
m_triangleNodes.push_back(node);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
NodeTriangleCallback callback(m_leafNodes);
|
||||
|
||||
SimdVector3 aabbMin(-1e30f,-1e30f,-1e30f);
|
||||
SimdVector3 aabbMax(1e30f,1e30f,1e30f);
|
||||
|
||||
triangles->InternalProcessAllTriangles(&callback,aabbMin,aabbMax);
|
||||
|
||||
//now we have an array of leafnodes in m_leafNodes
|
||||
|
||||
m_contiguousNodes = new OptimizedBvhNode[2*m_leafNodes.size()];
|
||||
m_curNodeIndex = 0;
|
||||
|
||||
m_rootNode1 = BuildTree(m_leafNodes,0,m_leafNodes.size());
|
||||
|
||||
|
||||
///create the leafnodes first
|
||||
// OptimizedBvhNode* leafNodes = new OptimizedBvhNode;
|
||||
}
|
||||
|
||||
|
||||
OptimizedBvhNode* OptimizedBvh::BuildTree (NodeArray& leafNodes,int startIndex,int endIndex)
|
||||
{
|
||||
|
||||
int numIndices =endIndex-startIndex;
|
||||
assert(numIndices>0);
|
||||
|
||||
int curIndex = m_curNodeIndex;
|
||||
|
||||
if (numIndices==1)
|
||||
{
|
||||
return new (&m_contiguousNodes[m_curNodeIndex++]) OptimizedBvhNode(leafNodes[startIndex]);
|
||||
}
|
||||
//calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
|
||||
|
||||
int splitAxis = CalcSplittingAxis(leafNodes,startIndex,endIndex);
|
||||
|
||||
int splitIndex = SortAndCalcSplittingIndex(leafNodes,startIndex,endIndex,splitAxis);
|
||||
|
||||
OptimizedBvhNode* internalNode = &m_contiguousNodes[m_curNodeIndex++];
|
||||
|
||||
internalNode->m_aabbMax.setValue(-1e30f,-1e30f,-1e30f);
|
||||
internalNode->m_aabbMin.setValue(1e30f,1e30f,1e30f);
|
||||
|
||||
for (int i=startIndex;i<endIndex;i++)
|
||||
{
|
||||
internalNode->m_aabbMax.setMax(leafNodes[i].m_aabbMax);
|
||||
internalNode->m_aabbMin.setMin(leafNodes[i].m_aabbMin);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//internalNode->m_escapeIndex;
|
||||
internalNode->m_leftChild = BuildTree(leafNodes,startIndex,splitIndex);
|
||||
internalNode->m_rightChild = BuildTree(leafNodes,splitIndex,endIndex);
|
||||
|
||||
internalNode->m_escapeIndex = m_curNodeIndex - curIndex;
|
||||
return internalNode;
|
||||
}
|
||||
|
||||
int OptimizedBvh::SortAndCalcSplittingIndex(NodeArray& leafNodes,int startIndex,int endIndex,int splitAxis)
|
||||
{
|
||||
int splitIndex =startIndex;
|
||||
int numIndices = endIndex - startIndex;
|
||||
|
||||
SimdVector3 means(0.f,0.f,0.f);
|
||||
for (int i=startIndex;i<endIndex;i++)
|
||||
{
|
||||
SimdVector3 center = 0.5f*(leafNodes[i].m_aabbMax+leafNodes[i].m_aabbMin);
|
||||
means+=center;
|
||||
}
|
||||
means *= (1.f/(float)numIndices);
|
||||
|
||||
float splitValue = means[splitAxis];
|
||||
|
||||
//sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
|
||||
for (int i=startIndex;i<endIndex;i++)
|
||||
{
|
||||
SimdVector3 center = 0.5f*(leafNodes[i].m_aabbMax+leafNodes[i].m_aabbMin);
|
||||
if (center[splitAxis] > splitValue)
|
||||
{
|
||||
//swap
|
||||
OptimizedBvhNode tmp = leafNodes[i];
|
||||
leafNodes[i] = leafNodes[splitIndex];
|
||||
leafNodes[splitIndex] = tmp;
|
||||
splitIndex++;
|
||||
}
|
||||
}
|
||||
if ((splitIndex==startIndex) || (splitIndex == (endIndex-1)))
|
||||
{
|
||||
splitIndex = startIndex+ (numIndices>>1);
|
||||
}
|
||||
return splitIndex;
|
||||
}
|
||||
|
||||
|
||||
int OptimizedBvh::CalcSplittingAxis(NodeArray& leafNodes,int startIndex,int endIndex)
|
||||
{
|
||||
SimdVector3 means(0.f,0.f,0.f);
|
||||
int numIndices = endIndex-startIndex;
|
||||
|
||||
for (int i=startIndex;i<endIndex;i++)
|
||||
{
|
||||
SimdVector3 center = 0.5f*(leafNodes[i].m_aabbMax+leafNodes[i].m_aabbMin);
|
||||
means+=center;
|
||||
}
|
||||
means *= (1.f/(float)numIndices);
|
||||
|
||||
SimdVector3 variance(0.f,0.f,0.f);
|
||||
|
||||
for (int i=startIndex;i<endIndex;i++)
|
||||
{
|
||||
SimdVector3 center = 0.5f*(leafNodes[i].m_aabbMax+leafNodes[i].m_aabbMin);
|
||||
SimdVector3 diff2 = center-means;
|
||||
diff2 = diff2 * diff2;
|
||||
variance += diff2;
|
||||
}
|
||||
variance *= (1.f/ ((float)numIndices-1) );
|
||||
|
||||
int biggestAxis = variance.maxAxis();
|
||||
return biggestAxis;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void OptimizedBvh::ReportAabbOverlappingNodex(NodeOverlapCallback* nodeCallback,const SimdVector3& aabbMin,const SimdVector3& aabbMax) const
|
||||
{
|
||||
if (aabbMin.length() > 1000.f)
|
||||
{
|
||||
for (int i=0;i<m_leafNodes.size();i++)
|
||||
{
|
||||
const OptimizedBvhNode& node = m_leafNodes[i];
|
||||
nodeCallback->ProcessNode(&node);
|
||||
}
|
||||
} else
|
||||
{
|
||||
//WalkTree(m_rootNode1,nodeCallback,aabbMin,aabbMax);
|
||||
WalkStacklessTree(m_rootNode1,nodeCallback,aabbMin,aabbMax);
|
||||
}
|
||||
}
|
||||
|
||||
void OptimizedBvh::WalkTree(OptimizedBvhNode* rootNode,NodeOverlapCallback* nodeCallback,const SimdVector3& aabbMin,const SimdVector3& aabbMax) const
|
||||
{
|
||||
bool aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMin,rootNode->m_aabbMax);
|
||||
if (aabbOverlap)
|
||||
{
|
||||
bool isLeafNode = (!rootNode->m_leftChild && !rootNode->m_rightChild);
|
||||
if (isLeafNode)
|
||||
{
|
||||
nodeCallback->ProcessNode(rootNode);
|
||||
} else
|
||||
{
|
||||
WalkTree(rootNode->m_leftChild,nodeCallback,aabbMin,aabbMax);
|
||||
WalkTree(rootNode->m_rightChild,nodeCallback,aabbMin,aabbMax);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int maxIterations = 0;
|
||||
|
||||
void OptimizedBvh::WalkStacklessTree(OptimizedBvhNode* rootNode,NodeOverlapCallback* nodeCallback,const SimdVector3& aabbMin,const SimdVector3& aabbMax) const
|
||||
{
|
||||
int curIndex = 0;
|
||||
int walkIterations = 0;
|
||||
|
||||
while (curIndex < m_curNodeIndex)
|
||||
{
|
||||
//catch bugs in tree data
|
||||
assert (walkIterations < m_curNodeIndex);
|
||||
|
||||
walkIterations++;
|
||||
bool aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMin,rootNode->m_aabbMax);
|
||||
bool isLeafNode = (!rootNode->m_leftChild && !rootNode->m_rightChild);
|
||||
|
||||
if (isLeafNode && aabbOverlap)
|
||||
{
|
||||
nodeCallback->ProcessNode(rootNode);
|
||||
}
|
||||
|
||||
if (aabbOverlap || isLeafNode)
|
||||
{
|
||||
rootNode++;
|
||||
curIndex++;
|
||||
} else
|
||||
{
|
||||
int escapeIndex = rootNode->m_escapeIndex;
|
||||
rootNode += escapeIndex;
|
||||
curIndex += escapeIndex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (maxIterations < walkIterations)
|
||||
maxIterations = walkIterations;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void OptimizedBvh::ReportSphereOverlappingNodex(NodeOverlapCallback* nodeCallback,const SimdVector3& aabbMin,const SimdVector3& aabbMax) const
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
92
extern/bullet/Bullet/CollisionShapes/OptimizedBvh.h
vendored
Normal file
92
extern/bullet/Bullet/CollisionShapes/OptimizedBvh.h
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies.
|
||||
* Erwin Coumans makes no representations about the suitability
|
||||
* of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
#ifndef OPTIMIZED_BVH_H
|
||||
#define OPTIMIZED_BVH_H
|
||||
#include "SimdVector3.h"
|
||||
#include <vector>
|
||||
|
||||
class StridingMeshInterface;
|
||||
|
||||
/// OptimizedBvhNode contains both internal and leaf node information.
|
||||
/// It hasn't been optimized yet for storage. Some obvious optimizations are:
|
||||
/// Removal of the pointers (can already be done, they are not used for traversal)
|
||||
/// and storing aabbmin/max as quantized integers.
|
||||
/// 'subpart' doesn't need an integer either. It allows to re-use graphics triangle
|
||||
/// meshes stored in a non-uniform way (like batches/subparts of triangle-fans
|
||||
struct OptimizedBvhNode
|
||||
{
|
||||
|
||||
SimdVector3 m_aabbMin;
|
||||
SimdVector3 m_aabbMax;
|
||||
|
||||
//these 2 pointers are obsolete, the stackless traversal just uses the escape index
|
||||
OptimizedBvhNode* m_leftChild;
|
||||
OptimizedBvhNode* m_rightChild;
|
||||
|
||||
int m_escapeIndex;
|
||||
|
||||
//for child nodes
|
||||
int m_subPart;
|
||||
int m_triangleIndex;
|
||||
|
||||
};
|
||||
|
||||
class NodeOverlapCallback
|
||||
{
|
||||
public:
|
||||
virtual void ProcessNode(const OptimizedBvhNode* node) = 0;
|
||||
};
|
||||
|
||||
typedef std::vector<OptimizedBvhNode> NodeArray;
|
||||
|
||||
|
||||
///OptimizedBvh store an AABB tree that can be quickly traversed on CPU (and SPU,GPU in future)
|
||||
class OptimizedBvh
|
||||
{
|
||||
OptimizedBvhNode* m_rootNode1;
|
||||
|
||||
OptimizedBvhNode* m_contiguousNodes;
|
||||
int m_curNodeIndex;
|
||||
|
||||
int m_numNodes;
|
||||
|
||||
NodeArray m_leafNodes;
|
||||
|
||||
public:
|
||||
OptimizedBvh() :m_rootNode1(0), m_numNodes(0) { }
|
||||
|
||||
void Build(StridingMeshInterface* triangles);
|
||||
|
||||
OptimizedBvhNode* BuildTree (NodeArray& leafNodes,int startIndex,int endIndex);
|
||||
|
||||
int CalcSplittingAxis(NodeArray& leafNodes,int startIndex,int endIndex);
|
||||
|
||||
int SortAndCalcSplittingIndex(NodeArray& leafNodes,int startIndex,int endIndex,int splitAxis);
|
||||
|
||||
void WalkTree(OptimizedBvhNode* rootNode,NodeOverlapCallback* nodeCallback,const SimdVector3& aabbMin,const SimdVector3& aabbMax) const;
|
||||
|
||||
void WalkStacklessTree(OptimizedBvhNode* rootNode,NodeOverlapCallback* nodeCallback,const SimdVector3& aabbMin,const SimdVector3& aabbMax) const;
|
||||
|
||||
|
||||
//OptimizedBvhNode* GetRootNode() { return m_rootNode1;}
|
||||
|
||||
int GetNumNodes() { return m_numNodes;}
|
||||
|
||||
void ReportAabbOverlappingNodex(NodeOverlapCallback* nodeCallback,const SimdVector3& aabbMin,const SimdVector3& aabbMax) const;
|
||||
|
||||
void ReportSphereOverlappingNodex(NodeOverlapCallback* nodeCallback,const SimdVector3& aabbMin,const SimdVector3& aabbMax) const;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif //OPTIMIZED_BVH_H
|
||||
23
extern/bullet/Bullet/CollisionShapes/TriangleCallback.cpp
vendored
Normal file
23
extern/bullet/Bullet/CollisionShapes/TriangleCallback.cpp
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies.
|
||||
* Erwin Coumans makes no representations about the suitability
|
||||
* of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include "TriangleCallback.h"
|
||||
|
||||
TriangleCallback::~TriangleCallback()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
InternalTriangleIndexCallback::~InternalTriangleIndexCallback()
|
||||
{
|
||||
|
||||
}
|
||||
49
extern/bullet/Bullet/CollisionShapes/TriangleIndexVertexArray.cpp
vendored
Normal file
49
extern/bullet/Bullet/CollisionShapes/TriangleIndexVertexArray.cpp
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies.
|
||||
* Erwin Coumans makes no representations about the suitability
|
||||
* of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include "TriangleIndexVertexArray.h"
|
||||
|
||||
TriangleIndexVertexArray::TriangleIndexVertexArray(int numTriangleIndices,int* triangleIndexBase,int triangleIndexStride,int numVertices,float* vertexBase,int vertexStride)
|
||||
:m_numTriangleIndices(numTriangleIndices),
|
||||
m_triangleIndexBase(triangleIndexBase),
|
||||
m_triangleIndexStride(triangleIndexStride),
|
||||
m_numVertices(numVertices),
|
||||
m_vertexBase(vertexBase),
|
||||
m_vertexStride(vertexStride)
|
||||
{
|
||||
}
|
||||
|
||||
void TriangleIndexVertexArray::getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart)
|
||||
{
|
||||
numverts = m_numVertices;
|
||||
(*vertexbase) = (unsigned char *)m_vertexBase;
|
||||
type = PHY_FLOAT;
|
||||
vertexStride = m_vertexStride;
|
||||
|
||||
numfaces = m_numTriangleIndices;
|
||||
(*indexbase) = (unsigned char *)m_triangleIndexBase;
|
||||
indexstride = m_triangleIndexStride;
|
||||
indicestype = PHY_INTEGER;
|
||||
}
|
||||
|
||||
void TriangleIndexVertexArray::getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) const
|
||||
{
|
||||
numverts = m_numVertices;
|
||||
(*vertexbase) = (unsigned char *)m_vertexBase;
|
||||
type = PHY_FLOAT;
|
||||
vertexStride = m_vertexStride;
|
||||
|
||||
numfaces = m_numTriangleIndices;
|
||||
(*indexbase) = (unsigned char *)m_triangleIndexBase;
|
||||
indexstride = m_triangleIndexStride;
|
||||
indicestype = PHY_INTEGER;
|
||||
}
|
||||
|
||||
46
extern/bullet/Bullet/CollisionShapes/TriangleIndexVertexArray.h
vendored
Normal file
46
extern/bullet/Bullet/CollisionShapes/TriangleIndexVertexArray.h
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2006 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies.
|
||||
* Erwin Coumans makes no representations about the suitability
|
||||
* of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
#include "StridingMeshInterface.h"
|
||||
|
||||
|
||||
class TriangleIndexVertexArray : public StridingMeshInterface
|
||||
{
|
||||
|
||||
int m_numTriangleIndices;
|
||||
int* m_triangleIndexBase;
|
||||
int m_triangleIndexStride;
|
||||
int m_numVertices;
|
||||
float* m_vertexBase;
|
||||
int m_vertexStride;
|
||||
|
||||
public:
|
||||
|
||||
TriangleIndexVertexArray(int numTriangleIndices,int* triangleIndexBase,int triangleIndexStride,int numVertices,float* vertexBase,int vertexStride);
|
||||
|
||||
virtual void getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0);
|
||||
|
||||
virtual void getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const;
|
||||
|
||||
/// unLockVertexBase finishes the access to a subpart of the triangle mesh
|
||||
/// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
|
||||
virtual void unLockVertexBase(int subpart) {}
|
||||
|
||||
virtual void unLockReadOnlyVertexBase(int subpart) const {}
|
||||
|
||||
/// getNumSubParts returns the number of seperate subparts
|
||||
/// each subpart has a continuous array of vertices and indices
|
||||
virtual int getNumSubParts() const { return 1;}
|
||||
|
||||
virtual void preallocateVertices(int numverts){}
|
||||
virtual void preallocateIndices(int numindices){}
|
||||
|
||||
};
|
||||
33
extern/bullet/Bullet/NarrowPhaseCollision/ManifoldContactAddResult.cpp
vendored
Normal file
33
extern/bullet/Bullet/NarrowPhaseCollision/ManifoldContactAddResult.cpp
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
|
||||
#include "ManifoldContactAddResult.h"
|
||||
#include "NarrowPhaseCollision/PersistentManifold.h"
|
||||
|
||||
ManifoldContactAddResult::ManifoldContactAddResult(SimdTransform transA,SimdTransform transB,PersistentManifold* manifoldPtr)
|
||||
:m_manifoldPtr(manifoldPtr)
|
||||
{
|
||||
m_transAInv = transA.inverse();
|
||||
m_transBInv = transB.inverse();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ManifoldContactAddResult::AddContactPoint(const SimdVector3& normalOnBInWorld,const SimdVector3& pointInWorld,float depth)
|
||||
{
|
||||
if (depth > m_manifoldPtr->GetManifoldMargin())
|
||||
return;
|
||||
|
||||
|
||||
SimdVector3 pointA = pointInWorld + normalOnBInWorld * depth;
|
||||
SimdVector3 localA = m_transAInv(pointA );
|
||||
SimdVector3 localB = m_transBInv(pointInWorld);
|
||||
ManifoldPoint newPt(localA,localB,normalOnBInWorld,depth);
|
||||
|
||||
int insertIndex = m_manifoldPtr->GetCacheEntry(newPt);
|
||||
if (insertIndex >= 0)
|
||||
{
|
||||
m_manifoldPtr->ReplaceContactPoint(newPt,insertIndex);
|
||||
} else
|
||||
{
|
||||
m_manifoldPtr->AddManifoldPoint(newPt);
|
||||
}
|
||||
}
|
||||
32
extern/bullet/Bullet/NarrowPhaseCollision/ManifoldContactAddResult.h
vendored
Normal file
32
extern/bullet/Bullet/NarrowPhaseCollision/ManifoldContactAddResult.h
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/
|
||||
*
|
||||
* Permission to use, copy, modify, distribute and sell this software
|
||||
* and its documentation for any purpose is hereby granted without fee,
|
||||
* provided that the above copyright notice appear in all copies.
|
||||
* Erwin Coumans makes no representations about the suitability
|
||||
* of this software for any purpose.
|
||||
* It is provided "as is" without express or implied warranty.
|
||||
*/
|
||||
|
||||
#ifndef MANIFOLD_CONTACT_ADD_RESULT_H
|
||||
#define MANIFOLD_CONTACT_ADD_RESULT_H
|
||||
|
||||
#include "NarrowPhaseCollision/DiscreteCollisionDetectorInterface.h"
|
||||
class PersistentManifold;
|
||||
|
||||
class ManifoldContactAddResult : public DiscreteCollisionDetectorInterface::Result
|
||||
{
|
||||
PersistentManifold* m_manifoldPtr;
|
||||
SimdTransform m_transAInv;
|
||||
SimdTransform m_transBInv;
|
||||
|
||||
public:
|
||||
|
||||
ManifoldContactAddResult(SimdTransform transA,SimdTransform transB,PersistentManifold* manifoldPtr);
|
||||
|
||||
virtual void AddContactPoint(const SimdVector3& normalOnBInWorld,const SimdVector3& pointInWorld,float depth);
|
||||
|
||||
};
|
||||
|
||||
#endif //MANIFOLD_CONTACT_ADD_RESULT_H
|
||||
673
release/scripts/3ds_export.py
Normal file
673
release/scripts/3ds_export.py
Normal file
@@ -0,0 +1,673 @@
|
||||
#!BPY
|
||||
|
||||
"""
|
||||
Name: '3D Studio (.3ds)...'
|
||||
Blender: 237
|
||||
Group: 'Export'
|
||||
Tooltip: 'Export to 3DS file format (.3ds).'
|
||||
"""
|
||||
|
||||
__author__ = ["Campbell Barton", "Bob Holcomb", "Richard L<>rk<72>ng", "Damien McGinnes"]
|
||||
__url__ = ("blender", "elysiun", "http://www.gametutorials.com")
|
||||
__version__ = "0.82"
|
||||
__bpydoc__ = """\
|
||||
|
||||
3ds Exporter
|
||||
|
||||
This script Exports a 3ds file and the materials into blender for editing.
|
||||
|
||||
Exporting is based on 3ds loader from www.gametutorials.com(Thanks DigiBen).
|
||||
"""
|
||||
|
||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||
#
|
||||
# Script copyright (C) Bob Holcomb
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# ***** END GPL LICENCE BLOCK *****
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
|
||||
######################################################
|
||||
# Importing modules
|
||||
######################################################
|
||||
|
||||
import Blender
|
||||
from Blender import NMesh, Scene, Object, Material
|
||||
import struct
|
||||
|
||||
|
||||
######################################################
|
||||
# Data Structures
|
||||
######################################################
|
||||
|
||||
#Some of the chunks that we will export
|
||||
#----- Primary Chunk, at the beginning of each file
|
||||
PRIMARY= long("0x4D4D",16)
|
||||
|
||||
#------ Main Chunks
|
||||
OBJECTINFO = long("0x3D3D",16); #This gives the version of the mesh and is found right before the material and object information
|
||||
VERSION = long("0x0002",16); #This gives the version of the .3ds file
|
||||
EDITKEYFRAME= long("0xB000",16); #This is the header for all of the key frame info
|
||||
|
||||
#------ sub defines of OBJECTINFO
|
||||
MATERIAL=45055 #0xAFFF // This stored the texture info
|
||||
OBJECT=16384 #0x4000 // This stores the faces, vertices, etc...
|
||||
|
||||
#>------ sub defines of MATERIAL
|
||||
MATNAME = long("0xA000",16); # This holds the material name
|
||||
MATAMBIENT = long("0xA010",16); # Ambient color of the object/material
|
||||
MATDIFFUSE = long("0xA020",16); # This holds the color of the object/material
|
||||
MATSPECULAR = long("0xA030",16); # SPecular color of the object/material
|
||||
MATSHINESS = long("0xA040",16); # ??
|
||||
MATMAP = long("0xA200",16); # This is a header for a new material
|
||||
MATMAPFILE = long("0xA300",16); # This holds the file name of the texture
|
||||
|
||||
RGB1= long("0x0011",16)
|
||||
RGB2= long("0x0012",16)
|
||||
|
||||
#>------ sub defines of OBJECT
|
||||
OBJECT_MESH = long("0x4100",16); # This lets us know that we are reading a new object
|
||||
OBJECT_LIGHT = long("0x4600",16); # This lets un know we are reading a light object
|
||||
OBJECT_CAMERA= long("0x4700",16); # This lets un know we are reading a camera object
|
||||
|
||||
#>------ sub defines of CAMERA
|
||||
OBJECT_CAM_RANGES= long("0x4720",16); # The camera range values
|
||||
|
||||
#>------ sub defines of OBJECT_MESH
|
||||
OBJECT_VERTICES = long("0x4110",16); # The objects vertices
|
||||
OBJECT_FACES = long("0x4120",16); # The objects faces
|
||||
OBJECT_MATERIAL = long("0x4130",16); # This is found if the object has a material, either texture map or color
|
||||
OBJECT_UV = long("0x4140",16); # The UV texture coordinates
|
||||
OBJECT_TRANS_MATRIX = long("0x4160",16); # The Object Matrix
|
||||
|
||||
#==============================================#
|
||||
# Strips the slashes from the back of a string #
|
||||
#==============================================#
|
||||
def stripPath(path):
|
||||
return path.split('/')[-1].split('\\')[-1]
|
||||
|
||||
#==================================================#
|
||||
# New name based on old with a different extension #
|
||||
#==================================================#
|
||||
def newFName(ext):
|
||||
return Blender.Get('filename')[: -len(Blender.Get('filename').split('.', -1)[-1]) ] + ext
|
||||
|
||||
|
||||
#the chunk class
|
||||
class chunk:
|
||||
ID=0
|
||||
size=0
|
||||
|
||||
def __init__(self):
|
||||
self.ID=0
|
||||
self.size=0
|
||||
|
||||
def get_size(self):
|
||||
self.size=6
|
||||
|
||||
def write(self, file):
|
||||
#write header
|
||||
data=struct.pack(\
|
||||
"<HI",\
|
||||
self.ID,\
|
||||
self.size)
|
||||
file.write(data)
|
||||
|
||||
def dump(self):
|
||||
print "ID: ", self.ID
|
||||
print "ID in hex: ", hex(self.ID)
|
||||
print "size: ", self.size
|
||||
|
||||
|
||||
|
||||
#may want to add light, camera, keyframe chunks.
|
||||
class vert_chunk(chunk):
|
||||
verts=[]
|
||||
|
||||
def __init__(self):
|
||||
self.verts=[]
|
||||
self.ID=OBJECT_VERTICES
|
||||
|
||||
def get_size(self):
|
||||
chunk.get_size(self)
|
||||
temp_size=2 #for the number of verts short
|
||||
temp_size += 12 * len(self.verts) #3 floats x 4 bytes each
|
||||
self.size+=temp_size
|
||||
#~ print "vert_chunk size: ", self.size
|
||||
return self.size
|
||||
|
||||
def write(self, file):
|
||||
chunk.write(self, file)
|
||||
#write header
|
||||
data=struct.pack("<H", len(self.verts))
|
||||
file.write(data)
|
||||
#write verts
|
||||
for vert in self.verts:
|
||||
data=struct.pack("<3f",vert[0],vert[1], vert[2])
|
||||
file.write(data)
|
||||
|
||||
class obj_material_chunk(chunk):
|
||||
name=""
|
||||
faces=[]
|
||||
|
||||
def __init__(self):
|
||||
self.name=""
|
||||
self.faces=[]
|
||||
self.ID=OBJECT_MATERIAL
|
||||
|
||||
def get_size(self):
|
||||
chunk.get_size(self)
|
||||
temp_size=(len(self.name)+1)
|
||||
temp_size+=2
|
||||
for face in self.faces:
|
||||
temp_size+=2
|
||||
self.size+=temp_size
|
||||
#~ print "obj material chunk size: ", self.size
|
||||
return self.size
|
||||
|
||||
def write(self, file):
|
||||
chunk.write(self, file)
|
||||
#write name
|
||||
name_length=len(self.name)+1
|
||||
binary_format="<"+str(name_length)+"s"
|
||||
data=struct.pack(binary_format, self.name)
|
||||
file.write(data)
|
||||
binary_format="<H"
|
||||
#~ print "Nr of faces: ", len(self.faces)
|
||||
data=struct.pack(binary_format, len(self.faces))
|
||||
file.write(data)
|
||||
for face in self.faces:
|
||||
data=struct.pack(binary_format, face)
|
||||
file.write(data)
|
||||
|
||||
class face_chunk(chunk):
|
||||
faces=[]
|
||||
num_faces=0
|
||||
m_chunks=[]
|
||||
|
||||
def __init__(self):
|
||||
self.faces=[]
|
||||
self.ID=OBJECT_FACES
|
||||
self.num_faces=0
|
||||
self.m_chunks=[]
|
||||
|
||||
def get_size(self):
|
||||
chunk.get_size(self)
|
||||
temp_size = 2 #num faces info
|
||||
temp_size += 8 * len(self.faces) #4 short ints x 2 bytes each
|
||||
for m in self.m_chunks:
|
||||
temp_size+=m.get_size()
|
||||
self.size += temp_size
|
||||
#~ print "face_chunk size: ", self.size
|
||||
return self.size
|
||||
|
||||
def write(self, file):
|
||||
chunk.write(self, file)
|
||||
data=struct.pack("<H", len(self.faces))
|
||||
file.write(data)
|
||||
#write faces
|
||||
for face in self.faces:
|
||||
data=struct.pack("<4H", face[0],face[1], face[2], 0) # The last zero is only used by 3d studio
|
||||
file.write(data)
|
||||
#write materials
|
||||
for m in self.m_chunks:
|
||||
m.write(file)
|
||||
|
||||
class uv_chunk(chunk):
|
||||
uv=[]
|
||||
num_uv=0
|
||||
|
||||
def __init__(self):
|
||||
self.uv=[]
|
||||
self.ID=OBJECT_UV
|
||||
self.num_uv=0
|
||||
|
||||
def get_size(self):
|
||||
chunk.get_size(self)
|
||||
temp_size=2 #for num UV
|
||||
for this_uv in self.uv:
|
||||
temp_size+=8 #2 floats at 4 bytes each
|
||||
self.size+=temp_size
|
||||
#~ print "uv chunk size: ", self.size
|
||||
return self.size
|
||||
|
||||
def write(self, file):
|
||||
chunk.write(self, file)
|
||||
|
||||
#write header
|
||||
data=struct.pack("<H", len(self.uv))
|
||||
file.write(data)
|
||||
|
||||
#write verts
|
||||
for this_uv in self.uv:
|
||||
data=struct.pack("<2f", this_uv[0], this_uv[1])
|
||||
file.write(data)
|
||||
|
||||
class mesh_chunk(chunk):
|
||||
v_chunk=vert_chunk()
|
||||
f_chunk=face_chunk()
|
||||
uv_chunk=uv_chunk()
|
||||
|
||||
def __init__(self):
|
||||
self.v_chunk=vert_chunk()
|
||||
self.f_chunk=face_chunk()
|
||||
self.uv_chunk=uv_chunk()
|
||||
self.ID=OBJECT_MESH
|
||||
|
||||
def get_size(self):
|
||||
chunk.get_size(self)
|
||||
temp_size=self.v_chunk.get_size()
|
||||
temp_size+=self.f_chunk.get_size()
|
||||
temp_size+=self.uv_chunk.get_size()
|
||||
self.size+=temp_size
|
||||
#~ print "object mesh chunk size: ", self.size
|
||||
return self.size
|
||||
|
||||
def write(self, file):
|
||||
chunk.write(self, file)
|
||||
#write stuff
|
||||
self.v_chunk.write(file)
|
||||
self.f_chunk.write(file)
|
||||
self.uv_chunk.write(file)
|
||||
|
||||
class object_chunk(chunk):
|
||||
name=""
|
||||
mesh_chunks=[]
|
||||
|
||||
def __init__(self):
|
||||
self.name=""
|
||||
self.mesh_chunks=[]
|
||||
self.ID=OBJECT
|
||||
|
||||
def get_size(self):
|
||||
chunk.get_size(self)
|
||||
temp_size=len(self.name)+1 #+1 for null character
|
||||
for mesh in self.mesh_chunks:
|
||||
temp_size+=mesh.get_size()
|
||||
self.size+=temp_size
|
||||
#~ print "object chunk size: ", self.size
|
||||
return self.size
|
||||
|
||||
def write(self, file):
|
||||
chunk.write(self, file)
|
||||
#write name
|
||||
|
||||
binary_format = "<%ds" % (len(self.name)+1)
|
||||
data=struct.pack(binary_format, self.name)
|
||||
file.write(data)
|
||||
#write stuff
|
||||
for mesh in self.mesh_chunks:
|
||||
mesh.write(file)
|
||||
|
||||
class object_info_chunk(chunk):
|
||||
obj_chunks=[]
|
||||
mat_chunks=[]
|
||||
|
||||
def __init__(self):
|
||||
self.obj_chunks=[]
|
||||
self.mat_chunks=[]
|
||||
self.ID=OBJECTINFO
|
||||
|
||||
def get_size(self):
|
||||
chunk.get_size(self)
|
||||
temp_size=0
|
||||
for mat in self.mat_chunks:
|
||||
temp_size+=mat.get_size()
|
||||
for obj in self.obj_chunks:
|
||||
temp_size+=obj.get_size()
|
||||
self.size+=temp_size
|
||||
#~ print "object info size: ", self.size
|
||||
return self.size
|
||||
|
||||
def write(self, file):
|
||||
chunk.write(self, file)
|
||||
#write all the materials
|
||||
for mat in self.mat_chunks:
|
||||
mat.write(file)
|
||||
#write all the objects
|
||||
for obj in self.obj_chunks:
|
||||
obj.write(file)
|
||||
|
||||
|
||||
|
||||
class version_chunk(chunk):
|
||||
version=3
|
||||
|
||||
def __init__(self):
|
||||
self.ID=VERSION
|
||||
self.version=3 #that the document that I'm using
|
||||
|
||||
def get_size(self):
|
||||
chunk.get_size(self)
|
||||
self.size += 4 #bytes for the version info
|
||||
#~ print "version chunk size: ", self.size
|
||||
return self.size
|
||||
|
||||
def write(self, file):
|
||||
chunk.write(self, file)
|
||||
#write header and version
|
||||
data=struct.pack("<I", self.version)
|
||||
file.write(data)
|
||||
|
||||
class rgb_chunk(chunk):
|
||||
col=[]
|
||||
|
||||
def __init__(self):
|
||||
self.col=[]
|
||||
|
||||
def get_size(self):
|
||||
chunk.get_size(self)
|
||||
self.size+=3 #color size
|
||||
#~ print "rgb chunk size: ", self.size
|
||||
return self.size
|
||||
|
||||
def write(self, file):
|
||||
chunk.write(self, file)
|
||||
#write colors
|
||||
for c in self.col:
|
||||
file.write( struct.pack("<c", chr(int(255*c))) )
|
||||
|
||||
|
||||
class rgb1_chunk(rgb_chunk):
|
||||
|
||||
def __init__(self):
|
||||
self.ID=RGB1
|
||||
|
||||
class rgb2_chunk(rgb_chunk):
|
||||
|
||||
def __init__(self):
|
||||
self.ID=RGB2
|
||||
|
||||
class material_ambient_chunk(chunk):
|
||||
col1=None
|
||||
col2=None
|
||||
|
||||
def __init__(self):
|
||||
self.ID=MATAMBIENT
|
||||
self.col1=rgb1_chunk()
|
||||
self.col2=rgb2_chunk()
|
||||
|
||||
def get_size(self):
|
||||
chunk.get_size(self)
|
||||
temp_size=self.col1.get_size()
|
||||
temp_size+=self.col2.get_size()
|
||||
self.size+=temp_size
|
||||
#~ print "material ambient size: ", self.size
|
||||
return self.size
|
||||
|
||||
def write(self, file):
|
||||
chunk.write(self, file)
|
||||
#write colors
|
||||
self.col1.write(file)
|
||||
self.col2.write(file)
|
||||
|
||||
class material_diffuse_chunk(chunk):
|
||||
col1=None
|
||||
col2=None
|
||||
|
||||
def __init__(self):
|
||||
self.ID=MATDIFFUSE
|
||||
self.col1=rgb1_chunk()
|
||||
self.col2=rgb2_chunk()
|
||||
|
||||
def get_size(self):
|
||||
chunk.get_size(self)
|
||||
temp_size=self.col1.get_size()
|
||||
temp_size+=self.col2.get_size()
|
||||
self.size+=temp_size
|
||||
#~ print "material diffuse size: ", self.size
|
||||
return self.size
|
||||
|
||||
def write(self, file):
|
||||
chunk.write(self, file)
|
||||
#write colors
|
||||
self.col1.write(file)
|
||||
self.col2.write(file)
|
||||
|
||||
class material_specular_chunk(chunk):
|
||||
col1=None
|
||||
col2=None
|
||||
|
||||
def __init__(self):
|
||||
self.ID=MATSPECULAR
|
||||
self.col1=rgb1_chunk()
|
||||
self.col2=rgb2_chunk()
|
||||
|
||||
def get_size(self):
|
||||
chunk.get_size(self)
|
||||
temp_size=self.col1.get_size()
|
||||
temp_size+=self.col2.get_size()
|
||||
self.size+=temp_size
|
||||
#~ print "material specular size: ", self.size
|
||||
return self.size
|
||||
|
||||
def write(self, file):
|
||||
chunk.write(self, file)
|
||||
#write colors
|
||||
self.col1.write(file)
|
||||
self.col2.write(file)
|
||||
|
||||
class material_name_chunk(chunk):
|
||||
name=""
|
||||
|
||||
def __init__(self):
|
||||
self.ID=MATNAME
|
||||
self.name=""
|
||||
|
||||
def get_size(self):
|
||||
chunk.get_size(self)
|
||||
temp_size=(len(self.name)+1)
|
||||
self.size+=temp_size
|
||||
#~ print "material name size: ", self.size
|
||||
return self.size
|
||||
|
||||
def write(self, file):
|
||||
chunk.write(self, file)
|
||||
#write name
|
||||
name_length=len(self.name)+1
|
||||
binary_format="<"+str(name_length)+"s"
|
||||
data=struct.pack(binary_format, self.name)
|
||||
file.write(data)
|
||||
|
||||
class material_chunk(chunk):
|
||||
matname_chunk=None
|
||||
matambient_chunk=None
|
||||
matdiffuse_chunk=None
|
||||
matspecular_chunk=None
|
||||
|
||||
def __init__(self):
|
||||
self.ID=MATERIAL
|
||||
self.matname_chunk=material_name_chunk()
|
||||
self.matambient_chunk=material_ambient_chunk()
|
||||
self.matdiffuse_chunk=material_diffuse_chunk()
|
||||
self.matspecular_chunk=material_specular_chunk()
|
||||
|
||||
def get_size(self):
|
||||
chunk.get_size(self)
|
||||
temp_size=self.matname_chunk.get_size()
|
||||
temp_size+=self.matambient_chunk.get_size()
|
||||
temp_size+=self.matdiffuse_chunk.get_size()
|
||||
temp_size+=self.matspecular_chunk.get_size()
|
||||
self.size+=temp_size
|
||||
#~ print "material chunk size: ", self.size
|
||||
return self.size
|
||||
|
||||
def write(self, file):
|
||||
chunk.write(self, file)
|
||||
#write name chunk
|
||||
self.matname_chunk.write(file)
|
||||
#write material colors
|
||||
self.matambient_chunk.write(file)
|
||||
self.matdiffuse_chunk.write(file)
|
||||
self.matspecular_chunk.write(file)
|
||||
|
||||
class primary_chunk(chunk):
|
||||
version=None
|
||||
obj_info=None
|
||||
|
||||
def __init__(self):
|
||||
self.version=version_chunk()
|
||||
self.obj_info=object_info_chunk()
|
||||
self.ID=PRIMARY
|
||||
|
||||
def get_size(self):
|
||||
chunk.get_size(self)
|
||||
temp_size=self.version.get_size()
|
||||
temp_size+=self.obj_info.get_size()
|
||||
self.size+=temp_size
|
||||
#~ print "primary chunk size: ", self.size
|
||||
return self.size
|
||||
|
||||
def write(self, file):
|
||||
chunk.write(self, file)
|
||||
#write version chunk
|
||||
self.version.write(file)
|
||||
#write object_info chunk
|
||||
self.obj_info.write(file)
|
||||
|
||||
def read_chunk(file, chunk):
|
||||
chunk.ID, chunk.size = \
|
||||
struct.unpack(\
|
||||
chunk.binary_format, \
|
||||
file.read(struct.calcsize(chunk.binary_format)) )
|
||||
|
||||
def read_string(file):
|
||||
s=""
|
||||
index=0
|
||||
|
||||
#read in the characters till we get a null character
|
||||
data=struct.unpack("c", file.read(struct.calcsize("c")))
|
||||
s=s+(data[0])
|
||||
#print "string: ",s
|
||||
while(ord(s[index])!=0):
|
||||
index+=1
|
||||
data=struct.unpack("c", file.read(struct.calcsize("c")))
|
||||
s=s+(data[0])
|
||||
#print "string: ",s
|
||||
return str(s)
|
||||
|
||||
######################################################
|
||||
# EXPORT
|
||||
######################################################
|
||||
def save_3ds(filename):
|
||||
# Time the export
|
||||
time1 = Blender.sys.time()
|
||||
|
||||
exported_materials = {}
|
||||
|
||||
#fill the chunks full of data
|
||||
primary=primary_chunk()
|
||||
#get all the objects in this scene
|
||||
object_list = [ ob for ob in Blender.Object.GetSelected() if ob.getType() == 'Mesh' ]
|
||||
#fill up the data structures with objects
|
||||
for obj in object_list:
|
||||
#create a new object chunk
|
||||
primary.obj_info.obj_chunks.append(object_chunk())
|
||||
#get the mesh data
|
||||
blender_mesh = obj.getData()
|
||||
blender_mesh.transform(obj.getMatrix())
|
||||
#set the object name
|
||||
primary.obj_info.obj_chunks[len(primary.obj_info.obj_chunks)-1].name=obj.getName()
|
||||
|
||||
matrix = obj.getMatrix()
|
||||
|
||||
#make a new mesh chunk object
|
||||
mesh=mesh_chunk()
|
||||
|
||||
mesh.v_chunk.verts = blender_mesh.verts
|
||||
|
||||
dummy = None # just incase...
|
||||
|
||||
for m in blender_mesh.materials:
|
||||
mesh.f_chunk.m_chunks.append(obj_material_chunk())
|
||||
mesh.f_chunk.m_chunks[len(mesh.f_chunk.m_chunks)-1].name = m.name
|
||||
|
||||
# materials should only be exported once
|
||||
try:
|
||||
dummy = exported_materials[m.name]
|
||||
|
||||
|
||||
except KeyError:
|
||||
material = material_chunk()
|
||||
material.matname_chunk.name=m.name
|
||||
material.matambient_chunk.col1.col = m.mirCol
|
||||
material.matambient_chunk.col2.col = m.mirCol
|
||||
material.matdiffuse_chunk.col1.col = m.rgbCol
|
||||
material.matdiffuse_chunk.col2.col = m.rgbCol
|
||||
material.matspecular_chunk.col1.col = m.specCol
|
||||
material.matspecular_chunk.col2.col = m.specCol
|
||||
|
||||
primary.obj_info.mat_chunks.append(material)
|
||||
|
||||
exported_materials[m.name] = None
|
||||
|
||||
del dummy # unpolute the namespace
|
||||
|
||||
valid_faces = [f for f in blender_mesh.faces if len(f) > 2]
|
||||
facenr=0
|
||||
#fill in faces
|
||||
for face in valid_faces:
|
||||
|
||||
#is this a tri or a quad
|
||||
num_fv=len(face.v)
|
||||
|
||||
|
||||
#it's a tri
|
||||
if num_fv==3:
|
||||
mesh.f_chunk.faces.append((face[0].index, face[1].index, face[2].index))
|
||||
if (face.materialIndex < len(mesh.f_chunk.m_chunks)):
|
||||
mesh.f_chunk.m_chunks[face.materialIndex].faces.append(facenr)
|
||||
facenr+=1
|
||||
|
||||
else: #it's a quad
|
||||
mesh.f_chunk.faces.append((face[0].index, face[1].index, face[2].index)) # 0,1,2
|
||||
mesh.f_chunk.faces.append((face[2].index, face[3].index, face[0].index)) # 2,3,0
|
||||
#first tri
|
||||
if (face.materialIndex < len(mesh.f_chunk.m_chunks)):
|
||||
mesh.f_chunk.m_chunks[face.materialIndex].faces.append(facenr)
|
||||
facenr+=1
|
||||
#other tri
|
||||
if (face.materialIndex < len(mesh.f_chunk.m_chunks)):
|
||||
mesh.f_chunk.m_chunks[face.materialIndex].faces.append(facenr)
|
||||
facenr+=1
|
||||
|
||||
|
||||
#fill in the UV info
|
||||
if blender_mesh.hasVertexUV():
|
||||
for vert in blender_mesh.verts:
|
||||
mesh.uv_chunk.uv.append((vert.uvco[0], vert.uvco[1]))
|
||||
|
||||
elif blender_mesh.hasFaceUV():
|
||||
for face in valid_faces:
|
||||
# Tri or quad.
|
||||
for uv_coord in face.uv:
|
||||
mesh.uv_chunk.uv.append((uv_coord[0], uv_coord[1]))
|
||||
|
||||
#filled in our mesh, lets add it to the file
|
||||
primary.obj_info.obj_chunks[len(primary.obj_info.obj_chunks)-1].mesh_chunks.append(mesh)
|
||||
|
||||
#check the size
|
||||
primary.get_size()
|
||||
#open the files up for writing
|
||||
file = open( filename, "wb" )
|
||||
#recursively write the stuff to file
|
||||
primary.write(file)
|
||||
file.close()
|
||||
print "3ds export time: %.2f" % (Blender.sys.time() - time1)
|
||||
|
||||
|
||||
Blender.Window.FileSelector(save_3ds, "Export 3DS", newFName('3ds'))
|
||||
662
release/scripts/3ds_import.py
Normal file
662
release/scripts/3ds_import.py
Normal file
@@ -0,0 +1,662 @@
|
||||
#!BPY
|
||||
|
||||
"""
|
||||
Name: '3D Studio (.3ds)...'
|
||||
Blender: 237
|
||||
Group: 'Import'
|
||||
Tooltip: 'Import from 3DS file format. (.3ds)'
|
||||
"""
|
||||
|
||||
__author__ = ["Bob Holcomb", "Richard L<>rk<72>ng", "Damien McGinnes", "Campbell Barton"]
|
||||
__url__ = ("blender", "elysiun", "http://www.gametutorials.com")
|
||||
__version__ = "0.92"
|
||||
__bpydoc__ = """\
|
||||
|
||||
3ds Importer
|
||||
|
||||
This script imports a 3ds file and the materials into Blender for editing.
|
||||
|
||||
Loader is based on 3ds loader from www.gametutorials.com (Thanks DigiBen).
|
||||
|
||||
Changes:
|
||||
|
||||
0.92<br>
|
||||
- Added support for diffuse, alpha, spec, bump maps in a single material
|
||||
|
||||
0.9<br>
|
||||
- Reorganized code into object/material block functions<br>
|
||||
- Use of Matrix() to copy matrix data<br>
|
||||
- added support for material transparency<br>
|
||||
|
||||
0.81a (fork- not 0.9) Campbell Barton 2005-06-08<br>
|
||||
- Simplified import code<br>
|
||||
- Never overwrite data<br>
|
||||
- Faster list handling<br>
|
||||
- Leaves import selected<br>
|
||||
|
||||
0.81 Damien McGinnes 2005-01-09<br>
|
||||
- handle missing images better<br>
|
||||
|
||||
0.8 Damien McGinnes 2005-01-08<br>
|
||||
- copies sticky UV coords to face ones<br>
|
||||
- handles images better<br>
|
||||
- Recommend that you run 'RemoveDoubles' on each imported mesh after using this script
|
||||
|
||||
"""
|
||||
|
||||
# $Id$
|
||||
#
|
||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||
#
|
||||
# Script copyright (C) Bob Holcomb
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# ***** END GPL LICENCE BLOCK *****
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
|
||||
# Importing modules
|
||||
|
||||
import Blender
|
||||
from Blender import NMesh, Scene, Object, Material, Image, Texture
|
||||
|
||||
import sys, struct, string
|
||||
|
||||
import os
|
||||
|
||||
######################################################
|
||||
# Data Structures
|
||||
######################################################
|
||||
#----- Primary Chunk,
|
||||
PRIMARY = long("0x4D4D",16) # should be aat the beginning of each file
|
||||
VERSION = long("0x0002",16) #This gives the version of the .3ds file
|
||||
EDITOR_BLOCK = long("0x3D3D",16) #this is the Editor Data block, contains objects, materials
|
||||
KEYFRAME_BLOCK = long("0xB000",16) #This is the header for all of the key frame info
|
||||
|
||||
#------ sub defines of EDITOR_BLOCK
|
||||
MATERIAL_BLOCK = long("0xAFFF",16) #This stores the Material info
|
||||
OBJECT_BLOCK = long("0x4000",16) #This stores the Object,Camera,Light
|
||||
|
||||
#------ sub defines of OBJECT_BLOCK
|
||||
OBJECT_MESH = long("0x4100",16) # This lets us know that we are reading a new object
|
||||
OBJECT_LIGHT = long("0x4600",16) # This lets un know we are reading a light object
|
||||
OBJECT_CAMERA = long("0x4700",16) # This lets un know we are reading a camera object
|
||||
|
||||
#------ sub defines of OBJECT_MESH
|
||||
MESH_VERTICES = long("0x4110",16) # The objects vertices
|
||||
MESH_FACES = long("0x4120",16) # The objects faces
|
||||
MESH_MATERIAL = long("0x4130",16) # This is found if the object has a material, either texture map or color
|
||||
MESH_UV = long("0x4140",16) # The UV texture coordinates
|
||||
MESH_TRANS_MATRIX = long("0x4160",16) # The Object Matrix
|
||||
MESH_COLOR = long("0x4165",16) # The color of the object
|
||||
MESH_TEXTURE_INFO = long("0x470",16) # Info about the Object Texture
|
||||
|
||||
#------ sub defines of OBJECT_CAMERA
|
||||
CAMERA_CONE = long("0x4710",16) # The camera see cone
|
||||
CAMERA_RANGES = long("0x4720",16) # The camera range values
|
||||
|
||||
#------ sub defines of OBJECT_LIGHT
|
||||
LIGHT_SPOTLIGHT = long("0x4610",16) # A spotlight
|
||||
LIGHT_ATTENUATE = long("0x4625",16) # Light attenuation values
|
||||
|
||||
|
||||
#------ sub defines of MATERIAL_BLOCK
|
||||
MAT_NAME = long("0xA000",16) # This holds the material name
|
||||
MAT_AMBIENT = long("0xA010",16) # Ambient color of the object/material
|
||||
MAT_DIFFUSE = long("0xA020",16) # This holds the color of the object/material
|
||||
MAT_SPECULAR = long("0xA030",16) # SPecular color of the object/material
|
||||
MAT_SHINESS = long("0xA040",16) # ??
|
||||
MAT_TRANSPARENCY= long("0xA050",16) # Transparency value of material
|
||||
MAT_SELF_ILLUM = long("0xA080",16) # Self Illumination value of material
|
||||
MAT_WIRE = long("0xA085",16) # Only render's wireframe
|
||||
|
||||
MAT_TEXTURE_MAP = long("0xA200",16) # This is a header for a new texture map
|
||||
MAT_SPECULAR_MAP= long("0xA204",16) # This is a header for a new specular map
|
||||
MAT_OPACITY_MAP = long("0xA210",16) # This is a header for a new opacity map
|
||||
MAT_REFLECTION_MAP= long("0xA220",16) # This is a header for a new reflection map
|
||||
MAT_BUMP_MAP = long("0xA230",16) # This is a header for a new bump map
|
||||
MAT_MAP_FILENAME= long("0xA300",16) # This holds the file name of the texture
|
||||
#lots more to add here for maps
|
||||
|
||||
######################################################
|
||||
# Globals
|
||||
######################################################
|
||||
TEXTURE_DICT={}
|
||||
MATERIAL_DICT={}
|
||||
|
||||
|
||||
######################################################
|
||||
# Chunk Class
|
||||
######################################################
|
||||
class chunk:
|
||||
ID=0
|
||||
length=0
|
||||
bytes_read=0
|
||||
|
||||
binary_format="<HI"
|
||||
|
||||
def __init__(self):
|
||||
self.ID=0
|
||||
self.length=0
|
||||
self.bytes_read=0
|
||||
|
||||
def dump(self):
|
||||
print "ID in hex: ", hex(self.ID)
|
||||
print "length: ", self.length
|
||||
print "bytes_read: ", self.bytes_read
|
||||
|
||||
|
||||
######################################################
|
||||
# Helper functions
|
||||
######################################################
|
||||
def read_chunk(file, chunk):
|
||||
temp_data=file.read(struct.calcsize(chunk.binary_format))
|
||||
data=struct.unpack(chunk.binary_format, temp_data)
|
||||
chunk.ID=data[0]
|
||||
chunk.length=data[1]
|
||||
chunk.bytes_read=6
|
||||
|
||||
def skip_to_end(file, skip_chunk):
|
||||
buffer_size=skip_chunk.length-skip_chunk.bytes_read
|
||||
binary_format=str(buffer_size)+"c"
|
||||
temp_data=file.read(struct.calcsize(binary_format))
|
||||
skip_chunk.bytes_read+=buffer_size
|
||||
|
||||
def read_string(file):
|
||||
s=""
|
||||
index=0
|
||||
#read the first character
|
||||
temp_data=file.read(1)
|
||||
data=struct.unpack("c", temp_data)
|
||||
s=s+(data[0])
|
||||
#read in the characters till we get a null character
|
||||
while(ord(s[index])!=0):
|
||||
index+=1
|
||||
temp_data=file.read(1)
|
||||
data=struct.unpack("c", temp_data)
|
||||
s=s+(data[0])
|
||||
the_string=s[:-1] #remove the null character from the string
|
||||
return str(the_string)
|
||||
|
||||
def getUniqueName(name):
|
||||
newName = name
|
||||
uniqueInt = 0
|
||||
while 1:
|
||||
try:
|
||||
ob = Object.Get(newName)
|
||||
# Okay, this is working, so lets make a new name
|
||||
newName = '%s.%d' % (name, uniqueInt)
|
||||
uniqueInt +=1
|
||||
except AttributeError:
|
||||
if newName not in NMesh.GetNames():
|
||||
return newName
|
||||
else:
|
||||
newName = '%s.%d' % (name, uniqueInt)
|
||||
uniqueInt +=1
|
||||
|
||||
def add_texture_to_material(image, texture, material, mapto):
|
||||
if mapto=="DIFFUSE":
|
||||
map=Texture.MapTo.COL
|
||||
elif mapto=="SPECULAR":
|
||||
map=Texture.MapTo.SPEC
|
||||
elif mapto=="OPACITY":
|
||||
map=Texture.MapTo.ALPHA
|
||||
elif mapto=="BUMP":
|
||||
map=Texture.MapTo.NOR
|
||||
else:
|
||||
print "/tError: Cannot map to ", mapto
|
||||
return
|
||||
|
||||
texture.setImage(image)
|
||||
texture_list=material.getTextures()
|
||||
index=0
|
||||
for tex in texture_list:
|
||||
if tex==None:
|
||||
material.setTexture(index,texture,Texture.TexCo.OBJECT,map)
|
||||
return
|
||||
else:
|
||||
index+=1
|
||||
if index>10:
|
||||
print "/tError: Cannot add diffuse map. Too many textures"
|
||||
|
||||
######################################################
|
||||
# Process an object (tri-mesh, Camera, or Light)
|
||||
######################################################
|
||||
def process_object_block(file, previous_chunk, object_list):
|
||||
# Localspace variable names, faster.
|
||||
STRUCT_SIZE_2FLOAT = struct.calcsize("2f")
|
||||
STRUCT_SIZE_3FLOAT = struct.calcsize("3f")
|
||||
STRUCT_SIZE_UNSIGNED_SHORT = struct.calcsize("H")
|
||||
STRUCT_SIZE_4UNSIGNED_SHORT = struct.calcsize("4H")
|
||||
STRUCT_SIZE_4x3MAT = struct.calcsize("ffffffffffff")
|
||||
|
||||
#spare chunks
|
||||
new_chunk=chunk()
|
||||
temp_chunk=chunk()
|
||||
|
||||
global TEXURE_DICT
|
||||
global MATERIAL_DICT
|
||||
|
||||
#don't know which one we're making, so let's have a place for one of each
|
||||
new_mesh=None
|
||||
new_light=None
|
||||
new_camera=None
|
||||
|
||||
#all objects have a name (first thing)
|
||||
tempName = str(read_string(file))
|
||||
obj_name = getUniqueName( tempName )
|
||||
previous_chunk.bytes_read += (len(tempName)+1)
|
||||
|
||||
while (previous_chunk.bytes_read<previous_chunk.length):
|
||||
read_chunk(file, new_chunk)
|
||||
|
||||
if (new_chunk.ID==OBJECT_MESH):
|
||||
new_mesh=Blender.NMesh.New(obj_name)
|
||||
while (new_chunk.bytes_read<new_chunk.length):
|
||||
read_chunk(file, temp_chunk)
|
||||
|
||||
if (temp_chunk.ID==MESH_VERTICES):
|
||||
temp_data=file.read(STRUCT_SIZE_UNSIGNED_SHORT)
|
||||
data=struct.unpack("H", temp_data)
|
||||
temp_chunk.bytes_read+=2
|
||||
num_verts=data[0]
|
||||
for counter in range (num_verts):
|
||||
temp_data=file.read(STRUCT_SIZE_3FLOAT)
|
||||
temp_chunk.bytes_read += STRUCT_SIZE_3FLOAT
|
||||
data=struct.unpack("3f", temp_data)
|
||||
v=NMesh.Vert(data[0],data[1],data[2])
|
||||
new_mesh.verts.append(v)
|
||||
|
||||
elif (temp_chunk.ID==MESH_FACES):
|
||||
temp_data=file.read(STRUCT_SIZE_UNSIGNED_SHORT)
|
||||
data=struct.unpack("H", temp_data)
|
||||
temp_chunk.bytes_read+=2
|
||||
num_faces=data[0]
|
||||
for counter in range(num_faces):
|
||||
temp_data=file.read(STRUCT_SIZE_4UNSIGNED_SHORT)
|
||||
temp_chunk.bytes_read += STRUCT_SIZE_4UNSIGNED_SHORT #4 short ints x 2 bytes each
|
||||
data=struct.unpack("4H", temp_data)
|
||||
#insert the mesh info into the faces, don't worry about data[3] it is a 3D studio thing
|
||||
f = NMesh.Face( [new_mesh.verts[data[i]] for i in xrange(3)] )
|
||||
f.uv = [ tuple(new_mesh.verts[data[i]].uvco[:2]) for i in xrange(3) ]
|
||||
new_mesh.faces.append(f)
|
||||
|
||||
elif (temp_chunk.ID==MESH_MATERIAL):
|
||||
material_name=""
|
||||
material_name=str(read_string(file))
|
||||
temp_chunk.bytes_read += len(material_name)+1 # remove 1 null character.
|
||||
material_found=0
|
||||
for mat in Material.Get():
|
||||
if(mat.name==material_name):
|
||||
if len(new_mesh.materials) >= 15:
|
||||
print "\tCant assign more than 16 materials per mesh, keep going..."
|
||||
break
|
||||
else:
|
||||
meshHasMat = 0
|
||||
for myMat in new_mesh.materials:
|
||||
if myMat.name == mat.name:
|
||||
meshHasMat = 1
|
||||
if meshHasMat == 0:
|
||||
new_mesh.addMaterial(mat)
|
||||
material_found=1
|
||||
#figure out what material index this is for the mesh
|
||||
for mat_counter in range(len(new_mesh.materials)):
|
||||
if new_mesh.materials[mat_counter].name == material_name:
|
||||
mat_index=mat_counter
|
||||
break # get out of this for loop so we don't accidentally set material_found back to 0
|
||||
else:
|
||||
material_found=0
|
||||
|
||||
if material_found == 1:
|
||||
#read the number of faces using this material
|
||||
temp_data=file.read(STRUCT_SIZE_UNSIGNED_SHORT)
|
||||
data=struct.unpack("H", temp_data)
|
||||
temp_chunk.bytes_read += STRUCT_SIZE_UNSIGNED_SHORT
|
||||
num_faces_using_mat=data[0]
|
||||
#list of faces using mat
|
||||
for face_counter in range(num_faces_using_mat):
|
||||
temp_data=file.read(STRUCT_SIZE_UNSIGNED_SHORT)
|
||||
temp_chunk.bytes_read += STRUCT_SIZE_UNSIGNED_SHORT
|
||||
data=struct.unpack("H", temp_data)
|
||||
new_mesh.faces[data[0]].materialIndex = mat_index
|
||||
try:
|
||||
mname = MATERIAL_DICT[mat.name]
|
||||
new_mesh.faces[data[0]].image = TEXTURE_DICT[mname]
|
||||
except:
|
||||
continue
|
||||
else:
|
||||
#read past the information about the material you couldn't find
|
||||
skip_to_end(file,temp_chunk)
|
||||
|
||||
elif (new_chunk.ID == MESH_UV):
|
||||
temp_data=file.read(STRUCT_SIZE_UNSIGNED_SHORT)
|
||||
data=struct.unpack("H", temp_data)
|
||||
temp_chunk.bytes_read+=2
|
||||
num_uv=data[0]
|
||||
|
||||
for counter in range(num_uv):
|
||||
temp_data=file.read(STRUCT_SIZE_2FLOAT)
|
||||
temp_chunk.bytes_read += STRUCT_SIZE_2FLOAT #2 float x 4 bytes each
|
||||
data=struct.unpack("2f", temp_data)
|
||||
#insert the insert the UV coords in the vertex data
|
||||
new_mesh.verts[counter].uvco = data
|
||||
|
||||
elif (new_chunk.ID == MESH_TRANS_MATRIX):
|
||||
temp_data=file.read(STRUCT_SIZE_4x3MAT)
|
||||
data = list( struct.unpack("ffffffffffff", temp_data) )
|
||||
temp_chunk.bytes_read += STRUCT_SIZE_4x3MAT
|
||||
new_matrix = Blender.Mathutils.Matrix(\
|
||||
data[:3] + [0],\
|
||||
data[3:6] + [0],\
|
||||
data[6:9] + [0],\
|
||||
data[9:] + [1])
|
||||
new_mesh.setMatrix(new_matrix)
|
||||
else:
|
||||
skip_to_end(file, temp_chunk)
|
||||
|
||||
new_chunk.bytes_read+=temp_chunk.bytes_read
|
||||
|
||||
elif (new_chunk.ID==OBJECT_LIGHT):
|
||||
skip_to_end(file,new_chunk)
|
||||
|
||||
elif (new_chunk.ID==OBJECT_CAMERA):
|
||||
skip_to_end(file,new_chunk)
|
||||
|
||||
else: #don't know what kind of object it is
|
||||
skip_to_end(file,new_chunk)
|
||||
|
||||
if new_mesh!=None:
|
||||
object_list.append(NMesh.PutRaw(new_mesh))
|
||||
if new_light!=None:
|
||||
object_list.append(new_light)
|
||||
if new_camera!=None:
|
||||
object_list.append(new_camera)
|
||||
|
||||
previous_chunk.bytes_read+=new_chunk.bytes_read
|
||||
|
||||
######################################################
|
||||
# Process a Material
|
||||
######################################################
|
||||
def process_material_block(file, previous_chunk):
|
||||
# Localspace variable names, faster.
|
||||
STRUCT_SIZE_3BYTE = struct.calcsize("3B")
|
||||
STRUCT_SIZE_UNSIGNED_SHORT = struct.calcsize("H")
|
||||
|
||||
#spare chunks
|
||||
new_chunk=chunk()
|
||||
temp_chunk=chunk()
|
||||
|
||||
global TEXURE_DICT
|
||||
global MATERIAL_DICT
|
||||
|
||||
new_material=Blender.Material.New()
|
||||
|
||||
while (previous_chunk.bytes_read<previous_chunk.length):
|
||||
#read the next chunk
|
||||
read_chunk(file, new_chunk)
|
||||
|
||||
if (new_chunk.ID==MAT_NAME):
|
||||
material_name=""
|
||||
material_name=str(read_string(file))
|
||||
new_chunk.bytes_read+=(len(material_name)+1) #plus one for the null character that ended the string
|
||||
new_material.setName(material_name)
|
||||
MATERIAL_DICT[material_name] = new_material.name
|
||||
|
||||
elif (new_chunk.ID==MAT_AMBIENT):
|
||||
read_chunk(file, temp_chunk)
|
||||
temp_data=file.read(STRUCT_SIZE_3BYTE)
|
||||
data=struct.unpack("3B", temp_data)
|
||||
temp_chunk.bytes_read+=3
|
||||
new_material.mirCol = [float(col)/255 for col in data] # data [0,1,2] == rgb
|
||||
new_chunk.bytes_read+=temp_chunk.bytes_read
|
||||
|
||||
elif (new_chunk.ID==MAT_DIFFUSE):
|
||||
read_chunk(file, temp_chunk)
|
||||
temp_data=file.read(STRUCT_SIZE_3BYTE)
|
||||
data=struct.unpack("3B", temp_data)
|
||||
temp_chunk.bytes_read+=3
|
||||
new_material.rgbCol = [float(col)/255 for col in data] # data [0,1,2] == rgb
|
||||
new_chunk.bytes_read+=temp_chunk.bytes_read
|
||||
|
||||
elif (new_chunk.ID==MAT_SPECULAR):
|
||||
read_chunk(file, temp_chunk)
|
||||
temp_data=file.read(STRUCT_SIZE_3BYTE)
|
||||
data=struct.unpack("3B", temp_data)
|
||||
temp_chunk.bytes_read+=3
|
||||
new_material.specCol = [float(col)/255 for col in data] # data [0,1,2] == rgb
|
||||
new_chunk.bytes_read+=temp_chunk.bytes_read
|
||||
|
||||
elif (new_chunk.ID==MAT_TEXTURE_MAP):
|
||||
new_texture=Blender.Texture.New('Diffuse')
|
||||
new_texture.setType('Image')
|
||||
while (new_chunk.bytes_read<new_chunk.length):
|
||||
read_chunk(file, temp_chunk)
|
||||
|
||||
if (temp_chunk.ID==MAT_MAP_FILENAME):
|
||||
texture_name=""
|
||||
texture_name=str(read_string(file))
|
||||
try:
|
||||
img = Image.Load(texture_name)
|
||||
TEXTURE_DICT[new_material.name]=img
|
||||
except IOError:
|
||||
fname = os.path.join( os.path.dirname(FILENAME), texture_name)
|
||||
try:
|
||||
img = Image.Load(fname)
|
||||
TEXTURE_DICT[new_material.name]=img
|
||||
except IOError:
|
||||
print "\tERROR: failed to load image ",texture_name
|
||||
TEXTURE_DICT[new_material.name] = None # Dummy
|
||||
img=Blender.Image.New(fname,1,1,24) #blank image
|
||||
new_chunk.bytes_read += (len(texture_name)+1) #plus one for the null character that gets removed
|
||||
|
||||
else:
|
||||
skip_to_end(file, temp_chunk)
|
||||
|
||||
new_chunk.bytes_read+=temp_chunk.bytes_read
|
||||
|
||||
#add the map to the material in the right channel
|
||||
add_texture_to_material(img, new_texture, new_material, "DIFFUSE")
|
||||
|
||||
elif (new_chunk.ID==MAT_SPECULAR_MAP):
|
||||
new_texture=Blender.Texture.New('Specular')
|
||||
new_texture.setType('Image')
|
||||
while (new_chunk.bytes_read<new_chunk.length):
|
||||
read_chunk(file, temp_chunk)
|
||||
|
||||
if (temp_chunk.ID==MAT_MAP_FILENAME):
|
||||
texture_name=""
|
||||
texture_name=str(read_string(file))
|
||||
try:
|
||||
img = Image.Load(texture_name)
|
||||
TEXTURE_DICT[new_material.name]=img
|
||||
except IOError:
|
||||
fname = os.path.join( os.path.dirname(FILENAME), texture_name)
|
||||
try:
|
||||
img = Image.Load(fname)
|
||||
TEXTURE_DICT[new_material.name]=img
|
||||
except IOError:
|
||||
print "\tERROR: failed to load image ",texture_name
|
||||
TEXTURE_DICT[new_material.name] = None # Dummy
|
||||
img=Blender.Image.New(fname,1,1,24) #blank image
|
||||
new_chunk.bytes_read += (len(texture_name)+1) #plus one for the null character that gets removed
|
||||
else:
|
||||
skip_to_end(file, temp_chunk)
|
||||
|
||||
new_chunk.bytes_read+=temp_chunk.bytes_read
|
||||
|
||||
#add the map to the material in the right channel
|
||||
add_texture_to_material(img, new_texture, new_material, "SPECULAR")
|
||||
|
||||
elif (new_chunk.ID==MAT_OPACITY_MAP):
|
||||
new_texture=Blender.Texture.New('Opacity')
|
||||
new_texture.setType('Image')
|
||||
while (new_chunk.bytes_read<new_chunk.length):
|
||||
read_chunk(file, temp_chunk)
|
||||
|
||||
if (temp_chunk.ID==MAT_MAP_FILENAME):
|
||||
texture_name=""
|
||||
texture_name=str(read_string(file))
|
||||
try:
|
||||
img = Image.Load(texture_name)
|
||||
TEXTURE_DICT[new_material.name]=img
|
||||
except IOError:
|
||||
fname = os.path.join( os.path.dirname(FILENAME), texture_name)
|
||||
try:
|
||||
img = Image.Load(fname)
|
||||
TEXTURE_DICT[new_material.name]=img
|
||||
except IOError:
|
||||
print "\tERROR: failed to load image ",texture_name
|
||||
TEXTURE_DICT[new_material.name] = None # Dummy
|
||||
img=Blender.Image.New(fname,1,1,24) #blank image
|
||||
new_chunk.bytes_read += (len(texture_name)+1) #plus one for the null character that gets removed
|
||||
else:
|
||||
skip_to_end(file, temp_chunk)
|
||||
|
||||
new_chunk.bytes_read+=temp_chunk.bytes_read
|
||||
|
||||
#add the map to the material in the right channel
|
||||
add_texture_to_material(img, new_texture, new_material, "OPACITY")
|
||||
|
||||
elif (new_chunk.ID==MAT_BUMP_MAP):
|
||||
new_texture=Blender.Texture.New('Bump')
|
||||
new_texture.setType('Image')
|
||||
while (new_chunk.bytes_read<new_chunk.length):
|
||||
read_chunk(file, temp_chunk)
|
||||
|
||||
if (temp_chunk.ID==MAT_MAP_FILENAME):
|
||||
texture_name=""
|
||||
texture_name=str(read_string(file))
|
||||
try:
|
||||
img = Image.Load(texture_name)
|
||||
TEXTURE_DICT[new_material.name]=img
|
||||
except IOError:
|
||||
fname = os.path.join( os.path.dirname(FILENAME), texture_name)
|
||||
try:
|
||||
img = Image.Load(fname)
|
||||
TEXTURE_DICT[new_material.name]=img
|
||||
except IOError:
|
||||
print "\tERROR: failed to load image ",texture_name
|
||||
TEXTURE_DICT[new_material.name] = None # Dummy
|
||||
img=Blender.Image.New(fname,1,1,24) #blank image
|
||||
new_chunk.bytes_read += (len(texture_name)+1) #plus one for the null character that gets removed
|
||||
else:
|
||||
skip_to_end(file, temp_chunk)
|
||||
|
||||
new_chunk.bytes_read+=temp_chunk.bytes_read
|
||||
|
||||
#add the map to the material in the right channel
|
||||
add_texture_to_material(img, new_texture, new_material, "BUMP")
|
||||
|
||||
elif (new_chunk.ID==MAT_TRANSPARENCY):
|
||||
read_chunk(file, temp_chunk)
|
||||
temp_data=file.read(STRUCT_SIZE_UNSIGNED_SHORT)
|
||||
data=struct.unpack("H", temp_data)
|
||||
temp_chunk.bytes_read+=2
|
||||
new_material.setAlpha(1-(float(data[0])/100))
|
||||
new_chunk.bytes_read+=temp_chunk.bytes_read
|
||||
|
||||
else:
|
||||
skip_to_end(file,new_chunk)
|
||||
|
||||
previous_chunk.bytes_read+=new_chunk.bytes_read
|
||||
|
||||
######################################################
|
||||
# process a main chunk
|
||||
######################################################
|
||||
def process_main_chunk(file,previous_chunk,new_object_list):
|
||||
|
||||
#spare chunks
|
||||
new_chunk=chunk()
|
||||
temp_chunk=chunk()
|
||||
|
||||
#Go through the main chunk
|
||||
while (previous_chunk.bytes_read<previous_chunk.length):
|
||||
read_chunk(file, new_chunk)
|
||||
|
||||
if (new_chunk.ID==VERSION):
|
||||
temp_data=file.read(struct.calcsize("I"))
|
||||
data=struct.unpack("I", temp_data)
|
||||
version=data[0]
|
||||
new_chunk.bytes_read+=4 #read the 4 bytes for the version number
|
||||
if (version>3): #this loader works with version 3 and below, but may not with 4 and above
|
||||
print "\tNon-Fatal Error: Version greater than 3, may not load correctly: ", version
|
||||
|
||||
elif (new_chunk.ID==EDITOR_BLOCK):
|
||||
while(new_chunk.bytes_read<new_chunk.length):
|
||||
read_chunk(file, temp_chunk)
|
||||
if (temp_chunk.ID==MATERIAL_BLOCK):
|
||||
process_material_block(file, temp_chunk)
|
||||
elif (temp_chunk.ID==OBJECT_BLOCK):
|
||||
process_object_block(file, temp_chunk,new_object_list)
|
||||
else:
|
||||
skip_to_end(file,temp_chunk)
|
||||
|
||||
new_chunk.bytes_read+=temp_chunk.bytes_read
|
||||
else:
|
||||
skip_to_end(file,new_chunk)
|
||||
|
||||
previous_chunk.bytes_read+=new_chunk.bytes_read
|
||||
|
||||
#***********************************************
|
||||
# main entry point for loading 3ds files
|
||||
#***********************************************
|
||||
def load_3ds (filename):
|
||||
current_chunk=chunk()
|
||||
print "--------------------------------"
|
||||
print 'Importing "%s"' % filename
|
||||
time1 = Blender.sys.time() #for timing purposes
|
||||
file=open(filename,"rb")
|
||||
new_object_list = []
|
||||
|
||||
global FILENAME
|
||||
FILENAME=filename
|
||||
|
||||
read_chunk(file, current_chunk)
|
||||
|
||||
if (current_chunk.ID!=PRIMARY):
|
||||
print "\tFatal Error: Not a valid 3ds file: ", filename
|
||||
file.close()
|
||||
return
|
||||
|
||||
process_main_chunk(file, current_chunk, new_object_list)
|
||||
|
||||
# Select all new objects.
|
||||
for ob in new_object_list: ob.sel = 1
|
||||
|
||||
print 'finished importing: "%s" in %.4f sec.' % (filename, (Blender.sys.time()-time1))
|
||||
file.close()
|
||||
|
||||
#***********************************************
|
||||
# MAIN
|
||||
#***********************************************
|
||||
def my_callback(filename):
|
||||
load_3ds(filename)
|
||||
|
||||
Blender.Window.FileSelector(my_callback, "Import 3DS", '*.3ds')
|
||||
|
||||
# For testing compatibility
|
||||
'''
|
||||
TIME = Blender.sys.time()
|
||||
import os
|
||||
for _3ds in os.listdir('/3ds/'):
|
||||
if _3ds.lower().endswith('3ds'):
|
||||
print _3ds
|
||||
newScn = Scene.New(_3ds)
|
||||
newScn.makeCurrent()
|
||||
my_callback('/3ds/' + _3ds)
|
||||
|
||||
print "TOTAL TIME: ", Blender.sys.time() - TIME
|
||||
'''
|
||||
602
release/scripts/blenderLipSynchro.py
Normal file
602
release/scripts/blenderLipSynchro.py
Normal file
@@ -0,0 +1,602 @@
|
||||
#!BPY
|
||||
|
||||
"""
|
||||
Name: 'BlenderLipSynchro'
|
||||
Blender: 239
|
||||
Group: 'Animation'
|
||||
Tooltip: 'Import phonemes from Papagayo or JLipSync for lip synchronisation'
|
||||
"""
|
||||
|
||||
__author__ = "Dienben: Benoit Foucque dienben_mail@yahoo.fr"
|
||||
__url__ = ("blenderLipSynchro Blog, http://blenderlipsynchro.blogspot.com/",
|
||||
"Papagayo (Python), http://www.lostmarble.com/papagayo/index.shtml",
|
||||
"JLipSync (Java), http://jlipsync.sourceforge.net/")
|
||||
__version__ = "1.2"
|
||||
__bpydoc__ = """\
|
||||
Description:
|
||||
|
||||
This script imports Voice Export made by Papagayo or JLipSync and maps the export with your shapes.
|
||||
|
||||
Usage:
|
||||
|
||||
Import a Papagayo or JLipSync voice export file and link it with your shapes.
|
||||
|
||||
Note:<br>
|
||||
- Naturally, you need files exported from one of the supported lip synching
|
||||
programs. Check their sites to learn more and download them.
|
||||
|
||||
"""
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# BlenderLipSynchro
|
||||
# --------------------------------------------------------------------------
|
||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# ***** END GPL LICENCE BLOCK *****
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
#il y a 3 etapes
|
||||
#la deuxieme on charge le dictionnaire de correspondance
|
||||
#la troisieme on fait le choix des correpondance
|
||||
#la quatrieme on construit les cles a partir du fichiers frame
|
||||
|
||||
#there are 3 stage
|
||||
#the second one load the mapping dictionnary
|
||||
#the tird make the mapping
|
||||
#the fourth make the key in the IPO Curve
|
||||
|
||||
#voici mes differents imports
|
||||
#the imports
|
||||
import os
|
||||
import Blender
|
||||
|
||||
from Blender import Ipo
|
||||
from Blender.Draw import *
|
||||
from Blender.BGL import *
|
||||
|
||||
|
||||
|
||||
#ici commencent mes fonctions
|
||||
#here begin my functions
|
||||
#cette fonction trace l'interface graphique
|
||||
#this functions draw the User interface
|
||||
def trace():
|
||||
#voici mes variables pouvant etre modifie
|
||||
#my variables
|
||||
global fichier_dico,repertoire_dictionaire,iponame,repertoire_phoneme,fichier_text,nbr_phoneme
|
||||
global let01, let02, let03, let04,let05, let06, let07, let08, let09, let10
|
||||
global let11, let12, let13, let14,let15, let16, let17, let18, let19, let20
|
||||
global let21, let22, let23, let24
|
||||
|
||||
global let01selectkey,let02selectkey,let03selectkey,let04selectkey,let05selectkey
|
||||
global let06selectkey,let07selectkey,let08selectkey,let09selectkey,let10selectkey,let11selectkey
|
||||
global let12selectkey,let13selectkey,let14selectkey,let15selectkey,let16selectkey,let17selectkey
|
||||
global let18selectkey,let19selectkey,let20selectkey,let21selectkey,let22selectkey,let23selectkey
|
||||
global let24selectkey
|
||||
|
||||
glClearColor(0.4,0.5,0.6 ,0.0)
|
||||
glClear(GL_COLOR_BUFFER_BIT)
|
||||
|
||||
glColor3d(1,1,1)
|
||||
glRasterPos2i(87, 375)
|
||||
Text("Blendersynchro V 1.1")
|
||||
glColor3d(1,1,1)
|
||||
glRasterPos2i(84, 360)
|
||||
Text("Programation: Dienben")
|
||||
|
||||
glColor3d(0,0,0)
|
||||
glRasterPos2i(13, 342)
|
||||
Text("Papagayo File importer")
|
||||
glColor3d(0,0,0)
|
||||
glRasterPos2i(13, 326)
|
||||
Text("Thanks to Chris Clawson and Liubomir Kovatchev")
|
||||
|
||||
glColor3d(1,1,1)
|
||||
glRasterPos2i(5, 320)
|
||||
Text("_______________________________________________________")
|
||||
glColor3d(0,0,0)
|
||||
glRasterPos2i(6, 318)
|
||||
Text("_______________________________________________________")
|
||||
|
||||
|
||||
if (etape==1):
|
||||
#cette etape permet de choisi la correspondance entre les phonemes et les cles
|
||||
#this stage offer the possibility to choose the mapping between phonems and shapes
|
||||
|
||||
glColor3d(1,1,1)
|
||||
glRasterPos2i(140, 300)
|
||||
Text("Objet: "+Blender.Object.GetSelected()[0].getName() )
|
||||
|
||||
glColor3d(1,1,1)
|
||||
glRasterPos2i(5, 215)
|
||||
Text("Assign phonems to shapes:")
|
||||
|
||||
#on mesure la taille de la liste de phonemes
|
||||
#this is the lenght of the phonem list
|
||||
nbr_phoneme=len(liste_phoneme)
|
||||
|
||||
#on dessine les listes de choix
|
||||
#we draw the choice list
|
||||
|
||||
let01 = String(" ", 4, 5, 185, 30, 16, liste_phoneme[0], 3)
|
||||
glColor3d(0,0,0)
|
||||
glRasterPos2i(40, 188)
|
||||
Text("=")
|
||||
let01selectkey = Menu(key_menu, 50, 50, 185, 70, 16, let01selectkey.val)
|
||||
|
||||
|
||||
let02 = String(" ", 4, 150, 185, 30, 16, liste_phoneme[1], 2)
|
||||
glColor3d(0,0,0)
|
||||
glRasterPos2i(185, 188)
|
||||
Text("=")
|
||||
let02selectkey = Menu(key_menu, 51, 195, 185, 70, 16, let02selectkey.val)
|
||||
|
||||
|
||||
let03 = String(" ", 4, 5, 165, 30, 16, liste_phoneme[2], 2)
|
||||
glColor3d(0,0,0)
|
||||
glRasterPos2i(40, 168)
|
||||
Text("=")
|
||||
let03selectkey = Menu(key_menu, 52, 50, 165, 70, 16, let03selectkey.val)
|
||||
|
||||
|
||||
let04 = String(" ", 4, 150, 165, 30, 16, liste_phoneme[3], 2)
|
||||
glColor3d(0,0,0)
|
||||
glRasterPos2i(185, 168)
|
||||
Text("=")
|
||||
let04selectkey = Menu(key_menu, 53, 195, 165, 70, 16, let04selectkey.val)
|
||||
|
||||
|
||||
let05 = String(" ", 4, 5, 145, 30, 16, liste_phoneme[4], 2)
|
||||
glColor3d(0,0,0)
|
||||
glRasterPos2i(40, 148)
|
||||
Text("=")
|
||||
let05selectkey = Menu(key_menu, 54, 50, 145, 70, 16, let05selectkey.val)
|
||||
|
||||
|
||||
let06 = String(" ", 4, 150, 145, 30, 16, liste_phoneme[5], 2)
|
||||
glColor3d(0,0,0)
|
||||
glRasterPos2i(185, 148)
|
||||
Text("=")
|
||||
let06selectkey = Menu(key_menu, 55, 195, 145, 70, 16, let06selectkey.val)
|
||||
|
||||
|
||||
let07 = String(" ", 4, 5, 125, 30, 16, liste_phoneme[6], 2)
|
||||
glColor3d(0,0,0)
|
||||
glRasterPos2i(40, 128)
|
||||
Text("=")
|
||||
let07selectkey = Menu(key_menu, 56, 50, 125, 70, 16, let07selectkey.val)
|
||||
|
||||
#
|
||||
let08 = String(" ", 4, 150, 125, 30, 16, liste_phoneme[7], 2)
|
||||
glColor3d(0,0,0)
|
||||
glRasterPos2i(185, 128)
|
||||
Text("=")
|
||||
let08selectkey = Menu(key_menu, 57, 195, 125, 70, 16,let08selectkey.val)
|
||||
|
||||
|
||||
let09 = String(" ", 4, 5, 105, 30, 16, liste_phoneme[8], 2)
|
||||
glColor3d(0,0,0)
|
||||
glRasterPos2i(40, 108)
|
||||
Text("=")
|
||||
let09selectkey = Menu(key_menu, 58, 50, 105, 70, 16,let09selectkey.val)
|
||||
|
||||
|
||||
let10 = String(" ", 4, 150, 105, 30, 16, liste_phoneme[9], 2)
|
||||
glColor3d(0,0,0)
|
||||
glRasterPos2i(185, 108)
|
||||
Text("=")
|
||||
let10selectkey = Menu(key_menu, 59, 195, 105, 70, 16, let10selectkey.val)
|
||||
|
||||
#soft_type = 0:Papagayo
|
||||
#soft_type = 1:JLipSync
|
||||
if (soft_type==1):
|
||||
let11 = String(" ", 4, 5, 85, 30, 16, liste_phoneme[10], 2)
|
||||
glColor3d(0,0,0)
|
||||
glRasterPos2i(40, 88)
|
||||
Text("=")
|
||||
let11selectkey = Menu(key_menu, 60, 50, 85, 70, 16, let11selectkey.val)
|
||||
|
||||
let12 = String(" ", 4, 150, 85, 30, 16, liste_phoneme[11], 2)
|
||||
glColor3d(0,0,0)
|
||||
Text("=")
|
||||
let12selectkey = Menu(key_menu, 61, 195, 85, 70, 16, let12selectkey.val)
|
||||
|
||||
let13 = String(" ", 4, 5, 65, 30, 16, liste_phoneme[12], 2)
|
||||
glColor3d(0,0,0)
|
||||
glRasterPos2i(40, 68)
|
||||
Text("=")
|
||||
let13selectkey = Menu(key_menu, 62, 50, 65, 70, 16, let13selectkey.val)
|
||||
|
||||
let14 = String(" ", 4, 150, 65, 30, 16, liste_phoneme[13], 2)
|
||||
glColor3d(0,0,0)
|
||||
glRasterPos2i(185, 68)
|
||||
Text("=")
|
||||
let14selectkey = Menu(key_menu, 63, 195, 65, 70, 16, let14selectkey.val)
|
||||
|
||||
let15 = String(" ", 4, 5, 45, 30, 16, liste_phoneme[14], 2)
|
||||
glColor3d(0,0,0)
|
||||
glRasterPos2i(40, 48)
|
||||
Text("=")
|
||||
let15selectkey = Menu(key_menu, 64, 50, 45, 70, 16, let15selectkey.val)
|
||||
|
||||
let16 = String(" ", 4, 150, 45, 30, 16, liste_phoneme[15], 2)
|
||||
glColor3d(0,0,0)
|
||||
glRasterPos2i(185, 48)
|
||||
Text("=")
|
||||
let16selectkey = Menu(key_menu, 65, 195, 45, 70, 16, let16selectkey.val)
|
||||
|
||||
let17 = String(" ", 4, 295, 185, 30, 16, liste_phoneme[16], 2)
|
||||
glColor3d(0,0,0)
|
||||
glRasterPos2i(330, 188)
|
||||
Text("=")
|
||||
let17selectkey = Menu(key_menu, 66, 340, 185, 70, 16, let17selectkey.val)
|
||||
|
||||
let18 = String(" ", 4, 440, 185, 70, 16, liste_phoneme[17], 8)
|
||||
glColor3d(0,0,0)
|
||||
glRasterPos2i(515, 188)
|
||||
Text("=")
|
||||
let18selectkey = Menu(key_menu, 67, 525, 185, 70, 16, let18selectkey.val)
|
||||
|
||||
let19 = String(" ", 4, 295, 165, 30, 16, liste_phoneme[18], 2)
|
||||
glColor3d(0,0,0)
|
||||
glRasterPos2i(330, 168)
|
||||
Text("=")
|
||||
let19selectkey = Menu(key_menu, 68, 340, 165, 70, 16, let19selectkey.val)
|
||||
|
||||
let20 = String(" ", 4, 440, 165, 70, 16, liste_phoneme[19], 8)
|
||||
glColor3d(0,0,0)
|
||||
glRasterPos2i(515, 168)
|
||||
Text("=")
|
||||
let20selectkey = Menu(key_menu, 69, 525, 165, 70, 16, let20selectkey.val)
|
||||
|
||||
let21 = String(" ", 4, 295, 145, 30, 16, liste_phoneme[20], 2)
|
||||
glColor3d(0,0,0)
|
||||
glRasterPos2i(330, 148)
|
||||
Text("=")
|
||||
let21selectkey = Menu(key_menu, 70, 340, 145, 70, 16, let21selectkey.val)
|
||||
|
||||
let22 = String(" ", 4, 440, 145, 70, 16, liste_phoneme[21], 8)
|
||||
glColor3d(0,0,0)
|
||||
glRasterPos2i(515, 148)
|
||||
Text("=")
|
||||
let22selectkey = Menu(key_menu, 71, 525, 145, 70, 16, let22selectkey.val)
|
||||
|
||||
let23 = String(" ", 4, 295, 125, 30, 16, liste_phoneme[22], 2)
|
||||
glColor3d(0,0,0)
|
||||
glRasterPos2i(330, 128)
|
||||
Text("=")
|
||||
let23selectkey = Menu(key_menu, 72, 340, 125, 70, 16,let23selectkey.val)
|
||||
|
||||
let24 = String(" ", 4, 440, 125, 70, 16, liste_phoneme[23], 8)
|
||||
glColor3d(0,0,0)
|
||||
glRasterPos2i(515, 128)
|
||||
Text("=")
|
||||
let24selectkey = Menu(key_menu, 73, 525, 125, 70, 16, let24selectkey.val)
|
||||
|
||||
|
||||
Button("Import Text", 3, 155, 5, 145, 22)
|
||||
Button("Choose Voice Export", 4, 120, 250, 250, 22)
|
||||
|
||||
|
||||
if (etape==2):
|
||||
glColor3d(1,1,1)
|
||||
glRasterPos2i(125, 200)
|
||||
Text("Operation Completed")
|
||||
|
||||
if (etape==0):
|
||||
glColor3d(1,1,1)
|
||||
glRasterPos2i(125, 200)
|
||||
Text("Please select a Mesh'Object and Create all the IPO Curves for your Shapes")
|
||||
|
||||
if (etape==3):
|
||||
Button("Papagayo", 5, 155, 250, 250, 22)
|
||||
Button("JlipSync", 6, 155, 225, 250, 22)
|
||||
|
||||
glColor3d(1,1,1)
|
||||
glRasterPos2i(6, 40)
|
||||
Text("_______________________________________________________")
|
||||
glColor3d(0,0,0)
|
||||
glRasterPos2i(6, 38)
|
||||
Text("_______________________________________________________")
|
||||
|
||||
Button("Exit", 1, 305, 5, 80, 22)
|
||||
|
||||
|
||||
|
||||
|
||||
#cette fonction sur evenement quite en cas d'ESC
|
||||
#this functions catch the ESC event and quit
|
||||
def event(evt,val):
|
||||
if (evt == ESCKEY and not val): Exit()
|
||||
|
||||
#cette fonction gere les evenements
|
||||
#the event functions
|
||||
def bevent(evt):
|
||||
global etape,soft_type,liste_phoneme
|
||||
|
||||
if (evt == 1):
|
||||
Exit()
|
||||
|
||||
|
||||
elif (evt == 4):
|
||||
#c'est le choix de l'export pamela
|
||||
#we choose the papagayo export
|
||||
Blender.Window.FileSelector(selectionner_export_papagayo,"Choose Export")
|
||||
|
||||
|
||||
elif (evt == 3):
|
||||
#c'est l'import Papagayo
|
||||
#we import
|
||||
lecture_chaine(mon_fichier_export_pamela,dico_phoneme_export_pamela)
|
||||
construction_dico_correspondance()
|
||||
construction_lipsynchro()
|
||||
#on change d'etape
|
||||
#we change the stage
|
||||
etape=2
|
||||
|
||||
elif (evt == 5):
|
||||
#we choose papagayo
|
||||
soft_type=0
|
||||
liste_phoneme=liste_phoneme_papagayo
|
||||
etape=1
|
||||
|
||||
elif (evt == 6):
|
||||
#we choose jlipsync
|
||||
soft_type=1
|
||||
liste_phoneme=liste_phoneme_jlipsinch
|
||||
etape=1
|
||||
|
||||
Blender.Redraw()
|
||||
|
||||
#cette fonction recupere le nom et le chemin du fichier dictionnaire
|
||||
#we catch the name and the path of the dictionnary
|
||||
def selectionner_export_papagayo(filename):
|
||||
global mon_fichier_export_pamela
|
||||
#debut
|
||||
mon_fichier_export_pamela=filename
|
||||
|
||||
#fonction de lecture de la liste frame phoneme
|
||||
#we read the frame and phonems
|
||||
def lecture_chaine(fichier,liste):
|
||||
mon_fichier=open(fichier)
|
||||
|
||||
#je lis la premiere ligne qui contiens la version de moho
|
||||
#first, we read the moho version
|
||||
mon_fichier.readline()
|
||||
|
||||
#je lis jusqu'a la fin
|
||||
#then we read until the end of the file
|
||||
while 1:
|
||||
ma_ligne=mon_fichier.readline()
|
||||
if ma_ligne=='':
|
||||
break
|
||||
decoup=ma_ligne.split()
|
||||
liste[decoup[0]]=decoup[1]
|
||||
print liste
|
||||
|
||||
|
||||
|
||||
|
||||
#fonction qui construit la liste dictionnaire simple
|
||||
#we make the dictionnary
|
||||
def construction_dictionnaire_phoneme():
|
||||
index_liste=0
|
||||
#je transforme mon dictionnaire en list de tulpes
|
||||
#we transform the list in tulpes
|
||||
ma_liste=dico_phoneme.items()
|
||||
#je parcours ma liste a la recherche d'elements non existant
|
||||
#we read the list to find non existing elements
|
||||
print dico_phoneme
|
||||
for index in range(len(ma_liste)):
|
||||
if ma_liste[index][1] not in liste_phoneme:
|
||||
liste_phoneme[index_liste:index_liste]=[ma_liste[index][1]]
|
||||
index_liste=index_liste+1
|
||||
print liste_phoneme
|
||||
|
||||
|
||||
|
||||
#cette fonction recupere les courbes cible
|
||||
#this functon catch the IPO curve
|
||||
def recuperation_courbe():
|
||||
global key_menu,dico_key
|
||||
|
||||
#on recupere le nom des shapes
|
||||
#we catch the shapes
|
||||
key=Blender.Object.GetSelected()[0].getData().getKey().getBlocks()
|
||||
for n in range(len(key)):
|
||||
#on vire la premi<6D>re cle (en effet basic n'est pas une cle en tant que telle)
|
||||
#we threw away the basic shapes
|
||||
if (n>0):
|
||||
key_menu=key_menu+key[n].name + " %x" + str(n-1) + "|"
|
||||
dico_key[str(n-1)]=Blender.Object.GetSelected()[0].getData().getKey().getIpo().getCurves()[n-1]
|
||||
|
||||
|
||||
print "dico_key"
|
||||
print dico_key
|
||||
print 'end dico_key'
|
||||
|
||||
#cette fonction construit un dictionnaire de correspondance entre les phonemes prononces et les cles a utiliser
|
||||
#we make the dictionnary for the mapping between shapes and phonems
|
||||
def construction_dico_correspondance():
|
||||
global dico_correspondance
|
||||
#je parcours les phonemes
|
||||
#we read the phonems
|
||||
dico_correspondance[liste_phoneme[0]]=dico_key[str(let01selectkey.val)]
|
||||
dico_correspondance[liste_phoneme[1]]=dico_key[str(let02selectkey.val)]
|
||||
dico_correspondance[liste_phoneme[2]]=dico_key[str(let03selectkey.val)]
|
||||
dico_correspondance[liste_phoneme[3]]=dico_key[str(let04selectkey.val)]
|
||||
dico_correspondance[liste_phoneme[4]]=dico_key[str(let05selectkey.val)]
|
||||
dico_correspondance[liste_phoneme[5]]=dico_key[str(let06selectkey.val)]
|
||||
dico_correspondance[liste_phoneme[6]]=dico_key[str(let07selectkey.val)]
|
||||
dico_correspondance[liste_phoneme[7]]=dico_key[str(let08selectkey.val)]
|
||||
dico_correspondance[liste_phoneme[8]]=dico_key[str(let09selectkey.val)]
|
||||
dico_correspondance[liste_phoneme[9]]=dico_key[str(let10selectkey.val)]
|
||||
|
||||
if (soft_type==1):
|
||||
dico_correspondance[liste_phoneme[10]]=dico_key[str(let11selectkey.val)]
|
||||
dico_correspondance[liste_phoneme[11]]=dico_key[str(let12selectkey.val)]
|
||||
dico_correspondance[liste_phoneme[12]]=dico_key[str(let13selectkey.val)]
|
||||
dico_correspondance[liste_phoneme[13]]=dico_key[str(let14selectkey.val)]
|
||||
dico_correspondance[liste_phoneme[14]]=dico_key[str(let15selectkey.val)]
|
||||
dico_correspondance[liste_phoneme[15]]=dico_key[str(let16selectkey.val)]
|
||||
dico_correspondance[liste_phoneme[16]]=dico_key[str(let17selectkey.val)]
|
||||
dico_correspondance[liste_phoneme[17]]=dico_key[str(let18selectkey.val)]
|
||||
dico_correspondance[liste_phoneme[18]]=dico_key[str(let19selectkey.val)]
|
||||
dico_correspondance[liste_phoneme[19]]=dico_key[str(let20selectkey.val)]
|
||||
dico_correspondance[liste_phoneme[20]]=dico_key[str(let21selectkey.val)]
|
||||
dico_correspondance[liste_phoneme[21]]=dico_key[str(let22selectkey.val)]
|
||||
dico_correspondance[liste_phoneme[22]]=dico_key[str(let23selectkey.val)]
|
||||
dico_correspondance[liste_phoneme[23]]=dico_key[str(let24selectkey.val)]
|
||||
|
||||
print dico_correspondance
|
||||
|
||||
|
||||
#cette fonction ajoute un points a la cle donnee a la frame donnee
|
||||
#we add a point to the IPO curve Target
|
||||
def ajoute_point(cle,frame,valeur):
|
||||
cle.setInterpolation('Linear')
|
||||
cle.addBezier((frame,valeur))
|
||||
cle.Recalc()
|
||||
|
||||
#cette fonction parcours le dictionnaire des frame <20> ajouter et construit les points
|
||||
#we add all the point to the IPO Curve
|
||||
def construction_lipsynchro():
|
||||
print "je construit"
|
||||
doublet_old=""
|
||||
#construction de la liste des frame
|
||||
cpt=0
|
||||
liste_frame=[]
|
||||
for frame in dico_phoneme_export_pamela:
|
||||
liste_frame.append(int(frame))
|
||||
cpt=cpt+1
|
||||
liste_frame.sort()
|
||||
print "listeframe"
|
||||
print liste_frame
|
||||
print "fini"
|
||||
|
||||
for doublet in liste_frame:
|
||||
ajoute_point(dico_correspondance[dico_phoneme_export_pamela[str(doublet)]],doublet,1)
|
||||
if (doublet_old==""):
|
||||
ajoute_point(dico_correspondance[dico_phoneme_export_pamela[str(doublet)]],(doublet-2),0)
|
||||
if (doublet_old!=''):
|
||||
if (dico_correspondance[dico_phoneme_export_pamela[str(doublet)]]!=dico_correspondance[dico_phoneme_export_pamela[doublet_old]]):
|
||||
print "doublet:"+str(doublet)
|
||||
print "doublet old:"+doublet_old
|
||||
ajoute_point(dico_correspondance[dico_phoneme_export_pamela[doublet_old]],(int(doublet_old)+2),0)
|
||||
ajoute_point(dico_correspondance[dico_phoneme_export_pamela[str(doublet)]],(doublet-2),0)
|
||||
doublet_old=str(doublet)
|
||||
|
||||
|
||||
#end of my functions we begin the execution
|
||||
#je commence l execution-----------------------------------------------------------------------------------------------
|
||||
#voici mes variables
|
||||
|
||||
#declaration et instanciation
|
||||
#decleration and instanciation
|
||||
#ce sont les repertoires
|
||||
repertoire_dictionaire=Create('C:/')
|
||||
repertoire_phoneme=Create('c:/')
|
||||
|
||||
#ce sont ls fichiers
|
||||
fichier_dico=Create("sample.mot")
|
||||
fichier_text=Create("")
|
||||
|
||||
#voici mon objet de travail
|
||||
objet_travail=Create(0)
|
||||
|
||||
#my soft type
|
||||
soft_type=1
|
||||
|
||||
#voici la liste des phoneme effectivement utilise
|
||||
#the phonems'list
|
||||
liste_phoneme_papagayo=['AI','E','O','U','FV','L','WQ','MBP','etc','rest']
|
||||
liste_phoneme_jlipsinch=['A','B','C','Closed','D','E','F','G','I','K','L','M','N','O','P','Q','R','S','SH','T','TH','U','V','W']
|
||||
|
||||
liste_phoneme=liste_phoneme_jlipsinch
|
||||
#voici mon dictionnaire des frames o
|
||||
dico_phoneme_export_pamela = Create(0)
|
||||
dico_phoneme_export_pamela={}
|
||||
|
||||
|
||||
|
||||
#voici mes cle
|
||||
key_menu=""
|
||||
dico_key={}
|
||||
|
||||
#voici mes ipo
|
||||
dico_bloc={}
|
||||
iponame = Create(0)
|
||||
|
||||
#voici mon dictionnaire de correspondance
|
||||
dico_correspondance={}
|
||||
|
||||
try:
|
||||
#on verifie est bien une mesh et qu'il a des courbes
|
||||
if ((Blender.Object.GetSelected()[0].getType()=='Mesh')):
|
||||
#on verifie que l'objet a bien toute ses Courbes
|
||||
if (len(Blender.Object.GetSelected()[0].getData().getKey().getBlocks())-1==Blender.Object.GetSelected()[0].getData().getKey().getIpo().getNcurves()):
|
||||
etape=3
|
||||
#on lance la creation du dictionnaire
|
||||
recuperation_courbe()
|
||||
else:
|
||||
print "not the good number of IPO Curve"
|
||||
etape = 0
|
||||
else:
|
||||
print "error: bad object Type:"
|
||||
print Blender.Object.GetSelected()[0].getType()
|
||||
etape = 0
|
||||
except:
|
||||
print 'error: exception'
|
||||
etape = 0
|
||||
|
||||
|
||||
#voici le fichier dictionnaire
|
||||
mon_fichier_dico=""
|
||||
|
||||
#voici le fichier export pamela
|
||||
mon_fichier_export_pamela=""
|
||||
|
||||
|
||||
let01selectkey = Create(0)
|
||||
let02selectkey = Create(0)
|
||||
let03selectkey = Create(0)
|
||||
let04selectkey = Create(0)
|
||||
let05selectkey = Create(0)
|
||||
let06selectkey = Create(0)
|
||||
let07selectkey = Create(0)
|
||||
let08selectkey = Create(0)
|
||||
let09selectkey = Create(0)
|
||||
let10selectkey = Create(0)
|
||||
let11selectkey = Create(0)
|
||||
let12selectkey = Create(0)
|
||||
let13selectkey = Create(0)
|
||||
let14selectkey = Create(0)
|
||||
let15selectkey = Create(0)
|
||||
let16selectkey = Create(0)
|
||||
let17selectkey = Create(0)
|
||||
let18selectkey = Create(0)
|
||||
let19selectkey = Create(0)
|
||||
let20selectkey = Create(0)
|
||||
let21selectkey = Create(0)
|
||||
let22selectkey = Create(0)
|
||||
let23selectkey = Create(0)
|
||||
let24selectkey = Create(0)
|
||||
|
||||
|
||||
Register (trace,event,bevent)
|
||||
723
release/scripts/flt_export.py
Executable file
723
release/scripts/flt_export.py
Executable file
@@ -0,0 +1,723 @@
|
||||
#!BPY
|
||||
|
||||
# flt_export.py is an OpenFlight exporter for blender.
|
||||
# Copyright (C) 2005 Greg MacDonald
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
""" Registration info for Blender menus:
|
||||
Name: 'OpenFlight (.flt)...'
|
||||
Blender: 237
|
||||
Group: 'Export'
|
||||
Tip: 'Export to OpenFlight v16.0 (.flt)'
|
||||
"""
|
||||
|
||||
__author__ = "Greg MacDonald"
|
||||
__version__ = "1.2 10/20/05"
|
||||
__url__ = ("blender", "elysiun", "Author's homepage, http://sourceforge.net/projects/blight/")
|
||||
__bpydoc__ = """\
|
||||
This script exports v16.0 OpenFlight files. OpenFlight is a
|
||||
registered trademark of MultiGen-Paradigm, Inc.
|
||||
|
||||
Run from "File->Export" menu.
|
||||
|
||||
Options are available from Blender's "Scripts Config Editor," accessible through
|
||||
the "Scripts->System" menu from the scripts window.
|
||||
|
||||
Features:<br>
|
||||
* Heirarchy retained.<br>
|
||||
* Normals retained.<br>
|
||||
* First texture exported.<br>
|
||||
* Diffuse material color is exported as the face color, material color, or both
|
||||
depending on the option settings.<br>
|
||||
* Double sided faces are exported as two faces.<br>
|
||||
* Object transforms exported.
|
||||
|
||||
Things To Be Aware Of:<br>
|
||||
* Object names are exported, not mesh or data names.
|
||||
* Material indices that don't have a material associated with them will confuse the
|
||||
exporter. If a warning appears about this, correct it by deleting the offending
|
||||
material indices in Blender.
|
||||
|
||||
What's Not Handled:<br>
|
||||
* Animations.<br>
|
||||
* Vetex colors.<br>
|
||||
"""
|
||||
|
||||
import Blender
|
||||
from flt_filewalker import FltOut
|
||||
|
||||
class ExporterOptions:
|
||||
def __init__(self):
|
||||
self.defaults = { 'Diffuse Color To OpenFlight Material': False,
|
||||
'Diffuse Color To OpenFlight Face': True}
|
||||
|
||||
d = Blender.Registry.GetKey('flt_export', True)
|
||||
|
||||
if d == None or d.keys() != self.defaults.keys():
|
||||
d = self.defaults
|
||||
Blender.Registry.SetKey('flt_export', d, True)
|
||||
|
||||
self.verbose = 1
|
||||
self.tolerance = 0.001
|
||||
self.use_mat_color = d['Diffuse Color To OpenFlight Material']
|
||||
self.use_face_color = d['Diffuse Color To OpenFlight Face']
|
||||
|
||||
options = ExporterOptions()
|
||||
|
||||
FLOAT_TOLERANCE = options.tolerance
|
||||
|
||||
identity_matrix = [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]]
|
||||
|
||||
def is_identity(m):
|
||||
for i in xrange(4):
|
||||
for j in xrange(4):
|
||||
if abs(m[i][j] - identity_matrix[i][j]) > FLOAT_TOLERANCE:
|
||||
return False
|
||||
return True
|
||||
|
||||
class MaterialDesc:
|
||||
def __init__(self):
|
||||
self.name = 'Blender'
|
||||
|
||||
# Colors, List of 3 floats.
|
||||
self.diffuse = [1.0, 1.0, 1.0]
|
||||
self.specular = [1.0, 1.0, 1.0]
|
||||
|
||||
# Scalars
|
||||
self.ambient = 0.1 # [0.0, 1.0]
|
||||
self.emissive = 0.0 # [0.0, 1.0]
|
||||
self.shininess = 32.0 # Range is [0.0, 128.0]
|
||||
self.alpha = 1.0 # Range is [0.0, 1.0]
|
||||
|
||||
class VertexDesc:
|
||||
def __init__(self, co=None, no=None, uv=None):
|
||||
if co: self.x, self.y, self.z = tuple(co)
|
||||
else: self.x = self.y = self.z = 0.0
|
||||
if no: self.nx, self.ny, self.nz = tuple(no)
|
||||
else: self.nx = self.ny = self.nz = 0.0
|
||||
if uv: self.u, self.v = tuple(uv)
|
||||
else: self.u = self.v = 0.0
|
||||
|
||||
class GlobalResourceRepository:
|
||||
def new_face_name(self):
|
||||
self.face_name += 1
|
||||
return 'f%i' % (self.face_name-1)
|
||||
|
||||
def vertex_count(self):
|
||||
return len(self.vertex_lst)
|
||||
|
||||
def request_vertex_desc(self, i):
|
||||
return self.vertex_lst[i]
|
||||
|
||||
def request_vertex_index(self, desc):
|
||||
match = None
|
||||
for i, v in enumerate(self.vertex_lst):
|
||||
if\
|
||||
abs(v.x - desc.x) > FLOAT_TOLERANCE or\
|
||||
abs(v.y - desc.y) > FLOAT_TOLERANCE or\
|
||||
abs(v.z - desc.z) > FLOAT_TOLERANCE or\
|
||||
abs(v.nx - desc.nx) > FLOAT_TOLERANCE or\
|
||||
abs(v.ny - desc.ny) > FLOAT_TOLERANCE or\
|
||||
abs(v.nz - desc.nz) > FLOAT_TOLERANCE or\
|
||||
abs(v.u - desc.u) > FLOAT_TOLERANCE or\
|
||||
abs(v.v - desc.v) > FLOAT_TOLERANCE:
|
||||
pass
|
||||
else:
|
||||
match = i
|
||||
break
|
||||
|
||||
if match != None:
|
||||
return match
|
||||
else:
|
||||
self.vertex_lst.append(desc)
|
||||
return len(self.vertex_lst) - 1
|
||||
|
||||
def request_texture_index(self, filename):
|
||||
match = None
|
||||
for i in xrange(len(self.texture_lst)):
|
||||
if self.texture_lst[i] != filename:
|
||||
continue
|
||||
match = i
|
||||
break
|
||||
if match != None:
|
||||
return match
|
||||
else:
|
||||
self.texture_lst.append(filename)
|
||||
return len(self.texture_lst) - 1
|
||||
|
||||
def request_texture_filename(self, index):
|
||||
return self.texture_lst[index]
|
||||
|
||||
def texture_count(self):
|
||||
return len(self.texture_lst)
|
||||
|
||||
def request_material_index(self, desc):
|
||||
match = None
|
||||
for i in xrange(len(self.material_lst)):
|
||||
if self.material_lst[i].diffuse != desc.diffuse:
|
||||
continue
|
||||
if self.material_lst[i].specular != desc.specular:
|
||||
continue
|
||||
if self.material_lst[i].ambient != desc.ambient:
|
||||
continue
|
||||
if self.material_lst[i].emissive != desc.emissive:
|
||||
continue
|
||||
if self.material_lst[i].shininess != desc.shininess:
|
||||
continue
|
||||
if self.material_lst[i].alpha != desc.alpha:
|
||||
continue
|
||||
match = i
|
||||
break
|
||||
|
||||
if match != None:
|
||||
return i
|
||||
else:
|
||||
self.material_lst.append(desc)
|
||||
return len(self.material_lst) - 1
|
||||
|
||||
def request_material_desc(self, index):
|
||||
return self.material_lst[index]
|
||||
|
||||
def material_count(self):
|
||||
return len(self.material_lst)
|
||||
|
||||
# Returns not actual index but one that includes intensity information.
|
||||
# color_index = 127*intensity + 128*actual_index
|
||||
def request_color_index(self, col):
|
||||
r,g,b = tuple(col)
|
||||
m = max(r, g, b)
|
||||
if m > 0.0:
|
||||
intensity = m / 1.0
|
||||
r = int(round(r/m * 255.0))
|
||||
g = int(round(g/m * 255.0))
|
||||
b = int(round(b/m * 255.0))
|
||||
brightest = [r, g, b]
|
||||
else:
|
||||
brightest = [255, 255, 255]
|
||||
intensity = 0.0
|
||||
|
||||
match = None
|
||||
for i in xrange(len(self.color_lst)):
|
||||
if self.color_lst[i] != brightest:
|
||||
continue
|
||||
|
||||
match = i
|
||||
break
|
||||
|
||||
if match != None:
|
||||
index = match
|
||||
else:
|
||||
length = len(self.color_lst)
|
||||
if length <= 1024:
|
||||
self.color_lst.append(brightest)
|
||||
index = length
|
||||
else:
|
||||
if options.verbose >= 1:
|
||||
print 'Warning: Exceeded max color limit.'
|
||||
index = 0
|
||||
|
||||
color_index = int(round(127.0*intensity)) + 128*index
|
||||
return color_index
|
||||
|
||||
# Returns color from actual index.
|
||||
def request_max_color(self, index):
|
||||
return self.color_lst[index]
|
||||
|
||||
def color_count(self):
|
||||
return len(self.color_lst)
|
||||
|
||||
def __init__(self):
|
||||
self.vertex_lst = []
|
||||
self.texture_lst = []
|
||||
self.material_lst = []
|
||||
self.color_lst = [[255, 255, 255]]
|
||||
self.face_name = 0
|
||||
|
||||
class Node:
|
||||
# Gathers info from blender needed for export.
|
||||
# The =[0] is a trick to emulate c-like static function variables
|
||||
# that are persistant between calls.
|
||||
def blender_export(self, level=[0]):
|
||||
if self.object:
|
||||
if options.verbose >= 2:
|
||||
print '\t' * level[0], self.name, self.object.getType()
|
||||
|
||||
level[0] += 1
|
||||
|
||||
for child in self.children:
|
||||
child.blender_export()
|
||||
|
||||
level[0] -= 1
|
||||
|
||||
# Exports this node's info to file.
|
||||
def write(self):
|
||||
pass
|
||||
|
||||
def write_matrix(self):
|
||||
if self.matrix and not is_identity(self.matrix):
|
||||
self.header.fw.write_short(49) # Matrix opcode
|
||||
self.header.fw.write_ushort(68) # Length of record
|
||||
for i in xrange(4):
|
||||
for j in xrange(4):
|
||||
self.header.fw.write_float(self.matrix[i][j])
|
||||
|
||||
def write_push(self):
|
||||
self.header.fw.write_short(10)
|
||||
self.header.fw.write_ushort(4)
|
||||
|
||||
def write_pop(self):
|
||||
self.header.fw.write_short(11)
|
||||
self.header.fw.write_ushort(4)
|
||||
|
||||
def write_longid(self, name):
|
||||
length = len(name)
|
||||
if length >= 8:
|
||||
self.header.fw.write_short(33) # Long ID opcode
|
||||
self.header.fw.write_ushort(length+5) # Length of record
|
||||
self.header.fw.write_string(name, length+1) # name + zero terminator
|
||||
|
||||
# Initialization sets up basic tree structure.
|
||||
def __init__(self, parent, header, object, object_lst):
|
||||
self.header = header
|
||||
self.object = object
|
||||
if object:
|
||||
self.name = self.object.getName()
|
||||
self.matrix = self.object.getMatrix('localspace')
|
||||
else:
|
||||
self.name = 'no name'
|
||||
self.matrix = None
|
||||
|
||||
self.children = []
|
||||
self.parent = parent
|
||||
if parent:
|
||||
parent.children.append(self)
|
||||
|
||||
left_over = object_lst[:]
|
||||
self.child_objects = []
|
||||
|
||||
# Add children to child list and remove from left_over list.
|
||||
|
||||
# Pop is faster then remove
|
||||
i = len(object_lst)
|
||||
while i:
|
||||
i-=1
|
||||
if object_lst[i].parent == object:
|
||||
self.child_objects.append(left_over.pop(i))
|
||||
|
||||
# Spawn children.
|
||||
self.has_object_child = False # For Database class.
|
||||
for child in self.child_objects:
|
||||
if child.getType() == 'Mesh':
|
||||
BlenderMesh(self, header, child, left_over)
|
||||
self.has_object_child = True
|
||||
else: # Treat all non meshes as emptys
|
||||
BlenderEmpty(self, header, child, left_over)
|
||||
|
||||
class FaceDesc:
|
||||
def __init__(self):
|
||||
self.vertex_index_lst = []
|
||||
self.texture_index = -1
|
||||
self.material_index = -1
|
||||
self.color_index = 127
|
||||
|
||||
class BlenderMesh(Node):
|
||||
def blender_export(self):
|
||||
Node.blender_export(self)
|
||||
|
||||
mesh = self.object.getData()
|
||||
mesh_hasuv = mesh.hasFaceUV()
|
||||
# Gather materials and textures.
|
||||
tex_index_lst = []
|
||||
mat_index_lst = []
|
||||
color_index_lst = []
|
||||
materials = mesh.getMaterials()
|
||||
|
||||
if not materials:
|
||||
materials = [Blender.Material.New()]
|
||||
|
||||
for mat in materials:
|
||||
# Gather Color.
|
||||
if options.use_face_color:
|
||||
color_index_lst.append(self.header.GRR.request_color_index(mat.getRGBCol()))
|
||||
else:
|
||||
color_index_lst.append(127) # white
|
||||
# Gather Texture.
|
||||
mtex_lst = mat.getTextures()
|
||||
|
||||
index = -1
|
||||
mtex = mtex_lst[0] # Not doing multi-texturing at the moment.
|
||||
if mtex != None:
|
||||
tex = mtex_lst[0].tex
|
||||
if tex != None:
|
||||
image = tex.getImage()
|
||||
if image != None:
|
||||
filename = image.getFilename()
|
||||
index = self.header.GRR.request_texture_index(filename)
|
||||
|
||||
tex_index_lst.append(index)
|
||||
|
||||
# Gather Material
|
||||
mat_desc = MaterialDesc()
|
||||
mat_desc.name = mat.getName()
|
||||
mat_desc.alpha = mat.getAlpha()
|
||||
mat_desc.shininess = mat.getSpec() * 64.0 # 2.0 => 128.0
|
||||
if options.use_mat_color:
|
||||
mat_desc.diffuse = mat.getRGBCol()
|
||||
else:
|
||||
mat_desc.diffuse = [1.0, 1.0, 1.0]
|
||||
|
||||
mat_desc.specular = mat.getSpecCol()
|
||||
amb = mat.getAmb()
|
||||
mat_desc.ambient = [amb, amb, amb]
|
||||
emit = mat.getEmit()
|
||||
mat_desc.emissive = [emit, emit, emit]
|
||||
|
||||
mat_index_lst.append(self.header.GRR.request_material_index(mat_desc))
|
||||
|
||||
# Faces described as lists of indices into the GRR's vertex_lst.
|
||||
for face in mesh.faces:
|
||||
|
||||
face_v = face.v # Faster access
|
||||
|
||||
# Create vertex description list for each face.
|
||||
if mesh_hasuv:
|
||||
vertex_lst = [VertexDesc(v.co, v.no, face.uv[i]) for i, v in enumerate(face_v)]
|
||||
else:
|
||||
vertex_lst = [VertexDesc(v.co, v.no) for i, v in enumerate(face_v)]
|
||||
|
||||
index_lst = []
|
||||
for vert_desc in vertex_lst:
|
||||
index_lst.append(self.header.GRR.request_vertex_index(vert_desc))
|
||||
|
||||
face_desc = FaceDesc()
|
||||
face_desc.vertex_index_lst = index_lst
|
||||
|
||||
if face.materialIndex < len(materials):
|
||||
face_desc.color_index = color_index_lst[face.materialIndex]
|
||||
face_desc.texture_index = tex_index_lst[face.materialIndex]
|
||||
face_desc.material_index = mat_index_lst[face.materialIndex]
|
||||
else:
|
||||
if options.verbose >=1:
|
||||
print 'Warning: Missing material for material index. Materials will not be imported correctly. Fix by deleting abandoned material indices in Blender.'
|
||||
|
||||
self.face_lst.append(face_desc)
|
||||
|
||||
# Export double sided face as 2 faces with opposite orientations.
|
||||
if mesh_hasuv and face.mode & Blender.NMesh.FaceModes['TWOSIDE']:
|
||||
# Create vertex description list for each face. they have a face mode, so we know they have a UV too.
|
||||
vertex_lst = [VertexDesc(v.co, -v.no, face.uv[i]) for i, v in enumerate(face_v)]
|
||||
vertex_lst.reverse() # Reversing flips the face.
|
||||
|
||||
index_lst = []
|
||||
for vert_desc in vertex_lst:
|
||||
index_lst.append(self.header.GRR.request_vertex_index(vert_desc))
|
||||
|
||||
face_desc = FaceDesc()
|
||||
face_desc.vertex_index_lst = index_lst
|
||||
if face.materialIndex < len(materials):
|
||||
face_desc.color_index = color_index_lst[face.materialIndex]
|
||||
face_desc.texture_index = tex_index_lst[face.materialIndex]
|
||||
face_desc.material_index = mat_index_lst[face.materialIndex]
|
||||
else:
|
||||
if options.verbose >=1:
|
||||
print 'Error: No material for material index. Delete abandoned material indices in Blender.'
|
||||
|
||||
self.face_lst.append(face_desc)
|
||||
|
||||
def write_faces(self):
|
||||
for face_desc in self.face_lst:
|
||||
face_name = self.header.GRR.new_face_name()
|
||||
|
||||
self.header.fw.write_short(5) # Face opcode
|
||||
self.header.fw.write_ushort(80) # Length of record
|
||||
self.header.fw.write_string(face_name, 8) # ASCII ID
|
||||
self.header.fw.write_int(-1) # IR color code
|
||||
self.header.fw.write_short(0) # Relative priority
|
||||
self.header.fw.write_char(0) # Draw type
|
||||
self.header.fw.write_char(0) # Draw textured white.
|
||||
self.header.fw.write_ushort(0) # Color name index
|
||||
self.header.fw.write_ushort(0) # Alt color name index
|
||||
self.header.fw.write_char(0) # Reserved
|
||||
self.header.fw.write_char(1) # Template
|
||||
self.header.fw.write_short(-1) # Detail tex pat index
|
||||
self.header.fw.write_short(face_desc.texture_index) # Tex pattern index
|
||||
self.header.fw.write_short(face_desc.material_index) # material index
|
||||
self.header.fw.write_short(0) # SMC code
|
||||
self.header.fw.write_short(0) # Feature code
|
||||
self.header.fw.write_int(0) # IR material code
|
||||
self.header.fw.write_ushort(0) # transparency 0 = opaque
|
||||
self.header.fw.write_uchar(0) # LOD generation control
|
||||
self.header.fw.write_uchar(0) # line style index
|
||||
self.header.fw.write_int(0x00000000) # Flags
|
||||
self.header.fw.write_uchar(2) # Light mode
|
||||
self.header.fw.pad(7) # Reserved
|
||||
self.header.fw.write_uint(-1) # Packed color
|
||||
self.header.fw.write_uint(-1) # Packed alt color
|
||||
self.header.fw.write_short(-1) # Tex map index
|
||||
self.header.fw.write_short(0) # Reserved
|
||||
self.header.fw.write_uint(face_desc.color_index) # Color index
|
||||
self.header.fw.write_uint(127) # Alt color index
|
||||
self.header.fw.write_short(0) # Reserved
|
||||
self.header.fw.write_short(-1) # Shader index
|
||||
|
||||
self.write_longid(face_name)
|
||||
|
||||
self.write_push()
|
||||
|
||||
# Vertex list record
|
||||
self.header.fw.write_short(72) # Vertex list opcode
|
||||
num_verts = len(face_desc.vertex_index_lst)
|
||||
self.header.fw.write_ushort(4*num_verts+4) # Length of record
|
||||
|
||||
for vert_index in face_desc.vertex_index_lst:
|
||||
# Offset into vertex palette
|
||||
self.header.fw.write_int(vert_index*64+8)
|
||||
|
||||
self.write_pop()
|
||||
|
||||
def write(self):
|
||||
if self.open_flight_type == 'Object':
|
||||
self.header.fw.write_short(4) # Object opcode
|
||||
self.header.fw.write_ushort(28) # Length of record
|
||||
self.header.fw.write_string(self.name, 8) # ASCII ID
|
||||
self.header.fw.pad(16)
|
||||
|
||||
self.write_longid(self.name)
|
||||
|
||||
self.write_matrix()
|
||||
|
||||
if self.face_lst != []:
|
||||
self.write_push()
|
||||
|
||||
self.write_faces()
|
||||
|
||||
self.write_pop()
|
||||
else:
|
||||
self.header.fw.write_short(2) # Group opcode
|
||||
self.header.fw.write_ushort(44) # Length of record
|
||||
self.header.fw.write_string(self.name, 8) # ASCII ID
|
||||
self.header.fw.pad(32)
|
||||
|
||||
self.write_longid(self.name)
|
||||
|
||||
# Because a group can contain faces as well as children.
|
||||
self.write_push()
|
||||
|
||||
self.write_faces()
|
||||
|
||||
for child in self.children:
|
||||
child.write()
|
||||
|
||||
self.write_pop()
|
||||
|
||||
def __init__(self, parent, header, object, object_lst):
|
||||
Node.__init__(self, parent, header, object, object_lst)
|
||||
self.face_lst = []
|
||||
|
||||
if self.children:
|
||||
self.open_flight_type= 'Group'
|
||||
else: # Empty list.
|
||||
self.open_flight_type = 'Object'
|
||||
|
||||
|
||||
class BlenderEmpty(Node):
|
||||
def write(self):
|
||||
self.header.fw.write_short(2) # Group opcode
|
||||
self.header.fw.write_ushort(44) # Length of record
|
||||
self.header.fw.write_string(self.name, 8) # ASCII ID
|
||||
self.header.fw.pad(32)
|
||||
|
||||
self.write_longid(self.name)
|
||||
|
||||
self.write_matrix()
|
||||
|
||||
if self.children: # != []
|
||||
self.write_push()
|
||||
|
||||
for child in self.children:
|
||||
child.write()
|
||||
|
||||
self.write_pop()
|
||||
|
||||
class Database(Node):
|
||||
def write_header(self):
|
||||
if options.verbose >= 2:
|
||||
print 'Writing header.'
|
||||
self.fw.write_short(1) # Header opcode
|
||||
self.fw.write_ushort(324) # Length of record
|
||||
self.fw.write_string('db', 8) # ASCII ID
|
||||
self.fw.write_int(1600) # Revision Number
|
||||
self.fw.pad(44)
|
||||
self.fw.write_short(1) # Unit multiplier.
|
||||
self.fw.write_char(0) # Units, 0 = meters
|
||||
self.fw.write_char(0) # texwhite on new faces 0 = false
|
||||
self.fw.write_uint(0x80000000) # misc flags set to saving vertex normals
|
||||
self.fw.pad(24)
|
||||
self.fw.write_int(0) # projection type, 0 = flat earth
|
||||
self.fw.pad(30)
|
||||
self.fw.write_short(1) # double precision
|
||||
self.fw.pad(140)
|
||||
self.fw.write_int(0) # ellipsoid model, 0 = WSG 1984
|
||||
self.fw.pad(52)
|
||||
|
||||
def write_vert_pal(self):
|
||||
if options.verbose >= 2:
|
||||
print 'Writing vertex palette.'
|
||||
# Write record for vertex palette
|
||||
self.fw.write_short(67) # Vertex palette opcode.
|
||||
self.fw.write_short(8) # Length of record
|
||||
self.fw.write_int(self.GRR.vertex_count() * 64 + 8) # Length of everything.
|
||||
|
||||
# Write records for individual vertices.
|
||||
for i in xrange(self.GRR.vertex_count()):
|
||||
desc = self.GRR.request_vertex_desc(i)
|
||||
self.fw.write_short(70) # Vertex with color normal and uv opcode.
|
||||
self.fw.write_ushort(64) # Length of record
|
||||
self.fw.write_ushort(0) # Color name index
|
||||
self.fw.write_short(0x2000) # Flags set to no color
|
||||
self.fw.write_double(desc.x)
|
||||
self.fw.write_double(desc.y)
|
||||
self.fw.write_double(desc.z)
|
||||
self.fw.write_float(desc.nx)
|
||||
self.fw.write_float(desc.ny)
|
||||
self.fw.write_float(desc.nz)
|
||||
self.fw.write_float(desc.u)
|
||||
self.fw.write_float(desc.v)
|
||||
self.fw.pad(12)
|
||||
|
||||
def write_tex_pal(self):
|
||||
if options.verbose >= 2:
|
||||
print 'Writing texture palette.'
|
||||
# Write record for texture palette
|
||||
for i in xrange(self.GRR.texture_count()):
|
||||
self.fw.write_short(64) # Texture palette opcode.
|
||||
self.fw.write_short(216) # Length of record
|
||||
self.fw.write_string(self.GRR.request_texture_filename(i), 200) # Filename
|
||||
self.fw.write_int(i) # Texture index
|
||||
self.fw.write_int(0) # X
|
||||
self.fw.write_int(0) # Y
|
||||
|
||||
def write_mat_pal(self):
|
||||
if options.verbose >= 2:
|
||||
print 'Writing material palette.'
|
||||
for i in xrange(self.GRR.material_count()):
|
||||
desc = self.GRR.request_material_desc(i)
|
||||
self.fw.write_short(113) # Material palette opcode.
|
||||
self.fw.write_short(84) # Length of record
|
||||
self.fw.write_int(i) # Material index
|
||||
self.fw.write_string(desc.name, 12) # Material name
|
||||
self.fw.write_uint(0x80000000) # Flags
|
||||
self.fw.write_float(desc.ambient[0]) # Ambient color.
|
||||
self.fw.write_float(desc.ambient[1]) # Ambient color.
|
||||
self.fw.write_float(desc.ambient[2]) # Ambient color.
|
||||
self.fw.write_float(desc.diffuse[0]) # Diffuse color.
|
||||
self.fw.write_float(desc.diffuse[1]) # Diffuse color.
|
||||
self.fw.write_float(desc.diffuse[2]) # Diffuse color.
|
||||
self.fw.write_float(desc.specular[0]) # Specular color.
|
||||
self.fw.write_float(desc.specular[1]) # Specular color.
|
||||
self.fw.write_float(desc.specular[2]) # Specular color.
|
||||
self.fw.write_float(desc.emissive[0]) # Emissive color.
|
||||
self.fw.write_float(desc.emissive[1]) # Emissive color.
|
||||
self.fw.write_float(desc.emissive[2]) # Emissive color.
|
||||
self.fw.write_float(desc.shininess)
|
||||
self.fw.write_float(desc.alpha)
|
||||
self.fw.write_int(0) # Reserved
|
||||
|
||||
def write_col_pal(self):
|
||||
if options.verbose >= 2:
|
||||
print 'Writing color palette.'
|
||||
self.fw.write_short(32) # Color palette opcode.
|
||||
self.fw.write_short(4228) # Length of record
|
||||
self.fw.pad(128)
|
||||
count = self.GRR.color_count()
|
||||
for i in xrange(count):
|
||||
col = self.GRR.request_max_color(i)
|
||||
self.fw.write_uchar(255) # alpha
|
||||
self.fw.write_uchar(col[2]) # b
|
||||
self.fw.write_uchar(col[1]) # g
|
||||
self.fw.write_uchar(col[0]) # r
|
||||
self.fw.pad(max(4096-count*4, 0))
|
||||
|
||||
def write(self):
|
||||
self.write_header()
|
||||
self.write_vert_pal()
|
||||
self.write_tex_pal()
|
||||
self.write_mat_pal()
|
||||
self.write_col_pal()
|
||||
|
||||
# Wrap everything in a group if it has an object child.
|
||||
if self.has_object_child:
|
||||
self.header.fw.write_short(2) # Group opcode
|
||||
self.header.fw.write_ushort(44) # Length of record
|
||||
self.header.fw.write_string('g1', 8) # ASCII ID
|
||||
self.header.fw.pad(32)
|
||||
|
||||
self.write_push()
|
||||
|
||||
for child in self.children:
|
||||
child.write()
|
||||
|
||||
self.write_pop()
|
||||
|
||||
def __init__(self, scene, fw):
|
||||
self.fw = fw
|
||||
self.scene = scene
|
||||
self.all_objects = scene.getChildren()
|
||||
self.GRR = GlobalResourceRepository()
|
||||
|
||||
Node.__init__(self, None, self, None, self.all_objects)
|
||||
|
||||
def fs_callback(filename):
|
||||
Blender.Window.WaitCursor(True)
|
||||
|
||||
if Blender.sys.exists(filename):
|
||||
r = Blender.Draw.PupMenu('Overwrite ' + filename + '?%t|Yes|No')
|
||||
if r != 1:
|
||||
if options.verbose >= 1:
|
||||
print 'Export cancelled.'
|
||||
return
|
||||
|
||||
time1 = Blender.sys.time() # Start timing
|
||||
|
||||
fw = FltOut(filename)
|
||||
|
||||
db = Database(Blender.Scene.GetCurrent(), fw)
|
||||
|
||||
if options.verbose >= 1:
|
||||
print 'Pass 1: Exporting from Blender.\n'
|
||||
|
||||
db.blender_export()
|
||||
|
||||
if options.verbose >= 1:
|
||||
print 'Pass 2: Writing %s\n' % filename
|
||||
|
||||
db.write()
|
||||
|
||||
fw.close_file()
|
||||
if options.verbose >= 1:
|
||||
print 'Done in %.4f sec.\n' % (Blender.sys.time() - time1)
|
||||
|
||||
Blender.Window.WaitCursor(False)
|
||||
|
||||
if options.verbose >= 1:
|
||||
print '\nOpenFlight Exporter'
|
||||
print 'Version:', __version__
|
||||
print 'Author: Greg MacDonald'
|
||||
print __url__[2]
|
||||
print
|
||||
|
||||
fname = Blender.sys.makename(ext=".flt")
|
||||
Blender.Window.FileSelector(fs_callback, "Export OpenFlight v16.0", fname)
|
||||
278
release/scripts/flt_filewalker.py
Normal file
278
release/scripts/flt_filewalker.py
Normal file
@@ -0,0 +1,278 @@
|
||||
#!BPY
|
||||
|
||||
# flt_filewalker.py is an utility module for OpenFlight IO scripts for blender.
|
||||
# Copyright (C) 2005 Greg MacDonald
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
import Blender
|
||||
from struct import *
|
||||
import re
|
||||
|
||||
class FltIn:
|
||||
def begin_record(self):
|
||||
if self.repeat == True:
|
||||
self.repeat = False
|
||||
else:
|
||||
self.position += self.length
|
||||
try:
|
||||
self.file.seek(self.position)
|
||||
input = self.file.read(4)
|
||||
except:
|
||||
print 'Parse Error!'
|
||||
return False
|
||||
|
||||
if not input:
|
||||
self.close_file()
|
||||
return False
|
||||
|
||||
self.opcode = unpack('>h', input[:2])[0]
|
||||
self.length = unpack('>H', input[-2:])[0]
|
||||
|
||||
self.next_position = self.position + self.length
|
||||
|
||||
return True
|
||||
|
||||
def repeat_record(self):
|
||||
self.repeat = True
|
||||
|
||||
def get_opcode(self):
|
||||
return self.opcode
|
||||
|
||||
def get_level(self):
|
||||
return self.level
|
||||
|
||||
def up_level(self):
|
||||
self.level += 1
|
||||
|
||||
def down_level(self):
|
||||
self.level -= 1
|
||||
|
||||
def read_string(self, length):
|
||||
s = ''
|
||||
if self.file.tell() + length <= self.next_position:
|
||||
start = self.file.tell()
|
||||
for i in range(length):
|
||||
char = self.file.read(1)
|
||||
if char == '\x00':
|
||||
break
|
||||
s = s + char
|
||||
|
||||
self.file.seek(start+length)
|
||||
# else:
|
||||
# print 'Warning: string truncated'
|
||||
|
||||
return s
|
||||
|
||||
def read_int(self):
|
||||
if self.file.tell() + 4 <= self.next_position:
|
||||
return unpack('>i', self.file.read(4))[0]
|
||||
else:
|
||||
#print 'Warning: int truncated'
|
||||
return 0
|
||||
|
||||
def read_uint(self):
|
||||
if self.file.tell() + 4 <= self.next_position:
|
||||
return unpack('>I', self.file.read(4))[0]
|
||||
else:
|
||||
#print 'Warning: uint truncated'
|
||||
return 0
|
||||
|
||||
def read_double(self):
|
||||
if self.file.tell() + 8 <= self.next_position:
|
||||
return unpack('>d', self.file.read(8))[0]
|
||||
else:
|
||||
#print 'Warning: double truncated'
|
||||
return 0.0
|
||||
|
||||
def read_float(self):
|
||||
if self.file.tell() + 4 <= self.next_position:
|
||||
return unpack('>f', self.file.read(4))[0]
|
||||
else:
|
||||
#print 'Warning: float truncated'
|
||||
return 0.0
|
||||
|
||||
def read_ushort(self):
|
||||
if self.file.tell() + 2 <= self.next_position:
|
||||
return unpack('>H', self.file.read(2))[0]
|
||||
else:
|
||||
#print 'Warning: ushort truncated'
|
||||
return 0
|
||||
|
||||
def read_short(self):
|
||||
if self.file.tell() + 2 <= self.next_position:
|
||||
return unpack('>h', self.file.read(2))[0]
|
||||
else:
|
||||
#print 'Warning: short trunated'
|
||||
return 0
|
||||
|
||||
def read_uchar(self):
|
||||
if self.file.tell() + 1 <= self.next_position:
|
||||
return unpack('>B', self.file.read(1))[0]
|
||||
else:
|
||||
#print 'Warning: uchar truncated'
|
||||
return 0
|
||||
|
||||
def read_char(self):
|
||||
if self.file.tell() + 1 <= self.next_position:
|
||||
return unpack('>b', self.file.read(1))[0]
|
||||
else:
|
||||
#print 'Warning: char truncated'
|
||||
return 0
|
||||
|
||||
def read_ahead(self, i):
|
||||
if self.file.tell() + i <= self.next_position:
|
||||
self.file.seek(i, 1)
|
||||
# else:
|
||||
# print 'Warning: attempt to seek past record'
|
||||
|
||||
def get_length(self):
|
||||
return self.length
|
||||
|
||||
def close_file(self):
|
||||
self.file.close()
|
||||
|
||||
def __init__(self, filename):
|
||||
self.file = open(filename, 'rb')
|
||||
self.position = 0
|
||||
self.next_position = 100000
|
||||
self.opcode = 0
|
||||
self.length = 0
|
||||
self.level = 0
|
||||
self.repeat = False # Repeat the last record.
|
||||
|
||||
class FltOut:
|
||||
# Length includes terminating null
|
||||
def write_string(self, string, length):
|
||||
if len(string) > length - 1:
|
||||
str_len = length - 1
|
||||
else:
|
||||
str_len = len(string)
|
||||
|
||||
pad_len = length - str_len
|
||||
|
||||
self.file.write(string[:str_len])
|
||||
|
||||
self.pad(pad_len)
|
||||
|
||||
def write_int(self, a):
|
||||
self.file.write( pack('>i', a) )
|
||||
|
||||
def write_uint(self, a):
|
||||
self.file.write( pack('>I', a) )
|
||||
|
||||
def write_double(self, a):
|
||||
self.file.write( pack('>d', a) )
|
||||
|
||||
def write_float(self, a):
|
||||
self.file.write( pack('>f', a) )
|
||||
|
||||
def write_ushort(self, a):
|
||||
self.file.write( pack('>H', a) )
|
||||
|
||||
def write_short(self, a):
|
||||
self.file.write( pack('>h', a) )
|
||||
|
||||
def write_uchar(self, a):
|
||||
self.file.write( pack('>B', a) )
|
||||
|
||||
def write_char(self, a):
|
||||
self.file.write( pack('>b', a) )
|
||||
|
||||
def pad(self, reps):
|
||||
for i in range(reps):
|
||||
self.file.write('\x00')
|
||||
|
||||
def close_file(self):
|
||||
self.file.close()
|
||||
|
||||
def __init__(self, filename):
|
||||
self.file = open(filename, 'wb')
|
||||
|
||||
class FileFinder:
|
||||
def add_file_to_search_path(self, filename):
|
||||
dir = Blender.sys.dirname(filename)
|
||||
if dir != None and dir != '':
|
||||
self.search_dirs.append(dir)
|
||||
|
||||
def strip_path(self, full_path):
|
||||
# One of my flt files had a windows path with unix seperation. Basename
|
||||
# returned the whole path + filename, which isn't expected. So my
|
||||
# attempt to fix it is to replace all / or \ with the platform specific
|
||||
# dir seperator.
|
||||
#
|
||||
# note: \\\\ is actually just one \ indirected twice, once for python
|
||||
# then again for re.sub
|
||||
if Blender.sys.sep == '\\':
|
||||
full_path = re.sub('/', '\\\\', full_path)
|
||||
elif Blender.sys.sep == '/':
|
||||
full_path = re.sub('\\\\', '/', full_path)
|
||||
|
||||
filename = Blender.sys.basename(full_path)
|
||||
return filename
|
||||
|
||||
def find(self, full_path):
|
||||
if full_path == '':
|
||||
return None
|
||||
|
||||
# Seperate out the path.
|
||||
dirname = Blender.sys.dirname(full_path)
|
||||
|
||||
# Try it first.
|
||||
if Blender.sys.exists(full_path):
|
||||
if not dirname in self.search_dirs:
|
||||
self.search_dirs.append(dirname)
|
||||
return full_path
|
||||
|
||||
# Maybe it's relative.
|
||||
for path in self.search_dirs:
|
||||
rel_full_path = Blender.sys.join(path, full_path)
|
||||
if Blender.sys.exists(rel_full_path):
|
||||
return rel_full_path
|
||||
|
||||
# Search previous directories that have worked.
|
||||
filename = self.strip_path(full_path)
|
||||
for path in self.search_dirs:
|
||||
t = Blender.sys.join(path, filename)
|
||||
if Blender.sys.exists(t):
|
||||
return t
|
||||
|
||||
# Ask user where it is.
|
||||
self.user_input = Blender.Draw.PupStrInput(filename + "? ", '', 100)
|
||||
if self.user_input != None:
|
||||
t = Blender.sys.join(self.user_input, filename)
|
||||
if Blender.sys.exists(t):
|
||||
user_dirname = Blender.sys.dirname(t)
|
||||
if not user_dirname in self.search_dirs:
|
||||
self.search_dirs.append(user_dirname)
|
||||
return t
|
||||
|
||||
# Couldn't find it.
|
||||
return None
|
||||
|
||||
def __init__(self):
|
||||
self.user_input = ''
|
||||
self.current_file = ''
|
||||
self.search_dirs = []
|
||||
|
||||
dir = Blender.Get('texturesdir')
|
||||
if dir != None and dir != '':
|
||||
self.search_dirs.append(dir)
|
||||
|
||||
dir = Blender.sys.dirname(Blender.Get('filename'))
|
||||
if dir != None and dir != '':
|
||||
print dir
|
||||
self.search_dirs.append(dir)
|
||||
|
||||
1803
release/scripts/flt_import.py
Executable file
1803
release/scripts/flt_import.py
Executable file
File diff suppressed because it is too large
Load Diff
1016
release/scripts/md2_export.py
Normal file
1016
release/scripts/md2_export.py
Normal file
File diff suppressed because it is too large
Load Diff
571
release/scripts/md2_import.py
Normal file
571
release/scripts/md2_import.py
Normal file
@@ -0,0 +1,571 @@
|
||||
#!BPY
|
||||
|
||||
"""
|
||||
Name: 'MD2 (.md2)'
|
||||
Blender: 239
|
||||
Group: 'Import'
|
||||
Tooltip: 'Import from Quake file format (.md2).'
|
||||
"""
|
||||
|
||||
__author__ = 'Bob Holcomb'
|
||||
__version__ = '0.15'
|
||||
__url__ = ["Bob's site, http://bane.servebeer.com",
|
||||
"Support forum, http://scourage.servebeer.com/phpbb/", "blender", "elysiun"]
|
||||
__email__ = ["Bob Holcomb, bob_holcomb:hotmail*com", "scripts"]
|
||||
__bpydoc__ = """\
|
||||
This script imports a Quake 2 file (MD2), textures,
|
||||
and animations into blender for editing. Loader is based on MD2 loader from www.gametutorials.com-Thanks DigiBen! and the md3 blender loader by PhaethonH <phaethon@linux.ucla.edu><br>
|
||||
|
||||
Additional help from: Shadwolf, Skandal, Rojo, Cambo<br>
|
||||
Thanks Guys!
|
||||
"""
|
||||
|
||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||
#
|
||||
# Script copyright (C) Bob Holcomb
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# ***** END GPL LICENCE BLOCK *****
|
||||
# --------------------------------------------------------------------------
|
||||
|
||||
|
||||
import Blender
|
||||
from Blender import NMesh, Object, sys
|
||||
from Blender.BGL import *
|
||||
from Blender.Draw import *
|
||||
from Blender.Window import *
|
||||
from Blender.Image import *
|
||||
|
||||
import struct, string
|
||||
from types import *
|
||||
|
||||
|
||||
|
||||
|
||||
######################################################
|
||||
# Main Body
|
||||
######################################################
|
||||
|
||||
#returns the string from a null terminated string
|
||||
def asciiz (s):
|
||||
n = 0
|
||||
while (ord(s[n]) != 0):
|
||||
n = n + 1
|
||||
return s[0:n]
|
||||
|
||||
|
||||
######################################################
|
||||
# MD2 Model Constants
|
||||
######################################################
|
||||
MD2_MAX_TRIANGLES=4096
|
||||
MD2_MAX_VERTICES=2048
|
||||
MD2_MAX_TEXCOORDS=2048
|
||||
MD2_MAX_FRAMES=512
|
||||
MD2_MAX_SKINS=32
|
||||
MD2_MAX_FRAMESIZE=(MD2_MAX_VERTICES * 4 + 128)
|
||||
|
||||
######################################################
|
||||
# MD2 data structures
|
||||
######################################################
|
||||
class md2_alias_triangle:
|
||||
vertices=[]
|
||||
lightnormalindex=0
|
||||
|
||||
binary_format="<3BB" #little-endian (<), 3 Unsigned char
|
||||
|
||||
def __init__(self):
|
||||
self.vertices=[0]*3
|
||||
self.lightnormalindex=0
|
||||
|
||||
def load(self, file):
|
||||
temp_data = file.read(struct.calcsize(self.binary_format))
|
||||
data = struct.unpack(self.binary_format, temp_data)
|
||||
self.vertices[0]=data[0]
|
||||
self.vertices[1]=data[1]
|
||||
self.vertices[2]=data[2]
|
||||
self.lightnormalindex=data[3]
|
||||
return self
|
||||
|
||||
def dump(self):
|
||||
print "MD2 Alias_Triangle Structure"
|
||||
print "vertex: ", self.vertices[0]
|
||||
print "vertex: ", self.vertices[1]
|
||||
print "vertex: ", self.vertices[2]
|
||||
print "lightnormalindex: ",self.lightnormalindex
|
||||
print ""
|
||||
|
||||
class md2_face:
|
||||
vertex_index=[]
|
||||
texture_index=[]
|
||||
|
||||
binary_format="<3h3h" #little-endian (<), 3 short, 3 short
|
||||
|
||||
def __init__(self):
|
||||
self.vertex_index = [ 0, 0, 0 ]
|
||||
self.texture_index = [ 0, 0, 0]
|
||||
|
||||
def load (self, file):
|
||||
temp_data=file.read(struct.calcsize(self.binary_format))
|
||||
data=struct.unpack(self.binary_format, temp_data)
|
||||
self.vertex_index[0]=data[0]
|
||||
self.vertex_index[1]=data[1]
|
||||
self.vertex_index[2]=data[2]
|
||||
self.texture_index[0]=data[3]
|
||||
self.texture_index[1]=data[4]
|
||||
self.texture_index[2]=data[5]
|
||||
return self
|
||||
|
||||
def dump (self):
|
||||
print "MD2 Face Structure"
|
||||
print "vertex index: ", self.vertex_index[0]
|
||||
print "vertex index: ", self.vertex_index[1]
|
||||
print "vertex index: ", self.vertex_index[2]
|
||||
print "texture index: ", self.texture_index[0]
|
||||
print "texture index: ", self.texture_index[1]
|
||||
print "texture index: ", self.texture_index[2]
|
||||
print ""
|
||||
|
||||
class md2_tex_coord:
|
||||
u=0
|
||||
v=0
|
||||
|
||||
binary_format="<2h" #little-endian (<), 2 unsigned short
|
||||
|
||||
def __init__(self):
|
||||
self.u=0
|
||||
self.v=0
|
||||
|
||||
def load (self, file):
|
||||
temp_data=file.read(struct.calcsize(self.binary_format))
|
||||
data=struct.unpack(self.binary_format, temp_data)
|
||||
self.u=data[0]
|
||||
self.v=data[1]
|
||||
return self
|
||||
|
||||
def dump (self):
|
||||
print "MD2 Texture Coordinate Structure"
|
||||
print "texture coordinate u: ",self.u
|
||||
print "texture coordinate v: ",self.v
|
||||
print ""
|
||||
|
||||
|
||||
class md2_skin:
|
||||
name=""
|
||||
|
||||
binary_format="<64s" #little-endian (<), char[64]
|
||||
|
||||
def __init__(self):
|
||||
self.name=""
|
||||
|
||||
def load (self, file):
|
||||
temp_data=file.read(struct.calcsize(self.binary_format))
|
||||
data=struct.unpack(self.binary_format, temp_data)
|
||||
self.name=asciiz(data[0])
|
||||
return self
|
||||
|
||||
def dump (self):
|
||||
print "MD2 Skin"
|
||||
print "skin name: ",self.name
|
||||
print ""
|
||||
|
||||
class md2_alias_frame:
|
||||
scale=[]
|
||||
translate=[]
|
||||
name=[]
|
||||
vertices=[]
|
||||
|
||||
binary_format="<3f3f16s" #little-endian (<), 3 float, 3 float char[16]
|
||||
#did not add the "3bb" to the end of the binary format
|
||||
#because the alias_vertices will be read in through
|
||||
#thier own loader
|
||||
|
||||
def __init__(self):
|
||||
self.scale=[0.0]*3
|
||||
self.translate=[0.0]*3
|
||||
self.name=""
|
||||
self.vertices=[]
|
||||
|
||||
|
||||
def load (self, file):
|
||||
temp_data=file.read(struct.calcsize(self.binary_format))
|
||||
data=struct.unpack(self.binary_format, temp_data)
|
||||
self.scale[0]=data[0]
|
||||
self.scale[1]=data[1]
|
||||
self.scale[2]=data[2]
|
||||
self.translate[0]=data[3]
|
||||
self.translate[1]=data[4]
|
||||
self.translate[2]=data[5]
|
||||
self.name=asciiz(data[6])
|
||||
return self
|
||||
|
||||
def dump (self):
|
||||
print "MD2 Alias Frame"
|
||||
print "scale x: ",self.scale[0]
|
||||
print "scale y: ",self.scale[1]
|
||||
print "scale z: ",self.scale[2]
|
||||
print "translate x: ",self.translate[0]
|
||||
print "translate y: ",self.translate[1]
|
||||
print "translate z: ",self.translate[2]
|
||||
print "name: ",self.name
|
||||
print ""
|
||||
|
||||
class md2_obj:
|
||||
#Header Structure
|
||||
ident=0 #int 0 This is used to identify the file
|
||||
version=0 #int 1 The version number of the file (Must be 8)
|
||||
skin_width=0 #int 2 The skin width in pixels
|
||||
skin_height=0 #int 3 The skin height in pixels
|
||||
frame_size=0 #int 4 The size in bytes the frames are
|
||||
num_skins=0 #int 5 The number of skins associated with the model
|
||||
num_vertices=0 #int 6 The number of vertices (constant for each frame)
|
||||
num_tex_coords=0 #int 7 The number of texture coordinates
|
||||
num_faces=0 #int 8 The number of faces (polygons)
|
||||
num_GL_commands=0 #int 9 The number of gl commands
|
||||
num_frames=0 #int 10 The number of animation frames
|
||||
offset_skins=0 #int 11 The offset in the file for the skin data
|
||||
offset_tex_coords=0 #int 12 The offset in the file for the texture data
|
||||
offset_faces=0 #int 13 The offset in the file for the face data
|
||||
offset_frames=0 #int 14 The offset in the file for the frames data
|
||||
offset_GL_commands=0#int 15 The offset in the file for the gl commands data
|
||||
offset_end=0 #int 16 The end of the file offset
|
||||
|
||||
binary_format="<17i" #little-endian (<), 17 integers (17i)
|
||||
|
||||
#md2 data objects
|
||||
tex_coords=[]
|
||||
faces=[]
|
||||
frames=[]
|
||||
skins=[]
|
||||
|
||||
def __init__ (self):
|
||||
self.tex_coords=[]
|
||||
self.faces=[]
|
||||
self.frames=[]
|
||||
self.skins=[]
|
||||
|
||||
|
||||
def load (self, file):
|
||||
temp_data = file.read(struct.calcsize(self.binary_format))
|
||||
data = struct.unpack(self.binary_format, temp_data)
|
||||
|
||||
self.ident=data[0]
|
||||
self.version=data[1]
|
||||
|
||||
if (self.ident!=844121161 or self.version!=8):
|
||||
print "Not a valid MD2 file"
|
||||
Exit()
|
||||
|
||||
self.skin_width=data[2]
|
||||
self.skin_height=data[3]
|
||||
self.frame_size=data[4]
|
||||
|
||||
#make the # of skin objects for model
|
||||
self.num_skins=data[5]
|
||||
for i in xrange(0,self.num_skins):
|
||||
self.skins.append(md2_skin())
|
||||
|
||||
self.num_vertices=data[6]
|
||||
|
||||
#make the # of texture coordinates for model
|
||||
self.num_tex_coords=data[7]
|
||||
for i in xrange(0,self.num_tex_coords):
|
||||
self.tex_coords.append(md2_tex_coord())
|
||||
|
||||
#make the # of triangle faces for model
|
||||
self.num_faces=data[8]
|
||||
for i in xrange(0,self.num_faces):
|
||||
self.faces.append(md2_face())
|
||||
|
||||
self.num_GL_commands=data[9]
|
||||
|
||||
#make the # of frames for the model
|
||||
self.num_frames=data[10]
|
||||
for i in xrange(0,self.num_frames):
|
||||
self.frames.append(md2_alias_frame())
|
||||
#make the # of vertices for each frame
|
||||
for j in xrange(0,self.num_vertices):
|
||||
self.frames[i].vertices.append(md2_alias_triangle())
|
||||
|
||||
self.offset_skins=data[11]
|
||||
self.offset_tex_coords=data[12]
|
||||
self.offset_faces=data[13]
|
||||
self.offset_frames=data[14]
|
||||
self.offset_GL_commands=data[15]
|
||||
|
||||
#load the skin info
|
||||
file.seek(self.offset_skins,0)
|
||||
for i in xrange(0, self.num_skins):
|
||||
self.skins[i].load(file)
|
||||
#self.skins[i].dump()
|
||||
|
||||
#load the texture coordinates
|
||||
file.seek(self.offset_tex_coords,0)
|
||||
for i in xrange(0, self.num_tex_coords):
|
||||
self.tex_coords[i].load(file)
|
||||
#self.tex_coords[i].dump()
|
||||
|
||||
#load the face info
|
||||
file.seek(self.offset_faces,0)
|
||||
for i in xrange(0, self.num_faces):
|
||||
self.faces[i].load(file)
|
||||
#self.faces[i].dump()
|
||||
|
||||
#load the frames
|
||||
file.seek(self.offset_frames,0)
|
||||
for i in xrange(0, self.num_frames):
|
||||
self.frames[i].load(file)
|
||||
#self.frames[i].dump()
|
||||
for j in xrange(0,self.num_vertices):
|
||||
self.frames[i].vertices[j].load(file)
|
||||
#self.frames[i].vertices[j].dump()
|
||||
return self
|
||||
|
||||
def dump (self):
|
||||
print "Header Information"
|
||||
print "ident: ", self.ident
|
||||
print "version: ", self.version
|
||||
print "skin width: ", self.skin_width
|
||||
print "skin height: ", self.skin_height
|
||||
print "frame size: ", self.frame_size
|
||||
print "number of skins: ", self.num_skins
|
||||
print "number of texture coordinates: ", self.num_tex_coords
|
||||
print "number of faces: ", self.num_faces
|
||||
print "number of frames: ", self.num_frames
|
||||
print "number of vertices: ", self.num_vertices
|
||||
print "offset skins: ", self.offset_skins
|
||||
print "offset texture coordinates: ", self.offset_tex_coords
|
||||
print "offset faces: ", self.offset_faces
|
||||
print "offset frames: ",self.offset_frames
|
||||
print ""
|
||||
|
||||
######################################################
|
||||
# Import functions
|
||||
######################################################
|
||||
def load_textures(md2, texture_filename):
|
||||
#did the user specify a texture they wanted to use?
|
||||
if (texture_filename!="texture"):
|
||||
if (Blender.sys.exists(texture_filename)):
|
||||
mesh_image=Blender.Image.Load(texture_filename)
|
||||
return mesh_image
|
||||
else:
|
||||
result=Blender.Draw.PupMenu("Cannot find texture: "+texture_filename+"-Continue?%t|OK")
|
||||
if(result==1):
|
||||
return -1
|
||||
#does the model have textures specified with it?
|
||||
if int(md2.num_skins) > 0:
|
||||
for i in xrange(0,md2.num_skins):
|
||||
#md2.skins[i].dump()
|
||||
if (Blender.sys.exists(md2.skins[i].name)):
|
||||
mesh_image=Blender.Image.Load(md2.skins[i].name)
|
||||
else:
|
||||
result=Blender.Draw.PupMenu("Cannot find texture: "+md2.skins[i].name+"-Continue?%t|OK")
|
||||
if(result==1):
|
||||
return -1
|
||||
return mesh_image
|
||||
else:
|
||||
result=Blender.Draw.PupMenu("There will be no Texutre"+"-Continue?%t|OK")
|
||||
if(result==1):
|
||||
return -1
|
||||
|
||||
|
||||
def animate_md2(md2, mesh_obj):
|
||||
######### Animate the verts through keyframe animation
|
||||
mesh=mesh_obj.getData()
|
||||
for i in xrange(1, md2.num_frames):
|
||||
#update the vertices
|
||||
for j in xrange(0,md2.num_vertices):
|
||||
x=(md2.frames[i].scale[0]*md2.frames[i].vertices[j].vertices[0]+md2.frames[i].translate[0])*g_scale.val
|
||||
y=(md2.frames[i].scale[1]*md2.frames[i].vertices[j].vertices[1]+md2.frames[i].translate[1])*g_scale.val
|
||||
z=(md2.frames[i].scale[2]*md2.frames[i].vertices[j].vertices[2]+md2.frames[i].translate[2])*g_scale.val
|
||||
|
||||
#put the vertex in the right spot
|
||||
mesh.verts[j].co[0]=y
|
||||
mesh.verts[j].co[1]=-x
|
||||
mesh.verts[j].co[2]=z
|
||||
|
||||
mesh.update()
|
||||
NMesh.PutRaw(mesh, mesh_obj.name)
|
||||
#absolute keys, need to figure out how to get them working around the 100 frame limitation
|
||||
mesh.insertKey(i,"absolute")
|
||||
|
||||
#not really necissary, but I like playing with the frame counter
|
||||
Blender.Set("curframe", i)
|
||||
|
||||
|
||||
def load_md2 (md2_filename, texture_filename):
|
||||
#read the file in
|
||||
file=open(md2_filename,"rb")
|
||||
md2=md2_obj()
|
||||
md2.load(file)
|
||||
#md2.dump()
|
||||
file.close()
|
||||
|
||||
######### Creates a new mesh
|
||||
mesh = NMesh.New()
|
||||
|
||||
uv_coord=[]
|
||||
uv_list=[]
|
||||
|
||||
#load the textures to use later
|
||||
#-1 if there is no texture to load
|
||||
mesh_image=load_textures(md2, texture_filename)
|
||||
|
||||
######### Make the verts
|
||||
DrawProgressBar(0.25,"Loading Vertex Data")
|
||||
for i in xrange(0,md2.num_vertices):
|
||||
#use the first frame for the mesh vertices
|
||||
x=(md2.frames[0].scale[0]*md2.frames[0].vertices[i].vertices[0]+md2.frames[0].translate[0])*g_scale.val
|
||||
y=(md2.frames[0].scale[1]*md2.frames[0].vertices[i].vertices[1]+md2.frames[0].translate[1])*g_scale.val
|
||||
z=(md2.frames[0].scale[2]*md2.frames[0].vertices[i].vertices[2]+md2.frames[0].translate[2])*g_scale.val
|
||||
vertex=NMesh.Vert(y,-x,z)
|
||||
mesh.verts.append(vertex)
|
||||
|
||||
######## Make the UV list
|
||||
DrawProgressBar(0.50,"Loading UV Data")
|
||||
mesh.hasFaceUV(1) #turn on face UV coordinates for this mesh
|
||||
for i in xrange(0, md2.num_tex_coords):
|
||||
u=(float(md2.tex_coords[i].u)/float(md2.skin_width))
|
||||
v=(float(md2.tex_coords[i].v)/float(md2.skin_height))
|
||||
#for some reason quake2 texture maps are upside down, flip that
|
||||
uv_coord=(u,1-v)
|
||||
uv_list.append(uv_coord)
|
||||
|
||||
######### Make the faces
|
||||
DrawProgressBar(0.75,"Loading Face Data")
|
||||
for i in xrange(0,md2.num_faces):
|
||||
face = NMesh.Face()
|
||||
#draw the triangles in reverse order so they show up
|
||||
face.v.append(mesh.verts[md2.faces[i].vertex_index[0]])
|
||||
face.v.append(mesh.verts[md2.faces[i].vertex_index[2]])
|
||||
face.v.append(mesh.verts[md2.faces[i].vertex_index[1]])
|
||||
#append the list of UV
|
||||
#ditto in reverse order with the texture verts
|
||||
face.uv.append(uv_list[md2.faces[i].texture_index[0]])
|
||||
face.uv.append(uv_list[md2.faces[i].texture_index[2]])
|
||||
face.uv.append(uv_list[md2.faces[i].texture_index[1]])
|
||||
|
||||
#set the texture that this face uses if it has one
|
||||
if (mesh_image!=-1):
|
||||
face.image=mesh_image
|
||||
|
||||
#add the face
|
||||
mesh.faces.append(face)
|
||||
|
||||
mesh_obj=NMesh.PutRaw(mesh)
|
||||
animate_md2(md2, mesh_obj)
|
||||
DrawProgressBar(0.999,"Loading Animation Data")
|
||||
|
||||
#locate the Object containing the mesh at the cursor location
|
||||
cursor_pos=Blender.Window.GetCursorPos()
|
||||
mesh_obj.setLocation(float(cursor_pos[0]),float(cursor_pos[1]),float(cursor_pos[2]))
|
||||
DrawProgressBar (1.0, "Finished")
|
||||
|
||||
#***********************************************
|
||||
# MAIN
|
||||
#***********************************************
|
||||
|
||||
# Import globals
|
||||
g_md2_filename=Create("model")
|
||||
g_texture_filename=Create("texture")
|
||||
|
||||
g_filename_search=Create("model")
|
||||
g_texture_search=Create("texture")
|
||||
|
||||
#Globals
|
||||
g_scale=Create(1.0)
|
||||
|
||||
# Events
|
||||
EVENT_NOEVENT=1
|
||||
EVENT_LOAD_MD2=2
|
||||
EVENT_CHOOSE_FILENAME=3
|
||||
EVENT_CHOOSE_TEXTURE=4
|
||||
EVENT_SAVE_MD2=5
|
||||
EVENT_EXIT=100
|
||||
|
||||
######################################################
|
||||
# Callbacks for Window functions
|
||||
######################################################
|
||||
def filename_callback(input_filename):
|
||||
global g_md2_filename
|
||||
g_md2_filename.val=input_filename
|
||||
|
||||
def texture_callback(input_texture):
|
||||
global g_texture_filename
|
||||
g_texture_filename.val=input_texture
|
||||
|
||||
######################################################
|
||||
# GUI Loader
|
||||
######################################################
|
||||
|
||||
|
||||
def draw_gui():
|
||||
global g_scale
|
||||
global g_md2_filename
|
||||
global g_texture_filename
|
||||
global EVENT_NOEVENT,EVENT_LOAD_MD2,EVENT_CHOOSE_FILENAME,EVENT_CHOOSE_TEXTURE,EVENT_EXIT
|
||||
|
||||
########## Titles
|
||||
glClear(GL_COLOR_BUFFER_BIT)
|
||||
glRasterPos2d(8, 125)
|
||||
Text("MD2 loader")
|
||||
|
||||
######### Parameters GUI Buttons
|
||||
g_md2_filename = String("MD2 file to load: ", EVENT_NOEVENT, 10, 55, 210, 18,
|
||||
g_md2_filename.val, 255, "MD2 file to load")
|
||||
########## MD2 File Search Button
|
||||
Button("Search",EVENT_CHOOSE_FILENAME,220,55,80,18)
|
||||
|
||||
g_texture_filename = String("Texture file to load: ", EVENT_NOEVENT, 10, 35, 210, 18,
|
||||
g_texture_filename.val, 255, "Texture file to load-overrides MD2 file")
|
||||
########## Texture Search Button
|
||||
Button("Search",EVENT_CHOOSE_TEXTURE,220,35,80,18)
|
||||
|
||||
########## Scale slider-default is 1/8 which is a good scale for md2->blender
|
||||
g_scale= Slider("Scale Factor: ", EVENT_NOEVENT, 10, 75, 210, 18,
|
||||
1.0, 0.001, 10.0, 1, "Scale factor for obj Model");
|
||||
|
||||
######### Draw and Exit Buttons
|
||||
Button("Load",EVENT_LOAD_MD2 , 10, 10, 80, 18)
|
||||
Button("Exit",EVENT_EXIT , 170, 10, 80, 18)
|
||||
|
||||
def event(evt, val):
|
||||
if (evt == QKEY and not val):
|
||||
Blender.Draw.Exit()
|
||||
|
||||
def bevent(evt):
|
||||
global g_md2_filename
|
||||
global g_texture_filename
|
||||
global EVENT_NOEVENT,EVENT_LOAD_MD2,EVENT_SAVE_MD2,EVENT_EXIT
|
||||
|
||||
######### Manages GUI events
|
||||
if (evt==EVENT_EXIT):
|
||||
Blender.Draw.Exit()
|
||||
elif (evt==EVENT_CHOOSE_FILENAME):
|
||||
FileSelector(filename_callback, "MD2 File Selection")
|
||||
elif (evt==EVENT_CHOOSE_TEXTURE):
|
||||
FileSelector(texture_callback, "Texture Selection")
|
||||
elif (evt==EVENT_LOAD_MD2):
|
||||
if (g_md2_filename.val == "model"):
|
||||
Blender.Draw.Exit()
|
||||
return
|
||||
else:
|
||||
load_md2(g_md2_filename.val, g_texture_filename.val)
|
||||
Blender.Redraw()
|
||||
Blender.Draw.Exit()
|
||||
return
|
||||
|
||||
|
||||
Register(draw_gui, event, bevent)
|
||||
218
release/scripts/mirror_bone_weights.py
Normal file
218
release/scripts/mirror_bone_weights.py
Normal file
@@ -0,0 +1,218 @@
|
||||
#!BPY
|
||||
"""
|
||||
Name: 'Mirror Bone Weights'
|
||||
Blender: 239
|
||||
Group: 'Mesh'
|
||||
Submenu: '-x to +x' nxtopx
|
||||
Submenu: '+x to -x' pxtonx
|
||||
Tooltip: 'Mirror vertex group influences of a model'
|
||||
"""
|
||||
|
||||
__author__ = "Thomas Oppl"
|
||||
__version__ = "5.12"
|
||||
__url__ = "elysiun"
|
||||
__email__ = "scripts"
|
||||
__bpydoc__ = """\
|
||||
Description:
|
||||
|
||||
This script copies vertex group influences from one half of a model to the
|
||||
other half of it.
|
||||
|
||||
Usage:
|
||||
|
||||
- Select the model<br>
|
||||
- Start the script (Object -> Scripts -> Mirror Bone Weights)<br>
|
||||
- Use the "-x to +x" or the "+x to -x" submenu depending on which side should
|
||||
be the source and which the destination.<br>
|
||||
|
||||
Notes:
|
||||
|
||||
- The model has to be in the center of the world along the x-axis.<br>
|
||||
- The model has to be symmetrical along the x-axis.<br>
|
||||
- You have to use the ".R" and ".L" suffix naming scheme for your vertex groups.<br>
|
||||
|
||||
"""
|
||||
|
||||
#------------------------------------------------------------
|
||||
# Mirror Bone Weights - (c) 2005 thomas oppl - toppl@fh-sbg.ac.at
|
||||
#------------------------------------------------------------
|
||||
# ***** BEGIN GPL LICENSE BLOCK *****
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# ***** END GPL LICENCE BLOCK *****
|
||||
#------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
from Blender import NMesh, Object, Draw, sys, Types, Window
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
threshold = 0.001
|
||||
|
||||
################################################################################
|
||||
def mirror(mode):
|
||||
print
|
||||
print "mirror bone weights: %s" % (mode)
|
||||
print "threshold: %.6f" % (threshold)
|
||||
|
||||
objects = Object.GetSelected()
|
||||
if not objects:
|
||||
Draw.PupMenu("Error: no object selected!")
|
||||
print "no object selected!"
|
||||
return
|
||||
mesh = objects[0].getData()
|
||||
if type(mesh) != Types.NMeshType:
|
||||
Draw.PupMenu("Error: object must be a mesh!")
|
||||
print "object is no mesh!"
|
||||
return
|
||||
|
||||
# nmesh.getvertexinfluences function seems to be broken so i create a dictionary instead
|
||||
Window.WaitCursor(1)
|
||||
time = sys.time()
|
||||
in_editmode = Window.EditMode()
|
||||
if in_editmode: Window.EditMode(0)
|
||||
vertexinfluences = {}
|
||||
for i in range(len(mesh.verts)):
|
||||
vertexinfluences[i] = []
|
||||
for groupname in mesh.getVertGroupNames():
|
||||
for vertex in mesh.getVertsFromGroup(groupname, 1):
|
||||
index, weight = vertex[0], vertex[1]
|
||||
vertexinfluences[index].append((groupname, weight))
|
||||
influencestime = sys.time() - time
|
||||
print "influence dictionary generated in %.6f seconds!" % (influencestime)
|
||||
|
||||
# generate binary tree to speed up looking for opposite vertex
|
||||
time = sys.time()
|
||||
tree = c_tree(mesh.verts)
|
||||
treetime = sys.time() - time
|
||||
print "binary tree generated in %.6f seconds!" % (treetime)
|
||||
|
||||
# mirror vertex group influences
|
||||
time = sys.time()
|
||||
if mode == "-x to +x":
|
||||
verticeshalf = [v for v in mesh.verts if v.co[0] < 0]
|
||||
else:
|
||||
verticeshalf = [v for v in mesh.verts if v.co[0] > 0]
|
||||
i = 0
|
||||
for vertex in verticeshalf:
|
||||
oppositeposition = (-vertex.co[0], vertex.co[1], vertex.co[2])
|
||||
foundvertex = []
|
||||
tree.findvertex(oppositeposition, foundvertex, threshold)
|
||||
if foundvertex:
|
||||
oppositevertex = foundvertex[0]
|
||||
# remove all influences from opposite vertex
|
||||
for influence in vertexinfluences[oppositevertex.index]:
|
||||
mesh.removeVertsFromGroup(influence[0], [oppositevertex.index])
|
||||
# copy influences to opposite vertex
|
||||
for influence in vertexinfluences[vertex.index]:
|
||||
name = influence[0]
|
||||
if name[-2:] == ".R":
|
||||
name = name[:-2] + ".L"
|
||||
elif name[-2:] == ".L":
|
||||
name = name[:-2] + ".R"
|
||||
if name not in mesh.getVertGroupNames(): # create opposite group if it doesn't exist
|
||||
mesh.addVertGroup(name)
|
||||
mesh.assignVertsToGroup(name, [oppositevertex.index], influence[1], "add")
|
||||
i += 1
|
||||
mirrortime = sys.time() - time
|
||||
print "%d vertices mirrored in %.6f seconds!" % (i, mirrortime)
|
||||
|
||||
# done!
|
||||
print "done in %.6f seconds total!" % (influencestime + treetime + mirrortime)
|
||||
if in_editmode: Window.EditMode(1)
|
||||
Window.WaitCursor(0)
|
||||
|
||||
|
||||
|
||||
|
||||
################################################################################
|
||||
NODE_VERTEX_LIMIT = 50
|
||||
|
||||
class c_boundingbox:
|
||||
def __init__(self, vertices):
|
||||
self.min_x = self.max_x = vertices[0].co[0]
|
||||
self.min_y = self.max_y = vertices[0].co[1]
|
||||
self.min_z = self.max_z = vertices[0].co[2]
|
||||
for vertex in vertices:
|
||||
self.min_x = min(self.min_x, vertex.co[0])
|
||||
self.min_y = min(self.min_y, vertex.co[1])
|
||||
self.min_z = min(self.min_z, vertex.co[2])
|
||||
self.max_x = max(self.max_x, vertex.co[0])
|
||||
self.max_y = max(self.max_y, vertex.co[1])
|
||||
self.max_z = max(self.max_z, vertex.co[2])
|
||||
self.dim_x = self.max_x - self.min_x
|
||||
self.dim_y = self.max_y - self.min_y
|
||||
self.dim_z = self.max_z - self.min_z
|
||||
self.splitaxis = [self.dim_x, self.dim_y, self.dim_z].index(max(self.dim_x, self.dim_y, self.dim_z))
|
||||
self.center_x = self.max_x - (self.dim_x / 2.0)
|
||||
self.center_y = self.max_y - (self.dim_y / 2.0)
|
||||
self.center_z = self.max_z - (self.dim_z / 2.0)
|
||||
self.splitcenter = [self.center_x, self.center_y, self.center_z][self.splitaxis]
|
||||
def __str__(self):
|
||||
return "min: %.3f %.3f %.3f max: %.3f %.3f %.3f dim: %.3f %.3f %.3f" %\
|
||||
(self.min_x, self.min_y, self.min_z,
|
||||
self.max_x, self.max_y, self.max_z,
|
||||
self.dim_x, self.dim_y, self.dim_z)
|
||||
def isinside(self, position, threshold):
|
||||
return (position[0] <= self.max_x + threshold and position[1] <= self.max_y + threshold and \
|
||||
position[2] <= self.max_z + threshold and position[0] >= self.min_x - threshold and \
|
||||
position[1] >= self.min_y - threshold and position[2] >= self.min_z - threshold)
|
||||
|
||||
class c_tree:
|
||||
def __init__(self, vertices, level = 0):
|
||||
self.level = level
|
||||
self.children = []
|
||||
self.vertices = []
|
||||
self.boundingbox = c_boundingbox(vertices)
|
||||
splitaxis = self.boundingbox.splitaxis
|
||||
splitcenter = self.boundingbox.splitcenter
|
||||
if len(vertices) > NODE_VERTEX_LIMIT:
|
||||
self.children.append(c_tree(
|
||||
[v for v in vertices if v.co[splitaxis] > splitcenter], self.level + 1))
|
||||
self.children.append(c_tree(
|
||||
[v for v in vertices if v.co[splitaxis] <= splitcenter], self.level + 1))
|
||||
else: # leaf node
|
||||
self.vertices = vertices
|
||||
def __str__(self):
|
||||
s = " " * self.level + "-node %d\n" % (len(self.vertices))
|
||||
for child in self.children:
|
||||
s += str(child)
|
||||
return s
|
||||
def findvertex(self, position, foundvertex, threshold):
|
||||
if self.boundingbox.isinside(position, threshold):
|
||||
if self.children:
|
||||
for child in self.children:
|
||||
child.findvertex(position, foundvertex, threshold)
|
||||
else: # node found
|
||||
for vertex in self.vertices:
|
||||
v, p, t = vertex.co, position, threshold
|
||||
if abs(v[0] - p[0]) < t and abs(v[1] - p[1]) < t and abs(v[2] - p[2]) < t: # vertex found
|
||||
foundvertex.append(vertex)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
################################################################################
|
||||
if __script__["arg"] == "nxtopx":
|
||||
mirror("-x to +x")
|
||||
if __script__["arg"] == "pxtonx":
|
||||
mirror("+x to -x")
|
||||
913
release/scripts/widgetwizard.py
Normal file
913
release/scripts/widgetwizard.py
Normal file
@@ -0,0 +1,913 @@
|
||||
#!BPY
|
||||
|
||||
"""
|
||||
Name: 'Shape Widget Wizard'
|
||||
Blender: 238
|
||||
Group: 'Animation'
|
||||
Tip: 'Adds Widgets for Driven Shapes'
|
||||
"""
|
||||
|
||||
__author__ = ["Johnny Matthews (guitargeek)"]
|
||||
__url__ = ("blender", "elysiun")
|
||||
__version__ = "0.0.9 12/15/05"
|
||||
|
||||
__bpydoc__ = """\
|
||||
"Shape Widget Wizard" creates objects that drive shape channels.
|
||||
|
||||
Explanation:
|
||||
|
||||
Shapes define morph targets and sometimes it is helpful to animate with a GUI
|
||||
control panel of widgets. This script lets you define several different types
|
||||
of controls that (depending on the type) control 1 to 4 shapes with a single
|
||||
controller.
|
||||
|
||||
Usage:
|
||||
|
||||
1. Click where you want the widget to go<br>
|
||||
2. Highlight the object that has shapes<br>
|
||||
3. Run the script<br>
|
||||
4. Choose the type of widget (there are next and back buttons if you pick the wrong kind)<br>
|
||||
5. Click next and choose what shapes go where on the widget<br>
|
||||
6. Choose a display name for the widget<br>
|
||||
7. Click finish
|
||||
|
||||
The widget is added and you are returned to the first screen for adding another widget.
|
||||
|
||||
"""
|
||||
|
||||
###################################################################
|
||||
# #
|
||||
# Shape Widget Wizard #
|
||||
# #
|
||||
# all versions (C) December 2005 Johnny Matthews (guitargeek) #
|
||||
# #
|
||||
# Released under the GPL #
|
||||
# #
|
||||
# Works in Blender 2.4 and higher #
|
||||
# #
|
||||
# This script can be found online at: #
|
||||
# http://guitargeek.superihost.com/widgetmaker #
|
||||
# #
|
||||
# email: johnny.matthews@gmail.com #
|
||||
###################################################################
|
||||
# History #
|
||||
# 0.9 #
|
||||
# Added Name Objects #
|
||||
# 0.81 #
|
||||
# Added Single Shape Toggle #
|
||||
# #
|
||||
# 0.8 #
|
||||
# Controller is Transform Locked and can only move #
|
||||
# in appropriate directions #
|
||||
# #
|
||||
# 0.7 #
|
||||
# Controller is named the same as the range + ".ctrl" #
|
||||
# #
|
||||
###################################################################
|
||||
|
||||
import Blender
|
||||
from Blender import Mesh,Object,Material,Window,IpoCurve,Ipo,Text3d
|
||||
from Blender.BGL import *
|
||||
from Blender.Draw import *
|
||||
print "----------------------"
|
||||
|
||||
SHAPE1_ONE_MONE = 1
|
||||
SHAPE1_ONE_ZERO = 2
|
||||
SHAPE1_ZERO_MONE = 3
|
||||
SHAPE1_TOGGLE = 12
|
||||
SHAPE2_EXCLUSIVE = 4
|
||||
SHAPE2_V = 5
|
||||
SHAPE2_T = 6
|
||||
SHAPE2_INVT = 7
|
||||
SHAPE2_PLUS = 8
|
||||
SHAPE3_T = 9
|
||||
SHAPE3_INVT = 10
|
||||
SHAPE4_X = 11
|
||||
|
||||
|
||||
stage = 1
|
||||
numshapes = Create(1)
|
||||
widmenu = Create(1)
|
||||
rangename = Create("Range")
|
||||
shapes = [Create(0),Create(0),Create(0),Create(0)]
|
||||
drawtype = 0
|
||||
|
||||
|
||||
#get rid of an ipo curve by deleting all its points
|
||||
def delCurve(ipo):
|
||||
while len(ipo.getPoints()) > 0:
|
||||
ipo.delBezier(0)
|
||||
ipo.recalc()
|
||||
|
||||
#if a given ipocurve is not there create it, otherwise get it
|
||||
def verifyIpocurve(ky,index):
|
||||
ipo = ky.ipo
|
||||
if ipo == None:
|
||||
nip = Ipo.New("Key","keyipo")
|
||||
ky.ipo = nip
|
||||
ipo = ky.ipo
|
||||
idx = "Key " + str(index)
|
||||
crv = ipo.getCurve(index)
|
||||
if crv == None:
|
||||
crv = ipo.addCurve(idx)
|
||||
crv.setInterpolation("Linear")
|
||||
return crv
|
||||
|
||||
# Add the Drivers and Curves
|
||||
def setupDrivers(ob,ctrl,type):
|
||||
global shapes
|
||||
me = ob.getData()
|
||||
ky = me.getKey()
|
||||
|
||||
if type in [SHAPE1_ONE_MONE,SHAPE1_ONE_ZERO,SHAPE1_ZERO_MONE]:
|
||||
ctrl.protectFlags = int("111111011",2)
|
||||
ipo = verifyIpocurve(ky,shapes[0].val)
|
||||
ipo.driver = 1
|
||||
ipo.driverObject = ctrl
|
||||
ipo.driverChannel = IpoCurve.LOC_Z
|
||||
ipo.recalc()
|
||||
|
||||
delCurve(ipo)
|
||||
if type == 1:
|
||||
ipo.addBezier((-1,-1))
|
||||
ipo.addBezier((0,0))
|
||||
ipo.addBezier((1,1))
|
||||
if type == 2:
|
||||
ipo.addBezier((0,0))
|
||||
ipo.addBezier((1,1))
|
||||
if type == 3:
|
||||
ipo.addBezier((-1,-1))
|
||||
ipo.addBezier((0,0))
|
||||
ipo.recalc()
|
||||
|
||||
if type == SHAPE1_TOGGLE:
|
||||
ctrl.protectFlags = int("111111011",2)
|
||||
ipo = verifyIpocurve(ky,shapes[0].val)
|
||||
ipo.driver = 1
|
||||
ipo.driverObject = ctrl
|
||||
ipo.driverChannel = IpoCurve.LOC_Z
|
||||
ipo.recalc()
|
||||
delCurve(ipo)
|
||||
ipo.addBezier((0,0))
|
||||
ipo.addBezier((0.5,0))
|
||||
ipo.addBezier((0.500001,1))
|
||||
ipo.addBezier((1,1))
|
||||
ipo.recalc()
|
||||
|
||||
if type == SHAPE2_EXCLUSIVE:
|
||||
ctrl.protectFlags = int("111111011",2)
|
||||
ipo = verifyIpocurve(ky,shapes[0].val)
|
||||
ipo.driver = 1
|
||||
ipo.driverObject = ctrl
|
||||
ipo.driverChannel = IpoCurve.LOC_Z
|
||||
ipo.recalc()
|
||||
delCurve(ipo)
|
||||
ipo.addBezier((0,0))
|
||||
ipo.addBezier((1,1))
|
||||
ipo.recalc()
|
||||
|
||||
ipo2 = verifyIpocurve(ky,shapes[1].val)
|
||||
ipo2.driver = 1
|
||||
ipo2.driverObject = ctrl
|
||||
ipo2.driverChannel = IpoCurve.LOC_Z
|
||||
ipo2.recalc()
|
||||
delCurve(ipo2)
|
||||
ipo2.addBezier((-1,1))
|
||||
ipo2.addBezier((0,0))
|
||||
ipo2.recalc()
|
||||
|
||||
if type == SHAPE2_T:
|
||||
ctrl.protectFlags = int("111111010",2)
|
||||
ipo = verifyIpocurve(ky,shapes[0].val)
|
||||
ipo.driver = 1
|
||||
ipo.driverObject = ctrl
|
||||
ipo.driverChannel = IpoCurve.LOC_Z
|
||||
ipo.recalc()
|
||||
delCurve(ipo)
|
||||
ipo.addBezier((-1,-1))
|
||||
ipo.addBezier((0,0))
|
||||
ipo.recalc()
|
||||
|
||||
ipo2 = verifyIpocurve(ky,shapes[1].val)
|
||||
ipo2.driver = 1
|
||||
ipo2.driverObject = ctrl
|
||||
ipo2.driverChannel = IpoCurve.LOC_X
|
||||
ipo2.recalc()
|
||||
delCurve(ipo2)
|
||||
ipo2.addBezier((-1,-1))
|
||||
ipo2.addBezier((1,1))
|
||||
ipo2.recalc()
|
||||
|
||||
if type == SHAPE2_INVT:
|
||||
ctrl.protectFlags = int("111111010",2)
|
||||
ipo = verifyIpocurve(ky,shapes[0].val)
|
||||
ipo.driver = 1
|
||||
ipo.driverObject = ctrl
|
||||
ipo.driverChannel = IpoCurve.LOC_Z
|
||||
ipo.recalc()
|
||||
delCurve(ipo)
|
||||
ipo.addBezier((0,0))
|
||||
ipo.addBezier((1,1))
|
||||
ipo.recalc()
|
||||
|
||||
ipo2 = verifyIpocurve(ky,shapes[1].val)
|
||||
ipo2.driver = 1
|
||||
ipo2.driverObject = ctrl
|
||||
ipo2.driverChannel = IpoCurve.LOC_X
|
||||
ipo2.recalc()
|
||||
delCurve(ipo2)
|
||||
ipo2.addBezier((-1,-1))
|
||||
ipo2.addBezier((1,1))
|
||||
ipo2.recalc()
|
||||
|
||||
if type == SHAPE2_PLUS:
|
||||
ctrl.protectFlags = int("111111010",2)
|
||||
ipo = verifyIpocurve(ky,shapes[0].val)
|
||||
ipo.driver = 1
|
||||
ipo.driverObject = ctrl
|
||||
ipo.driverChannel = IpoCurve.LOC_Z
|
||||
ipo.recalc()
|
||||
delCurve(ipo)
|
||||
ipo.addBezier((-1,-1))
|
||||
ipo.addBezier((1,1))
|
||||
ipo.recalc()
|
||||
|
||||
ipo2 = verifyIpocurve(ky,shapes[1].val)
|
||||
ipo2.driver = 1
|
||||
ipo2.driverObject = ctrl
|
||||
ipo2.driverChannel = IpoCurve.LOC_X
|
||||
ipo2.recalc()
|
||||
delCurve(ipo2)
|
||||
ipo2.addBezier((-1,-1))
|
||||
ipo2.addBezier((1,1))
|
||||
ipo2.recalc()
|
||||
|
||||
if type == SHAPE2_V: # 2 Shape Mix
|
||||
ctrl.protectFlags = int("111111010",2)
|
||||
ipo = verifyIpocurve(ky,shapes[0].val)
|
||||
ipo.driver = 1
|
||||
ipo.driverObject = ctrl
|
||||
ipo.driverChannel = IpoCurve.LOC_Z
|
||||
delCurve(ipo)
|
||||
ipo.addBezier((0,0))
|
||||
ipo.addBezier((1,1))
|
||||
ipo.recalc()
|
||||
|
||||
ipo2 = verifyIpocurve(ky,shapes[1].val)
|
||||
ipo2.driver = 1
|
||||
ipo2.driverObject = ctrl
|
||||
ipo2.driverChannel = IpoCurve.LOC_X
|
||||
delCurve(ipo2)
|
||||
ipo2.addBezier((0,0))
|
||||
ipo2.addBezier((1,1))
|
||||
ipo2.recalc()
|
||||
|
||||
|
||||
if type == SHAPE3_INVT:
|
||||
ctrl.protectFlags = int("111111010",2)
|
||||
ipo = verifyIpocurve(ky,shapes[0].val)
|
||||
ipo.driver = 1
|
||||
ipo.driverObject = ctrl
|
||||
ipo.driverChannel = IpoCurve.LOC_Z
|
||||
ipo.recalc()
|
||||
delCurve(ipo)
|
||||
ipo.addBezier((0,0))
|
||||
ipo.addBezier((1,1))
|
||||
ipo.recalc()
|
||||
|
||||
ipo2 = verifyIpocurve(ky,shapes[1].val)
|
||||
ipo2.driver = 1
|
||||
ipo2.driverObject = ctrl
|
||||
ipo2.driverChannel = IpoCurve.LOC_X
|
||||
ipo2.recalc()
|
||||
delCurve(ipo2)
|
||||
ipo2.addBezier((-1,1))
|
||||
ipo2.addBezier((0,0))
|
||||
ipo2.recalc()
|
||||
|
||||
ipo2 = verifyIpocurve(ky,shapes[2].val)
|
||||
ipo2.driver = 1
|
||||
ipo2.driverObject = ctrl
|
||||
ipo2.driverChannel = IpoCurve.LOC_X
|
||||
ipo2.recalc()
|
||||
delCurve(ipo2)
|
||||
ipo2.addBezier((0,0))
|
||||
ipo2.addBezier((1,1))
|
||||
ipo2.recalc()
|
||||
|
||||
if type == SHAPE3_T:
|
||||
ctrl.protectFlags = int("111111010",2)
|
||||
ipo = verifyIpocurve(ky,shapes[0].val)
|
||||
ipo.driver = 1
|
||||
ipo.driverObject = ctrl
|
||||
ipo.driverChannel = IpoCurve.LOC_Z
|
||||
ipo.recalc()
|
||||
delCurve(ipo)
|
||||
ipo.addBezier((-1,-1))
|
||||
ipo.addBezier((0,0))
|
||||
ipo.recalc()
|
||||
|
||||
ipo2 = verifyIpocurve(ky,shapes[1].val)
|
||||
ipo2.driver = 1
|
||||
ipo2.driverObject = ctrl
|
||||
ipo2.driverChannel = IpoCurve.LOC_X
|
||||
ipo2.recalc()
|
||||
delCurve(ipo2)
|
||||
ipo2.addBezier((-1,1))
|
||||
ipo2.addBezier((0,0))
|
||||
ipo2.recalc()
|
||||
|
||||
ipo2 = verifyIpocurve(ky,shapes[2].val)
|
||||
ipo2.driver = 1
|
||||
ipo2.driverObject = ctrl
|
||||
ipo2.driverChannel = IpoCurve.LOC_X
|
||||
ipo2.recalc()
|
||||
delCurve(ipo2)
|
||||
ipo2.addBezier((0,0))
|
||||
ipo2.addBezier((1,1))
|
||||
ipo2.recalc()
|
||||
|
||||
if type == SHAPE4_X:
|
||||
ctrl.protectFlags = int("111111010",2)
|
||||
ipo = verifyIpocurve(ky,shapes[0].val)
|
||||
ipo.driver = 1
|
||||
ipo.driverObject = ctrl
|
||||
ipo.driverChannel = IpoCurve.LOC_Z
|
||||
delCurve(ipo)
|
||||
ipo.addBezier((0,0))
|
||||
ipo.addBezier((1,1))
|
||||
ipo.recalc()
|
||||
|
||||
ipo2 = verifyIpocurve(ky,shapes[1].val)
|
||||
ipo2.driver = 1
|
||||
ipo2.driverObject = ctrl
|
||||
ipo2.driverChannel = IpoCurve.LOC_X
|
||||
delCurve(ipo2)
|
||||
ipo2.addBezier((0,0))
|
||||
ipo2.addBezier((1,1))
|
||||
ipo2.recalc()
|
||||
|
||||
ipo3 = verifyIpocurve(ky,shapes[2].val)
|
||||
ipo3.driver = 1
|
||||
ipo3.driverObject = ctrl
|
||||
ipo3.driverChannel = IpoCurve.LOC_X
|
||||
delCurve(ipo3)
|
||||
ipo3.addBezier((-1,1))
|
||||
ipo3.addBezier((0,0))
|
||||
ipo3.recalc()
|
||||
|
||||
ipo4 = verifyIpocurve(ky,shapes[3].val)
|
||||
ipo4.driver = 1
|
||||
ipo4.driverObject = ctrl
|
||||
ipo4.driverChannel = IpoCurve.LOC_Z
|
||||
delCurve(ipo4)
|
||||
ipo4.addBezier((-1,1))
|
||||
ipo4.addBezier((0,0))
|
||||
ipo4.recalc()
|
||||
|
||||
#The Main Call to Build the Widget
|
||||
|
||||
def build(type):
|
||||
global shapes,widmenu,rangename
|
||||
sce = Blender.Scene.getCurrent()
|
||||
loc = Window.GetCursorPos()
|
||||
range = makeRange(type,rangename.val)
|
||||
controller = makeController(rangename.val)
|
||||
text = makeText(rangename.val)
|
||||
|
||||
sce.link(range)
|
||||
sce.link(controller)
|
||||
sce.link(text)
|
||||
|
||||
range.setLocation(loc)
|
||||
controller.setLocation(loc)
|
||||
text.setLocation(loc)
|
||||
|
||||
range.makeParent([controller],1)
|
||||
range.makeParent([text],0)
|
||||
|
||||
sce.update()
|
||||
|
||||
ob = Object.GetSelected()[0]
|
||||
setupDrivers(ob,controller,widmenu.val)
|
||||
|
||||
#Create the text
|
||||
|
||||
def makeText(name):
|
||||
ob = Object.New("Text",name+".name")
|
||||
txt = Text3d.New(name+".name")
|
||||
txt.setDrawMode(Text3d.DRAW3D)
|
||||
txt.setAlignment(Text3d.MIDDLE)
|
||||
txt.setText(name)
|
||||
ob.link(txt)
|
||||
ob.setEuler(3.14159/2,0,0)
|
||||
return ob
|
||||
|
||||
|
||||
#Create the mesh controller
|
||||
|
||||
def makeController(name):
|
||||
ob = Object.New("Mesh",name+".ctrl")
|
||||
me = Mesh.New(name+".ctrl")
|
||||
|
||||
me.verts.extend(-0.15,0, 0)
|
||||
me.verts.extend( 0,0, 0.15)
|
||||
me.verts.extend( 0.15,0, 0)
|
||||
me.verts.extend( 0,0,-0.15)
|
||||
v = me.verts
|
||||
c = [(v[0],v[1],v[2],v[3])]
|
||||
me.edges.extend(c)
|
||||
ob.link(me)
|
||||
return ob
|
||||
|
||||
#Create the mesh range
|
||||
|
||||
def makeRange(type,name):
|
||||
ob = Object.New("Mesh",name)
|
||||
#ob.setDrawMode(8) # Draw Name
|
||||
me = Mesh.New(name)
|
||||
|
||||
l=[]
|
||||
|
||||
if type == SHAPE1_ONE_ZERO:
|
||||
me.verts.extend(-0.15,0,0)
|
||||
me.verts.extend( 0.15,0,0)
|
||||
me.verts.extend(-0.15,0,1)
|
||||
me.verts.extend( 0.15,0,1)
|
||||
me.verts.extend(-0.25,0,.1)
|
||||
me.verts.extend(-0.25,0,-.10)
|
||||
me.verts.extend(0.25,0,.1)
|
||||
me.verts.extend(0.25,0,-0.10)
|
||||
v = me.verts
|
||||
l = [(v[0],v[1],v[3],v[2]),(v[4],v[5],v[0]),(v[6],v[7],v[1])]
|
||||
me.edges.extend(l)
|
||||
ob.link(me)
|
||||
|
||||
elif type == SHAPE1_TOGGLE:
|
||||
me.verts.extend(-0.15,0,-0.5)
|
||||
me.verts.extend( 0.15,0,-0.5)
|
||||
me.verts.extend( 0.15,0, 0.5)
|
||||
me.verts.extend(-0.15,0, 0.5)
|
||||
me.verts.extend(-0.15,0, 1.5)
|
||||
me.verts.extend( 0.15,0, 1.5)
|
||||
v = me.verts
|
||||
l = [(v[0],v[1],v[2],v[3]),(v[3],v[4],v[5],v[2])]
|
||||
me.edges.extend(l)
|
||||
ob.link(me)
|
||||
|
||||
elif type == SHAPE1_ZERO_MONE:
|
||||
me.verts.extend(-0.15,0,0)
|
||||
me.verts.extend( 0.15,0,0)
|
||||
me.verts.extend(-0.15,0,-1)
|
||||
me.verts.extend( 0.15,0,-1)
|
||||
me.verts.extend(-0.25,0,.1)
|
||||
me.verts.extend(-0.25,0,-.10)
|
||||
me.verts.extend(0.25,0,.1)
|
||||
me.verts.extend(0.25,0,-0.10)
|
||||
v = me.verts
|
||||
l = [(v[0],v[1],v[3],v[2]),(v[4],v[5],v[0]),(v[6],v[7],v[1])]
|
||||
me.edges.extend(l)
|
||||
ob.link(me)
|
||||
|
||||
elif type in [SHAPE1_ONE_MONE,SHAPE2_EXCLUSIVE]:
|
||||
me.verts.extend(-0.15,0,-1)
|
||||
me.verts.extend( 0.15,0,-1)
|
||||
me.verts.extend(-0.15,0,1)
|
||||
me.verts.extend( 0.15,0,1)
|
||||
me.verts.extend(-0.25,0,.1)
|
||||
me.verts.extend(-0.25,0,-.10)
|
||||
me.verts.extend(0.25,0,.1)
|
||||
me.verts.extend(0.25,0,-0.10)
|
||||
me.verts.extend(-0.15,0,0)
|
||||
me.verts.extend( 0.15,0,0)
|
||||
|
||||
v = me.verts
|
||||
l = [(v[0],v[1],v[3],v[2]),(v[4],v[5],v[8]),(v[6],v[7],v[9])]
|
||||
me.edges.extend(l)
|
||||
ob.link(me)
|
||||
|
||||
elif type == SHAPE2_T:
|
||||
me.verts.extend(-1,0,0)
|
||||
me.verts.extend( 1,0,0)
|
||||
me.verts.extend( 1,0,-1)
|
||||
me.verts.extend(-1,0,-1)
|
||||
|
||||
v = me.verts
|
||||
l = [(v[0],v[1],v[2],v[3])]
|
||||
me.edges.extend(l)
|
||||
ob.link(me)
|
||||
|
||||
elif type == SHAPE2_INVT:
|
||||
me.verts.extend(-1,0,0)
|
||||
me.verts.extend( 1,0,0)
|
||||
me.verts.extend( 1,0,1)
|
||||
me.verts.extend(-1,0,1)
|
||||
|
||||
v = me.verts
|
||||
l = [(v[0],v[1],v[2],v[3])]
|
||||
me.edges.extend(l)
|
||||
ob.link(me)
|
||||
|
||||
elif type == SHAPE2_PLUS:
|
||||
me.verts.extend(-1,0,-1)
|
||||
me.verts.extend( 1,0,-1)
|
||||
me.verts.extend( 1,0,1)
|
||||
me.verts.extend(-1,0,1)
|
||||
|
||||
v = me.verts
|
||||
l = [(v[0],v[1],v[2],v[3])]
|
||||
me.edges.extend(l)
|
||||
ob.link(me)
|
||||
|
||||
elif type == SHAPE2_V:
|
||||
me.verts.extend(0,0,0)
|
||||
me.verts.extend(1,0,0)
|
||||
me.verts.extend(1,0,1)
|
||||
me.verts.extend(0,0,1)
|
||||
v = me.verts
|
||||
l = [(v[0],v[1],v[2],v[3])]
|
||||
me.edges.extend(l)
|
||||
ob.link(me)
|
||||
ob.setEuler(0,-0.78539,0)
|
||||
|
||||
elif type == SHAPE3_INVT:
|
||||
me.verts.extend(-1,0,0)
|
||||
me.verts.extend( 1,0,0)
|
||||
me.verts.extend( 1,0,1)
|
||||
me.verts.extend(-1,0,1)
|
||||
|
||||
v = me.verts
|
||||
l = [(v[0],v[1],v[2],v[3])]
|
||||
me.edges.extend(l)
|
||||
ob.link(me)
|
||||
|
||||
elif type == SHAPE3_T:
|
||||
me.verts.extend(-1,0,0)
|
||||
me.verts.extend( 1,0,0)
|
||||
me.verts.extend( 1,0,-1)
|
||||
me.verts.extend(-1,0,-1)
|
||||
|
||||
v = me.verts
|
||||
l = [(v[0],v[1],v[2],v[3])]
|
||||
me.edges.extend(l)
|
||||
ob.link(me)
|
||||
|
||||
|
||||
elif type == SHAPE4_X:
|
||||
me.verts.extend(0,0,-1)
|
||||
me.verts.extend(1,0,-1)
|
||||
me.verts.extend(1,0,0)
|
||||
me.verts.extend(1,0,1)
|
||||
me.verts.extend(0,0,1)
|
||||
me.verts.extend(-1,0,1)
|
||||
me.verts.extend(-1,0,0)
|
||||
me.verts.extend(-1,0,-1)
|
||||
v = me.verts
|
||||
l = [(v[0],v[1]),(v[1],v[2]),(v[2],v[3]),(v[3],v[4]),(v[4],v[5]),(v[5],v[6]),(v[6],v[7]),(v[7],v[0])]
|
||||
me.edges.extend(l)
|
||||
ob.link(me)
|
||||
ob.setEuler(0,-0.78539,0)
|
||||
|
||||
return ob
|
||||
|
||||
|
||||
def create():
|
||||
main()
|
||||
|
||||
####################### gui ######################
|
||||
|
||||
|
||||
EVENT_NONE = 1
|
||||
EVENT_EXIT = 100
|
||||
EVENT_WIDGET_MENU = 101
|
||||
EVENT_NEXT = 102
|
||||
EVENT_BACK = 103
|
||||
|
||||
#get the list of shapes from the selected object
|
||||
|
||||
def shapeMenuText():
|
||||
if len(Object.GetSelected()) == 0:
|
||||
return ""
|
||||
ob = Object.GetSelected()[0]
|
||||
me = ob.getData()
|
||||
key= me.getKey()
|
||||
if key == None:
|
||||
return ""
|
||||
blocks = key.getBlocks()
|
||||
menu = "Choose Shape %t|"
|
||||
for n in range(len(blocks)):
|
||||
menu = menu + blocks[n].name + " %x" + str(n) + "|"
|
||||
return menu
|
||||
|
||||
|
||||
#draw the widget for the gui
|
||||
|
||||
def drawWidget(type):
|
||||
global shapes
|
||||
if type == SHAPE1_ONE_MONE:# 1 to -1 Single Shape
|
||||
glBegin(GL_LINE_STRIP)
|
||||
glVertex2i(150,50)
|
||||
glVertex2i(170,50)
|
||||
glVertex2i(170,150)
|
||||
glVertex2i(150,150)
|
||||
glVertex2i(150,50)
|
||||
glEnd()
|
||||
glBegin(GL_LINE_STRIP)
|
||||
glVertex2i(140,100)
|
||||
glVertex2i(190,100)
|
||||
glEnd()
|
||||
glRasterPos2d(180,140)
|
||||
Text("1","normal")
|
||||
glRasterPos2d(180,60)
|
||||
Text("-1","normal")
|
||||
shapes[0] = Menu(shapeMenuText(), EVENT_NONE, 190, 100, 100, 18, shapes[0].val, "Choose Shape.")
|
||||
elif type == SHAPE1_TOGGLE:# Toggle Single Shape
|
||||
glBegin(GL_LINE_STRIP)
|
||||
glVertex2i(150,50)
|
||||
glVertex2i(170,50)
|
||||
glVertex2i(170,100)
|
||||
glVertex2i(150,100)
|
||||
glVertex2i(150,50)
|
||||
glEnd()
|
||||
glBegin(GL_LINE_STRIP)
|
||||
glVertex2i(170,100)
|
||||
glVertex2i(170,150)
|
||||
glVertex2i(150,150)
|
||||
glVertex2i(150,100)
|
||||
glEnd()
|
||||
glRasterPos2d(180,140)
|
||||
Text("On","normal")
|
||||
glRasterPos2d(180,60)
|
||||
Text("Off","normal")
|
||||
shapes[0] = Menu(shapeMenuText(), EVENT_NONE, 190, 100, 100, 18, shapes[0].val, "Choose Shape.")
|
||||
elif type == SHAPE1_ONE_ZERO: # 1 to 0 Single Shape
|
||||
glBegin(GL_LINE_STRIP)
|
||||
glVertex2i(150,50)
|
||||
glVertex2i(170,50)
|
||||
glVertex2i(170,150)
|
||||
glVertex2i(150,150)
|
||||
glVertex2i(150,50)
|
||||
glEnd()
|
||||
glBegin(GL_LINE_STRIP)
|
||||
glVertex2i(140,50)
|
||||
glVertex2i(190,50)
|
||||
glEnd()
|
||||
glRasterPos2d(180,140)
|
||||
Text("1","normal")
|
||||
glRasterPos2d(180,60)
|
||||
Text("0","normal")
|
||||
shapes[0] = Menu(shapeMenuText(), EVENT_NONE, 190, 100, 100, 18, shapes[0].val, "Choose Shape.")
|
||||
elif type == SHAPE1_ZERO_MONE:
|
||||
glBegin(GL_LINE_STRIP)
|
||||
glVertex2i(150,50)
|
||||
glVertex2i(170,50)
|
||||
glVertex2i(170,150)
|
||||
glVertex2i(150,150)
|
||||
glVertex2i(150,50)
|
||||
glEnd()
|
||||
glBegin(GL_LINE_STRIP)
|
||||
glVertex2i(140,150)
|
||||
glVertex2i(190,150)
|
||||
glEnd()
|
||||
glRasterPos2d(180,140)
|
||||
Text("0","normal")
|
||||
glRasterPos2d(180,60)
|
||||
Text("-1","normal")
|
||||
shapes[0] = Menu(shapeMenuText(), EVENT_NONE, 190, 100, 100, 18, shapes[0].val, "Choose Shape.")
|
||||
elif type == SHAPE2_EXCLUSIVE:
|
||||
glBegin(GL_LINE_STRIP)
|
||||
glVertex2i(150,50)
|
||||
glVertex2i(170,50)
|
||||
glVertex2i(170,150)
|
||||
glVertex2i(150,150)
|
||||
glVertex2i(150,50)
|
||||
glEnd()
|
||||
glBegin(GL_LINE_STRIP)
|
||||
glVertex2i(140,100)
|
||||
glVertex2i(190,100)
|
||||
glEnd()
|
||||
glRasterPos2d(180,140)
|
||||
Text("1","normal")
|
||||
glRasterPos2d(180,60)
|
||||
Text("1","normal")
|
||||
shapes[0] = Menu(shapeMenuText(), EVENT_NONE, 195, 135, 100, 18, shapes[0].val, "Choose Shape 1.")
|
||||
shapes[1] = Menu(shapeMenuText(), EVENT_NONE, 195, 52, 100, 18, shapes[1].val, "Choose Shape 2.")
|
||||
elif type == SHAPE2_T:
|
||||
glBegin(GL_LINE_STRIP)
|
||||
glVertex2i(150,75)
|
||||
glVertex2i(250,75)
|
||||
glVertex2i(250,125)
|
||||
glVertex2i(150,125)
|
||||
glVertex2i(150,75)
|
||||
glEnd()
|
||||
glBegin(GL_LINE_STRIP)
|
||||
glVertex2i(140,125)
|
||||
glVertex2i(260,125)
|
||||
glEnd()
|
||||
glRasterPos2d(200,140)
|
||||
Text("0","normal")
|
||||
glRasterPos2d(200,60)
|
||||
Text("-1","normal")
|
||||
glRasterPos2d(250,140)
|
||||
Text("1","normal")
|
||||
glRasterPos2d(150,140)
|
||||
Text("-1","normal")
|
||||
shapes[0] = Menu(shapeMenuText(), EVENT_NONE, 220, 52, 100, 18, shapes[0].val, "Choose Shape 1.")
|
||||
shapes[1] = Menu(shapeMenuText(), EVENT_NONE, 260, 135, 100, 18, shapes[1].val, "Choose Shape 2.")
|
||||
elif type == SHAPE2_INVT:
|
||||
glBegin(GL_LINE_STRIP)
|
||||
glVertex2i(150,75)
|
||||
glVertex2i(250,75)
|
||||
glVertex2i(250,125)
|
||||
glVertex2i(150,125)
|
||||
glVertex2i(150,75)
|
||||
glEnd()
|
||||
glBegin(GL_LINE_STRIP)
|
||||
glVertex2i(140,75)
|
||||
glVertex2i(260,75)
|
||||
glEnd()
|
||||
glRasterPos2d(200,60)
|
||||
Text("0","normal")
|
||||
glRasterPos2d(200,140)
|
||||
Text("1","normal")
|
||||
glRasterPos2d(250,60)
|
||||
Text("1","normal")
|
||||
glRasterPos2d(150,60)
|
||||
Text("-1","normal")
|
||||
shapes[0] = Menu(shapeMenuText(), EVENT_NONE, 220, 135, 100, 18, shapes[0].val, "Choose Shape 1.")
|
||||
shapes[1] = Menu(shapeMenuText(), EVENT_NONE, 260, 52, 100, 18, shapes[1].val, "Choose Shape 2.")
|
||||
elif type == SHAPE2_PLUS:
|
||||
glBegin(GL_LINE_STRIP)
|
||||
glVertex2i(150,50)
|
||||
glVertex2i(250,50)
|
||||
glVertex2i(250,150)
|
||||
glVertex2i(150,150)
|
||||
glVertex2i(150,50)
|
||||
glEnd()
|
||||
glBegin(GL_LINE_STRIP)
|
||||
glVertex2i(140,100)
|
||||
glVertex2i(260,100)
|
||||
glEnd()
|
||||
glRasterPos2d(200,105)
|
||||
Text("0","normal")
|
||||
glRasterPos2d(200,140)
|
||||
Text("1","normal")
|
||||
glRasterPos2d(200,55)
|
||||
Text("-1","normal")
|
||||
glRasterPos2d(250,105)
|
||||
Text("1","normal")
|
||||
glRasterPos2d(150,105)
|
||||
Text("-1","normal")
|
||||
shapes[0] = Menu(shapeMenuText(), EVENT_NONE, 220, 155, 100, 18, shapes[0].val, "Choose Shape 1.")
|
||||
shapes[1] = Menu(shapeMenuText(), EVENT_NONE, 260, 100, 100, 18, shapes[1].val, "Choose Shape 2.")
|
||||
elif type == SHAPE2_V:
|
||||
glBegin(GL_LINE_STRIP)
|
||||
glVertex2i(150,70)
|
||||
glVertex2i(185,105)
|
||||
glVertex2i(150,141)
|
||||
glVertex2i(115,105)
|
||||
glVertex2i(150,70)
|
||||
glEnd()
|
||||
glRasterPos2d(110,105)
|
||||
Text("1","normal")
|
||||
glRasterPos2d(190,105)
|
||||
Text("1","normal")
|
||||
glRasterPos2d(150,80)
|
||||
Text("0","normal")
|
||||
shapes[0] = Menu(shapeMenuText(), EVENT_NONE, 20, 125, 100, 18, shapes[0].val, "Choose Shape 1.")
|
||||
shapes[1] = Menu(shapeMenuText(), EVENT_NONE, 195, 125, 100, 18, shapes[1].val, "Choose Shape 2.")
|
||||
|
||||
|
||||
|
||||
elif type == SHAPE3_T:
|
||||
glBegin(GL_LINE_STRIP)
|
||||
glVertex2i(150,75)
|
||||
glVertex2i(250,75)
|
||||
glVertex2i(250,125)
|
||||
glVertex2i(150,125)
|
||||
glVertex2i(150,75)
|
||||
glEnd()
|
||||
glBegin(GL_LINE_STRIP)
|
||||
glVertex2i(140,125)
|
||||
glVertex2i(260,125)
|
||||
glEnd()
|
||||
glRasterPos2d(200,140)
|
||||
Text("0","normal")
|
||||
glRasterPos2d(200,60)
|
||||
Text("-1","normal")
|
||||
glRasterPos2d(250,140)
|
||||
Text("1","normal")
|
||||
glRasterPos2d(150,140)
|
||||
Text("1","normal")
|
||||
shapes[0] = Menu(shapeMenuText(), EVENT_NONE, 220, 52, 100, 18, shapes[0].val, "Choose Shape 1.")
|
||||
shapes[1] = Menu(shapeMenuText(), EVENT_NONE, 45, 135, 100, 18, shapes[1].val, "Choose Shape 2.")
|
||||
shapes[2] = Menu(shapeMenuText(), EVENT_NONE, 260, 135, 100, 18, shapes[2].val, "Choose Shape 3.")
|
||||
elif type == SHAPE3_INVT:
|
||||
glBegin(GL_LINE_STRIP)
|
||||
glVertex2i(150,75)
|
||||
glVertex2i(250,75)
|
||||
glVertex2i(250,125)
|
||||
glVertex2i(150,125)
|
||||
glVertex2i(150,75)
|
||||
glEnd()
|
||||
glBegin(GL_LINE_STRIP)
|
||||
glVertex2i(140,75)
|
||||
glVertex2i(260,75)
|
||||
glEnd()
|
||||
glRasterPos2d(200,60)
|
||||
Text("0","normal")
|
||||
glRasterPos2d(200,140)
|
||||
Text("1","normal")
|
||||
glRasterPos2d(250,60)
|
||||
Text("1","normal")
|
||||
glRasterPos2d(150,60)
|
||||
Text("1","normal")
|
||||
shapes[0] = Menu(shapeMenuText(), EVENT_NONE, 220, 135, 100, 18, shapes[0].val, "Choose Shape 1.")
|
||||
shapes[1] = Menu(shapeMenuText(), EVENT_NONE, 45, 52, 100, 18, shapes[1].val, "Choose Shape 2.")
|
||||
shapes[2] = Menu(shapeMenuText(), EVENT_NONE, 260, 52, 100, 18, shapes[2].val, "Choose Shape 3.")
|
||||
|
||||
|
||||
elif type == SHAPE4_X:
|
||||
glBegin(GL_LINE_STRIP)
|
||||
glVertex2i(150,70)
|
||||
glVertex2i(185,105)
|
||||
glVertex2i(150,141)
|
||||
glVertex2i(115,105)
|
||||
glVertex2i(150,70)
|
||||
glEnd()
|
||||
glRasterPos2d(120,125)
|
||||
Text("1","normal")
|
||||
glRasterPos2d(180,125)
|
||||
Text("1","normal")
|
||||
glRasterPos2d(120,80)
|
||||
Text("1","normal")
|
||||
glRasterPos2d(180,80)
|
||||
Text("1","normal")
|
||||
|
||||
glRasterPos2d(145,105)
|
||||
Text("0","normal")
|
||||
shapes[0] = Menu(shapeMenuText(), EVENT_NONE, 10, 125, 100, 18, shapes[0].val, "Choose Shape 1.")
|
||||
shapes[1] = Menu(shapeMenuText(), EVENT_NONE, 195, 125, 100, 18, shapes[1].val, "Choose Shape 2.")
|
||||
shapes[2] = Menu(shapeMenuText(), EVENT_NONE, 10, 60, 100, 18, shapes[2].val, "Choose Shape 3.")
|
||||
shapes[3] = Menu(shapeMenuText(), EVENT_NONE, 195, 60, 100, 18, shapes[3].val, "Choose Shape 4.")
|
||||
|
||||
#the gui callback
|
||||
|
||||
def draw():
|
||||
global widmenu,numshapes,stage,type, shapes,rangename
|
||||
glRasterPos2d(5,200)
|
||||
Text("Shape Widget Wizard","large")
|
||||
PushButton("Quit", EVENT_EXIT, 5, 5, 50, 18)
|
||||
|
||||
if stage == 1:
|
||||
name = "Choose Widget Type %t|\
|
||||
1 Shape: 1 / -1 %x" +str(SHAPE1_ONE_MONE) +"|\
|
||||
1 Shape: 1,0 %x" +str(SHAPE1_ONE_ZERO) +"|\
|
||||
1 Shape: 0,-1 %x" +str(SHAPE1_ZERO_MONE)+"|\
|
||||
1 Shape: Toggle %x" +str(SHAPE1_TOGGLE) +"|\
|
||||
2 Shape Exclusive %x"+str(SHAPE2_EXCLUSIVE)+"|\
|
||||
2 Shape - V %x" +str(SHAPE2_V) +"|\
|
||||
2 Shape - T %x" +str(SHAPE2_T) +"|\
|
||||
2 Shape - Inv T %x" +str(SHAPE2_INVT) +"|\
|
||||
2 Shape - + %x" +str(SHAPE2_PLUS) +"|\
|
||||
3 Shape - T %x" +str(SHAPE3_T) +"|\
|
||||
3 Shape - Inv T%x" +str(SHAPE3_INVT) +"|\
|
||||
4 Shape - Mix %x" +str(SHAPE4_X)
|
||||
widmenu = Menu(name, EVENT_NONE, 5, 120, 200, 40, widmenu.val, "Choose Widget Type.")
|
||||
PushButton("Next", EVENT_NEXT, 5, 25, 50, 18)
|
||||
|
||||
elif stage == 2:
|
||||
glRasterPos2d(60,140)
|
||||
rangename = String("Name: ", EVENT_NONE, 5, 170, 200, 18, rangename.val, 50, "Name for Range Object")
|
||||
drawWidget(widmenu.val)
|
||||
PushButton("Back", EVENT_BACK, 5, 25, 50, 18)
|
||||
PushButton("Finish", EVENT_NEXT, 55, 25, 50, 18)
|
||||
return
|
||||
|
||||
|
||||
|
||||
def event(evt, val):
|
||||
if (evt == QKEY and not val):
|
||||
Exit()
|
||||
|
||||
|
||||
def bevent(evt):
|
||||
global widmenu,stage,drawtype
|
||||
######### Manages GUI events
|
||||
if evt==EVENT_EXIT:
|
||||
Exit()
|
||||
elif evt==EVENT_BACK:
|
||||
if stage == 2:
|
||||
stage = 1
|
||||
Redraw()
|
||||
elif evt==EVENT_NEXT:
|
||||
if stage == 1:
|
||||
stage = 2
|
||||
Redraw()
|
||||
elif stage == 2:
|
||||
build(widmenu.val)
|
||||
stage = 1
|
||||
Window.RedrawAll()
|
||||
|
||||
|
||||
Register(draw, event, bevent)
|
||||
1245
release/scripts/xsi_export.py
Normal file
1245
release/scripts/xsi_export.py
Normal file
File diff suppressed because it is too large
Load Diff
@@ -192,6 +192,7 @@ typedef struct Global {
|
||||
#define G_FIle_PUBLISH (1 << 9)
|
||||
#define G_FILE_NO_UI (1 << 10)
|
||||
#define G_FILE_GAME_TO_IPO (1 << 11)
|
||||
#define G_FILE_GAME_MAT (1 << 12)
|
||||
|
||||
/* G.windowstate */
|
||||
#define G_WINDOWSTATE_USERDEF 0
|
||||
|
||||
@@ -92,6 +92,22 @@ void mesh_calc_normals(struct MVert *mverts, int numVerts, struct MFace *mfaces,
|
||||
* (_numVerts_r_ may be NULL) */
|
||||
float (*mesh_getVertexCos(struct Mesh *me, int *numVerts_r))[3];
|
||||
|
||||
/* map from uv vertex to face (for select linked, stitch, uv suburf) */
|
||||
|
||||
struct UvVertMap;
|
||||
typedef struct UvVertMap UvVertMap;
|
||||
|
||||
typedef struct UvMapVert {
|
||||
struct UvMapVert *next;
|
||||
unsigned int f;
|
||||
unsigned char tfindex, separate;
|
||||
} UvMapVert;
|
||||
|
||||
UvVertMap *make_uv_vert_map(struct MFace *mface, struct TFace *tface, unsigned int totface, unsigned int totvert, int selected, float *limit);
|
||||
UvMapVert *get_uv_map_vert(UvVertMap *vmap, unsigned int v);
|
||||
UvMapVert *get_first_uv_map_vert(UvVertMap *vmap);
|
||||
void free_uv_vert_map(UvVertMap *vmap);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -223,6 +223,7 @@ static int _edge_isBoundary(CCGEdge *e);
|
||||
enum {
|
||||
Vert_eEffected= (1<<0),
|
||||
Vert_eChanged= (1<<1),
|
||||
Vert_eSeam= (1<<2),
|
||||
} VertFlags;
|
||||
enum {
|
||||
Edge_eEffected= (1<<0),
|
||||
@@ -400,6 +401,10 @@ static void _vert_free(CCGVert *v, CCGSubSurf *ss) {
|
||||
CCGSUBSURF_free(ss, v);
|
||||
}
|
||||
|
||||
static int VERT_seam(CCGVert *v, CCGSubSurf *ss) {
|
||||
return ((v->flags & Vert_eSeam) != 0);
|
||||
}
|
||||
|
||||
/***/
|
||||
|
||||
static CCGEdge *_edge_new(CCGEdgeHDL eHDL, CCGVert *v0, CCGVert *v1, float crease, int levels, int dataSize, CCGSubSurf *ss) {
|
||||
@@ -871,9 +876,10 @@ CCGError ccgSubSurf_syncFaceDel(CCGSubSurf *ss, CCGFaceHDL fHDL) {
|
||||
return eCCGError_None;
|
||||
}
|
||||
|
||||
CCGError ccgSubSurf_syncVert(CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData, CCGVert **v_r) {
|
||||
CCGError ccgSubSurf_syncVert(CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData, int seam, CCGVert **v_r) {
|
||||
void **prevp;
|
||||
CCGVert *v = NULL;
|
||||
short seamflag = (seam)? Vert_eSeam: 0;
|
||||
|
||||
if (ss->syncState==eSyncState_Partial) {
|
||||
v = _ehash_lookupWithPrev(ss->vMap, vHDL, &prevp);
|
||||
@@ -881,12 +887,12 @@ CCGError ccgSubSurf_syncVert(CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData, CC
|
||||
v = _vert_new(vHDL, ss->subdivLevels, ss->meshIFC.vertDataSize, ss);
|
||||
VertDataCopy(_vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData);
|
||||
_ehash_insert(ss->vMap, (EHEntry*) v);
|
||||
v->flags = Vert_eEffected;
|
||||
} else if (!VertDataEqual(vertData, _vert_getCo(v, 0, ss->meshIFC.vertDataSize))) {
|
||||
v->flags = Vert_eEffected|seamflag;
|
||||
} else if (!VertDataEqual(vertData, _vert_getCo(v, 0, ss->meshIFC.vertDataSize)) || ((v->flags & Vert_eSeam) != seamflag)) {
|
||||
int i, j;
|
||||
|
||||
VertDataCopy(_vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData);
|
||||
v->flags = Vert_eEffected;
|
||||
v->flags = Vert_eEffected|seamflag;
|
||||
|
||||
for (i=0; i<v->numEdges; i++) {
|
||||
CCGEdge *e = v->edges[i];
|
||||
@@ -910,12 +916,12 @@ CCGError ccgSubSurf_syncVert(CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData, CC
|
||||
v = _vert_new(vHDL, ss->subdivLevels, ss->meshIFC.vertDataSize, ss);
|
||||
VertDataCopy(_vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData);
|
||||
_ehash_insert(ss->vMap, (EHEntry*) v);
|
||||
v->flags = Vert_eEffected;
|
||||
} else if (!VertDataEqual(vertData, _vert_getCo(v, 0, ss->meshIFC.vertDataSize))) {
|
||||
v->flags = Vert_eEffected|seamflag;
|
||||
} else if (!VertDataEqual(vertData, _vert_getCo(v, 0, ss->meshIFC.vertDataSize)) || ((v->flags & Vert_eSeam) != seamflag)) {
|
||||
*prevp = v->next;
|
||||
_ehash_insert(ss->vMap, (EHEntry*) v);
|
||||
VertDataCopy(_vert_getCo(v,0,ss->meshIFC.vertDataSize), vertData);
|
||||
v->flags = Vert_eEffected|Vert_eChanged;
|
||||
v->flags = Vert_eEffected|Vert_eChanged|seamflag;
|
||||
} else {
|
||||
*prevp = v->next;
|
||||
_ehash_insert(ss->vMap, (EHEntry*) v);
|
||||
@@ -1222,11 +1228,15 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
|
||||
void *nCo = VERT_getCo(v, nextLvl);
|
||||
int sharpCount = 0, allSharp = 1;
|
||||
float avgSharpness = 0.0;
|
||||
int seam = VERT_seam(v, ss), seamEdges = 0;
|
||||
|
||||
for (i=0; i<v->numEdges; i++) {
|
||||
CCGEdge *e = v->edges[i];
|
||||
float sharpness = EDGE_getSharpness(e, curLvl, ss);
|
||||
|
||||
if (seam && _edge_isBoundary(e))
|
||||
seamEdges++;
|
||||
|
||||
if (sharpness!=0.0f) {
|
||||
sharpCount++;
|
||||
avgSharpness += sharpness;
|
||||
@@ -1240,6 +1250,9 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
|
||||
avgSharpness = 1.0;
|
||||
}
|
||||
|
||||
if (seam && seamEdges < 2)
|
||||
seam = 0;
|
||||
|
||||
if (!v->numEdges) {
|
||||
VertDataCopy(nCo, co);
|
||||
} else if (_vert_isBoundary(v)) {
|
||||
@@ -1282,14 +1295,25 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
|
||||
VertDataMulN(nCo, 1.0f/numEdges);
|
||||
}
|
||||
|
||||
if (sharpCount>1 && v->numFaces) {
|
||||
if ((sharpCount>1 && v->numFaces) || seam) {
|
||||
VertDataZero(q);
|
||||
|
||||
if (seam) {
|
||||
avgSharpness = 1.0f;
|
||||
sharpCount = seamEdges;
|
||||
allSharp = 1;
|
||||
}
|
||||
|
||||
for (i=0; i<v->numEdges; i++) {
|
||||
CCGEdge *e = v->edges[i];
|
||||
float sharpness = EDGE_getSharpness(e, curLvl, ss);
|
||||
|
||||
if (sharpness != 0.0) {
|
||||
if (seam) {
|
||||
if (_edge_isBoundary(e)) {
|
||||
CCGVert *oV = _edge_getOtherVert(e, v);
|
||||
VertDataAdd(q, VERT_getCo(oV, curLvl));
|
||||
}
|
||||
} else if (sharpness != 0.0) {
|
||||
CCGVert *oV = _edge_getOtherVert(e, v);
|
||||
VertDataAdd(q, VERT_getCo(oV, curLvl));
|
||||
}
|
||||
@@ -1502,11 +1526,15 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
|
||||
void *nCo = VERT_getCo(v, nextLvl);
|
||||
int sharpCount = 0, allSharp = 1;
|
||||
float avgSharpness = 0.0;
|
||||
int seam = VERT_seam(v, ss), seamEdges = 0;
|
||||
|
||||
for (i=0; i<v->numEdges; i++) {
|
||||
CCGEdge *e = v->edges[i];
|
||||
float sharpness = EDGE_getSharpness(e, curLvl, ss);
|
||||
|
||||
if (seam && _edge_isBoundary(e))
|
||||
seamEdges++;
|
||||
|
||||
if (sharpness!=0.0f) {
|
||||
sharpCount++;
|
||||
avgSharpness += sharpness;
|
||||
@@ -1520,6 +1548,9 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
|
||||
avgSharpness = 1.0;
|
||||
}
|
||||
|
||||
if (seam && seamEdges < 2)
|
||||
seam = 0;
|
||||
|
||||
if (!v->numEdges) {
|
||||
VertDataCopy(nCo, co);
|
||||
} else if (_vert_isBoundary(v)) {
|
||||
@@ -1564,14 +1595,23 @@ static void ccgSubSurf__sync(CCGSubSurf *ss) {
|
||||
VertDataMulN(nCo, 1.0f/numEdges);
|
||||
}
|
||||
|
||||
if (sharpCount>1 && v->numFaces) {
|
||||
if ((sharpCount>1 && v->numFaces) || seam) {
|
||||
VertDataZero(q);
|
||||
|
||||
if (seam) {
|
||||
avgSharpness = 1.0f;
|
||||
sharpCount = seamEdges;
|
||||
allSharp = 1;
|
||||
}
|
||||
|
||||
for (i=0; i<v->numEdges; i++) {
|
||||
CCGEdge *e = v->edges[i];
|
||||
float sharpness = EDGE_getSharpness(e, curLvl, ss);
|
||||
|
||||
if (sharpness != 0.0) {
|
||||
if (seam) {
|
||||
if (_edge_isBoundary(e))
|
||||
VertDataAdd(q, _edge_getCoVert(e, v, curLvl, 1, vertDataSize));
|
||||
} else if (sharpness != 0.0) {
|
||||
VertDataAdd(q, _edge_getCoVert(e, v, curLvl, 1, vertDataSize));
|
||||
}
|
||||
}
|
||||
@@ -2121,6 +2161,9 @@ void *ccgSubSurf_getEdgeLevelData(CCGSubSurf *ss, CCGEdge *e, int x, int level)
|
||||
return _edge_getCo(e, level, x, ss->meshIFC.vertDataSize);
|
||||
}
|
||||
}
|
||||
float ccgSubSurf_getEdgeCrease(CCGSubSurf *ss, CCGEdge *e) {
|
||||
return e->crease;
|
||||
}
|
||||
|
||||
/* Face accessors */
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ CCGError ccgSubSurf_sync (CCGSubSurf *ss);
|
||||
CCGError ccgSubSurf_initFullSync (CCGSubSurf *ss);
|
||||
CCGError ccgSubSurf_initPartialSync (CCGSubSurf *ss);
|
||||
|
||||
CCGError ccgSubSurf_syncVert (CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData, CCGVert **v_r);
|
||||
CCGError ccgSubSurf_syncVert (CCGSubSurf *ss, CCGVertHDL vHDL, void *vertData, int seam, CCGVert **v_r);
|
||||
CCGError ccgSubSurf_syncEdge (CCGSubSurf *ss, CCGEdgeHDL eHDL, CCGVertHDL e_vHDL0, CCGVertHDL e_vHDL1, float crease, CCGEdge **e_r);
|
||||
CCGError ccgSubSurf_syncFace (CCGSubSurf *ss, CCGFaceHDL fHDL, int numVerts, CCGVertHDL *vHDLs, CCGFace **f_r);
|
||||
|
||||
@@ -99,6 +99,7 @@ int ccgSubSurf_getEdgeNumFaces (CCGSubSurf *ss, CCGEdge *e);
|
||||
CCGFace* ccgSubSurf_getEdgeFace (CCGSubSurf *ss, CCGEdge *e, int index);
|
||||
CCGVert* ccgSubSurf_getEdgeVert0 (CCGSubSurf *ss, CCGEdge *e);
|
||||
CCGVert* ccgSubSurf_getEdgeVert1 (CCGSubSurf *ss, CCGEdge *e);
|
||||
float ccgSubSurf_getEdgeCrease (CCGSubSurf *ss, CCGEdge *e);
|
||||
|
||||
int ccgSubSurf_getEdgeAge (CCGSubSurf *ss, CCGEdge *e);
|
||||
void* ccgSubSurf_getEdgeUserData (CCGSubSurf *ss, CCGEdge *e);
|
||||
|
||||
@@ -2266,7 +2266,7 @@ void loadFluidsimMesh(Object *srcob, int useRenderParams)
|
||||
float *bbStart = NULL, *bbSize = NULL;
|
||||
float lastBB[3];
|
||||
int displaymode = 0;
|
||||
int curFrame = G.scene->r.cfra - G.scene->r.sfra; /* start with 0 at start frame */
|
||||
int curFrame = G.scene->r.cfra - 1 /*G.scene->r.sfra*/; /* start with 0 at start frame */
|
||||
char targetDir[FILE_MAXFILE+FILE_MAXDIR], targetFile[FILE_MAXFILE+FILE_MAXDIR];
|
||||
char debugStrBuffer[256];
|
||||
//snprintf(debugStrBuffer,256,"loadFluidsimMesh call (obid '%s', rp %d)\n", srcob->id.name, useRenderParams); // debug
|
||||
|
||||
@@ -291,6 +291,7 @@ void copy_displist(ListBase *lbn, ListBase *lb)
|
||||
static void initfastshade(void)
|
||||
{
|
||||
Base *base;
|
||||
Scene *setscene;
|
||||
Object *ob;
|
||||
Lamp *la;
|
||||
FastLamp *fl;
|
||||
@@ -309,7 +310,7 @@ static void initfastshade(void)
|
||||
Mat4Invert(fviewmat, R.viewinv);
|
||||
|
||||
/* initrendertexture(); */
|
||||
|
||||
setscene = G.scene->set;
|
||||
base= G.scene->base.first;
|
||||
while(base) {
|
||||
ob= base->object;
|
||||
@@ -349,8 +350,12 @@ static void initfastshade(void)
|
||||
fl->b= la->energy*la->b;
|
||||
}
|
||||
|
||||
if(base->next==0 && G.scene->set && base==G.scene->base.last) base= G.scene->set->base.first;
|
||||
else base= base->next;
|
||||
if(base->next==0 && setscene && setscene->set) {/*if(base->next==0 && G.scene->set && base==G.scene->base.last) {*/
|
||||
setscene = setscene->set;
|
||||
base= setscene->base.first; /* base= G.scene->set->base.first;*/
|
||||
} else {
|
||||
base= base->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -126,7 +126,9 @@ int te_ar[TE_TOTIPO] ={
|
||||
|
||||
TE_MG_TYP, TE_MGH, TE_MG_LAC, TE_MG_OCT, TE_MG_OFF, TE_MG_GAIN,
|
||||
|
||||
TE_N_BAS1, TE_N_BAS2
|
||||
TE_N_BAS1, TE_N_BAS2,
|
||||
|
||||
TE_COL_R, TE_COL_G, TE_COL_B, TE_BRIGHT, TE_CONTRA
|
||||
};
|
||||
|
||||
int seq_ar[SEQ_TOTIPO]= {
|
||||
@@ -1068,6 +1070,17 @@ static void *give_tex_poin(Tex *tex, int adrcode, int *type )
|
||||
poin= &(tex->noisebasis); *type= IPO_SHORT; break;
|
||||
case TE_N_BAS2:
|
||||
poin= &(tex->noisebasis2); *type= IPO_SHORT; break;
|
||||
case TE_COL_R:
|
||||
poin= &(tex->rfac); break;
|
||||
case TE_COL_G:
|
||||
poin= &(tex->gfac); break;
|
||||
case TE_COL_B:
|
||||
poin= &(tex->bfac); break;
|
||||
case TE_BRIGHT:
|
||||
poin= &(tex->bright); break;
|
||||
case TE_CONTRA:
|
||||
poin= &(tex->contrast); break;
|
||||
|
||||
}
|
||||
|
||||
return poin;
|
||||
@@ -1576,7 +1589,7 @@ void set_icu_vars(IpoCurve *icu)
|
||||
case TE_MG_TYP:
|
||||
icu->vartype= IPO_SHORT;
|
||||
icu->ipo= IPO_CONST;
|
||||
icu->ymax= 4.0; break;
|
||||
icu->ymax= 6.0; break;
|
||||
case TE_MGH:
|
||||
icu->ymin= 0.0001;
|
||||
icu->ymax= 2.0; break;
|
||||
@@ -1591,6 +1604,17 @@ void set_icu_vars(IpoCurve *icu)
|
||||
icu->vartype= IPO_SHORT;
|
||||
icu->ipo= IPO_CONST;
|
||||
icu->ymax= 8.0; break;
|
||||
case TE_COL_R:
|
||||
icu->ymax= 0.0; break;
|
||||
case TE_COL_G:
|
||||
icu->ymax= 2.0; break;
|
||||
case TE_COL_B:
|
||||
icu->ymax= 2.0; break;
|
||||
case TE_BRIGHT:
|
||||
icu->ymax= 2.0; break;
|
||||
case TE_CONTRA:
|
||||
icu->ymax= 5.0; break;
|
||||
|
||||
}
|
||||
}
|
||||
else if(icu->blocktype==ID_SEQ) {
|
||||
|
||||
@@ -1082,3 +1082,124 @@ float (*mesh_getVertexCos(Mesh *me, int *numVerts_r))[3]
|
||||
|
||||
return cos;
|
||||
}
|
||||
|
||||
/* UvVertMap */
|
||||
|
||||
struct UvVertMap {
|
||||
struct UvMapVert **vert;
|
||||
struct UvMapVert *buf;
|
||||
};
|
||||
|
||||
UvVertMap *make_uv_vert_map(struct MFace *mface, struct TFace *tface, unsigned int totface, unsigned int totvert, int selected, float *limit)
|
||||
{
|
||||
UvVertMap *vmap;
|
||||
UvMapVert *buf;
|
||||
MFace *mf;
|
||||
TFace *tf;
|
||||
int a, i, totuv, nverts;
|
||||
|
||||
totuv = 0;
|
||||
|
||||
/* generate UvMapVert array */
|
||||
mf= mface;
|
||||
tf= tface;
|
||||
for(a=0; a<totface; a++, mf++, tf++)
|
||||
if(!selected || (!(tf->flag & TF_HIDE) && (tf->flag & TF_SELECT)))
|
||||
totuv += (mf->v4)? 4: 3;
|
||||
|
||||
if(totuv==0)
|
||||
return NULL;
|
||||
|
||||
vmap= (UvVertMap*)MEM_mallocN(sizeof(*vmap), "UvVertMap");
|
||||
if (!vmap)
|
||||
return NULL;
|
||||
|
||||
vmap->vert= (UvMapVert**)MEM_callocN(sizeof(*vmap->vert)*totvert, "UvMapVert*");
|
||||
buf= vmap->buf= (UvMapVert*)MEM_mallocN(sizeof(*vmap->buf)*totuv, "UvMapVert");
|
||||
|
||||
if (!vmap->vert || !vmap->buf) {
|
||||
free_uv_vert_map(vmap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mf= mface;
|
||||
tf= tface;
|
||||
for(a=0; a<totface; a++, mf++, tf++) {
|
||||
if(!selected || (!(tf->flag & TF_HIDE) && (tf->flag & TF_SELECT))) {
|
||||
nverts= (mf->v4)? 4: 3;
|
||||
|
||||
for(i=0; i<nverts; i++) {
|
||||
buf->tfindex= i;
|
||||
buf->f= a;
|
||||
buf->separate = 0;
|
||||
buf->next= vmap->vert[*(&mf->v1 + i)];
|
||||
vmap->vert[*(&mf->v1 + i)]= buf;
|
||||
buf++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* sort individual uvs for each vert */
|
||||
tf= tface;
|
||||
for(a=0; a<totvert; a++) {
|
||||
UvMapVert *newvlist= NULL, *vlist=vmap->vert[a];
|
||||
UvMapVert *iterv, *v, *lastv, *next;
|
||||
float *uv, *uv2, uvdiff[2];
|
||||
|
||||
while(vlist) {
|
||||
v= vlist;
|
||||
vlist= vlist->next;
|
||||
v->next= newvlist;
|
||||
newvlist= v;
|
||||
|
||||
uv= (tf+v->f)->uv[v->tfindex];
|
||||
lastv= NULL;
|
||||
iterv= vlist;
|
||||
|
||||
while(iterv) {
|
||||
next= iterv->next;
|
||||
|
||||
uv2= (tf+iterv->f)->uv[iterv->tfindex];
|
||||
Vec2Subf(uvdiff, uv2, uv);
|
||||
|
||||
|
||||
if(fabs(uv[0]-uv2[0]) < limit[0] && fabs(uv[1]-uv2[1]) < limit[1]) {
|
||||
if(lastv) lastv->next= next;
|
||||
else vlist= next;
|
||||
iterv->next= newvlist;
|
||||
newvlist= iterv;
|
||||
}
|
||||
else
|
||||
lastv=iterv;
|
||||
|
||||
iterv= next;
|
||||
}
|
||||
|
||||
newvlist->separate = 1;
|
||||
}
|
||||
|
||||
vmap->vert[a]= newvlist;
|
||||
}
|
||||
|
||||
return vmap;
|
||||
}
|
||||
|
||||
UvMapVert *get_uv_map_vert(UvVertMap *vmap, unsigned int v)
|
||||
{
|
||||
return vmap->vert[v];
|
||||
}
|
||||
|
||||
UvMapVert *get_first_uv_map_vert(UvVertMap *vmap)
|
||||
{
|
||||
return ((vmap->buf != NULL)? vmap->buf: NULL);
|
||||
}
|
||||
|
||||
void free_uv_vert_map(UvVertMap *vmap)
|
||||
{
|
||||
if (vmap) {
|
||||
if (vmap->vert) MEM_freeN(vmap->vert);
|
||||
if (vmap->buf) MEM_freeN(vmap->buf);
|
||||
MEM_freeN(vmap);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -147,6 +147,7 @@ static void subsurfModifier_initData(ModifierData *md)
|
||||
|
||||
smd->levels = 1;
|
||||
smd->renderLevels = 2;
|
||||
smd->flags |= eSubsurfModifierFlag_SubsurfUv;
|
||||
}
|
||||
|
||||
static void subsurfModifier_copyData(ModifierData *md, ModifierData *target)
|
||||
@@ -505,6 +506,7 @@ static DispListMesh *mirrorModifier__doMirror(MirrorModifierData *mmd, DispListM
|
||||
|
||||
if (isShared) {
|
||||
mv->co[axis] = 0;
|
||||
mv->flag |= ME_VERT_MERGED;
|
||||
} else {
|
||||
MVert *mv2 = &dlm->mvert[dlm->totvert++];
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_linklist.h"
|
||||
#include "BLI_memarena.h"
|
||||
#include "BLI_edgehash.h"
|
||||
|
||||
#include "BIF_gl.h"
|
||||
|
||||
@@ -66,6 +67,16 @@ typedef struct _VertData {
|
||||
float no[3];
|
||||
} VertData;
|
||||
|
||||
struct CCGDerivedMesh {
|
||||
DerivedMesh dm;
|
||||
|
||||
CCGSubSurf *ss;
|
||||
int fromEditmesh, drawInteriorEdges, useSubsurfUv;
|
||||
|
||||
Mesh *me;
|
||||
DispListMesh *dlm;
|
||||
};
|
||||
|
||||
typedef struct CCGDerivedMesh CCGDerivedMesh;
|
||||
|
||||
static int ccgDM_getVertMapIndex(CCGDerivedMesh *ccgdm, CCGSubSurf *ss, CCGVert *v);
|
||||
@@ -194,6 +205,154 @@ static int getFaceIndex(CCGSubSurf *ss, CCGFace *f, int S, int x, int y, int edg
|
||||
}
|
||||
}
|
||||
|
||||
static float *getFaceUV(CCGSubSurf *ss, CCGFace *f, int S, int x, int y, int edgeSize, int gridSize)
|
||||
{
|
||||
int numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
|
||||
|
||||
if (x==gridSize-1 && y==gridSize-1) {
|
||||
CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
|
||||
return ccgSubSurf_getVertData(ss, v);
|
||||
}
|
||||
else if (x==gridSize-1) {
|
||||
CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
|
||||
CCGEdge *e = ccgSubSurf_getFaceEdge(ss, f, S);
|
||||
|
||||
if (v==ccgSubSurf_getEdgeVert0(ss, e))
|
||||
return ccgSubSurf_getEdgeData(ss, e, gridSize-1-y);
|
||||
else
|
||||
return ccgSubSurf_getEdgeData(ss, e, (edgeSize-2-1)-(gridSize-1-y-2));
|
||||
}
|
||||
else if (y==gridSize-1) {
|
||||
CCGVert *v = ccgSubSurf_getFaceVert(ss, f, S);
|
||||
CCGEdge *e = ccgSubSurf_getFaceEdge(ss, f, (S+numVerts-1)%numVerts);
|
||||
|
||||
if (v==ccgSubSurf_getEdgeVert0(ss, e))
|
||||
return ccgSubSurf_getEdgeData(ss, e, gridSize-1-x);
|
||||
else
|
||||
return ccgSubSurf_getEdgeData(ss, e, (edgeSize-2-1)-(gridSize-1-x-2));
|
||||
}
|
||||
else if (x==0 && y==0)
|
||||
return ccgSubSurf_getFaceCenterData(ss, f);
|
||||
else if (x==0)
|
||||
return ccgSubSurf_getFaceGridEdgeData(ss, f, (S+numVerts-1)%numVerts, y);
|
||||
else if (y==0)
|
||||
return ccgSubSurf_getFaceGridEdgeData(ss, f, S, x);
|
||||
else
|
||||
return ccgSubSurf_getFaceGridData(ss, f, S, x, y);
|
||||
}
|
||||
|
||||
static void get_face_uv_map_vert(UvVertMap *vmap, struct MFace *mf, int fi, CCGVertHDL *fverts) {
|
||||
unsigned int *fv = &mf->v1;
|
||||
UvMapVert *v, *nv, *firstv = get_first_uv_map_vert(vmap);
|
||||
int j, nverts= mf->v4? 4: 3;
|
||||
|
||||
for (j=0; j<nverts; j++, fv++) {
|
||||
for (nv=v=get_uv_map_vert(vmap, *fv); v; v=v->next) {
|
||||
if (v->separate)
|
||||
nv= v;
|
||||
if (v->f == fi)
|
||||
break;
|
||||
}
|
||||
|
||||
fverts[j]= (CCGVertHDL)(nv - firstv);
|
||||
}
|
||||
}
|
||||
|
||||
static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, Mesh *me, DispListMesh *dlm) {
|
||||
MFace *mface = dlm?dlm->mface:me->mface;
|
||||
TFace *tface = dlm?dlm->tface:me->tface;
|
||||
MVert *mvert = dlm?dlm->mvert:me->mvert;
|
||||
int totvert = dlm?dlm->totvert:me->totvert;
|
||||
int totface = dlm?dlm->totface:me->totface;
|
||||
int i, j, seam;
|
||||
UvMapVert *v, *firstv;
|
||||
UvVertMap *vmap;
|
||||
float limit[2];
|
||||
CCGVertHDL fverts[4];
|
||||
EdgeHash *ehash;
|
||||
|
||||
limit[0]= limit[1]= 0.0001f;
|
||||
vmap= make_uv_vert_map(mface, tface, totface, totvert, 0, limit);
|
||||
if (!vmap)
|
||||
return 0;
|
||||
|
||||
ccgSubSurf_initFullSync(ss);
|
||||
|
||||
/* use this to get consistent vert handles with different heap addresses */
|
||||
firstv= (totvert > 0)? get_first_uv_map_vert(vmap): NULL;
|
||||
|
||||
/* create vertices */
|
||||
for (i=0; i<totvert; i++) {
|
||||
for (v=get_uv_map_vert(vmap, i)->next; v; v=v->next)
|
||||
if (v->separate)
|
||||
break;
|
||||
|
||||
seam = (v != NULL) || ((mvert+i)->flag & ME_VERT_MERGED);
|
||||
|
||||
for (v=get_uv_map_vert(vmap, i); v; v=v->next) {
|
||||
if (v->separate) {
|
||||
CCGVert *ssv;
|
||||
CCGVertHDL vhdl = (CCGVertHDL)(v - firstv);
|
||||
float uv[3];
|
||||
|
||||
uv[0]= (tface+v->f)->uv[v->tfindex][0];
|
||||
uv[1]= (tface+v->f)->uv[v->tfindex][1];
|
||||
uv[2]= 0.0f;
|
||||
|
||||
ccgSubSurf_syncVert(ss, vhdl, uv, seam, &ssv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* create edges */
|
||||
ehash = BLI_edgehash_new();
|
||||
|
||||
for (i=0; i<totface; i++) {
|
||||
MFace *mf = &((MFace*) mface)[i];
|
||||
int nverts= mf->v4? 4: 3;
|
||||
CCGFace *origf= ccgSubSurf_getFace(origss, (CCGFaceHDL)i);
|
||||
unsigned int *fv = &mf->v1;
|
||||
|
||||
get_face_uv_map_vert(vmap, mf, i, fverts);
|
||||
|
||||
for (j=0; j<nverts; j++) {
|
||||
int v0 = (int)fverts[j];
|
||||
int v1 = (int)fverts[(j+1)%nverts];
|
||||
MVert *mv0 = mvert + *(fv+j);
|
||||
MVert *mv1 = mvert + *(fv+((j+1)%nverts));
|
||||
|
||||
if (!BLI_edgehash_haskey(ehash, v0, v1)) {
|
||||
CCGEdge *e, *orige= ccgSubSurf_getFaceEdge(origss, origf, j);
|
||||
CCGEdgeHDL ehdl= (CCGEdgeHDL)((int)fverts[j], (int)fverts[(j+1)%nverts]);
|
||||
float crease = ccgSubSurf_getEdgeCrease(origss, orige);
|
||||
|
||||
if ((mv0->flag&mv1->flag) & ME_VERT_MERGED)
|
||||
crease = 2.0f;
|
||||
|
||||
ccgSubSurf_syncEdge(ss, ehdl, fverts[j], fverts[(j+1)%nverts], crease, &e);
|
||||
BLI_edgehash_insert(ehash, v0, v1, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BLI_edgehash_free(ehash, NULL);
|
||||
|
||||
/* create faces */
|
||||
for (i=0; i<totface; i++) {
|
||||
MFace *mf = &((MFace*) mface)[i];
|
||||
int nverts= mf->v4? 4: 3;
|
||||
CCGFace *f;
|
||||
|
||||
get_face_uv_map_vert(vmap, mf, i, fverts);
|
||||
ccgSubSurf_syncFace(ss, (CCGFaceHDL)i, nverts, fverts, &f);
|
||||
}
|
||||
|
||||
free_uv_vert_map(vmap);
|
||||
ccgSubSurf_processSync(ss);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static unsigned int ss_getEdgeFlags(CCGSubSurf *ss, CCGEdge *e, int ssFromEditmesh, DispListMesh *dlm, MEdge *medge, TFace *tface)
|
||||
{
|
||||
@@ -225,7 +384,7 @@ static unsigned int ss_getEdgeFlags(CCGSubSurf *ss, CCGEdge *e, int ssFromEditme
|
||||
}
|
||||
#endif
|
||||
|
||||
static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, int ssFromEditmesh, int drawInteriorEdges, Mesh *inMe, DispListMesh *inDLM) {
|
||||
static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, int ssFromEditmesh, int drawInteriorEdges, int useSubsurfUv, Mesh *inMe, DispListMesh *inDLM) {
|
||||
DispListMesh *dlm = MEM_callocN(sizeof(*dlm), "dlm");
|
||||
int edgeSize = ccgSubSurf_getEdgeSize(ss);
|
||||
int gridSize = ccgSubSurf_getGridSize(ss);
|
||||
@@ -239,10 +398,11 @@ static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, i
|
||||
CCGVertIterator *vi;
|
||||
CCGEdgeIterator *ei;
|
||||
CCGFaceIterator *fi;
|
||||
CCGFace **faceMap2;
|
||||
CCGFace **faceMap2, **faceMap2Uv = NULL;
|
||||
CCGEdge **edgeMap2;
|
||||
CCGVert **vertMap2;
|
||||
int totvert, totedge, totface;
|
||||
CCGSubSurf *uvss= NULL;
|
||||
|
||||
totvert = ccgSubSurf_getNumVerts(ss);
|
||||
vertMap2 = MEM_mallocN(totvert*sizeof(*vertMap2), "vertmap");
|
||||
@@ -317,6 +477,23 @@ static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, i
|
||||
dlm->mcol = NULL;
|
||||
}
|
||||
|
||||
|
||||
if (useSubsurfUv && tface) {
|
||||
/* not for editmesh currently */
|
||||
uvss= _getSubSurf(NULL, ccgSubSurf_getSubdivisionLevels(ss), 0, 1, 0);
|
||||
|
||||
if (ss_sync_from_uv(uvss, ss, inMe, inDLM)) {
|
||||
faceMap2Uv = MEM_mallocN(totface*sizeof(*faceMap2Uv), "facemapuv");
|
||||
|
||||
fi = ccgSubSurf_getFaceIterator(uvss);
|
||||
for (; !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) {
|
||||
CCGFace *f = ccgFaceIterator_getCurrent(fi);
|
||||
faceMap2Uv[(int) ccgSubSurf_getFaceFaceHandle(uvss, f)] = f;
|
||||
}
|
||||
ccgFaceIterator_free(fi);
|
||||
}
|
||||
}
|
||||
|
||||
/* Load vertices... we do in this funny order because
|
||||
* all "added" vertices" are required to appear first
|
||||
* in the displist (before STEPINDEX flags start). Also
|
||||
@@ -460,6 +637,7 @@ static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, i
|
||||
lastIndex = -1;
|
||||
for (index=0; index<totface; index++) {
|
||||
CCGFace *f = faceMap2[index];
|
||||
CCGFace *uvf = faceMap2Uv? faceMap2Uv[index]: NULL;
|
||||
int numVerts = ccgSubSurf_getFaceNumVerts(ss, f);
|
||||
float edge_data[4][6];
|
||||
float corner_data[4][6];
|
||||
@@ -483,10 +661,12 @@ static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, i
|
||||
corner_data[S][1] = col[1]/255.0f;
|
||||
corner_data[S][2] = col[2]/255.0f;
|
||||
corner_data[S][3] = col[3]/255.0f;
|
||||
if (!uvf) {
|
||||
corner_data[S][4] = origTFace->uv[S][0];
|
||||
corner_data[S][5] = origTFace->uv[S][1];
|
||||
}
|
||||
numDataComponents = 6;
|
||||
}
|
||||
numDataComponents = uvf? 4: 6;
|
||||
} else if (mcol) {
|
||||
MCol *origMCol = &mcol[origIdx*4];
|
||||
|
||||
@@ -523,6 +703,8 @@ static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, i
|
||||
|
||||
for (y=0; y<gridSize-1; y++) {
|
||||
for (x=0; x<gridSize-1; x++) {
|
||||
float smoothuv[4][3];
|
||||
|
||||
MFace *mf = &dlm->mface[i];
|
||||
mf->v1 = getFaceIndex(ss, f, S, x+0, y+0, edgeSize, gridSize);
|
||||
mf->v2 = getFaceIndex(ss, f, S, x+0, y+1, edgeSize, gridSize);
|
||||
@@ -531,6 +713,13 @@ static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, i
|
||||
mf->mat_nr = mat_nr;
|
||||
mf->flag = flag&~ME_FACE_STEPINDEX;
|
||||
|
||||
if(uvf) {
|
||||
VECCOPY(smoothuv[0], getFaceUV(uvss, uvf, S, x+0, y+0, edgeSize, gridSize));
|
||||
VECCOPY(smoothuv[1], getFaceUV(uvss, uvf, S, x+0, y+1, edgeSize, gridSize));
|
||||
VECCOPY(smoothuv[2], getFaceUV(uvss, uvf, S, x+1, y+1, edgeSize, gridSize));
|
||||
VECCOPY(smoothuv[3], getFaceUV(uvss, uvf, S, x+1, y+0, edgeSize, gridSize));
|
||||
}
|
||||
|
||||
if (S==0 && x==0 && y==0) {
|
||||
if (mapIndex!=lastIndex)
|
||||
mf->flag |= ME_FACE_STEPINDEX;
|
||||
@@ -557,8 +746,14 @@ static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, i
|
||||
col[2] = (int) (data[2]*255);
|
||||
col[3] = (int) (data[3]*255);
|
||||
tf->col[j] = *((unsigned int*) col);
|
||||
tf->uv[j][0] = data[4];
|
||||
tf->uv[j][1] = data[5];
|
||||
if (uvf) {
|
||||
tf->uv[j][0] = smoothuv[j][0];
|
||||
tf->uv[j][1] = smoothuv[j][1];
|
||||
}
|
||||
else {
|
||||
tf->uv[j][0] = (float)(data[4]);
|
||||
tf->uv[j][1] = (float)(data[5]);
|
||||
}
|
||||
} else if (dlm->mcol) {
|
||||
unsigned char *col = (unsigned char*) &dlm->mcol[i*4+j];
|
||||
col[0] = (int) (data[0]*255);
|
||||
@@ -587,6 +782,11 @@ static DispListMesh *ss_to_displistmesh(CCGSubSurf *ss, CCGDerivedMesh *ccgdm, i
|
||||
MEM_freeN(edgeMap2);
|
||||
MEM_freeN(vertMap2);
|
||||
|
||||
if(uvss) {
|
||||
ccgSubSurf_free(uvss);
|
||||
MEM_freeN(faceMap2Uv);
|
||||
}
|
||||
|
||||
mesh_calc_normals(dlm->mvert, dlm->totvert, dlm->mface, dlm->totface, &dlm->nors);
|
||||
|
||||
return dlm;
|
||||
@@ -607,7 +807,7 @@ static void ss_sync_from_mesh(CCGSubSurf *ss, Mesh *me, DispListMesh *dlm, float
|
||||
|
||||
for (i=0,index=-1; i<totvert; i++) {
|
||||
CCGVert *v;
|
||||
ccgSubSurf_syncVert(ss, (CCGVertHDL) i, vertexCos?vertexCos[i]:mvert[i].co, &v);
|
||||
ccgSubSurf_syncVert(ss, (CCGVertHDL) i, vertexCos?vertexCos[i]:mvert[i].co, 0, &v);
|
||||
|
||||
if (!dlm || (mvert[i].flag&ME_VERT_STEPINDEX)) index++;
|
||||
((int*) ccgSubSurf_getVertUserData(ss, v))[1] = index;
|
||||
@@ -676,13 +876,13 @@ void ss_sync_from_editmesh(CCGSubSurf *ss, EditMesh *em, float (*vertCos)[3], in
|
||||
if (vertCos) {
|
||||
for (i=0,ev=em->verts.first; ev; i++,ev=ev->next) {
|
||||
CCGVert *v;
|
||||
ccgSubSurf_syncVert(ss, ev, vertCos[i], &v);
|
||||
ccgSubSurf_syncVert(ss, ev, vertCos[i], 0, &v);
|
||||
((int*) ccgSubSurf_getVertUserData(ss, v))[1] = i;
|
||||
}
|
||||
} else {
|
||||
for (i=0,ev=em->verts.first; ev; i++,ev=ev->next) {
|
||||
CCGVert *v;
|
||||
ccgSubSurf_syncVert(ss, ev, ev->co, &v);
|
||||
ccgSubSurf_syncVert(ss, ev, ev->co, 0, &v);
|
||||
((int*) ccgSubSurf_getVertUserData(ss, v))[1] = i;
|
||||
}
|
||||
}
|
||||
@@ -710,16 +910,6 @@ void ss_sync_from_editmesh(CCGSubSurf *ss, EditMesh *em, float (*vertCos)[3], in
|
||||
|
||||
/***/
|
||||
|
||||
struct CCGDerivedMesh {
|
||||
DerivedMesh dm;
|
||||
|
||||
CCGSubSurf *ss;
|
||||
int fromEditmesh, drawInteriorEdges;
|
||||
|
||||
Mesh *me;
|
||||
DispListMesh *dlm;
|
||||
};
|
||||
|
||||
static int ccgDM_getVertMapIndex(CCGDerivedMesh *ccgdm, CCGSubSurf *ss, CCGVert *v) {
|
||||
return ((int*) ccgSubSurf_getVertUserData(ss, v))[1];
|
||||
}
|
||||
@@ -918,7 +1108,7 @@ static void ccgDM_foreachMappedEdge(DerivedMesh *dm, void (*func)(void *userData
|
||||
static DispListMesh *ccgDM_convertToDispListMesh(DerivedMesh *dm, int allowShared) {
|
||||
CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
|
||||
|
||||
return ss_to_displistmesh(ccgdm->ss, ccgdm, ccgdm->fromEditmesh, ccgdm->drawInteriorEdges, ccgdm->me, ccgdm->dlm);
|
||||
return ss_to_displistmesh(ccgdm->ss, ccgdm, ccgdm->fromEditmesh, ccgdm->drawInteriorEdges, ccgdm->useSubsurfUv, ccgdm->me, ccgdm->dlm);
|
||||
}
|
||||
|
||||
static void ccgDM_drawVerts(DerivedMesh *dm) {
|
||||
@@ -1452,7 +1642,7 @@ static void ccgDM_release(DerivedMesh *dm) {
|
||||
MEM_freeN(ccgdm);
|
||||
}
|
||||
|
||||
static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, int fromEditmesh, int drawInteriorEdges, Mesh *me, DispListMesh *dlm) {
|
||||
static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, int fromEditmesh, int drawInteriorEdges, int useSubsurfUv, Mesh *me, DispListMesh *dlm) {
|
||||
CCGDerivedMesh *ccgdm = MEM_callocN(sizeof(*ccgdm), "ccgdm");
|
||||
|
||||
ccgdm->dm.getMinMax = ccgDM_getMinMax;
|
||||
@@ -1480,6 +1670,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, int fromEditmesh, int d
|
||||
ccgdm->ss = ss;
|
||||
ccgdm->fromEditmesh = fromEditmesh;
|
||||
ccgdm->drawInteriorEdges = drawInteriorEdges;
|
||||
ccgdm->useSubsurfUv = useSubsurfUv;
|
||||
ccgdm->me = me;
|
||||
ccgdm->dlm = dlm;
|
||||
|
||||
@@ -1496,23 +1687,25 @@ DerivedMesh *subsurf_make_derived_from_editmesh(EditMesh *em, SubsurfModifierDat
|
||||
smd->emCache = _getSubSurf(smd->emCache, smd->levels, useAging, 0, useSimple);
|
||||
ss_sync_from_editmesh(smd->emCache, em, vertCos, useSimple);
|
||||
|
||||
return (DerivedMesh*) getCCGDerivedMesh(smd->emCache, 1, drawInteriorEdges, NULL, NULL);
|
||||
return (DerivedMesh*) getCCGDerivedMesh(smd->emCache, 1, drawInteriorEdges, 0, NULL, NULL);
|
||||
}
|
||||
|
||||
DerivedMesh *subsurf_make_derived_from_dlm_em(DispListMesh *dlm, SubsurfModifierData *smd, float (*vertCos)[3]) {
|
||||
int useSimple = smd->subdivType==ME_SIMPLE_SUBSURF;
|
||||
int useAging = smd->flags&eSubsurfModifierFlag_DebugIncr;
|
||||
int useSubsurfUv = smd->flags&eSubsurfModifierFlag_SubsurfUv;
|
||||
int drawInteriorEdges = !(smd->flags&eSubsurfModifierFlag_ControlEdges);
|
||||
|
||||
smd->emCache = _getSubSurf(smd->emCache, smd->levels, useAging, 0, useSimple);
|
||||
|
||||
ss_sync_from_mesh(smd->emCache, NULL, dlm, vertCos, useSimple);
|
||||
|
||||
return (DerivedMesh*) getCCGDerivedMesh(smd->emCache, 0, drawInteriorEdges, NULL, dlm);
|
||||
return (DerivedMesh*) getCCGDerivedMesh(smd->emCache, 0, drawInteriorEdges, useSubsurfUv, NULL, dlm);
|
||||
}
|
||||
|
||||
DerivedMesh *subsurf_make_derived_from_mesh(Mesh *me, DispListMesh *dlm, SubsurfModifierData *smd, int useRenderParams, float (*vertCos)[3], int isFinalCalc) {
|
||||
int useSimple = smd->subdivType==ME_SIMPLE_SUBSURF;
|
||||
int useSubsurfUv = smd->flags&eSubsurfModifierFlag_SubsurfUv;
|
||||
int drawInteriorEdges = !(smd->flags&eSubsurfModifierFlag_ControlEdges);
|
||||
DispListMesh *ndlm;
|
||||
|
||||
@@ -1522,7 +1715,7 @@ DerivedMesh *subsurf_make_derived_from_mesh(Mesh *me, DispListMesh *dlm, Subsurf
|
||||
|
||||
ss_sync_from_mesh(ss, me, dlm, vertCos, useSimple);
|
||||
|
||||
ndlm = ss_to_displistmesh(ss, NULL, 0, drawInteriorEdges, me, dlm);
|
||||
ndlm = ss_to_displistmesh(ss, NULL, 0, drawInteriorEdges, useSubsurfUv, me, dlm);
|
||||
if (dlm) displistmesh_free(dlm);
|
||||
|
||||
ccgSubSurf_free(ss);
|
||||
@@ -1551,7 +1744,7 @@ DerivedMesh *subsurf_make_derived_from_mesh(Mesh *me, DispListMesh *dlm, Subsurf
|
||||
|
||||
ss_sync_from_mesh(ss, me, dlm, vertCos, useSimple);
|
||||
|
||||
return (DerivedMesh*) getCCGDerivedMesh(ss, 0, drawInteriorEdges, me, dlm);
|
||||
return (DerivedMesh*) getCCGDerivedMesh(ss, 0, drawInteriorEdges, useSubsurfUv, me, dlm);
|
||||
} else {
|
||||
if (smd->mCache && isFinalCalc) {
|
||||
ccgSubSurf_free(smd->mCache);
|
||||
@@ -1561,7 +1754,7 @@ DerivedMesh *subsurf_make_derived_from_mesh(Mesh *me, DispListMesh *dlm, Subsurf
|
||||
ss = _getSubSurf(NULL, smd->levels, 0, 1, useSimple);
|
||||
ss_sync_from_mesh(ss, me, dlm, vertCos, useSimple);
|
||||
|
||||
ndlm = ss_to_displistmesh(ss, NULL, 0, drawInteriorEdges, me, dlm);
|
||||
ndlm = ss_to_displistmesh(ss, NULL, 0, drawInteriorEdges, useSubsurfUv, me, dlm);
|
||||
|
||||
if (dlm) displistmesh_free(dlm);
|
||||
ccgSubSurf_free(ss);
|
||||
|
||||
@@ -320,6 +320,7 @@ Text *add_text(char *file)
|
||||
char str[FILE_MAXDIR+FILE_MAXFILE];
|
||||
|
||||
BLI_strncpy(str, file, FILE_MAXDIR+FILE_MAXFILE);
|
||||
if (G.scene) /* can be NULL (bg mode) */
|
||||
BLI_convertstringcode(str, G.sce, G.scene->r.cfra);
|
||||
BLI_split_dirfile(str, sdir, sfile);
|
||||
|
||||
|
||||
@@ -171,8 +171,8 @@ typedef short IPO_Channel;
|
||||
|
||||
/* ******************** */
|
||||
|
||||
#define TE_TOTIPO 21
|
||||
#define TE_TOTNAM 21
|
||||
#define TE_TOTIPO 26
|
||||
#define TE_TOTNAM 26
|
||||
|
||||
#define TE_NSIZE 1
|
||||
#define TE_NDEPTH 2
|
||||
@@ -200,6 +200,12 @@ typedef short IPO_Channel;
|
||||
#define TE_N_BAS1 20
|
||||
#define TE_N_BAS2 21
|
||||
|
||||
#define TE_COL_R 22
|
||||
#define TE_COL_G 23
|
||||
#define TE_COL_B 24
|
||||
#define TE_BRIGHT 25
|
||||
#define TE_CONTRA 26
|
||||
|
||||
/* ******************** */
|
||||
|
||||
#define SEQ_TOTIPO 1
|
||||
|
||||
@@ -75,6 +75,7 @@ typedef struct MSticky {
|
||||
#define ME_SPHERETEST 2
|
||||
#define ME_SPHERETEMP 4
|
||||
#define ME_HIDE 16
|
||||
#define ME_VERT_MERGED (1<<6)
|
||||
#define ME_VERT_STEPINDEX (1<<7)
|
||||
|
||||
/* medge->flag (1=SELECT)*/
|
||||
|
||||
@@ -47,7 +47,8 @@ typedef struct ModifierData {
|
||||
typedef enum {
|
||||
eSubsurfModifierFlag_Incremental = (1<<0),
|
||||
eSubsurfModifierFlag_DebugIncr = (1<<1),
|
||||
eSubsurfModifierFlag_ControlEdges = (1<<2)
|
||||
eSubsurfModifierFlag_ControlEdges = (1<<2),
|
||||
eSubsurfModifierFlag_SubsurfUv = (1<<3)
|
||||
} SubsurfModifierFlag;
|
||||
|
||||
typedef struct SubsurfModifierData {
|
||||
|
||||
@@ -318,7 +318,7 @@ typedef struct Scene {
|
||||
/* none of the dependancy graph vars is mean to be saved */
|
||||
struct DagForest *theDag;
|
||||
short dagisvalid, dagflags;
|
||||
int pad1;
|
||||
int dirty;
|
||||
} Scene;
|
||||
|
||||
|
||||
@@ -424,6 +424,10 @@ typedef struct Scene {
|
||||
#define SCE_SELECT_EDGE 2
|
||||
#define SCE_SELECT_FACE 4
|
||||
|
||||
/* sce->dirty */
|
||||
#define SCE_CLEAN 0
|
||||
#define SCE_DIRTY 1
|
||||
|
||||
/* sce->prop_mode (proportional falloff) */
|
||||
#define PROP_SMOOTH 0
|
||||
#define PROP_SPHERE 1
|
||||
|
||||
@@ -460,11 +460,12 @@ static int EditBone_setOptions(BPy_EditBone *self, PyObject *value, void *closur
|
||||
//set the options
|
||||
if(self->editbone){
|
||||
//make sure the 'connected' property is set up correctly
|
||||
if (new_flag & BONE_CONNECTED)
|
||||
if (new_flag & BONE_CONNECTED) {
|
||||
if(!self->editbone->parent)
|
||||
goto AttributeError3;
|
||||
else
|
||||
VECCOPY(self->editbone->head, self->editbone->parent->tail);
|
||||
}
|
||||
self->editbone->flag = new_flag;
|
||||
}else{
|
||||
self->flag = new_flag;
|
||||
@@ -479,11 +480,12 @@ static int EditBone_setOptions(BPy_EditBone *self, PyObject *value, void *closur
|
||||
|
||||
if(self->editbone){
|
||||
//make sure the 'connected' property is set up correctly
|
||||
if (numeric_value & BONE_CONNECTED)
|
||||
if (numeric_value & BONE_CONNECTED) {
|
||||
if(!self->editbone->parent)
|
||||
goto AttributeError3;
|
||||
else
|
||||
VECCOPY(self->editbone->head, self->editbone->parent->tail);
|
||||
}
|
||||
self->editbone->flag = numeric_value;
|
||||
}else{
|
||||
self->flag = numeric_value;
|
||||
|
||||
@@ -107,6 +107,8 @@ static PyObject *Method_PupFloatInput( PyObject * self, PyObject * args );
|
||||
static PyObject *Method_PupStrInput( PyObject * self, PyObject * args );
|
||||
/* next by Jonathan Merritt (lancelet): */
|
||||
static PyObject *Method_Image( PyObject * self, PyObject * args);
|
||||
/* CLEVER NUMBUT */
|
||||
static PyObject *Method_PupBlock( PyObject * self, PyObject * args );
|
||||
|
||||
static uiBlock *Get_uiBlock( void );
|
||||
static void py_slider_update( void *butv, void *data2_unused );
|
||||
@@ -277,6 +279,22 @@ static char Method_PupStrInput_doc[] =
|
||||
(max = 20) - The maximum number of chars the user can input;\n\
|
||||
Return the user input value or None on user exit";
|
||||
|
||||
static char Method_PupBlock_doc[] =
|
||||
"(title, sequence) - Display a pop-up block.\n\
|
||||
(title) - The title of the block.\n\
|
||||
(sequence) - A sequence defining what the block contains. \
|
||||
The order of the list is the order of appearance, from top down.\n\
|
||||
Possible format for sequence items:\n\
|
||||
[value is an object created with Create]\n\
|
||||
\ttext: Defines a label in the block\n\
|
||||
\t(text, value, tooltip = ''): Defines a toggle button \n\
|
||||
\t(text, value, min, max, tooltip = ''): Defines a num or string button \n\
|
||||
\t\t\tdepending on the value.\n\
|
||||
\t\tFor string, max is the maximum length of the text and min is unused.\n\
|
||||
Return 1 if the pop-up is confirmed, 0 otherwise. \n\
|
||||
Warning: On cancel, the value objects are brought back to there previous values, \
|
||||
\texcept for string values which will still contain the modified values.\n";
|
||||
|
||||
static char Method_Exit_doc[] = "() - Exit the windowing interface";
|
||||
|
||||
/*
|
||||
@@ -307,6 +325,7 @@ static struct PyMethodDef Draw_methods[] = {
|
||||
MethodDef( PupIntInput ),
|
||||
MethodDef( PupFloatInput ),
|
||||
MethodDef( PupStrInput ),
|
||||
MethodDef( PupBlock ),
|
||||
MethodDef( Image ),
|
||||
MethodDef( Exit ),
|
||||
MethodDef( Redraw ),
|
||||
@@ -335,7 +354,7 @@ static void Button_dealloc( PyObject * self )
|
||||
{
|
||||
Button *but = ( Button * ) self;
|
||||
|
||||
if( but->type == 3 ) {
|
||||
if( but->type == BSTRING_TYPE ) {
|
||||
if( but->val.asstr )
|
||||
MEM_freeN( but->val.asstr );
|
||||
}
|
||||
@@ -348,11 +367,11 @@ static PyObject *Button_getattr( PyObject * self, char *name )
|
||||
Button *but = ( Button * ) self;
|
||||
|
||||
if( strcmp( name, "val" ) == 0 ) {
|
||||
if( but->type == 1 )
|
||||
if( but->type == BINT_TYPE )
|
||||
return Py_BuildValue( "i", but->val.asint );
|
||||
else if( but->type == 2 )
|
||||
else if( but->type == BFLOAT_TYPE )
|
||||
return Py_BuildValue( "f", but->val.asfloat );
|
||||
else if( but->type == 3 )
|
||||
else if( but->type == BSTRING_TYPE )
|
||||
return Py_BuildValue( "s", but->val.asstr );
|
||||
}
|
||||
|
||||
@@ -365,11 +384,11 @@ static int Button_setattr( PyObject * self, char *name, PyObject * v )
|
||||
Button *but = ( Button * ) self;
|
||||
|
||||
if( strcmp( name, "val" ) == 0 ) {
|
||||
if( but->type == 1 )
|
||||
if( but->type == BINT_TYPE )
|
||||
PyArg_Parse( v, "i", &but->val.asint );
|
||||
else if( but->type == 2 )
|
||||
else if( but->type == BFLOAT_TYPE )
|
||||
PyArg_Parse( v, "f", &but->val.asfloat );
|
||||
else if( but->type == 3 ) {
|
||||
else if( but->type == BSTRING_TYPE ) {
|
||||
char *newstr;
|
||||
PyArg_Parse( v, "s", &newstr );
|
||||
|
||||
@@ -705,15 +724,15 @@ static PyObject *Method_Create( PyObject * self, PyObject * args )
|
||||
|
||||
but = newbutton( );
|
||||
if( PyFloat_Check( in ) ) {
|
||||
but->type = 2;
|
||||
but->type = BFLOAT_TYPE;
|
||||
but->val.asfloat = (float)PyFloat_AsDouble( in );
|
||||
} else if( PyInt_Check( in ) ) {
|
||||
but->type = 1;
|
||||
but->type = BINT_TYPE;
|
||||
but->val.asint = PyInt_AsLong( in );
|
||||
} else if( PyString_Check( in ) ) {
|
||||
char *newstr = PyString_AsString( in );
|
||||
|
||||
but->type = 3;
|
||||
but->type = BSTRING_TYPE;
|
||||
but->slen = strlen( newstr );
|
||||
but->val.asstr = MEM_mallocN( but->slen + 1, "button string" );
|
||||
|
||||
@@ -790,7 +809,7 @@ static PyObject *Method_Menu( PyObject * self, PyObject * args )
|
||||
"button event argument must be in the range [0, 16382]");
|
||||
|
||||
but = newbutton( );
|
||||
but->type = 1;
|
||||
but->type = BINT_TYPE;
|
||||
but->val.asint = def;
|
||||
|
||||
block = Get_uiBlock( );
|
||||
@@ -819,7 +838,7 @@ static PyObject *Method_Toggle( PyObject * self, PyObject * args )
|
||||
"button event argument must be in the range [0, 16382]");
|
||||
|
||||
but = newbutton( );
|
||||
but->type = 1;
|
||||
but->type = BINT_TYPE;
|
||||
but->val.asint = def;
|
||||
|
||||
block = Get_uiBlock( );
|
||||
@@ -895,7 +914,7 @@ static PyObject *Method_Slider( PyObject * self, PyObject * args )
|
||||
min = (float)PyFloat_AsDouble( mino );
|
||||
max = (float)PyFloat_AsDouble( maxo );
|
||||
|
||||
but->type = 2;
|
||||
but->type = BFLOAT_TYPE;
|
||||
but->val.asfloat = ini;
|
||||
|
||||
block = Get_uiBlock( );
|
||||
@@ -915,7 +934,7 @@ static PyObject *Method_Slider( PyObject * self, PyObject * args )
|
||||
min = PyInt_AsLong( mino );
|
||||
max = PyInt_AsLong( maxo );
|
||||
|
||||
but->type = 1;
|
||||
but->type = BINT_TYPE;
|
||||
but->val.asint = ini;
|
||||
|
||||
block = Get_uiBlock( );
|
||||
@@ -960,15 +979,15 @@ another int and string as arguments" );
|
||||
but = newbutton( );
|
||||
|
||||
if( PyFloat_Check( inio ) )
|
||||
but->type = 2;
|
||||
but->type = BFLOAT_TYPE;
|
||||
else
|
||||
but->type = 1;
|
||||
but->type = BINT_TYPE;
|
||||
|
||||
ini = (float)PyFloat_AsDouble( inio );
|
||||
min = (float)PyFloat_AsDouble( mino );
|
||||
max = (float)PyFloat_AsDouble( maxo );
|
||||
|
||||
if( but->type == 2 ) {
|
||||
if( but->type == BFLOAT_TYPE ) {
|
||||
but->val.asfloat = ini;
|
||||
block = Get_uiBlock( );
|
||||
if( block ) {
|
||||
@@ -1025,7 +1044,7 @@ static PyObject *Method_Number( PyObject * self, PyObject * args )
|
||||
min = (float)PyFloat_AsDouble( mino );
|
||||
max = (float)PyFloat_AsDouble( maxo );
|
||||
|
||||
but->type = 2;
|
||||
but->type = BFLOAT_TYPE;
|
||||
but->val.asfloat = ini;
|
||||
|
||||
block = Get_uiBlock( );
|
||||
@@ -1039,7 +1058,7 @@ static PyObject *Method_Number( PyObject * self, PyObject * args )
|
||||
min = PyInt_AsLong( mino );
|
||||
max = PyInt_AsLong( maxo );
|
||||
|
||||
but->type = 1;
|
||||
but->type = BINT_TYPE;
|
||||
but->val.asint = ini;
|
||||
|
||||
block = Get_uiBlock( );
|
||||
@@ -1079,7 +1098,7 @@ static PyObject *Method_String( PyObject * self, PyObject * args )
|
||||
if (real_len > len) real_len = len;
|
||||
|
||||
but = newbutton( );
|
||||
but->type = 3;
|
||||
but->type = BSTRING_TYPE;
|
||||
but->slen = len;
|
||||
but->val.asstr = MEM_mallocN( len + 1, "pybutton str" );
|
||||
|
||||
@@ -1260,6 +1279,125 @@ static PyObject *Method_PupStrInput( PyObject * self, PyObject * args )
|
||||
"couldn't create a PyString" );
|
||||
}
|
||||
|
||||
static PyObject *Method_PupBlock( PyObject * self, PyObject * args )
|
||||
{
|
||||
PyObject *pyList, *pyItem;
|
||||
float min, max;
|
||||
int len, i;
|
||||
char *title;
|
||||
|
||||
if (!PyArg_ParseTuple( args, "sO", &title, &pyList ) || !PySequence_Check( pyList ))
|
||||
return EXPP_ReturnPyObjError( PyExc_TypeError, "expected a string and a sequence" );
|
||||
|
||||
|
||||
len = PySequence_Length(pyList);
|
||||
|
||||
if (len == 0)
|
||||
return EXPP_ReturnPyObjError( PyExc_ValueError, "expected a string and a non-empty sequence." );
|
||||
|
||||
if (len > 24) /* LIMIT DEFINED IN toolbox.c */
|
||||
return EXPP_ReturnPyObjError( PyExc_ValueError, "sequence cannot have more than 24 elements" );
|
||||
|
||||
for ( i=0 ; i<len ; i++ ) {
|
||||
PyObject *pyMin = NULL, *pyMax = NULL;
|
||||
PyObject *f1, *f2;
|
||||
Button *but = NULL;
|
||||
int tlen;
|
||||
char *text, *tip = NULL;
|
||||
|
||||
pyItem = PySequence_GetItem( pyList, i );
|
||||
if (!pyItem)
|
||||
return NULL;
|
||||
|
||||
if (PyString_Check( pyItem )) {
|
||||
tlen = -2; /* single string for label, giving it a special len for later */
|
||||
}
|
||||
else if (PyTuple_Check( pyItem )) {
|
||||
/* tuple for other button, get the length for later */
|
||||
tlen = PyTuple_Size( pyItem );
|
||||
}
|
||||
else {
|
||||
/* Neither a string or a tuple, error */
|
||||
Py_DECREF( pyItem );
|
||||
return EXPP_ReturnPyObjError( PyExc_ValueError, "expected a string or a tuple containing 2 to 5 values." );
|
||||
}
|
||||
|
||||
switch (tlen) {
|
||||
case -2: /* LABEL */
|
||||
text = PyString_AsString( pyItem );
|
||||
add_numbut(i, LABEL, text, 0, 0, NULL, NULL);
|
||||
break;
|
||||
case 2: /* TOGGLE (no tooltip) */
|
||||
case 3: /* TOGGLE */
|
||||
if (!PyArg_ParseTuple( pyItem, "sO!|s", &text, &Button_Type, &but, &tip )) {
|
||||
Py_DECREF( pyItem );
|
||||
return EXPP_ReturnPyObjError( PyExc_ValueError, "expected a tuple containing a string, a Button object and optionally a string for toggles" );
|
||||
}
|
||||
|
||||
if (but->type != BINT_TYPE) {
|
||||
Py_DECREF( pyItem );
|
||||
return EXPP_ReturnPyObjError( PyExc_ValueError, "Button object for toggles should hold an integer" );
|
||||
}
|
||||
|
||||
add_numbut(i, TOG|INT, text, 0, 0, &but->val.asint, tip);
|
||||
break;
|
||||
case 4: /* TEX and NUM (no tooltip) */
|
||||
case 5: /* TEX and NUM */
|
||||
if (!PyArg_ParseTuple( pyItem, "sO!OO|s", &text, &Button_Type, &but, &pyMin, &pyMax, &tip )) {
|
||||
Py_DECREF( pyItem );
|
||||
return EXPP_ReturnPyObjError( PyExc_ValueError, "expected a tuple containing a string, a Button object, two numerical values and optionally a string for Text and Num buttons" );
|
||||
}
|
||||
|
||||
f1 = PyNumber_Float(pyMin);
|
||||
f2 = PyNumber_Float(pyMax);
|
||||
|
||||
if (!f1 || !f2) {
|
||||
Py_DECREF( pyItem );
|
||||
return EXPP_ReturnPyObjError( PyExc_ValueError, "expected a tuple containing a string, a Button object, two numerical values and optionally a string for Text and Num buttons" );
|
||||
}
|
||||
|
||||
min = (float)PyFloat_AS_DOUBLE(f1);
|
||||
max = (float)PyFloat_AS_DOUBLE(f2);
|
||||
Py_DECREF( f1 );
|
||||
Py_DECREF( f2 );
|
||||
|
||||
switch ( but->type ) {
|
||||
case BINT_TYPE:
|
||||
add_numbut(i, NUM|INT, text, min, max, &but->val.asint, tip);
|
||||
break;
|
||||
case BFLOAT_TYPE:
|
||||
add_numbut(i, NUM|FLO, text, min, max, &but->val.asfloat, tip);
|
||||
break;
|
||||
case BSTRING_TYPE:
|
||||
max = (float)floor(max);
|
||||
|
||||
if (max > but->slen) {
|
||||
int old_len = but->slen;
|
||||
char *old_str = but->val.asstr;
|
||||
but->slen = (int)max;
|
||||
but->val.asstr = MEM_callocN( but->slen + 1, "button pupblock");
|
||||
BLI_strncpy( but->val.asstr, old_str, old_len + 1 );
|
||||
MEM_freeN(old_str);
|
||||
}
|
||||
|
||||
add_numbut(i, TEX, text, 0.0f, max, but->val.asstr, tip);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
Py_DECREF( pyItem );
|
||||
return EXPP_ReturnPyObjError( PyExc_ValueError, "expected a string or a tuple containing 2 to 5 values." );
|
||||
}
|
||||
Py_DECREF( pyItem );
|
||||
}
|
||||
|
||||
if (do_clever_numbuts(title, len, REDRAW))
|
||||
return EXPP_incr_ret_True();
|
||||
else
|
||||
return EXPP_incr_ret_False();
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* Function: Method_Image *
|
||||
* Python equivalent: Blender.Draw.Image *
|
||||
|
||||
@@ -59,6 +59,10 @@ typedef struct _Button {
|
||||
char *tooltip;
|
||||
} Button;
|
||||
|
||||
#define BINT_TYPE 1
|
||||
#define BFLOAT_TYPE 2
|
||||
#define BSTRING_TYPE 3
|
||||
|
||||
|
||||
/*
|
||||
* these are declared in ../BPY_extern.h
|
||||
|
||||
@@ -914,9 +914,9 @@ static PyObject *Ipo_addCurve( BPy_Ipo * self, PyObject * args )
|
||||
/* create the new ipo curve */
|
||||
icu = MEM_callocN(sizeof(IpoCurve), "Python added ipocurve");
|
||||
icu->blocktype= ipo->blocktype;
|
||||
icu->flag |= IPO_VISIBLE|IPO_AUTO_HORIZ;
|
||||
icu->blocktype= ipo->blocktype;
|
||||
icu->adrcode= (short)param;
|
||||
icu->flag |= IPO_VISIBLE|IPO_AUTO_HORIZ;
|
||||
set_icu_vars( icu );
|
||||
BLI_addtail( &(ipo->curve), icu);
|
||||
|
||||
allspace( REMAKEIPO, 0 );
|
||||
|
||||
@@ -1857,15 +1857,10 @@ static PyObject *Object_join( BPy_Object * self, PyObject * args )
|
||||
short type;
|
||||
int i, ok=0, ret_value=0, list_length=0;
|
||||
|
||||
/* cant join in editmode */
|
||||
if( G.obedit )
|
||||
return EXPP_ReturnPyObjError(PyExc_RuntimeError,
|
||||
"can't join objects while in edit mode" );
|
||||
|
||||
/* Check if the arguments passed to makeParent are valid. */
|
||||
if( !PyArg_ParseTuple( args, "O", &list ) )
|
||||
return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
|
||||
"expected a list of objects and one or two integers as arguments" ) );
|
||||
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
|
||||
"expected a list of objects" ) );
|
||||
|
||||
if( !PySequence_Check( list ) )
|
||||
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
|
||||
@@ -1880,11 +1875,16 @@ static PyObject *Object_join( BPy_Object * self, PyObject * args )
|
||||
parent = ( Object * ) self->object;
|
||||
type = parent->type;
|
||||
|
||||
/* Only these object types are sypported */
|
||||
if (type==OB_MESH || type==OB_MESH || type==OB_CURVE || type==OB_SURF || type==OB_ARMATURE);
|
||||
else
|
||||
return ( EXPP_ReturnPyObjError( PyExc_TypeError,
|
||||
"Base object is not a type blender can join" ) );
|
||||
|
||||
/* exit editmode so join can be done */
|
||||
if( G.obedit )
|
||||
exit_editmode( 1 );
|
||||
|
||||
temp_scene = add_scene( "Scene" ); /* make the new scene */
|
||||
temp_scene->lay= 2097151; /* all layers on */
|
||||
|
||||
@@ -1940,8 +1940,9 @@ static PyObject *Object_join( BPy_Object * self, PyObject * args )
|
||||
else if(type == OB_SURF)
|
||||
ret_value = join_curve(OB_SURF);
|
||||
else if(type == OB_ARMATURE)
|
||||
ret_value = join_armature ();
|
||||
/* May use for correcting object user counts */
|
||||
ret_value = join_armature();
|
||||
|
||||
/* May use this for correcting object user counts later on */
|
||||
/*
|
||||
if (!ret_value) {
|
||||
temp_base = temp_scene->base.first;
|
||||
@@ -1952,15 +1953,23 @@ static PyObject *Object_join( BPy_Object * self, PyObject * args )
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
/* remove old scene */
|
||||
set_scene( orig_scene );
|
||||
free_libblock( &G.main->scene, temp_scene );
|
||||
|
||||
if (!ok) /* no objects were of the correct type, return 0 */
|
||||
return ( PyInt_FromLong(0) );
|
||||
|
||||
return ( PyInt_FromLong(ret_value) );
|
||||
/* no objects were of the correct type, return None */
|
||||
if (!ok)
|
||||
return EXPP_incr_ret( Py_None );
|
||||
|
||||
/* If the join failed then raise an error */
|
||||
if (!ret_value)
|
||||
return ( EXPP_ReturnPyObjError( PyExc_RuntimeError,
|
||||
"Blender failed to join the objects, this is not a script error\n\
|
||||
Please add exception handeling to your script with a RuntimeError exception\n\
|
||||
letting the user know that their data could not be joined." ) );
|
||||
|
||||
return EXPP_incr_ret( Py_None );
|
||||
}
|
||||
|
||||
static PyObject *internal_makeParent(Object *parent, PyObject *py_child,
|
||||
|
||||
@@ -934,7 +934,7 @@ static PyObject *Scene_setCurrentCamera( BPy_Scene * self, PyObject * args )
|
||||
scene->camera = object; /* set the current Camera */
|
||||
|
||||
/* if this is the current scene, update its window now */
|
||||
if( scene == G.scene )
|
||||
if( !G.background && scene == G.scene ) /* Traced a crash to redrawing while in background mode -Campbell */
|
||||
copy_view3d_lock( REDRAW );
|
||||
|
||||
/* XXX copy_view3d_lock(REDRAW) prints "bad call to addqueue: 0 (18, 1)".
|
||||
|
||||
@@ -9,6 +9,7 @@ Draw
|
||||
B{New}:
|
||||
- access to ASCII values in L{events<Register>} callbacks;
|
||||
- 'large' fonts for L{Text} and L{GetStringWidth}.
|
||||
- Pop-up blocks with L{PupBlock}
|
||||
|
||||
This module provides access to a B{windowing interface} in Blender. Its widgets
|
||||
include many kinds of buttons: push, toggle, menu, number, string, slider,
|
||||
@@ -406,6 +407,50 @@ def PupStrInput(text, default, max = 20):
|
||||
@return: The text entered by the user or None if none was chosen.
|
||||
"""
|
||||
|
||||
def PupBlock(title, sequence):
|
||||
"""
|
||||
Display a pop-up block.
|
||||
|
||||
Possible formats for the items in the sequence parameter.
|
||||
(Value are objects created with L{Create})
|
||||
- string: Defines a label
|
||||
- (string, Value, string): Defines a toggle button. The first string is the text on the button, the optional second string is the tooltip.
|
||||
- (string, Value, min, max, string): Defines a numeric or string button, depending on the content of Value. The first string is the text on the button, the optional second string is the tooltip. I{For string, max is the maximum length of the string and min is unused.}
|
||||
|
||||
Example::
|
||||
import Blender
|
||||
|
||||
text = Blender.Draw.Create("short text")
|
||||
f = Blender.Draw.Create(1.0)
|
||||
i = Blender.Draw.Create(2)
|
||||
tog = Blender.Draw.Create(0)
|
||||
|
||||
block = []
|
||||
|
||||
block.append(("Name: ", text, 0, 30, "this is some tool tip"))
|
||||
block.append("Some Label")
|
||||
block.append(("Value: ", f, 0.0, 100.0))
|
||||
block.append(("Value: ", i, 0, 100))
|
||||
block.append(("Option", tog, "another tooltip"))
|
||||
|
||||
retval = Blender.Draw.PupBlock("PupBlock test", block)
|
||||
|
||||
print "PupBlock returned", retval
|
||||
|
||||
print "text\\t", text
|
||||
print "float\\t", f
|
||||
print "int\\t", i
|
||||
print "toggle\\t", tog
|
||||
|
||||
@warning: On cancel, the Value objects are brought back to there initial values except for string values which will still contain the modified values.
|
||||
@type title: string
|
||||
@param title: The title of the block.
|
||||
@param sequence: A sequence defining what the block contains.
|
||||
The order of the list is the order of appearance, from top down.
|
||||
@rtype: int
|
||||
@return: 1 if the pop-up is confirmed, 0 otherwise
|
||||
"""
|
||||
|
||||
def Menu(name, event, x, y, width, height, default, tooltip = None):
|
||||
"""
|
||||
Create a new Menu Button object.
|
||||
|
||||
@@ -39,7 +39,7 @@ Example::
|
||||
- 'NoDiffuse'
|
||||
- 'RayShadow'
|
||||
|
||||
Example::
|
||||
Example::
|
||||
from Blender import Lamp, Object
|
||||
# Change the mode of selected lamp objects.
|
||||
for ob in Object.GetSelected(): # Loop through the current selection
|
||||
|
||||
@@ -556,12 +556,17 @@ class Object:
|
||||
|
||||
@type objects: Sequence of Blender Object
|
||||
@param objects: A list of objects matching the objects type.
|
||||
@note: Objects in the list will not be removed, to avoid duplicate data you may want to remove them manualy after joining.
|
||||
@note: Join modifies the object in place so that other objects are joined into it. no new object or data is created.
|
||||
@note: Join will only work for object types Mesh, Armature, Curve and Surface, an error will be raised if the object is not of this type.
|
||||
@note: Objects in the list will not be removed from the scene,
|
||||
to avoid overlapping data you may want to remove them manualy after joining.
|
||||
@note: Join modifies the base objects data in place so that
|
||||
other objects are joined into it. no new object or data is created.
|
||||
@note: Join will only work for object types Mesh, Armature, Curve and Surface,
|
||||
an error will be raised if the object is not of this type.
|
||||
@note: objects in the list will be ignored if they to not match the base object.
|
||||
@rtype: int
|
||||
@return: 0 is returned if the join is not successfull, otherwise 1 will be returned.
|
||||
@note: An error in the join function input will raise a TypeError,
|
||||
otherwise an error in the data input will raise a RuntimeError,
|
||||
for situations where you don't have tight control on the data that is being joined,
|
||||
you should handel the RuntimeError error, litting the user know the data cant be joined.
|
||||
"""
|
||||
|
||||
def makeParentDeform(objects, noninverse = 0, fast = 0):
|
||||
|
||||
@@ -100,7 +100,7 @@ PyObject *Matrix_toEuler(MatrixObject * self)
|
||||
//---------------------------Matrix.resize4x4() ------------------
|
||||
PyObject *Matrix_Resize4x4(MatrixObject * self)
|
||||
{
|
||||
int x, first_row_elem, curr_pos, new_pos, blank_columns, blank_rows;
|
||||
int x, first_row_elem, curr_pos, new_pos, blank_columns, blank_rows, index;
|
||||
|
||||
if(self->data.blend_data){
|
||||
return EXPP_ReturnPyObjError(PyExc_TypeError,
|
||||
@@ -125,7 +125,12 @@ PyObject *Matrix_Resize4x4(MatrixObject * self)
|
||||
//move data to new spot in array + clean
|
||||
for(blank_rows = (4 - self->rowSize); blank_rows > 0; blank_rows--){
|
||||
for(x = 0; x < 4; x++){
|
||||
self->contigPtr[(4 * (self->rowSize + (blank_rows - 1))) + x] = 0.0f;
|
||||
index = (4 * (self->rowSize + (blank_rows - 1))) + x;
|
||||
if (index == 10 || index == 15){
|
||||
self->contigPtr[index] = 1.0f;
|
||||
}else{
|
||||
self->contigPtr[index] = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(x = 1; x <= self->rowSize; x++){
|
||||
|
||||
@@ -2840,8 +2840,8 @@ extern ListBase duplilist;
|
||||
void RE_rotateBlenderScene(void)
|
||||
{
|
||||
Base *base;
|
||||
Object *ob;
|
||||
Scene *sce;
|
||||
Object *ob, *obd;
|
||||
Scene *sce, *setscene;
|
||||
unsigned int lay;
|
||||
float mat[4][4];
|
||||
|
||||
@@ -2908,7 +2908,7 @@ void RE_rotateBlenderScene(void)
|
||||
}
|
||||
|
||||
sce= G.scene;
|
||||
|
||||
setscene= G.scene->set;
|
||||
base= G.scene->base.first;
|
||||
while(base) {
|
||||
|
||||
@@ -3014,11 +3014,17 @@ void RE_rotateBlenderScene(void)
|
||||
}
|
||||
if(blender_test_break()) break;
|
||||
|
||||
if(base->next==0 && G.scene->set && base==G.scene->base.last) {
|
||||
base= base->next;
|
||||
if(base==0 && setscene) {
|
||||
sce= setscene;
|
||||
base= setscene->base.first;
|
||||
setscene= setscene->set;
|
||||
}
|
||||
/*if(base->next==0 && G.scene->set && base==G.scene->base.last) {
|
||||
base= G.scene->set->base.first;
|
||||
sce= G.scene->set;
|
||||
}
|
||||
else base= base->next;
|
||||
else base= base->next;*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -52,10 +52,6 @@
|
||||
|
||||
#include "BLI_arithb.h"
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Implementation of boolean ops mesh interface.
|
||||
*/
|
||||
@@ -304,5 +300,5 @@ NewBooleanMeshTest(
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1212,7 +1212,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
|
||||
int lx = x + width - 60 - 15;
|
||||
|
||||
if (md->type==eModifierType_Subsurf) {
|
||||
height = 86;
|
||||
height = 106;
|
||||
} else if (md->type==eModifierType_Lattice) {
|
||||
height = 46;
|
||||
} else if (md->type==eModifierType_Curve) {
|
||||
@@ -1274,6 +1274,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco
|
||||
*/
|
||||
|
||||
uiDefButBitS(block, TOG, eSubsurfModifierFlag_ControlEdges, B_MODIFIER_RECALC, "Optimal Draw", lx, (cy-=19), buttonWidth,19,&smd->flags, 0, 0, 0, 0, "Skip drawing/rendering of interior subdivided edges");
|
||||
uiDefButBitS(block, TOG, eSubsurfModifierFlag_SubsurfUv, B_MODIFIER_RECALC, "Subsurf UV", lx, (cy-=19),buttonWidth,19,&smd->flags, 0, 0, 0, 0, "Use subsurf to subdivide UVs");
|
||||
} else if (md->type==eModifierType_Lattice) {
|
||||
LatticeModifierData *lmd = (LatticeModifierData*) md;
|
||||
uiDefIDPoinBut(block, modifier_testLatticeObj, ID_OB, B_CHANGEDEP, "Ob: ", lx, (cy-=19), buttonWidth,19, &lmd->object, "Lattice object to deform with");
|
||||
|
||||
@@ -457,10 +457,46 @@ static void ftype_pic(char *name)
|
||||
allqueue(REDRAWBUTSSCENE, 0);
|
||||
}
|
||||
|
||||
static void scene_chain_cleanup(Scene *sc) {
|
||||
while(sc) {
|
||||
sc->dirty = SCE_CLEAN;
|
||||
sc = sc->set;
|
||||
}
|
||||
}
|
||||
|
||||
static void scene_change_set(Scene *sc, Scene *set) {
|
||||
Scene *scene = G.main->scene.first;
|
||||
int clean = SCE_CLEAN;
|
||||
int breakout = 0;
|
||||
if (sc->set!=set) {
|
||||
sc->set= set;
|
||||
while(breakout==0 && scene) {
|
||||
Scene *setchain = scene;
|
||||
while(breakout==0 && setchain) {
|
||||
clean = setchain->dirty;
|
||||
if(clean == SCE_DIRTY) {
|
||||
/* we have not reached yet end of chain, and we
|
||||
* encountered dirty node - we have a cycle.
|
||||
* sc->set = 0, clean the chain and break out.
|
||||
*/
|
||||
error("Can't change set. It would create a loop!");
|
||||
sc->set = 0;
|
||||
breakout = 1;
|
||||
scene_chain_cleanup(scene);
|
||||
|
||||
}
|
||||
|
||||
if(breakout == 0) {
|
||||
setchain->dirty = SCE_DIRTY;
|
||||
setchain = setchain->set;
|
||||
}
|
||||
}
|
||||
|
||||
if(breakout == 0) {
|
||||
scene_chain_cleanup(scene);
|
||||
scene = scene->id.next;
|
||||
}
|
||||
}
|
||||
|
||||
allqueue(REDRAWBUTSSCENE, 0);
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
|
||||
@@ -2167,6 +2167,7 @@ void drawview3dspace(ScrArea *sa, void *spacedata)
|
||||
View3D *v3d= spacedata;
|
||||
Base *base;
|
||||
Object *ob;
|
||||
Scene *setscene;
|
||||
|
||||
setwinmatrixview3d(0); /* 0= no pick rect */
|
||||
setviewmatrixview3d(); /* note: calls where_is_object for camera... */
|
||||
@@ -2249,9 +2250,10 @@ void drawview3dspace(ScrArea *sa, void *spacedata)
|
||||
view3d_set_clipping(v3d);
|
||||
|
||||
/* draw set first */
|
||||
if(G.scene->set) {
|
||||
setscene= G.scene->set;
|
||||
if(setscene) { /* if(G.scene->set) { */
|
||||
|
||||
base= G.scene->set->base.first;
|
||||
base= setscene->base.first; /* base= G.scene->set->base.first; */
|
||||
while(base) {
|
||||
|
||||
if(v3d->lay & base->lay) {
|
||||
@@ -2265,7 +2267,12 @@ void drawview3dspace(ScrArea *sa, void *spacedata)
|
||||
draw_dupli_objects(v3d, base);
|
||||
}
|
||||
}
|
||||
|
||||
base= base->next;
|
||||
if(base==0 && setscene && setscene->set) {
|
||||
setscene= setscene->set;
|
||||
base= setscene->base.first;
|
||||
}
|
||||
}
|
||||
|
||||
/* Transp and X-ray afterdraw stuff */
|
||||
@@ -2372,6 +2379,7 @@ void drawview3d_render(struct View3D *v3d)
|
||||
{
|
||||
extern short v3d_windowmode;
|
||||
Base *base;
|
||||
Scene *setscene;
|
||||
|
||||
update_for_newframe_muted(); /* first, since camera can be animated */
|
||||
|
||||
@@ -2415,9 +2423,10 @@ void drawview3d_render(struct View3D *v3d)
|
||||
G.f |= G_SIMULATION;
|
||||
|
||||
/* first draw set */
|
||||
if(G.scene->set) {
|
||||
setscene= G.scene->set;
|
||||
if(setscene) { /* if(G.scene->set) { */
|
||||
|
||||
base= G.scene->set->base.first;
|
||||
base= setscene->base.first; /* base= G.scene->set->base.first; */
|
||||
while(base) {
|
||||
if(v3d->lay & base->lay) {
|
||||
if ELEM3(base->object->type, OB_LAMP, OB_CAMERA, OB_LATTICE);
|
||||
@@ -2433,6 +2442,10 @@ void drawview3d_render(struct View3D *v3d)
|
||||
}
|
||||
}
|
||||
base= base->next;
|
||||
if(base==0 && setscene && setscene->set) {
|
||||
setscene= setscene->set;
|
||||
base= setscene->base.first;
|
||||
}
|
||||
}
|
||||
|
||||
/* Transp and X-ray afterdraw stuff */
|
||||
|
||||
@@ -33,10 +33,6 @@
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "PIL_time.h"
|
||||
@@ -97,6 +93,10 @@
|
||||
#include "nla.h"
|
||||
|
||||
extern int count_action_levels (bAction *act);
|
||||
void top_sel_action();
|
||||
void up_sel_action();
|
||||
void bottom_sel_action();
|
||||
void down_sel_action();
|
||||
|
||||
#define BEZSELECTED(bezt) (((bezt)->f1 & 1) || ((bezt)->f2 & 1) || ((bezt)->f3 & 1))
|
||||
|
||||
|
||||
@@ -784,3 +784,4 @@ void ob_clear_constraints(void)
|
||||
BIF_undo_push("Clear Constraint(s)");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -587,7 +587,7 @@ static void make_mat_editipo(SpaceIpo *si)
|
||||
static void make_texture_editipo(SpaceIpo *si)
|
||||
{
|
||||
EditIpo *ei;
|
||||
int a;
|
||||
int a, len;
|
||||
char *name;
|
||||
|
||||
if(si->from==0) return;
|
||||
@@ -603,6 +603,12 @@ static void make_texture_editipo(SpaceIpo *si)
|
||||
|
||||
ei->col= ipo_rainbow(a, TE_TOTIPO);
|
||||
|
||||
len= strlen(ei->name);
|
||||
if(len) {
|
||||
if( ei->name[ len-1 ]=='R') ei->col= 0x5050FF;
|
||||
else if( ei->name[ len-1 ]=='G') ei->col= 0x50FF50;
|
||||
else if( ei->name[ len-1 ]=='B') ei->col= 0xFF7050;
|
||||
}
|
||||
ei->icu= find_ipocurve(si->ipo, ei->adrcode);
|
||||
if(ei->icu) {
|
||||
ei->flag= ei->icu->flag;
|
||||
@@ -2133,6 +2139,7 @@ void common_insertkey(void)
|
||||
IpoCurve *icu;
|
||||
World *wo;
|
||||
Lamp *la;
|
||||
Tex *te;
|
||||
int tlay, map, event;
|
||||
char menustr[256];
|
||||
|
||||
@@ -2285,6 +2292,85 @@ void common_insertkey(void)
|
||||
|
||||
}
|
||||
}
|
||||
else if(tab==TAB_SHADING_TEX) {
|
||||
id= G.buts->lockpoin;
|
||||
te= G.buts->lockpoin;
|
||||
if(id) {
|
||||
event= pupmenu("Insert Key %t|Cloud%x0|Mable%x1|Stucci%x2|Wood%x3|Magic%x4|Blend%x5|Musgrave%x6|Voronoi%x7|Distnoise%x8|ColourFilter%x9");
|
||||
if(event== -1) return;
|
||||
|
||||
if(event==0) {
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_NSIZE);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_NDEPTH);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_NTYPE);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_N_BAS1);
|
||||
}
|
||||
if(event==1) {
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_NSIZE);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_NDEPTH);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_NTYPE);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_TURB);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_N_BAS1);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_N_BAS2);
|
||||
}
|
||||
if(event==2) {
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_NSIZE);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_NTYPE);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_TURB);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_N_BAS1);
|
||||
}
|
||||
if(event==3) {
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_NSIZE);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_NTYPE);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_TURB);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_N_BAS1);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_N_BAS2);
|
||||
}
|
||||
if(event==4) {
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_NDEPTH);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_TURB);
|
||||
}
|
||||
if(event==5) {
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP);
|
||||
}
|
||||
if(event==6) {
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_MGH);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_MG_LAC);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_MG_OCT);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_MG_OFF);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_MG_GAIN);
|
||||
}
|
||||
if(event==7) {
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_VNW1);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_VNW2);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_VNW3);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_VNW4);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_VNMEXP);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_VN_DISTM);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_VN_COLT);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_ISCA);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_NSIZE);
|
||||
}
|
||||
if(event==8) {
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_MG_OCT);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_MG_OFF);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_MG_GAIN);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_DISTA);
|
||||
}
|
||||
if(event==9) {
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_COL_R);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_COL_G);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_COL_B);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_BRIGHT);
|
||||
insertkey(id, ID_TE, NULL, NULL, TE_CONTRA);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(G.buts->mainb==CONTEXT_OBJECT) {
|
||||
ob= OBACT;
|
||||
@@ -2385,7 +2471,6 @@ void common_insertkey(void)
|
||||
base= base->next;
|
||||
}
|
||||
if(base==NULL) return;
|
||||
|
||||
strcpy(menustr, "Insert Key%t|Loc%x0|Rot%x1|Size%x2|LocRot%x3|LocRotSize%x4|Layer%x5|Avail%x9|VisualLoc%x11|VisualRot%x12|VisualLocRot%x13");
|
||||
}
|
||||
|
||||
@@ -4531,3 +4616,4 @@ void bone2objectspace(float obSpaceBoneMat[][4], float obSpace[][4], float restP
|
||||
Mat4Invert(imat, restPos);
|
||||
Mat4MulMat4(obSpaceBoneMat, obSpace, imat);
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ char *mtex_ic_names[TEX_TOTNAM] = { "OfsX", "OfsY", "OfsZ", "SizeX", "SizeY", "S
|
||||
char *tex_ic_names[TE_TOTNAM] = { "NSize", "NDepth", "NType", "Turb", "Vnw1", "Vnw2",
|
||||
"Vnw3", "Vnw4", "MinkMExp", "DistM", "ColT", "iScale",
|
||||
"DistA", "MgType", "MgH", "Lacu", "Oct", "MgOff",
|
||||
"MgGain", "NBase1", "NBase2" };
|
||||
"MgGain", "NBase1", "NBase2", "ColR", "ColG", "ColB", "Bright", "Contras"};
|
||||
char *ma_ic_names[MA_TOTNAM] = { "R", "G", "B", "SpecR", "SpecG", "SpecB", "MirR",
|
||||
"MirG", "MirB", "Ref", "Alpha", "Emit", "Amb", "Spec",
|
||||
"Hard", "SpTra", "Ior", "Mode", "HaSize", "Translu",
|
||||
@@ -133,7 +133,7 @@ char *getname_ob_ei(int nr, int colipo)
|
||||
|
||||
char *getname_tex_ei(int nr)
|
||||
{
|
||||
if(nr>=TE_NSIZE && nr<=TE_N_BAS2) return tex_ic_names[nr-1];
|
||||
if(nr>=TE_NSIZE && nr<=TE_CONTRA) return tex_ic_names[nr-1];
|
||||
|
||||
return ic_name_empty[0];
|
||||
}
|
||||
|
||||
@@ -2221,7 +2221,7 @@ void special_editmenu(void)
|
||||
void convertmenu(void)
|
||||
{
|
||||
Base *base, *basen, *basact, *basedel=NULL;
|
||||
Object *ob, *ob1;
|
||||
Object *obact, *ob, *ob1;
|
||||
Curve *cu;
|
||||
MetaBall *mb;
|
||||
Mesh *me;
|
||||
@@ -2230,30 +2230,30 @@ void convertmenu(void)
|
||||
|
||||
if(G.scene->id.lib) return;
|
||||
|
||||
ob= OBACT;
|
||||
if(ob==0) return;
|
||||
obact= OBACT;
|
||||
if(obact==0) return;
|
||||
if(!obact->flag & SELECT) return;
|
||||
if(G.obedit) return;
|
||||
|
||||
basact= BASACT; /* will be restored */
|
||||
|
||||
if(ob->type==OB_FONT) {
|
||||
if(obact->type==OB_FONT) {
|
||||
nr= pupmenu("Convert Font to%t|Curve");
|
||||
if(nr>0) ok= 1;
|
||||
}
|
||||
else if(ob->type==OB_MBALL) {
|
||||
else if(obact->type==OB_MBALL) {
|
||||
nr= pupmenu("Convert Metaball to%t|Mesh (keep original)%x1|Mesh (Delete Original)%x2");
|
||||
if(nr>0) ok= 1;
|
||||
}
|
||||
else if(ob->type==OB_CURVE) {
|
||||
else if(obact->type==OB_CURVE) {
|
||||
nr= pupmenu("Convert Curve to%t|Mesh");
|
||||
if(nr>0) ok= 1;
|
||||
}
|
||||
else if(ob->type==OB_SURF) {
|
||||
else if(obact->type==OB_SURF) {
|
||||
nr= pupmenu("Convert Nurbs Surface to%t|Mesh");
|
||||
if(nr>0) ok= 1;
|
||||
}
|
||||
else if(ob->type==OB_MESH) {
|
||||
if(ob->modifiers.first)
|
||||
else if(obact->type==OB_MESH) {
|
||||
nr= pupmenu("Convert Modifiers to%t|Mesh (Keep Original)%x1|Mesh (Delete Original)%x2");
|
||||
if(nr>0) ok= 1;
|
||||
}
|
||||
@@ -2277,7 +2277,7 @@ void convertmenu(void)
|
||||
ob= base->object;
|
||||
|
||||
if(ob->flag & OB_DONE);
|
||||
else if(ob->type==OB_MESH) {
|
||||
else if(ob->type==OB_MESH && ob->modifiers.first) { /* converting a mesh with no modifiers causes a segfault */
|
||||
DispListMesh *dlm;
|
||||
DerivedMesh *dm;
|
||||
|
||||
@@ -2293,7 +2293,9 @@ void convertmenu(void)
|
||||
*basen= *base;
|
||||
BLI_addhead(&G.scene->base, basen); /* addhead: otherwise eternal loop */
|
||||
basen->object= ob1;
|
||||
basen->flag &= ~SELECT;
|
||||
basen->flag |= SELECT;
|
||||
base->flag &= ~SELECT;
|
||||
ob->flag &= ~SELECT;
|
||||
|
||||
/* decrement original mesh's usage count */
|
||||
me= ob1->data;
|
||||
@@ -2308,6 +2310,12 @@ void convertmenu(void)
|
||||
dlm= dm->convertToDispListMesh(dm, 0);
|
||||
displistmesh_to_mesh(dlm, ob1->data);
|
||||
dm->release(dm);
|
||||
|
||||
/* If the original object is active then make this object active */
|
||||
if (ob == obact) {
|
||||
set_active_base( basen );
|
||||
basact = basen;
|
||||
}
|
||||
}
|
||||
else if(ob->type==OB_FONT) {
|
||||
if(nr==1) {
|
||||
@@ -2381,7 +2389,9 @@ void convertmenu(void)
|
||||
*basen= *base;
|
||||
BLI_addhead(&G.scene->base, basen); /* addhead: othwise eternal loop */
|
||||
basen->object= ob1;
|
||||
basen->flag &= ~SELECT;
|
||||
basen->flag |= SELECT;
|
||||
basedel->flag &= ~SELECT;
|
||||
ob->flag &= ~SELECT;
|
||||
|
||||
mb= ob1->data;
|
||||
mb->id.us--;
|
||||
@@ -2398,6 +2408,19 @@ void convertmenu(void)
|
||||
}
|
||||
|
||||
mball_to_mesh(&ob->disp, ob1->data);
|
||||
|
||||
/* So we can see the wireframe */
|
||||
BASACT= basen;
|
||||
enter_editmode();
|
||||
exit_editmode(1); // freedata, but no undo
|
||||
BASACT= basact;
|
||||
|
||||
/* If the original object is active then make this object active */
|
||||
if (ob == obact) {
|
||||
set_active_base( basen );
|
||||
basact = basen;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,25 +90,11 @@
|
||||
#include "blendef.h"
|
||||
#include "mydevice.h"
|
||||
|
||||
struct uvvertsort {
|
||||
unsigned int v, f;
|
||||
unsigned char tf_sel;
|
||||
char flag;
|
||||
};
|
||||
|
||||
/* local prototypes */
|
||||
void clever_numbuts_sima(void);
|
||||
void sel_uvco_inside_radius(short , TFace *, int , float *, float *, short);
|
||||
void uvedit_selectionCB(short , Object *, short *, float ); /* used in edit.c*/
|
||||
|
||||
static int compuvvert(const void *u1, const void *u2)
|
||||
{
|
||||
const struct uvvertsort *v1=u1, *v2=u2;
|
||||
if (v1->v > v2->v) return 1;
|
||||
else if (v1->v < v2->v) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void object_uvs_changed(Object *ob)
|
||||
{
|
||||
DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);
|
||||
@@ -597,7 +583,7 @@ void mouse_select_sima(void)
|
||||
{
|
||||
Mesh *me;
|
||||
TFace *tf, *nearesttf;
|
||||
MFace *mf, *nearestmf;
|
||||
MFace *mf, *nearestmf=NULL;
|
||||
int a, selectsticky, sticky, actface, nearestuv, i;
|
||||
unsigned int hitv[4], nearestv;
|
||||
float *hituv[4], limit[2];
|
||||
@@ -1027,14 +1013,15 @@ void reveal_tface_uv(void)
|
||||
|
||||
void stitch_uv_tface(int mode)
|
||||
{
|
||||
MFace *mf;
|
||||
TFace *tf, *tface;
|
||||
Mesh *me;
|
||||
int a, b, c, tot, vtot, vtot2;
|
||||
float newuv[2], limit[2], *uv, *uv1;
|
||||
struct uvvertsort *sortblock, *sb, *sb1, *sb2;
|
||||
TFace *tf;
|
||||
int a, vtot;
|
||||
float newuv[2], limit[2];
|
||||
UvMapVert *vlist, *iterv, *v;
|
||||
UvVertMap *vmap;
|
||||
|
||||
if( is_uv_tface_editing_allowed()==0 ) return;
|
||||
if(is_uv_tface_editing_allowed()==0)
|
||||
return;
|
||||
|
||||
limit[0]= limit[1]= 20.0;
|
||||
if(mode==1) {
|
||||
@@ -1052,113 +1039,78 @@ void stitch_uv_tface(int mode)
|
||||
limit[0]= limit[1]= limit[0]/256.0;
|
||||
|
||||
me= get_mesh(OBACT);
|
||||
tface= (TFace*)me->tface;
|
||||
tf= me->tface;
|
||||
|
||||
tot= 0;
|
||||
mf= (MFace*)me->mface;
|
||||
tf= (TFace*)me->tface;
|
||||
for(a=me->totface; a>0; a--, tf++, mf++) {
|
||||
if((tf->flag & TF_SELECT)) {
|
||||
if(tf->flag & TF_SEL1) tot++;
|
||||
if(tf->flag & TF_SEL2) tot++;
|
||||
if(tf->flag & TF_SEL3) tot++;
|
||||
if(mf->v4 && tf->flag & TF_SEL4) tot++;
|
||||
}
|
||||
}
|
||||
if(tot==0) return;
|
||||
|
||||
sb= sortblock= MEM_callocN(sizeof(struct uvvertsort)*tot,"sortstitchuv");
|
||||
|
||||
mf= (MFace*)me->mface;
|
||||
tf= (TFace*)me->tface;
|
||||
for(a=0; a<me->totface; a++, tf++, mf++) {
|
||||
if((tf->flag & TF_SELECT)) {
|
||||
if(tf->flag & TF_SEL1) {
|
||||
sb->v= mf->v1;
|
||||
sb->f= a;
|
||||
sb->tf_sel= 0;
|
||||
sb++;
|
||||
}
|
||||
if(tf->flag & TF_SEL2) {
|
||||
sb->v= mf->v2;
|
||||
sb->f= a;
|
||||
sb->tf_sel= 1;
|
||||
sb++;
|
||||
}
|
||||
if(tf->flag & TF_SEL3) {
|
||||
sb->v= mf->v3;
|
||||
sb->f= a;
|
||||
sb->tf_sel= 2;
|
||||
sb++;
|
||||
}
|
||||
if(mf->v4 && tf->flag & TF_SEL4) {
|
||||
sb->v= mf->v4;
|
||||
sb->f= a;
|
||||
sb->tf_sel= 3;
|
||||
sb++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* sort by vertex */
|
||||
qsort(sortblock, tot, sizeof(struct uvvertsort), compuvvert);
|
||||
vmap= make_uv_vert_map(me->mface, tf, me->totface, me->totvert, 1, limit);
|
||||
if(vmap == NULL)
|
||||
return;
|
||||
|
||||
if(mode==0) {
|
||||
for (a=0, sb=sortblock; a<tot; a+=vtot, sb+=vtot) {
|
||||
for(a=0; a<me->totvert; a++) {
|
||||
v = get_uv_map_vert(vmap, a);
|
||||
|
||||
if(v == NULL)
|
||||
continue;
|
||||
|
||||
newuv[0]= 0; newuv[1]= 0;
|
||||
vtot= 0;
|
||||
|
||||
for (b=a, sb1=sb; b<tot && sb1->v==sb->v; b++, sb1++) {
|
||||
newuv[0] += tface[sb1->f].uv[sb1->tf_sel][0];
|
||||
newuv[1] += tface[sb1->f].uv[sb1->tf_sel][1];
|
||||
for(iterv=v; iterv; iterv=iterv->next) {
|
||||
if (tf[iterv->f].flag & TF_SEL_MASK(iterv->tfindex)) {
|
||||
newuv[0] += tf[iterv->f].uv[iterv->tfindex][0];
|
||||
newuv[1] += tf[iterv->f].uv[iterv->tfindex][1];
|
||||
vtot++;
|
||||
}
|
||||
}
|
||||
|
||||
if (vtot > 1) {
|
||||
newuv[0] /= vtot; newuv[1] /= vtot;
|
||||
|
||||
for (b=a, sb1=sb; b<a+vtot; b++, sb1++) {
|
||||
tface[sb1->f].uv[sb1->tf_sel][0]= newuv[0];
|
||||
tface[sb1->f].uv[sb1->tf_sel][1]= newuv[1];
|
||||
for(iterv=v; iterv; iterv=iterv->next) {
|
||||
if (tf[iterv->f].flag & TF_SEL_MASK(iterv->tfindex)) {
|
||||
tf[iterv->f].uv[iterv->tfindex][0]= newuv[0];
|
||||
tf[iterv->f].uv[iterv->tfindex][1]= newuv[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(mode==1) {
|
||||
for (a=0, sb=sortblock; a<tot; a+=vtot, sb+=vtot) {
|
||||
vtot= 0;
|
||||
for (b=a, sb1=sb; b<tot && sb1->v==sb->v; b++, sb1++)
|
||||
vtot++;
|
||||
|
||||
for (b=a, sb1=sb; b<a+vtot; b++, sb1++) {
|
||||
if(sb1->flag & 2) continue;
|
||||
for(a=0; a<me->totvert; a++) {
|
||||
vlist= get_uv_map_vert(vmap, a);
|
||||
|
||||
while(vlist) {
|
||||
newuv[0]= 0; newuv[1]= 0;
|
||||
vtot2 = 0;
|
||||
vtot= 0;
|
||||
|
||||
for (c=b, sb2=sb1; c<a+vtot; c++, sb2++) {
|
||||
uv = tface[sb2->f].uv[sb2->tf_sel];
|
||||
uv1 = tface[sb1->f].uv[sb1->tf_sel];
|
||||
if (fabs(uv[0]-uv1[0]) < limit[0] &&
|
||||
fabs(uv[1]-uv1[1]) < limit[1]) {
|
||||
newuv[0] += uv[0];
|
||||
newuv[1] += uv[1];
|
||||
sb2->flag |= 2;
|
||||
sb2->flag |= 4;
|
||||
vtot2++;
|
||||
for(iterv=vlist; iterv; iterv=iterv->next) {
|
||||
if((iterv != vlist) && iterv->separate)
|
||||
break;
|
||||
if (tf[iterv->f].flag & TF_SEL_MASK(iterv->tfindex)) {
|
||||
newuv[0] += tf[iterv->f].uv[iterv->tfindex][0];
|
||||
newuv[1] += tf[iterv->f].uv[iterv->tfindex][1];
|
||||
vtot++;
|
||||
}
|
||||
}
|
||||
|
||||
newuv[0] /= vtot2; newuv[1] /= vtot2;
|
||||
if (vtot > 1) {
|
||||
newuv[0] /= vtot; newuv[1] /= vtot;
|
||||
|
||||
for (c=b, sb2=sb1; c<a+vtot; c++, sb2++) {
|
||||
if(sb2->flag & 4) {
|
||||
tface[sb2->f].uv[sb2->tf_sel][0]= newuv[0];
|
||||
tface[sb2->f].uv[sb2->tf_sel][1]= newuv[1];
|
||||
sb2->flag &= ~4;
|
||||
for(iterv=vlist; iterv; iterv=iterv->next) {
|
||||
if((iterv != vlist) && iterv->separate)
|
||||
break;
|
||||
if (tf[iterv->f].flag & TF_SEL_MASK(iterv->tfindex)) {
|
||||
tf[iterv->f].uv[iterv->tfindex][0]= newuv[0];
|
||||
tf[iterv->f].uv[iterv->tfindex][1]= newuv[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vlist= iterv;
|
||||
}
|
||||
}
|
||||
MEM_freeN(sortblock);
|
||||
}
|
||||
|
||||
free_uv_vert_map(vmap);
|
||||
|
||||
if(G.sima->flag & SI_BE_SQUARE) be_square_tface_uv(me);
|
||||
|
||||
@@ -1169,109 +1121,102 @@ void stitch_uv_tface(int mode)
|
||||
|
||||
void select_linked_tface_uv(int mode)
|
||||
{
|
||||
MFace *mf;
|
||||
TFace *tface, *tf, *nearesttf=NULL;
|
||||
Mesh *me;
|
||||
char sel, *linkflag;
|
||||
int a, b, c, tot, vtot, nearestv, nearestuv, i, nverts;
|
||||
float limit[2], *uv, *uv1;
|
||||
struct uvvertsort *sortblock, *sb, *sb1, *sb2;
|
||||
MFace *mf;
|
||||
TFace *tf, *nearesttf=NULL;
|
||||
UvVertMap *vmap;
|
||||
UvMapVert *vlist, *iterv, *startv;
|
||||
unsigned int *stack, stacksize= 0, nearestv;
|
||||
char *flag;
|
||||
int a, nearestuv, i, nverts;
|
||||
float limit[2];
|
||||
|
||||
if( is_uv_tface_editing_allowed()==0 ) return;
|
||||
if(is_uv_tface_editing_allowed()==0)
|
||||
return;
|
||||
|
||||
me= get_mesh(OBACT);
|
||||
get_connected_limit_tface_uv(limit);
|
||||
|
||||
tot= 0;
|
||||
mf= (MFace*)me->mface;
|
||||
tf= (TFace*)me->tface;
|
||||
for(a=me->totface; a>0; a--, tf++, mf++)
|
||||
if(tf->flag & TF_SELECT)
|
||||
tot += mf->v4? 4: 3;
|
||||
|
||||
if(tot==0) return;
|
||||
|
||||
if (mode!=2) {
|
||||
find_nearest_uv(&nearesttf, &nearestv, &nearestuv);
|
||||
|
||||
if(nearesttf==NULL)
|
||||
return;
|
||||
}
|
||||
else {
|
||||
if (mode == 2) {
|
||||
nearesttf= NULL;
|
||||
nearestuv= 0;
|
||||
}
|
||||
|
||||
sb= sortblock= MEM_callocN(sizeof(struct uvvertsort)*tot, "sortsellinkuv");
|
||||
linkflag= MEM_callocN(sizeof(char)*me->totface, "linkflaguv");
|
||||
|
||||
mf= (MFace*)me->mface;
|
||||
tf= (TFace*)me->tface;
|
||||
for(a=0; a<me->totface; a++, tf++, mf++) {
|
||||
if(!(tf->flag & TF_HIDE) && (tf->flag & TF_SELECT)) {
|
||||
sel= 0;
|
||||
sb1= sb;
|
||||
nverts= mf->v4? 4: 3;
|
||||
for(i=0; i<nverts; i++) {
|
||||
if(tf->flag & TF_SEL_MASK(i))
|
||||
sel= 1;
|
||||
sb->f= a;
|
||||
sb->tf_sel= i;
|
||||
sb++;
|
||||
if (mode!=2) {
|
||||
find_nearest_uv(&nearesttf, &nearestv, &nearestuv);
|
||||
if(nearesttf==NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
if(nearesttf==tf || ((sel && mode==2)))
|
||||
linkflag[a] = 1;
|
||||
get_connected_limit_tface_uv(limit);
|
||||
vmap= make_uv_vert_map(me->mface, me->tface, me->totface, me->totvert, 1, limit);
|
||||
if(vmap == NULL)
|
||||
return;
|
||||
|
||||
(sb1)->v= mf->v1;
|
||||
(sb1+1)->v= mf->v2;
|
||||
(sb1+2)->v= mf->v3;
|
||||
if(mf->v4) (sb1+3)->v= mf->v4;
|
||||
stack= MEM_mallocN(sizeof(*stack)*me->totface, "UvLinkStack");
|
||||
flag= MEM_callocN(sizeof(*flag)*me->totface, "UvLinkFlag");
|
||||
|
||||
if (mode == 2) {
|
||||
tf= me->tface;
|
||||
for(a=0; a<me->totface; a++, tf++)
|
||||
if(!(tf->flag & TF_HIDE) && (tf->flag & TF_SELECT))
|
||||
if(tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)) {
|
||||
stack[stacksize]= a;
|
||||
stacksize++;
|
||||
flag[a]= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* sort by vertex */
|
||||
qsort(sortblock, tot, sizeof(struct uvvertsort), compuvvert);
|
||||
|
||||
tface= (TFace*)me->tface;
|
||||
sel= 1;
|
||||
while(sel) {
|
||||
sel= 0;
|
||||
|
||||
/* select all tex vertices that are near a selected tex vertex */
|
||||
for (a=0, sb=sortblock; a<tot; a+=vtot, sb+=vtot) {
|
||||
vtot= 0;
|
||||
for (b=a, sb1=sb; b<tot && sb1->v==sb->v; b++, sb1++)
|
||||
vtot++;
|
||||
for (b=a, sb1=sb; b<a+vtot; b++, sb1++) {
|
||||
if(linkflag[sb1->f]) continue;
|
||||
|
||||
for (c=a, sb2=sb; c<a+vtot; c++, sb2++) {
|
||||
if(!(linkflag[sb2->f])) continue;
|
||||
|
||||
uv = tface[sb2->f].uv[sb2->tf_sel];
|
||||
uv1 = tface[sb1->f].uv[sb1->tf_sel];
|
||||
if (fabs(uv[0]-uv1[0]) < limit[0] &&
|
||||
fabs(uv[1]-uv1[1]) < limit[1]) {
|
||||
linkflag[sb1->f] = 1;
|
||||
sel= 1;
|
||||
else {
|
||||
tf= me->tface;
|
||||
for(a=0; a<me->totface; a++, tf++)
|
||||
if(tf == nearesttf) {
|
||||
stack[stacksize]= a;
|
||||
stacksize++;
|
||||
flag[a]= 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while(stacksize > 0) {
|
||||
stacksize--;
|
||||
a= stack[stacksize];
|
||||
mf= me->mface+a;
|
||||
tf= me->tface+a;
|
||||
|
||||
nverts= mf->v4? 4: 3;
|
||||
|
||||
for(i=0; i<nverts; i++) {
|
||||
vlist= get_uv_map_vert(vmap, *(&mf->v1 + i));
|
||||
startv= vlist;
|
||||
|
||||
for(iterv=vlist; iterv; iterv=iterv->next) {
|
||||
if(iterv->separate)
|
||||
startv= iterv;
|
||||
if(iterv->f == a)
|
||||
break;
|
||||
}
|
||||
|
||||
for(iterv=startv; iterv; iterv=iterv->next) {
|
||||
if((startv != iterv) && (iterv->separate))
|
||||
break;
|
||||
else if(!flag[iterv->f]) {
|
||||
flag[iterv->f]= 1;
|
||||
stack[stacksize]= iterv->f;;
|
||||
stacksize++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(mode==0 || mode==2) {
|
||||
for(a=0, tf=tface; a<me->totface; a++, tf++)
|
||||
if(linkflag[a])
|
||||
for(a=0, tf=me->tface; a<me->totface; a++, tf++)
|
||||
if(flag[a])
|
||||
tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
|
||||
else
|
||||
tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
|
||||
}
|
||||
else if(mode==1) {
|
||||
for(a=0, tf=tface; a<me->totface; a++, tf++) {
|
||||
if(linkflag[a]) {
|
||||
mf= me->mface;
|
||||
for(a=0, tf=me->tface; a<me->totface; a++, tf++, mf++) {
|
||||
if(flag[a]) {
|
||||
if (mf->v4) {
|
||||
if((tf->flag & (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4)))
|
||||
break;
|
||||
@@ -1282,19 +1227,20 @@ void select_linked_tface_uv(int mode)
|
||||
}
|
||||
|
||||
if (a<me->totface) {
|
||||
for(a=0, tf=tface; a<me->totface; a++, tf++)
|
||||
if(linkflag[a])
|
||||
for(a=0, tf=me->tface; a<me->totface; a++, tf++)
|
||||
if(flag[a])
|
||||
tf->flag &= ~(TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
|
||||
}
|
||||
else {
|
||||
for(a=0, tf=tface; a<me->totface; a++, tf++)
|
||||
if(linkflag[a])
|
||||
for(a=0, tf=me->tface; a<me->totface; a++, tf++)
|
||||
if(flag[a])
|
||||
tf->flag |= (TF_SEL1|TF_SEL2|TF_SEL3|TF_SEL4);
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(sortblock);
|
||||
MEM_freeN(linkflag);
|
||||
MEM_freeN(stack);
|
||||
MEM_freeN(flag);
|
||||
free_uv_vert_map(vmap);
|
||||
|
||||
BIF_undo_push("Select linked UV");
|
||||
scrarea_queue_winredraw(curarea);
|
||||
|
||||
@@ -276,7 +276,7 @@ void fluidsimBake(struct Object *ob)
|
||||
char targetFile[FILE_MAXDIR+FILE_MAXFILE]; // temp. store filename from targetDir for access
|
||||
int outStringsChanged = 0; // modified? copy back before baking
|
||||
int haveSomeFluid = 0; // check if any fluid objects are set
|
||||
int noFrames = G.scene->r.efra - G.scene->r.sfra;
|
||||
int noFrames = G.scene->r.efra - 1 /*G.scene->r.sfra*/;
|
||||
|
||||
const char *strEnvName = "BLENDER_ELBEEMDEBUG"; // from blendercall.cpp
|
||||
|
||||
@@ -400,7 +400,7 @@ void fluidsimBake(struct Object *ob)
|
||||
}
|
||||
|
||||
// dump data for frame 0
|
||||
G.scene->r.cfra = G.scene->r.sfra;
|
||||
G.scene->r.cfra = 1 /*G.scene->r.sfra*/;
|
||||
scene_update_for_newframe(G.scene, G.scene->lay);
|
||||
|
||||
// start writing
|
||||
@@ -468,15 +468,15 @@ void fluidsimBake(struct Object *ob)
|
||||
int i;
|
||||
float tsum=0.0, shouldbe=0.0;
|
||||
fprintf(fileCfg, " CHANNEL p_aniframetime = ");
|
||||
for(i=G.scene->r.sfra; i<G.scene->r.efra; i++) {
|
||||
for(i=1 /*G.scene->r.sfra*/; i<G.scene->r.efra; i++) {
|
||||
float anit = (calc_ipo_time(fsDomain->ipo, i+1) -
|
||||
calc_ipo_time(fsDomain->ipo, i)) * aniFrameTime;
|
||||
if(anit<0.0) anit = 0.0;
|
||||
tsum += anit;
|
||||
}
|
||||
// make sure inaccurate integration doesnt modify end time
|
||||
shouldbe = ((float)(G.scene->r.efra - G.scene->r.sfra)) *aniFrameTime;
|
||||
for(i=G.scene->r.sfra; i<G.scene->r.efra; i++) {
|
||||
shouldbe = ((float)(G.scene->r.efra - 1 /*G.scene->r.sfra*/)) *aniFrameTime;
|
||||
for(i=1 /*G.scene->r.sfra*/; i<G.scene->r.efra; i++) {
|
||||
float anit = (calc_ipo_time(fsDomain->ipo, i+1) -
|
||||
calc_ipo_time(fsDomain->ipo, i)) * aniFrameTime;
|
||||
if(anit<0.0) anit = 0.0;
|
||||
@@ -771,7 +771,7 @@ void fluidsimBake(struct Object *ob)
|
||||
}
|
||||
for(i=0; i<numCreatedFiles; i++) {
|
||||
if(doDeleteCreatedFiles>0) {
|
||||
fprintf(stderr," CREATED '%s' deleting... \n", createdFiles[i]);
|
||||
//fprintf(stderr," CREATED '%s' deleting... \n", createdFiles[i]); // debug
|
||||
BLI_delete(createdFiles[i], 0,0);
|
||||
}
|
||||
free(createdFiles[i]);
|
||||
|
||||
@@ -177,7 +177,6 @@ static void save_paint(char *name)
|
||||
{
|
||||
char str[FILE_MAXDIR+FILE_MAXFILE];
|
||||
Image *ima = G.sima->image;
|
||||
ImBuf *ibuf;
|
||||
|
||||
if (ima && ima->ibuf) {
|
||||
BLI_strncpy(str, name, sizeof(str));
|
||||
@@ -185,7 +184,7 @@ static void save_paint(char *name)
|
||||
BLI_convertstringcode(str, G.sce, G.scene->r.cfra);
|
||||
|
||||
if (saveover(str)) {
|
||||
if (BIF_write_ibuf(ibuf, str)) {
|
||||
if (BIF_write_ibuf(ima->ibuf, str)) {
|
||||
BLI_strncpy(ima->name, name, sizeof(ima->name));
|
||||
ima->ibuf->userflags &= ~IB_BITMAPDIRTY;
|
||||
allqueue(REDRAWHEADERS, 0);
|
||||
|
||||
@@ -1264,6 +1264,7 @@ static void do_info_gamemenu(void *arg, int event)
|
||||
case G_FILE_SHOW_DEBUG_PROPS:
|
||||
case G_FILE_AUTOPLAY:
|
||||
case G_FILE_GAME_TO_IPO:
|
||||
case G_FILE_GAME_MAT:
|
||||
G.fileflags ^= event;
|
||||
break;
|
||||
default:
|
||||
@@ -1298,6 +1299,11 @@ static uiBlock *info_gamemenu(void *arg_unused)
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Record Game Physics to IPO", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_TO_IPO, "");
|
||||
}
|
||||
|
||||
if(G.fileflags & G_FILE_GAME_MAT) {
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_HLT, "Use Blender Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_MAT, "");
|
||||
} else {
|
||||
uiDefIconTextBut(block, BUTM, 1, ICON_CHECKBOX_DEHLT, "Use Blender Materials", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, G_FILE_GAME_MAT, "");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1322,7 +1328,7 @@ static uiBlock *info_gamemenu(void *arg_unused)
|
||||
}
|
||||
|
||||
uiBlockSetDirection(block, UI_DOWN);
|
||||
uiTextBoundsBlock(block, 50);
|
||||
uiTextBoundsBlock(block, 70);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
@@ -1671,7 +1671,8 @@ static int ui_do_but_TEX(uiBut *but)
|
||||
else if(dev==MOUSEY) val= 0;
|
||||
|
||||
if(ascii) {
|
||||
if(len <= but->max) {
|
||||
|
||||
if(len-SELWIDTH+1 <= but->max) {
|
||||
|
||||
/* type over the current selection */
|
||||
if (SELWIDTH > 0) {
|
||||
|
||||
@@ -365,6 +365,9 @@ void space_set_commmandline_options(void) {
|
||||
a= (G.fileflags & G_FILE_GAME_TO_IPO);
|
||||
SYS_WriteCommandLineInt(syshandle, "game2ipo", a);
|
||||
|
||||
a=(G.fileflags & G_FILE_GAME_MAT);
|
||||
SYS_WriteCommandLineInt(syshandle, "blender_material", a);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1383,16 +1383,16 @@ int do_clever_numbuts(char *name, int tot, int winevent)
|
||||
uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1|UI_BLOCK_ENTER_OK);
|
||||
|
||||
/* WATCH IT: TEX BUTTON EXCEPTION */
|
||||
/* WARNING: ONLY A SINGLE BIT-BUTTON POSSIBLE: WE WORK AT COPIED DATA!
|
||||
*/
|
||||
|
||||
/* WARNING: ONLY A SINGLE BIT-BUTTON POSSIBLE: WE WORK AT COPIED DATA! */
|
||||
uiDefBut(block, LABEL, 0, name, (short)(x1+15), (short)(y2-35), (short)(sizex-60), 19, 0, 1.0, 0.0, 0, 0, "");
|
||||
|
||||
/*
|
||||
if(name[0]=='A' && name[7]=='O') {
|
||||
y2 -= 20;
|
||||
uiDefBut(block, LABEL, 0, "Rotations in degrees!", (short)(x1+15), (short)(y2-35), (short)(sizex-60), 19, 0, 0.0, 0.0, 0, 0, "");
|
||||
}
|
||||
}*/
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
varstr= &numbuts[0];
|
||||
for(a=0; a<tot; a++, varstr++) {
|
||||
if(varstr->type==TEX) {
|
||||
@@ -1402,6 +1402,7 @@ int do_clever_numbuts(char *name, int tot, int winevent)
|
||||
uiDefBut(block, varstr->type, 0, varstr->name,(short)(x1+15),(short)(y2-55-20*a), (short)(sizex-60), 19, &(numbdata[a]), varstr->min, varstr->max, 100, 0, varstr->tip);
|
||||
}
|
||||
}
|
||||
uiBlockEndAlign(block);
|
||||
|
||||
uiDefBut(block, BUT, 4000, "OK", (short)(x1+sizex-40),(short)(y2-35-20*a), 25, (short)(sizey-50), 0, 0, 0, 0, 0, "OK: Assign Values");
|
||||
|
||||
@@ -1419,12 +1420,13 @@ int do_clever_numbuts(char *name, int tot, int winevent)
|
||||
else if ELEM( (varstr->type & BUTPOIN), FLO, INT ) memcpy(numbpoin[a], numbdata+a, 4);
|
||||
else if((varstr->type & BUTPOIN)==SHO ) *((short *)(numbpoin[a]))= *( (short *)(numbdata+a));
|
||||
|
||||
/*
|
||||
if( strncmp(varstr->name, "Rot", 3)==0 ) {
|
||||
float *fp;
|
||||
|
||||
fp= numbpoin[a];
|
||||
fp[0]= M_PI*fp[0]/180.0;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
if(winevent) {
|
||||
@@ -1463,12 +1465,12 @@ void add_numbut(int nr, int type, char *str, float min, float max, void *poin, c
|
||||
if ELEM( (type & BUTPOIN), FLO, INT ) memcpy(numbdata+nr, poin, 4);
|
||||
if((type & BUTPOIN)==SHO ) *((short *)(numbdata+nr))= *( (short *)poin);
|
||||
|
||||
if( strncmp(numbuts[nr].name, "Rot", 3)==0 ) {
|
||||
/* if( strncmp(numbuts[nr].name, "Rot", 3)==0 ) {
|
||||
float *fp;
|
||||
|
||||
fp= (float *)(numbdata+nr);
|
||||
fp[0]= 180.0*fp[0]/M_PI;
|
||||
}
|
||||
} */
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#include "KX_BlenderMouseDevice.h"
|
||||
#include "KX_BlenderRenderTools.h"
|
||||
#include "KX_BlenderSystem.h"
|
||||
#include "BL_Material.h"
|
||||
|
||||
#include "KX_KetsjiEngine.h"
|
||||
#include "KX_BlenderSceneConverter.h"
|
||||
@@ -118,6 +119,21 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
|
||||
bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0);
|
||||
bool game2ipo = (SYS_GetCommandLineInt(syshandle, "game2ipo", 0) != 0);
|
||||
|
||||
bool usemat = false;
|
||||
|
||||
#ifdef GL_ARB_multitexture
|
||||
if(bgl::RAS_EXT_support._ARB_multitexture && bgl::QueryVersion(1, 1)) {
|
||||
usemat = (SYS_GetCommandLineInt(syshandle, "blender_material", 0) != 0);
|
||||
int unitmax=0;
|
||||
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, (GLint*)&unitmax);
|
||||
bgl::max_texture_units = MAXTEX>unitmax?unitmax:MAXTEX;
|
||||
//std::cout << "using(" << bgl::max_texture_units << ") of(" << unitmax << ") texture units." << std::endl;
|
||||
} else {
|
||||
bgl::max_texture_units = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// create the canvas, rasterizer and rendertools
|
||||
RAS_ICanvas* canvas = new KX_BlenderCanvas(area);
|
||||
canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE);
|
||||
@@ -273,6 +289,8 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
|
||||
if (always_use_expand_framing)
|
||||
sceneconverter->SetAlwaysUseExpandFraming(true);
|
||||
|
||||
if(usemat)
|
||||
sceneconverter->SetMaterials(true);
|
||||
|
||||
KX_Scene* startscene = new KX_Scene(keyboarddevice,
|
||||
mousedevice,
|
||||
@@ -400,7 +418,6 @@ extern "C" void StartKetsjiShell(struct ScrArea *area,
|
||||
delete canvas;
|
||||
canvas = NULL;
|
||||
}
|
||||
|
||||
SND_DeviceManager::Unsubscribe();
|
||||
|
||||
} while (exitrequested == KX_EXIT_REQUEST_RESTART_GAME || exitrequested == KX_EXIT_REQUEST_START_OTHER_GAME);
|
||||
|
||||
@@ -53,6 +53,8 @@
|
||||
|
||||
#include "KX_BlenderPolyMaterial.h"
|
||||
#include "KX_PolygonMaterial.h"
|
||||
#include "KX_BlenderMaterial.h"
|
||||
|
||||
#include "Value.h"
|
||||
|
||||
#include "KX_BlenderGL.h" // for text printing
|
||||
@@ -256,8 +258,16 @@ void KX_BlenderRenderTools::RenderText(int mode,RAS_IPolyMaterial* polymat,float
|
||||
|
||||
STR_String mytext = ((CValue*)m_clientobject)->GetPropertyText("Text");
|
||||
|
||||
const unsigned int flag = polymat->GetFlag();
|
||||
struct TFace* tface = 0;
|
||||
|
||||
if(flag & RAS_BLENDERMAT) {
|
||||
KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(polymat);
|
||||
tface = bl_mat->GetTFace();
|
||||
} else {
|
||||
KX_PolygonMaterial* blenderpoly = static_cast<KX_PolygonMaterial*>(polymat);
|
||||
struct TFace* tface = blenderpoly->GetTFace();
|
||||
tface = blenderpoly->GetTFace();
|
||||
}
|
||||
|
||||
BL_RenderText( mode,mytext,mytext.Length(),tface,v1,v2,v3,v4);
|
||||
|
||||
@@ -288,8 +298,8 @@ void KX_BlenderRenderTools::EnableOpenGLLights()
|
||||
glEnable(GL_LIGHTING);
|
||||
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
glColorMaterial(GL_FRONT_AND_BACK,GL_DIFFUSE);
|
||||
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, false);
|
||||
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
|
||||
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, true);
|
||||
if (bgl::QueryExtension(bgl::_GL_EXT_separate_specular_color) || bgl::QueryVersion(1, 2))
|
||||
glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
|
||||
|
||||
|
||||
@@ -48,6 +48,24 @@
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
BL_ArmatureObject::BL_ArmatureObject(
|
||||
void* sgReplicationInfo,
|
||||
SG_Callbacks callbacks,
|
||||
Object *armature )
|
||||
|
||||
: KX_GameObject(sgReplicationInfo,callbacks),
|
||||
m_objArma(armature),
|
||||
m_mrdPose(NULL),
|
||||
m_lastframe(0.),
|
||||
m_activeAct(NULL),
|
||||
m_activePriority(999)
|
||||
{
|
||||
m_armature = get_armature(m_objArma);
|
||||
m_pose = m_objArma->pose;
|
||||
}
|
||||
|
||||
|
||||
CValue* BL_ArmatureObject::GetReplica()
|
||||
{
|
||||
BL_ArmatureObject* replica = new BL_ArmatureObject(*this);
|
||||
@@ -78,10 +96,14 @@ BL_ArmatureObject::~BL_ArmatureObject()
|
||||
void BL_ArmatureObject::ApplyPose()
|
||||
{
|
||||
if (m_pose){
|
||||
if (!m_mrdPose)
|
||||
copy_pose (&m_mrdPose, m_pose, 0);
|
||||
else
|
||||
extract_pose_from_pose(m_mrdPose, m_pose);
|
||||
// copy to armature object
|
||||
extract_pose_from_pose(m_objArma->pose, m_pose);
|
||||
|
||||
// is this needed anymore?
|
||||
//if (!m_mrdPose)
|
||||
// copy_pose (&m_mrdPose, m_pose, 0);
|
||||
//else
|
||||
// extract_pose_from_pose(m_mrdPose, m_pose);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,14 +158,15 @@ void BL_ArmatureObject::GetMRDPose(bPose **pose)
|
||||
/* If the caller supplies a null pose, create a new one. */
|
||||
/* Otherwise, copy the armature's pose channels into the caller-supplied pose */
|
||||
|
||||
if (!m_mrdPose){
|
||||
copy_pose (&m_mrdPose, m_pose, 0);
|
||||
}
|
||||
// is this needed anymore?
|
||||
//if (!m_mrdPose){
|
||||
// copy_pose (&m_mrdPose, m_pose, 0);
|
||||
//}
|
||||
|
||||
if (!*pose)
|
||||
copy_pose(pose, m_mrdPose, 0);
|
||||
copy_pose(pose, m_objArma->pose, 0);
|
||||
else
|
||||
extract_pose_from_pose(*pose, m_mrdPose);
|
||||
extract_pose_from_pose(*pose, m_objArma->pose);
|
||||
|
||||
}
|
||||
|
||||
@@ -171,7 +194,5 @@ bool BL_ArmatureObject::GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix) const
|
||||
|
||||
float BL_ArmatureObject::GetBoneLength(Bone* bone) const
|
||||
{
|
||||
return (MT_Point3(bone->head) - MT_Point3(bone->tail)).length();
|
||||
return (float)(MT_Point3(bone->head) - MT_Point3(bone->tail)).length();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -39,9 +39,9 @@
|
||||
|
||||
struct bArmature;
|
||||
struct Bone;
|
||||
|
||||
class BL_ActionActuator;
|
||||
class MT_Matrix4x4;
|
||||
struct Object;
|
||||
|
||||
class BL_ArmatureObject : public KX_GameObject
|
||||
{
|
||||
@@ -50,30 +50,26 @@ public:
|
||||
short GetActivePriority();
|
||||
virtual void ProcessReplica(BL_ArmatureObject *replica);
|
||||
class BL_ActionActuator * GetActiveAction();
|
||||
BL_ArmatureObject(void* sgReplicationInfo, SG_Callbacks callbacks,
|
||||
bArmature *armature,
|
||||
struct bPose *pose) :
|
||||
KX_GameObject(sgReplicationInfo,callbacks),
|
||||
m_armature(armature),
|
||||
m_pose(pose),
|
||||
m_mrdPose(NULL),
|
||||
m_lastframe(0.),
|
||||
m_activeAct(NULL),
|
||||
m_activePriority(999)
|
||||
{}
|
||||
|
||||
BL_ArmatureObject(
|
||||
void* sgReplicationInfo,
|
||||
SG_Callbacks callbacks,
|
||||
Object *armature
|
||||
);
|
||||
virtual ~BL_ArmatureObject();
|
||||
|
||||
virtual CValue* GetReplica();
|
||||
virtual ~BL_ArmatureObject();
|
||||
void GetMRDPose(bPose **pose);
|
||||
void GetMRDPose(struct bPose **pose);
|
||||
void GetPose(struct bPose **pose);
|
||||
void SetPose (struct bPose *pose);
|
||||
void ApplyPose();
|
||||
bool SetActiveAction(class BL_ActionActuator *act, short priority, double curtime);
|
||||
|
||||
struct bArmature * GetArmature() { return m_armature; }
|
||||
|
||||
const struct bArmature * GetArmature() const { return m_armature; }
|
||||
|
||||
Object* GetArmatureObject() {return m_objArma;}
|
||||
|
||||
/// Retrieve the pose matrix for the specified bone.
|
||||
/// Returns true on success.
|
||||
bool GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix) const;
|
||||
@@ -82,6 +78,7 @@ public:
|
||||
float GetBoneLength(Bone* bone) const;
|
||||
|
||||
protected:
|
||||
Object *m_objArma;
|
||||
struct bArmature *m_armature;
|
||||
struct bPose *m_pose;
|
||||
struct bPose *m_mrdPose;
|
||||
|
||||
@@ -83,6 +83,9 @@
|
||||
#include "RAS_TexVert.h"
|
||||
#include "RAS_BucketManager.h"
|
||||
#include "RAS_IRenderTools.h"
|
||||
#include "BL_Material.h"
|
||||
#include "KX_BlenderMaterial.h"
|
||||
#include "BL_Texture.h"
|
||||
|
||||
#include "DNA_action_types.h"
|
||||
#include "BKE_main.h"
|
||||
@@ -108,6 +111,7 @@
|
||||
/* This list includes only data type definitions */
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_texture_types.h"
|
||||
#include "DNA_image_types.h"
|
||||
#include "DNA_lamp_types.h"
|
||||
#include "DNA_group_types.h"
|
||||
@@ -217,6 +221,340 @@ static void SetDefaultFaceType(Scene* scene)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// --
|
||||
static void GetRGB(short type,
|
||||
MFace* mface,
|
||||
MCol* mmcol,
|
||||
Material *mat,
|
||||
TFace *tface,
|
||||
unsigned int &c0,
|
||||
unsigned int &c1,
|
||||
unsigned int &c2,
|
||||
unsigned int &c3)
|
||||
{
|
||||
unsigned int colour = 0xFFFFFFFFL;
|
||||
switch(type)
|
||||
{
|
||||
case 0: // vertex colors?
|
||||
{
|
||||
if(mmcol) {
|
||||
c0 = KX_Mcol2uint_new(mmcol[0]);
|
||||
c1 = KX_Mcol2uint_new(mmcol[1]);
|
||||
c2 = KX_Mcol2uint_new(mmcol[2]);
|
||||
if (mface->v4)
|
||||
c3 = KX_Mcol2uint_new(mmcol[3]);
|
||||
mmcol += 4;
|
||||
}else // backup white
|
||||
{
|
||||
c0 = KX_rgbaint2uint_new(colour);
|
||||
c1 = KX_rgbaint2uint_new(colour);
|
||||
c2 = KX_rgbaint2uint_new(colour);
|
||||
if (mface->v4)
|
||||
c3 = KX_rgbaint2uint_new( colour );
|
||||
}
|
||||
} break;
|
||||
|
||||
|
||||
case 1: // material rgba
|
||||
{
|
||||
if (mat) {
|
||||
union {
|
||||
unsigned char cp[4];
|
||||
unsigned int integer;
|
||||
} col_converter;
|
||||
col_converter.cp[3] = (unsigned char) (mat->r*255.0);
|
||||
col_converter.cp[2] = (unsigned char) (mat->g*255.0);
|
||||
col_converter.cp[1] = (unsigned char) (mat->b*255.0);
|
||||
col_converter.cp[0] = (unsigned char) (mat->alpha*255.0);
|
||||
colour = col_converter.integer;
|
||||
}
|
||||
c0 = KX_rgbaint2uint_new(colour);
|
||||
c1 = KX_rgbaint2uint_new(colour);
|
||||
c2 = KX_rgbaint2uint_new(colour);
|
||||
if (mface->v4)
|
||||
c3 = KX_rgbaint2uint_new(colour);
|
||||
} break;
|
||||
|
||||
case 2: // vertex colors
|
||||
{
|
||||
if(tface ) {
|
||||
c0 = KX_rgbaint2uint_new(tface->col[0]);
|
||||
c1 = KX_rgbaint2uint_new(tface->col[1]);
|
||||
c2 = KX_rgbaint2uint_new(tface->col[2]);
|
||||
|
||||
if (mface->v4) {
|
||||
c3 = KX_rgbaint2uint_new(tface->col[3]);
|
||||
}
|
||||
}else {
|
||||
c0 = KX_rgbaint2uint_new(colour);
|
||||
c1 = KX_rgbaint2uint_new(colour);
|
||||
c2 = KX_rgbaint2uint_new(colour);
|
||||
if (mface->v4)
|
||||
c3 = KX_rgbaint2uint_new( colour );
|
||||
}
|
||||
} break;
|
||||
|
||||
case 3: // white
|
||||
{
|
||||
c0 = KX_rgbaint2uint_new(colour);
|
||||
c1 = KX_rgbaint2uint_new(colour);
|
||||
c2 = KX_rgbaint2uint_new(colour);
|
||||
if (mface->v4)
|
||||
c3 = KX_rgbaint2uint_new(colour);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------
|
||||
BL_Material* ConvertMaterial( Mesh* mesh, Material *mat, TFace* tface, MFace* mface, MCol* mmcol, int lightlayer, Object* blenderobj )
|
||||
{
|
||||
BL_Material *material = new BL_Material();
|
||||
//initBL_Material(material);
|
||||
int numchan = -1;
|
||||
bool validmat = (mat!=0);
|
||||
bool using_facetexture = false;
|
||||
|
||||
short type = 0;
|
||||
if( validmat )
|
||||
type = 1; // material color
|
||||
else if(mesh->tface && tface)
|
||||
type = 2; // vertex colors
|
||||
|
||||
material->IdMode = DEFAULT_BLENDER;
|
||||
|
||||
// --------------------------------
|
||||
if(validmat) {
|
||||
|
||||
// use vertex colors by explicitly setting
|
||||
if(mat->mode &MA_VERTEXCOLP)
|
||||
type = 2;
|
||||
|
||||
// use lighting?
|
||||
material->ras_mode |= ( mat->mode & MA_SHLESS )?0:USE_LIGHT;
|
||||
MTex *mttmp = 0;
|
||||
numchan = getNumTexChannels(mat);
|
||||
int valid_index = 0;
|
||||
|
||||
bool facetex = ((mat->mode & MA_FACETEXTURE) && (mesh->tface && tface) );
|
||||
|
||||
numchan = numchan>MAXTEX?MAXTEX:(numchan>=0&& facetex)?numchan+1:numchan;
|
||||
|
||||
// foreach MTex
|
||||
for(int i=0; i<numchan; i++) {
|
||||
// use face tex
|
||||
if(i==0 && facetex ) {
|
||||
Image*tmp = (Image*)(tface->tpage);
|
||||
if(tmp) {
|
||||
material->img[i] = tmp;
|
||||
material->texname[i] = material->img[i]->id.name;
|
||||
material->flag[i] |= ( tface->transp &TF_ALPHA )?USEALPHA:0;
|
||||
material->flag[i] |= ( tface->transp &TF_ADD )?CALCALPHA:0;
|
||||
material->ras_mode|= ( tface->transp &(TF_ADD | TF_ALPHA))?TRANSP:0;
|
||||
material->mapping[i].mapping |= ( (material->img[i]->flag & IMA_REFLECT)!=0 )?USEREFL:0;
|
||||
material->blend_mode[i] = BLEND_MUL;
|
||||
i++;// skip to the next image
|
||||
valid_index++;
|
||||
}
|
||||
}
|
||||
|
||||
mttmp = getImageFromMaterial( mat, i );
|
||||
if( mttmp ) {
|
||||
if( mttmp->tex ) {
|
||||
if( mttmp->tex->type == TEX_IMAGE ) {
|
||||
material->mtexname[i] = mttmp->tex->id.name;
|
||||
material->img[i] = mttmp->tex->ima;
|
||||
if( material->img[i] ) {
|
||||
|
||||
material->texname[i] = material->img[i]->id.name;
|
||||
material->flag[i] |= ( mttmp->tex->imaflag &TEX_MIPMAP )?MIPMAP:0;
|
||||
// -----------------------
|
||||
if( mttmp->tex->imaflag &TEX_USEALPHA ) {
|
||||
material->flag[i] |= USEALPHA;
|
||||
material->ras_mode |= TRANSP;
|
||||
}
|
||||
// -----------------------
|
||||
else if( mttmp->tex->imaflag &TEX_CALCALPHA ) {
|
||||
material->flag[i] |= CALCALPHA;
|
||||
material->ras_mode |= TRANSP;
|
||||
}
|
||||
|
||||
material->color_blend[i] = mttmp->colfac;
|
||||
material->flag[i] |= ( mttmp->mapto & MAP_ALPHA )?TEXALPHA:0;
|
||||
material->flag[i] |= ( mttmp->texflag& MTEX_NEGATIVE )?TEXNEG:0;
|
||||
|
||||
}
|
||||
}
|
||||
else if(mttmp->tex->type == TEX_ENVMAP) {
|
||||
if( mttmp->tex->env->stype == ENV_LOAD ) {
|
||||
|
||||
material->mtexname[i]= mttmp->tex->id.name;
|
||||
material->cubemap[i] = mttmp->tex->env;
|
||||
if(material->cubemap[i]->ima) {
|
||||
material->texname[i] = material->cubemap[i]->ima->id.name;
|
||||
material->mapping[i].mapping |= USEENV;
|
||||
}
|
||||
else {
|
||||
// in the player, we need to split it our self
|
||||
material->cubemap[i]->ima = mttmp->tex->ima;
|
||||
if(material->cubemap[i]->ima) {
|
||||
material->texname[i] = material->cubemap[i]->ima->id.name;
|
||||
material->mapping[i].mapping |= USEENV;
|
||||
}
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
material->flag[i] |= (mat->ipo!=0)?HASIPO:0;
|
||||
/// --------------------------------
|
||||
// mapping methods
|
||||
material->mapping[i].mapping |= ( mttmp->texco & TEXCO_REFL )?USEREFL:0;
|
||||
|
||||
if(mttmp->texco & TEXCO_OBJECT) {
|
||||
material->mapping[i].mapping |= USEOBJ;
|
||||
if(mttmp->object)
|
||||
material->mapping[i].objconame = mttmp->object->id.name;
|
||||
}
|
||||
|
||||
material->mapping[i].scale[0] = mttmp->size[0];
|
||||
material->mapping[i].scale[1] = mttmp->size[1];
|
||||
material->mapping[i].scale[2] = mttmp->size[2];
|
||||
material->mapping[i].offsets[0] = mttmp->ofs[0];
|
||||
material->mapping[i].offsets[1] = mttmp->ofs[1];
|
||||
material->mapping[i].offsets[2] = mttmp->ofs[2];
|
||||
|
||||
material->mapping[i].projplane[0] = mttmp->projx;
|
||||
material->mapping[i].projplane[1] = mttmp->projy;
|
||||
material->mapping[i].projplane[2] = mttmp->projz;
|
||||
/// --------------------------------
|
||||
|
||||
switch( mttmp->blendtype ) {
|
||||
case MTEX_BLEND:
|
||||
material->blend_mode[i] = BLEND_MIX;
|
||||
break;
|
||||
case MTEX_MUL:
|
||||
material->blend_mode[i] = BLEND_MUL;
|
||||
break;
|
||||
case MTEX_ADD:
|
||||
material->blend_mode[i] = BLEND_ADD;
|
||||
break;
|
||||
case MTEX_SUB:
|
||||
material->blend_mode[i] = BLEND_SUB;
|
||||
break;
|
||||
case MTEX_SCREEN:
|
||||
material->blend_mode[i] = BLEND_SCR;
|
||||
break;
|
||||
}
|
||||
valid_index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// above one tex the switches here
|
||||
// are not used
|
||||
switch(valid_index) {
|
||||
case 0:
|
||||
material->IdMode = DEFAULT_BLENDER;
|
||||
break;
|
||||
case 1:
|
||||
material->IdMode = ONETEX;
|
||||
break;
|
||||
default:
|
||||
material->IdMode = GREATERTHAN2;
|
||||
break;
|
||||
}
|
||||
|
||||
material->num_enabled = valid_index;
|
||||
|
||||
material->speccolor[0] = mat->specr;
|
||||
material->speccolor[1] = mat->specg;
|
||||
material->speccolor[2] = mat->specb;
|
||||
material->hard = (float)mat->har/4.0f;
|
||||
material->matcolor[0] = mat->r;
|
||||
material->matcolor[1] = mat->g;
|
||||
material->matcolor[2] = mat->b;
|
||||
material->matcolor[3] = mat->alpha;
|
||||
material->alpha = mat->alpha;
|
||||
material->emit = mat->emit;
|
||||
material->spec_f = mat->spec;
|
||||
material->ref = mat->ref;
|
||||
material->amb = mat->amb;
|
||||
material->ras_mode |= ((mat->mode & MA_ZTRA) != 0)?ZSORT:0;
|
||||
material->ras_mode |= ((mat->mode & MA_WIRE) != 0)?WIRE:0;
|
||||
}
|
||||
else {
|
||||
int valid = 0;
|
||||
// check for tface tex to fallback on
|
||||
if( mesh->tface && tface ){
|
||||
material->img[0] = (Image*)(tface->tpage);
|
||||
// ------------------------
|
||||
if(material->img[0]) {
|
||||
material->texname[0] = material->img[0]->id.name;
|
||||
material->mapping[0].mapping |= ( (material->img[0]->flag & IMA_REFLECT)!=0 )?USEREFL:0;
|
||||
material->flag[0] |= ( tface->transp &TF_ALPHA )?USEALPHA:0;
|
||||
material->flag[0] |= ( tface->transp &TF_ADD )?CALCALPHA:0;
|
||||
material->ras_mode|= ( tface->transp & (TF_ADD|TF_ALPHA))?TRANSP:0;
|
||||
valid++;
|
||||
}
|
||||
}
|
||||
material->num_enabled = valid;
|
||||
material->IdMode = TEXFACE;
|
||||
material->speccolor[0] = 1.f;
|
||||
material->speccolor[1] = 1.f;
|
||||
material->speccolor[2] = 1.f;
|
||||
material->hard = 35.f;
|
||||
material->matcolor[0] = 0.5f;
|
||||
material->matcolor[1] = 0.5f;
|
||||
material->matcolor[2] = 0.5f;
|
||||
material->spec_f = 0.5f;
|
||||
material->ref = 0.8f;
|
||||
}
|
||||
MT_Point2 uv[4];
|
||||
|
||||
if( mesh->tface && tface ) {
|
||||
|
||||
material->ras_mode |= !(
|
||||
(tface->flag & TF_HIDE) ||
|
||||
(tface->mode & TF_INVISIBLE)
|
||||
)?POLY_VIS:0;
|
||||
|
||||
material->ras_mode |= ( (tface->mode & TF_DYNAMIC)!= 0 )?COLLIDER:0;
|
||||
material->transp = tface->transp;
|
||||
|
||||
if(tface->transp)
|
||||
material->ras_mode |= TRANSP;
|
||||
|
||||
material->tile = tface->tile;
|
||||
material->mode = tface->mode;
|
||||
|
||||
uv[0] = MT_Point2(tface->uv[0]);
|
||||
uv[1] = MT_Point2(tface->uv[1]);
|
||||
uv[2] = MT_Point2(tface->uv[2]);
|
||||
|
||||
if (mface->v4)
|
||||
uv[3] = MT_Point2(tface->uv[3]);
|
||||
}
|
||||
else {
|
||||
// nothing at all
|
||||
material->ras_mode |= (COLLIDER|POLY_VIS| (validmat?0:USE_LIGHT));
|
||||
material->mode = default_face_mode;
|
||||
material->transp = TF_SOLID;
|
||||
material->tile = 0;
|
||||
}
|
||||
unsigned int rgb[4];
|
||||
GetRGB(type,mface,mmcol,mat,tface,rgb[0],rgb[1],rgb[2], rgb[3]);
|
||||
material->SetConversionRGB(rgb);
|
||||
material->SetConversionUV(uv);
|
||||
|
||||
material->ras_mode |= (mface->v4==0)?TRIANGLE:0;
|
||||
if(validmat)
|
||||
material->matname =(mat->id.name);
|
||||
|
||||
material->tface = tface;
|
||||
material->material = mat;
|
||||
return material;
|
||||
}
|
||||
|
||||
|
||||
RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* rendertools, KX_Scene* scene, KX_BlenderSceneConverter *converter)
|
||||
{
|
||||
RAS_MeshObject *meshobj;
|
||||
@@ -283,6 +621,46 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
|
||||
}
|
||||
|
||||
{
|
||||
Material* ma = 0;
|
||||
bool polyvisible = true;
|
||||
RAS_IPolyMaterial* polymat = NULL;
|
||||
|
||||
if(converter->GetMaterials())
|
||||
{
|
||||
if(mesh->totcol > 1)
|
||||
ma = mesh->mat[mface->mat_nr];
|
||||
else
|
||||
ma = give_current_material(blenderobj, 1);
|
||||
|
||||
BL_Material *bl_mat = ConvertMaterial(mesh, ma, tface, mface, mmcol, lightlayer, blenderobj);
|
||||
// set the index were dealing with
|
||||
bl_mat->material_index = (int)mface->mat_nr;
|
||||
|
||||
polyvisible = ((bl_mat->ras_mode & POLY_VIS)!=0);
|
||||
collider = ((bl_mat->ras_mode & COLLIDER)!=0);
|
||||
|
||||
polymat = new KX_BlenderMaterial(scene, bl_mat, skinMesh, lightlayer, blenderobj );
|
||||
converter->RegisterBlenderMaterial(bl_mat);
|
||||
|
||||
unsigned int rgb[4];
|
||||
bl_mat->GetConversionRGB(rgb);
|
||||
rgb0 = rgb[0];
|
||||
rgb1 = rgb[1];
|
||||
rgb2 = rgb[2];
|
||||
rgb3 = rgb[3];
|
||||
MT_Point2 uv[4];
|
||||
bl_mat->GetConversionUV(uv);
|
||||
uv0 = uv[0];
|
||||
uv1 = uv[1];
|
||||
uv2 = uv[2];
|
||||
uv3 = uv[3];
|
||||
// this is needed to free up memory afterwards
|
||||
converter->RegisterPolyMaterial(polymat);
|
||||
}
|
||||
else
|
||||
{
|
||||
ma = give_current_material(blenderobj, 1);
|
||||
|
||||
Image* bima = ((mesh->tface && tface) ? (Image*) tface->tpage : NULL);
|
||||
|
||||
STR_String imastr =
|
||||
@@ -300,15 +678,11 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
|
||||
|
||||
}
|
||||
|
||||
Material* ma = give_current_material(blenderobj, 1 /* mface->mat_nr */);
|
||||
//const char* matnameptr = (ma ? ma->id.name : ""); /*unused*/
|
||||
|
||||
bool polyvisible = true;
|
||||
if (mesh->tface && tface)
|
||||
{
|
||||
// Use texface colors if available
|
||||
//TF_DYNAMIC means the polygon is a collision face
|
||||
collider = (tface->mode & TF_DYNAMIC != 0);
|
||||
collider = ((tface->mode & TF_DYNAMIC) != 0);
|
||||
transp = tface->transp;
|
||||
tile = tface->tile;
|
||||
mode = tface->mode;
|
||||
@@ -385,7 +759,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
|
||||
bool istriangle = (mface->v4==0);
|
||||
bool zsort = ma?(ma->mode & MA_ZTRA) != 0:false;
|
||||
|
||||
RAS_IPolyMaterial* polymat = new KX_PolygonMaterial(imastr, ma,
|
||||
polymat = new KX_PolygonMaterial(imastr, ma,
|
||||
tile, tilexrep, tileyrep,
|
||||
mode, transp, zsort, lightlayer, istriangle, blenderobj, tface);
|
||||
|
||||
@@ -400,11 +774,11 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
|
||||
polymat->m_specular = MT_Vector3(0.0f,0.0f,0.0f);
|
||||
polymat->m_shininess = 35.0;
|
||||
}
|
||||
|
||||
|
||||
// this is needed to free up memory afterwards
|
||||
converter->RegisterPolyMaterial(polymat);
|
||||
|
||||
}
|
||||
|
||||
RAS_MaterialBucket* bucket = scene->FindBucket(polymat);
|
||||
|
||||
int nverts = mface->v4?4:3;
|
||||
@@ -467,6 +841,15 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools*
|
||||
}
|
||||
meshobj->UpdateMaterialList();
|
||||
|
||||
|
||||
|
||||
// -----------------------------------
|
||||
// pre calculate texture generation
|
||||
for(int matid=0; matid<meshobj->NumMaterials(); matid++)
|
||||
meshobj->GetMaterialBucket(matid)->GetPolyMaterial()->OnConstruction();
|
||||
// -----------------------------------
|
||||
|
||||
|
||||
return meshobj;
|
||||
}
|
||||
|
||||
@@ -961,11 +1344,11 @@ static KX_GameObject *gameobject_from_blenderobject(
|
||||
|
||||
// If this is a skin object, make Skin Controller
|
||||
if (ob->parent && ob->parent->type == OB_ARMATURE && ob->partype==PARSKEL && ((Mesh*)ob->data)->dvert){
|
||||
BL_SkinDeformer *dcont = new BL_SkinDeformer(ob, (BL_SkinMeshObject*)meshobj,ob->parent);
|
||||
BL_SkinDeformer *dcont = new BL_SkinDeformer(ob, (BL_SkinMeshObject*)meshobj );
|
||||
((BL_DeformableGameObject*)gameobj)->m_pDeformer = dcont;
|
||||
}
|
||||
else if (((Mesh*)ob->data)->dvert){
|
||||
BL_MeshDeformer *dcont = new BL_MeshDeformer(ob, (BL_SkinMeshObject*)meshobj,ob->parent);
|
||||
BL_MeshDeformer *dcont = new BL_MeshDeformer(ob, (BL_SkinMeshObject*)meshobj );
|
||||
((BL_DeformableGameObject*)gameobj)->m_pDeformer = dcont;
|
||||
}
|
||||
|
||||
@@ -980,10 +1363,11 @@ static KX_GameObject *gameobject_from_blenderobject(
|
||||
|
||||
case OB_ARMATURE:
|
||||
{
|
||||
gameobj = new BL_ArmatureObject (kxscene, KX_Scene::m_callbacks,
|
||||
get_armature(ob),
|
||||
ob->pose);
|
||||
|
||||
gameobj = new BL_ArmatureObject(
|
||||
kxscene,
|
||||
KX_Scene::m_callbacks,
|
||||
ob // handle
|
||||
);
|
||||
/* Get the current pose from the armature object and apply it as the rest pose */
|
||||
break;
|
||||
}
|
||||
@@ -1018,6 +1402,7 @@ static struct Scene *GetSceneForName(struct Main *maggie, const STR_String& scen
|
||||
return (Scene*) maggie->scene.first;
|
||||
}
|
||||
|
||||
|
||||
// convert blender objects into ketsji gameobjects
|
||||
void BL_ConvertBlenderObjects(struct Main* maggie,
|
||||
const STR_String& scenename,
|
||||
@@ -1141,6 +1526,9 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
|
||||
gameobj->NodeUpdateGS(0,true);
|
||||
|
||||
BL_ConvertIpos(blenderobject,gameobj,converter);
|
||||
// TODO: expand to multiple ipos per mesh
|
||||
Material *mat = give_current_material(blenderobject, 1);
|
||||
if(mat) BL_ConvertMaterialIpos(mat, gameobj, converter);
|
||||
|
||||
bool isInActiveLayer = (blenderobject->lay & activeLayerBitInfo) !=0;
|
||||
|
||||
|
||||
@@ -128,9 +128,7 @@ void BL_MeshDeformer::RecalcNormals()
|
||||
m_transnors[mf->v3]+=MT_Point3(fnor);
|
||||
if (mf->v4)
|
||||
m_transnors[mf->v4]+=MT_Point3(fnor);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (v =0; v<m_bmesh->totvert; v++){
|
||||
@@ -154,7 +152,7 @@ void BL_MeshDeformer::VerifyStorage()
|
||||
delete []m_transnors;
|
||||
|
||||
m_transnors =new MT_Point3[m_bmesh->totvert+m_bmesh->totface];
|
||||
m_transverts=new MT_Point3[m_bmesh->totvert];
|
||||
m_transverts=new float[(sizeof(*m_transverts)*m_bmesh->totvert)][3];
|
||||
m_tvtot = m_bmesh->totvert;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,14 +48,13 @@ public:
|
||||
void VerifyStorage();
|
||||
void RecalcNormals();
|
||||
virtual void Relink(GEN_Map<class GEN_HashedPtr, void*>*map){};
|
||||
BL_MeshDeformer(struct Object* obj, class BL_SkinMeshObject *meshobj,struct Object* armatureObj):
|
||||
BL_MeshDeformer(struct Object* obj, class BL_SkinMeshObject *meshobj ):
|
||||
m_pMeshObject(meshobj),
|
||||
m_bmesh((struct Mesh*)(obj->data)),
|
||||
m_objMesh(obj),
|
||||
m_transnors(NULL),
|
||||
m_transverts(NULL),
|
||||
m_tvtot(0),
|
||||
m_blenderMeshObject(obj),
|
||||
m_blenderArmatureObj(armatureObj)
|
||||
m_tvtot(0)
|
||||
{};
|
||||
virtual ~BL_MeshDeformer();
|
||||
virtual void SetSimulatedTime(double time){};
|
||||
@@ -64,14 +63,17 @@ public:
|
||||
virtual RAS_Deformer* GetReplica(){return NULL;};
|
||||
// virtual void InitDeform(double time){};
|
||||
protected:
|
||||
class BL_SkinMeshObject *m_pMeshObject;
|
||||
struct Mesh *m_bmesh;
|
||||
MT_Point3 *m_transnors;
|
||||
MT_Point3 *m_transverts;
|
||||
int m_tvtot;
|
||||
Object* m_blenderMeshObject;
|
||||
Object* m_blenderArmatureObj;
|
||||
class BL_SkinMeshObject* m_pMeshObject;
|
||||
struct Mesh* m_bmesh;
|
||||
MT_Point3* m_transnors;
|
||||
|
||||
//MT_Point3* m_transverts;
|
||||
// this is so m_transverts doesn't need to be converted
|
||||
// before deformation
|
||||
float (*m_transverts)[3];
|
||||
struct Object* m_objMesh;
|
||||
// --
|
||||
int m_tvtot;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -49,6 +49,11 @@
|
||||
#include "BKE_action.h"
|
||||
#include "MT_Point3.h"
|
||||
|
||||
extern "C"{
|
||||
#include "BKE_lattice.h"
|
||||
}
|
||||
#include "BKE_utildefines.h"
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_arithb.h"
|
||||
|
||||
@@ -57,6 +62,8 @@
|
||||
|
||||
BL_SkinDeformer::~BL_SkinDeformer()
|
||||
{
|
||||
if(m_releaseobject && m_armobj)
|
||||
m_armobj->Release();
|
||||
};
|
||||
|
||||
/* XXX note, this __NLA_OLDDEFORM define seems to be obsolete */
|
||||
@@ -147,11 +154,8 @@ void BL_SkinDeformer::ProcessReplica()
|
||||
|
||||
//void where_is_pose (Object *ob);
|
||||
//void armature_deform_verts(Object *armOb, Object *target, float (*vertexCos)[3], int numVerts, int deformflag);
|
||||
extern "C" void armature_deform_verts(struct Object *armOb, struct Object *target, float (*vertexCos)[3], int numVerts, int deformflag);
|
||||
|
||||
void BL_SkinDeformer::Update(void)
|
||||
{
|
||||
|
||||
/* See if the armature has been updated for this frame */
|
||||
if (m_lastUpdate!=m_armobj->GetLastFrame()){
|
||||
|
||||
@@ -161,50 +165,38 @@ void BL_SkinDeformer::Update(void)
|
||||
/* XXX note: where_is_pose() (from BKE_armature.h) calculates all matrices needed to start deforming */
|
||||
/* but it requires the blender object pointer... */
|
||||
//void where_is_pose (Object *ob);
|
||||
where_is_pose (m_blenderArmatureObj);
|
||||
// where_is_pose (m_blenderArmatureObj);
|
||||
|
||||
/* store verts locally */
|
||||
for (int v =0; v<m_bmesh->totvert; v++){
|
||||
float co[3];
|
||||
// for (int v =0; v<m_bmesh->totvert; v++){
|
||||
/* XXX note, dunno about this line */
|
||||
m_transverts[v]=MT_Point3(m_bmesh->mvert[v].co);
|
||||
}
|
||||
// m_transverts[v]=MT_Point3(m_bmesh->mvert[v].co);
|
||||
// }
|
||||
|
||||
float test[1000][3];
|
||||
// float test[1000][3];
|
||||
|
||||
armature_deform_verts(m_blenderArmatureObj,m_blenderMeshObject,test,m_bmesh->totvert,ARM_DEF_VGROUP);
|
||||
// armature_deform_verts(m_blenderArmatureObj,m_blenderMeshObject,test,m_bmesh->totvert,ARM_DEF_VGROUP);
|
||||
|
||||
|
||||
/* XXX note: now use this call instead */
|
||||
// void armature_deform_verts(Object *armOb, Object *target, float (*vertexCos)[3], int numVerts, int deformflag)
|
||||
// - armOb = armature object
|
||||
// - target = Mesh
|
||||
// - vertexCos[3] = array of numVerts float vectors (3 floats)
|
||||
// - set deformflag to ARM_DEF_VGROUP
|
||||
// example (after having filled the m_transverts array):
|
||||
// armature_deform_verts(m_armobj, m_meshobj, m_transverts, m_bmesh->totvert, ARM_DEF_VGROUP);
|
||||
|
||||
Object* par_arma = m_armobj->GetArmatureObject();
|
||||
where_is_pose( par_arma );
|
||||
/* store verts locally */
|
||||
VerifyStorage();
|
||||
for (int v =0; v<m_bmesh->totvert; v++)
|
||||
VECCOPY(m_transverts[v], m_bmesh->mvert[v].co);
|
||||
|
||||
armature_deform_verts( par_arma, m_objMesh,m_transverts, m_bmesh->totvert, ARM_DEF_VGROUP );
|
||||
RecalcNormals();
|
||||
|
||||
|
||||
/* Update the current frame */
|
||||
m_lastUpdate=m_armobj->GetLastFrame();
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX note: I propose to drop this function */
|
||||
|
||||
void BL_SkinDeformer::SetArmature(BL_ArmatureObject *armobj)
|
||||
{
|
||||
// m_armobj = armobj;
|
||||
|
||||
// for (bDeformGroup *dg=(bDeformGroup*)m_defbase->first; dg; dg=(bDeformGroup*)dg->next) {
|
||||
|
||||
/* dg->data no longer exists needs update
|
||||
dg->data = (void*)get_named_bone(m_armobj->GetArmature(), dg->name); */
|
||||
// }
|
||||
|
||||
// GB_validate_defgroups(m_bmesh, m_defbase);
|
||||
// --
|
||||
// only used to set the object now
|
||||
m_armobj = armobj;
|
||||
}
|
||||
|
||||
@@ -64,37 +64,31 @@ public:
|
||||
}
|
||||
void SetArmature (class BL_ArmatureObject *armobj);
|
||||
|
||||
BL_SkinDeformer( struct Object *bmeshobj,
|
||||
class BL_SkinMeshObject *mesh,struct Object* blenderArmatureObj)
|
||||
:BL_MeshDeformer(bmeshobj, mesh,blenderArmatureObj),
|
||||
m_armobj(NULL),
|
||||
BL_SkinDeformer(struct Object *bmeshobj,
|
||||
class BL_SkinMeshObject *mesh,
|
||||
BL_ArmatureObject* arma = NULL)
|
||||
: //
|
||||
BL_MeshDeformer(bmeshobj, mesh),
|
||||
m_armobj(arma),
|
||||
m_lastUpdate(-1),
|
||||
m_defbase(&bmeshobj->defbase)
|
||||
m_defbase(&bmeshobj->defbase),
|
||||
m_releaseobject(false)
|
||||
{
|
||||
/* Build all precalculatable matrices for bones */
|
||||
/* XXX note: obsolete */
|
||||
// GB_build_mats(bmeshobj->parent->obmat, bmeshobj->obmat, m_premat, m_postmat);
|
||||
// GB_validate_defgroups((Mesh*)bmeshobj->data, m_defbase);
|
||||
// Validate bone data in bDeformGroups
|
||||
/*
|
||||
for (bDeformGroup *dg=(bDeformGroup*)m_defbase->first; dg; dg=(bDeformGroup*)dg->next)
|
||||
dg->data = (void*)get_named_bone(barm, dg->name);
|
||||
*/
|
||||
};
|
||||
|
||||
/* this second constructor is needed for making a mesh deformable on the fly. */
|
||||
|
||||
BL_SkinDeformer( struct Object *bmeshobj_old,
|
||||
BL_SkinDeformer(struct Object *bmeshobj_old,
|
||||
struct Object *bmeshobj_new,
|
||||
class BL_SkinMeshObject *mesh,struct Object *bArmatureObj)
|
||||
:BL_MeshDeformer(bmeshobj_old, mesh,bArmatureObj),
|
||||
m_armobj(NULL),
|
||||
class BL_SkinMeshObject *mesh,
|
||||
bool release_object,
|
||||
BL_ArmatureObject* arma = NULL)
|
||||
: //
|
||||
BL_MeshDeformer(bmeshobj_old, mesh),
|
||||
m_armobj(arma),
|
||||
m_lastUpdate(-1),
|
||||
m_defbase(&bmeshobj_old->defbase)
|
||||
m_defbase(&bmeshobj_old->defbase),
|
||||
m_releaseobject(release_object)
|
||||
{
|
||||
/* XXX note: obsolete */
|
||||
// GB_build_mats(bmeshobj_new->parent->obmat, bmeshobj_new->obmat, m_premat, m_postmat);
|
||||
// GB_validate_defgroups((Mesh*)bmeshobj_old->data, m_defbase);
|
||||
};
|
||||
|
||||
virtual void ProcessReplica();
|
||||
@@ -104,13 +98,12 @@ public:
|
||||
bool Apply (class RAS_IPolyMaterial *polymat);
|
||||
|
||||
protected:
|
||||
BL_ArmatureObject *m_armobj; // Our parent object
|
||||
/* XXX note obsolete */
|
||||
// float m_premat[4][4];
|
||||
// float m_postmat[4][4];
|
||||
BL_ArmatureObject* m_armobj; // Our parent object
|
||||
float m_time;
|
||||
double m_lastUpdate;
|
||||
ListBase *m_defbase;
|
||||
ListBase* m_defbase;
|
||||
bool m_releaseobject;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -95,6 +95,10 @@ BlenderWorldInfo::BlenderWorldInfo(struct World* blenderworld)
|
||||
m_backgroundred = blenderworld->horr;
|
||||
m_backgroundgreen = blenderworld->horg;
|
||||
m_backgroundblue = blenderworld->horb;
|
||||
|
||||
m_ambientred = blenderworld->ambr;
|
||||
m_ambientgreen = blenderworld->ambg;
|
||||
m_ambientblue = blenderworld->ambb;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -144,6 +148,20 @@ float BlenderWorldInfo::getBackColorBlue()
|
||||
}
|
||||
|
||||
|
||||
float BlenderWorldInfo::getAmbientColorRed()
|
||||
{
|
||||
return m_ambientred;
|
||||
}
|
||||
|
||||
float BlenderWorldInfo::getAmbientColorGreen()
|
||||
{
|
||||
return m_ambientgreen;
|
||||
}
|
||||
|
||||
float BlenderWorldInfo::getAmbientColorBlue()
|
||||
{
|
||||
return m_ambientblue;
|
||||
}
|
||||
|
||||
float BlenderWorldInfo::getMistStart()
|
||||
{
|
||||
|
||||
@@ -49,6 +49,10 @@ class BlenderWorldInfo : public KX_WorldInfo
|
||||
float m_mistgreen;
|
||||
float m_mistblue;
|
||||
|
||||
float m_ambientred;
|
||||
float m_ambientgreen;
|
||||
float m_ambientblue;
|
||||
|
||||
public:
|
||||
BlenderWorldInfo(struct World* blenderworld);
|
||||
~BlenderWorldInfo();
|
||||
@@ -59,6 +63,10 @@ public:
|
||||
float getBackColorGreen();
|
||||
float getBackColorBlue();
|
||||
|
||||
float getAmbientColorRed();
|
||||
float getAmbientColorGreen();
|
||||
float getAmbientColorBlue();
|
||||
|
||||
float getMistStart();
|
||||
float getMistDistance();
|
||||
float getMistColorRed();
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "PHY_IPhysicsEnvironment.h"
|
||||
#include "KX_KetsjiEngine.h"
|
||||
#include "KX_IPhysicsController.h"
|
||||
#include "BL_Material.h"
|
||||
|
||||
#include "DummyPhysicsEnvironment.h"
|
||||
|
||||
@@ -98,7 +99,8 @@ KX_BlenderSceneConverter::KX_BlenderSceneConverter(
|
||||
: m_maggie(maggie),
|
||||
m_sipo(sipo),
|
||||
m_ketsjiEngine(engine),
|
||||
m_alwaysUseExpandFraming(false)
|
||||
m_alwaysUseExpandFraming(false),
|
||||
m_usemat(false)
|
||||
{
|
||||
m_newfilename = "";
|
||||
}
|
||||
@@ -130,6 +132,14 @@ KX_BlenderSceneConverter::~KX_BlenderSceneConverter()
|
||||
itp++;
|
||||
}
|
||||
|
||||
// delete after RAS_IPolyMaterial
|
||||
vector<BL_Material *>::iterator itmat = m_materials.begin();
|
||||
while (itmat != m_materials.end()) {
|
||||
delete (*itmat);
|
||||
itmat++;
|
||||
}
|
||||
|
||||
|
||||
vector<RAS_MeshObject*>::iterator itm = m_meshobjects.begin();
|
||||
while (itm != m_meshobjects.end()) {
|
||||
delete (*itm);
|
||||
@@ -345,6 +355,24 @@ void KX_BlenderSceneConverter::ConvertScene(const STR_String& scenename,
|
||||
}
|
||||
|
||||
|
||||
// use blender materials
|
||||
void KX_BlenderSceneConverter::SetMaterials(bool val)
|
||||
{
|
||||
m_usemat = val;
|
||||
}
|
||||
|
||||
bool KX_BlenderSceneConverter::GetMaterials()
|
||||
{
|
||||
return m_usemat;
|
||||
}
|
||||
|
||||
|
||||
void KX_BlenderSceneConverter::RegisterBlenderMaterial(BL_Material *mat)
|
||||
{
|
||||
m_materials.push_back(mat);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void KX_BlenderSceneConverter::SetAlwaysUseExpandFraming(
|
||||
bool to_what)
|
||||
|
||||
@@ -44,6 +44,7 @@ class SCA_IController;
|
||||
class RAS_MeshObject;
|
||||
class RAS_IPolyMaterial;
|
||||
class BL_InterpolatorList;
|
||||
class BL_Material;
|
||||
struct IpoCurve;
|
||||
struct Main;
|
||||
struct SpaceIpo;
|
||||
@@ -53,6 +54,7 @@ class KX_BlenderSceneConverter : public KX_ISceneConverter
|
||||
vector<KX_WorldInfo*> m_worldinfos;
|
||||
vector<RAS_IPolyMaterial*> m_polymaterials;
|
||||
vector<RAS_MeshObject*> m_meshobjects;
|
||||
vector<BL_Material *> m_materials;
|
||||
|
||||
GEN_Map<CHashedPtr,struct Object*> m_map_gameobject_to_blender;
|
||||
GEN_Map<CHashedPtr,KX_GameObject*> m_map_blender_to_gameobject;
|
||||
@@ -71,6 +73,7 @@ class KX_BlenderSceneConverter : public KX_ISceneConverter
|
||||
STR_String m_newfilename;
|
||||
class KX_KetsjiEngine* m_ketsjiEngine;
|
||||
bool m_alwaysUseExpandFraming;
|
||||
bool m_usemat;
|
||||
|
||||
void localDel_ipoCurve ( IpoCurve * icu ,struct SpaceIpo* sipo);
|
||||
struct Ipo* findIpoForName(char* objName);
|
||||
@@ -114,6 +117,8 @@ public:
|
||||
|
||||
void RegisterPolyMaterial(RAS_IPolyMaterial *polymat);
|
||||
|
||||
void RegisterBlenderMaterial(BL_Material *mat);
|
||||
|
||||
void RegisterInterpolatorList(BL_InterpolatorList *ipoList, struct Ipo *for_ipo);
|
||||
BL_InterpolatorList *FindInterpolatorList(struct Ipo *for_ipo);
|
||||
|
||||
@@ -131,7 +136,9 @@ public:
|
||||
virtual void WritePhysicsObjectToAnimationIpo(int frameNumber);
|
||||
virtual void TestHandlesPhysicsObjectToAnimationIpo();
|
||||
|
||||
|
||||
// use blender materials
|
||||
virtual void SetMaterials(bool val);
|
||||
virtual bool GetMaterials();
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
#include "DNA_lamp_types.h"
|
||||
#include "DNA_world_types.h"
|
||||
#include "DNA_camera_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
/* end of blender include block */
|
||||
|
||||
#include "KX_IPO_SGController.h"
|
||||
@@ -66,6 +67,7 @@
|
||||
#include "KX_CameraIpoSGController.h"
|
||||
#include "KX_WorldIpoController.h"
|
||||
#include "KX_ObColorIpoSGController.h"
|
||||
#include "KX_MaterialIpoController.h"
|
||||
|
||||
#include "SG_Node.h"
|
||||
|
||||
@@ -561,3 +563,195 @@ void BL_ConvertWorldIpos(struct World* blenderworld,KX_BlenderSceneConverter *co
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BL_ConvertMaterialIpos(
|
||||
Material* blendermaterial,
|
||||
KX_GameObject* gameobj,
|
||||
KX_BlenderSceneConverter *converter
|
||||
)
|
||||
{
|
||||
if (blendermaterial->ipo) {
|
||||
|
||||
KX_MaterialIpoController* ipocontr = new KX_MaterialIpoController();
|
||||
gameobj->GetSGNode()->AddSGController(ipocontr);
|
||||
ipocontr->SetObject(gameobj->GetSGNode());
|
||||
|
||||
BL_InterpolatorList *ipoList= GetIpoList(blendermaterial->ipo, converter);
|
||||
|
||||
|
||||
ipocontr->m_rgba[0] = blendermaterial->r;
|
||||
ipocontr->m_rgba[1] = blendermaterial->g;
|
||||
ipocontr->m_rgba[2] = blendermaterial->b;
|
||||
ipocontr->m_rgba[3] = blendermaterial->alpha;
|
||||
|
||||
ipocontr->m_specrgb[0] = blendermaterial->specr;
|
||||
ipocontr->m_specrgb[1] = blendermaterial->specg;
|
||||
ipocontr->m_specrgb[2] = blendermaterial->specb;
|
||||
|
||||
ipocontr->m_hard = blendermaterial->har;
|
||||
ipocontr->m_spec = blendermaterial->spec;
|
||||
ipocontr->m_ref = blendermaterial->ref;
|
||||
ipocontr->m_emit = blendermaterial->emit;
|
||||
ipocontr->m_alpha = blendermaterial->alpha;
|
||||
KX_IScalarInterpolator *ipo;
|
||||
|
||||
// --
|
||||
ipo = ipoList->GetScalarInterpolator(MA_COL_R);
|
||||
if (ipo) {
|
||||
if (!ipocontr) {
|
||||
ipocontr = new KX_MaterialIpoController();
|
||||
gameobj->GetSGNode()->AddSGController(ipocontr);
|
||||
ipocontr->SetObject(gameobj->GetSGNode());
|
||||
}
|
||||
KX_IInterpolator *interpolator =
|
||||
new KX_ScalarInterpolator(
|
||||
&ipocontr->m_rgba[0],
|
||||
ipo);
|
||||
ipocontr->AddInterpolator(interpolator);
|
||||
}
|
||||
|
||||
ipo = ipoList->GetScalarInterpolator(MA_COL_G);
|
||||
if (ipo) {
|
||||
if (!ipocontr) {
|
||||
ipocontr = new KX_MaterialIpoController();
|
||||
gameobj->GetSGNode()->AddSGController(ipocontr);
|
||||
ipocontr->SetObject(gameobj->GetSGNode());
|
||||
}
|
||||
KX_IInterpolator *interpolator =
|
||||
new KX_ScalarInterpolator(
|
||||
&ipocontr->m_rgba[1],
|
||||
ipo);
|
||||
ipocontr->AddInterpolator(interpolator);
|
||||
}
|
||||
|
||||
ipo = ipoList->GetScalarInterpolator(MA_COL_B);
|
||||
if (ipo) {
|
||||
if (!ipocontr) {
|
||||
ipocontr = new KX_MaterialIpoController();
|
||||
gameobj->GetSGNode()->AddSGController(ipocontr);
|
||||
ipocontr->SetObject(gameobj->GetSGNode());
|
||||
}
|
||||
KX_IInterpolator *interpolator =
|
||||
new KX_ScalarInterpolator(
|
||||
&ipocontr->m_rgba[2],
|
||||
ipo);
|
||||
ipocontr->AddInterpolator(interpolator);
|
||||
}
|
||||
|
||||
ipo = ipoList->GetScalarInterpolator(MA_ALPHA);
|
||||
if (ipo) {
|
||||
if (!ipocontr) {
|
||||
ipocontr = new KX_MaterialIpoController();
|
||||
gameobj->GetSGNode()->AddSGController(ipocontr);
|
||||
ipocontr->SetObject(gameobj->GetSGNode());
|
||||
}
|
||||
KX_IInterpolator *interpolator =
|
||||
new KX_ScalarInterpolator(
|
||||
&ipocontr->m_rgba[3],
|
||||
ipo);
|
||||
ipocontr->AddInterpolator(interpolator);
|
||||
}
|
||||
// --
|
||||
|
||||
ipo = ipoList->GetScalarInterpolator(MA_SPEC_R );
|
||||
if (ipo) {
|
||||
if (!ipocontr) {
|
||||
ipocontr = new KX_MaterialIpoController();
|
||||
gameobj->GetSGNode()->AddSGController(ipocontr);
|
||||
ipocontr->SetObject(gameobj->GetSGNode());
|
||||
}
|
||||
KX_IInterpolator *interpolator =
|
||||
new KX_ScalarInterpolator(
|
||||
&ipocontr->m_specrgb[0],
|
||||
ipo);
|
||||
ipocontr->AddInterpolator(interpolator);
|
||||
}
|
||||
|
||||
ipo = ipoList->GetScalarInterpolator(MA_SPEC_G);
|
||||
if (ipo) {
|
||||
if (!ipocontr) {
|
||||
ipocontr = new KX_MaterialIpoController();
|
||||
gameobj->GetSGNode()->AddSGController(ipocontr);
|
||||
ipocontr->SetObject(gameobj->GetSGNode());
|
||||
}
|
||||
KX_IInterpolator *interpolator =
|
||||
new KX_ScalarInterpolator(
|
||||
&ipocontr->m_specrgb[1],
|
||||
ipo);
|
||||
ipocontr->AddInterpolator(interpolator);
|
||||
}
|
||||
|
||||
ipo = ipoList->GetScalarInterpolator(MA_SPEC_B);
|
||||
if (ipo) {
|
||||
if (!ipocontr) {
|
||||
ipocontr = new KX_MaterialIpoController();
|
||||
gameobj->GetSGNode()->AddSGController(ipocontr);
|
||||
ipocontr->SetObject(gameobj->GetSGNode());
|
||||
}
|
||||
KX_IInterpolator *interpolator =
|
||||
new KX_ScalarInterpolator(
|
||||
&ipocontr->m_specrgb[2],
|
||||
ipo);
|
||||
ipocontr->AddInterpolator(interpolator);
|
||||
}
|
||||
|
||||
// --
|
||||
ipo = ipoList->GetScalarInterpolator(MA_HARD);
|
||||
if (ipo) {
|
||||
if (!ipocontr) {
|
||||
ipocontr = new KX_MaterialIpoController();
|
||||
gameobj->GetSGNode()->AddSGController(ipocontr);
|
||||
ipocontr->SetObject(gameobj->GetSGNode());
|
||||
}
|
||||
KX_IInterpolator *interpolator =
|
||||
new KX_ScalarInterpolator(
|
||||
&ipocontr->m_hard,
|
||||
ipo);
|
||||
ipocontr->AddInterpolator(interpolator);
|
||||
}
|
||||
|
||||
ipo = ipoList->GetScalarInterpolator(MA_SPEC);
|
||||
if (ipo) {
|
||||
if (!ipocontr) {
|
||||
ipocontr = new KX_MaterialIpoController();
|
||||
gameobj->GetSGNode()->AddSGController(ipocontr);
|
||||
ipocontr->SetObject(gameobj->GetSGNode());
|
||||
}
|
||||
KX_IInterpolator *interpolator =
|
||||
new KX_ScalarInterpolator(
|
||||
&ipocontr->m_spec,
|
||||
ipo);
|
||||
ipocontr->AddInterpolator(interpolator);
|
||||
}
|
||||
|
||||
|
||||
ipo = ipoList->GetScalarInterpolator(MA_REF);
|
||||
if (ipo) {
|
||||
if (!ipocontr) {
|
||||
ipocontr = new KX_MaterialIpoController();
|
||||
gameobj->GetSGNode()->AddSGController(ipocontr);
|
||||
ipocontr->SetObject(gameobj->GetSGNode());
|
||||
}
|
||||
KX_IInterpolator *interpolator =
|
||||
new KX_ScalarInterpolator(
|
||||
&ipocontr->m_ref,
|
||||
ipo);
|
||||
ipocontr->AddInterpolator(interpolator);
|
||||
}
|
||||
|
||||
ipo = ipoList->GetScalarInterpolator(MA_EMIT);
|
||||
if (ipo) {
|
||||
if (!ipocontr) {
|
||||
ipocontr = new KX_MaterialIpoController();
|
||||
gameobj->GetSGNode()->AddSGController(ipocontr);
|
||||
ipocontr->SetObject(gameobj->GetSGNode());
|
||||
}
|
||||
KX_IInterpolator *interpolator =
|
||||
new KX_ScalarInterpolator(
|
||||
&ipocontr->m_emit,
|
||||
ipo);
|
||||
ipocontr->AddInterpolator(interpolator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,10 @@ void BL_ConvertCameraIpos(struct Camera* blendercamera,
|
||||
class KX_GameObject* cameraobj,
|
||||
class KX_BlenderSceneConverter *converter);
|
||||
|
||||
void BL_ConvertMaterialIpos(struct Material* blendermaterial,
|
||||
class KX_GameObject* materialobj,
|
||||
class KX_BlenderSceneConverter *converter);
|
||||
|
||||
|
||||
#endif //__KX_IPOCONVERT_H
|
||||
|
||||
|
||||
@@ -63,3 +63,4 @@ CPPFLAGS += -I../Network -I../Ketsji/KXNetwork
|
||||
CPPFLAGS += -I../Physics/common -I../Physics/Dummy
|
||||
CPPFLAGS += -I../Physics/BlOde
|
||||
CPPFLAGS += -I../Physics/Bullet
|
||||
CPPFLAGS += -I.
|
||||
|
||||
@@ -44,6 +44,7 @@ kx_converter_env.Append (CPPPATH = ['.',
|
||||
'#source/blender/include',
|
||||
'#source/blender/makesdna',
|
||||
'#source/gameengine/Rasterizer',
|
||||
'#source/gameengine/Rasterizer/RAS_OpenGLRasterizer',
|
||||
'#source/gameengine/GameLogic',
|
||||
'#source/gameengine/Expressions',
|
||||
'#source/gameengine/Network',
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
* purpose. It is provided "as is" without express or implied warranty.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Value.h"
|
||||
#include "FloatValue.h"
|
||||
#include "IntValue.h"
|
||||
@@ -497,9 +496,6 @@ double* CValue::GetVector3(bool bGetTransformedVec)
|
||||
/*---------------------------------------------------------------------------------------------------------------------
|
||||
Reference Counting
|
||||
---------------------------------------------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Add a reference to this value
|
||||
//
|
||||
|
||||
@@ -184,6 +184,7 @@ public:
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef NO_EXP_PYTHON_EMBEDDING
|
||||
#include "PyObjectPlus.h"
|
||||
#include "object.h"
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
*
|
||||
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
||||
*/
|
||||
#include <iostream>
|
||||
|
||||
#include "SCA_IObject.h"
|
||||
#include "SCA_ISensor.h"
|
||||
@@ -40,7 +41,6 @@
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
|
||||
MT_Point3 SCA_IObject::m_sDummy=MT_Point3(0,0,0);
|
||||
|
||||
SCA_IObject::SCA_IObject(PyTypeObject* T): CValue(T)
|
||||
|
||||
@@ -60,7 +60,6 @@ SCA_LogicManager::~SCA_LogicManager()
|
||||
(*gameobjptr)->Release();
|
||||
|
||||
}
|
||||
|
||||
/*for (int i=0;i<m_sensorcontrollermap.size();i++)
|
||||
{
|
||||
vector<SCA_IController*>* controllerarray = *(m_sensorcontrollermap[i]);
|
||||
@@ -175,7 +174,6 @@ void SCA_LogicManager::RemoveSensor(SCA_ISensor* sensor)
|
||||
|
||||
void SCA_LogicManager::RemoveDestroyedActuator(SCA_IActuator* actuator)
|
||||
{
|
||||
|
||||
m_removedActuators.push_back(SmartActuatorPtr(actuator,0));
|
||||
// take care that no controller can use this actuator again !
|
||||
|
||||
|
||||
@@ -96,8 +96,6 @@ public:
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
class SCA_LogicManager
|
||||
{
|
||||
vector<class SCA_EventManager*> m_eventmanagers;
|
||||
@@ -117,7 +115,6 @@ class SCA_LogicManager
|
||||
GEN_Map<CHashedPtr,void*> m_map_gameobj_to_blendobj;
|
||||
|
||||
vector<SmartActuatorPtr> m_removedActuators;
|
||||
|
||||
public:
|
||||
SCA_LogicManager();
|
||||
virtual ~SCA_LogicManager();
|
||||
|
||||
@@ -145,7 +145,6 @@ PyObject* SCA_PythonController::sPyGetCurrentController(PyObject* self,
|
||||
static char* sPyAddActiveActuator__doc__;
|
||||
#endif
|
||||
|
||||
|
||||
PyObject* SCA_PythonController::sPyAddActiveActuator(
|
||||
|
||||
PyObject* self,
|
||||
@@ -156,18 +155,27 @@ PyObject* SCA_PythonController::sPyAddActiveActuator(
|
||||
PyObject* ob1;
|
||||
int activate;
|
||||
if (!PyArg_ParseTuple(args, "Oi", &ob1,&activate))
|
||||
{
|
||||
return NULL;
|
||||
|
||||
}
|
||||
// for safety, todo: only allow for registered actuators (pointertable)
|
||||
// we don't want to crash gameengine/blender by python scripts
|
||||
std::vector<SCA_IActuator*> lacts = m_sCurrentController->GetLinkedActuators();
|
||||
|
||||
CValue* ac = (CValue*)ob1;
|
||||
std::vector<SCA_IActuator*>::iterator it;
|
||||
bool found = false;
|
||||
CValue* act = (CValue*)ob1;
|
||||
|
||||
for(it = lacts.begin(); it!= lacts.end(); it++) {
|
||||
if( static_cast<SCA_IActuator*>(act) == (*it) ) {
|
||||
found=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(found){
|
||||
CValue* boolval = new CBoolValue(activate!=0);
|
||||
m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)ac,boolval);
|
||||
m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)act,boolval);
|
||||
boolval->Release();
|
||||
|
||||
}
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
@@ -269,10 +277,22 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr)
|
||||
PyDict_Clear(excdict);
|
||||
Py_DECREF(excdict);*/
|
||||
|
||||
// FIXME:: still happining, will try to fix. snailrose...
|
||||
PyObject *excdict= PyDict_Copy(m_pythondictionary);
|
||||
PyObject* resultobj = PyEval_EvalCode((PyCodeObject*)m_bytecode,
|
||||
excdict,
|
||||
excdict
|
||||
);
|
||||
PyDict_Clear(excdict);
|
||||
Py_DECREF(excdict);
|
||||
|
||||
|
||||
#if 0
|
||||
PyObject* resultobj = PyEval_EvalCode((PyCodeObject*)m_bytecode,
|
||||
m_pythondictionary,
|
||||
m_pythondictionary
|
||||
);
|
||||
#endif
|
||||
|
||||
if (resultobj)
|
||||
{
|
||||
|
||||
@@ -62,6 +62,8 @@ extern "C"
|
||||
#endif // __cplusplus
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLO_readfile.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_main.h"
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
@@ -82,6 +84,7 @@ extern "C"
|
||||
#include "RAS_GLExtensionManager.h"
|
||||
#include "KX_PythonInit.h"
|
||||
#include "KX_PyConstraintBinding.h"
|
||||
#include "BL_Material.h" // MAXTEX
|
||||
|
||||
#include "KX_BlenderSceneConverter.h"
|
||||
#include "NG_LoopBackNetworkDeviceInterface.h"
|
||||
@@ -126,7 +129,8 @@ GPG_Application::GPG_Application(GHOST_ISystem* system, struct Main* maggie, STR
|
||||
m_rasterizer(0),
|
||||
m_sceneconverter(0),
|
||||
m_networkdevice(0),
|
||||
m_audiodevice(0)
|
||||
m_audiodevice(0),
|
||||
m_blendermat(0)
|
||||
{
|
||||
fSystem = system;
|
||||
}
|
||||
@@ -147,6 +151,7 @@ bool GPG_Application::SetGameEngineData(struct Main* maggie, STR_String startSce
|
||||
|
||||
if (maggie != NULL && startSceneName != "")
|
||||
{
|
||||
G.scene = (Scene*)maggie->scene.first;
|
||||
m_maggie = maggie;
|
||||
m_startSceneName = startSceneName;
|
||||
result = true;
|
||||
@@ -488,6 +493,23 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode)
|
||||
bool profile = (SYS_GetCommandLineInt(syshandle, "show_profile", 0) != 0);
|
||||
bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0);
|
||||
bool useVertexArrays = SYS_GetCommandLineInt(syshandle,"vertexarrays",1) != 0;
|
||||
|
||||
#ifdef GL_ARB_multitexture
|
||||
// ----------------------------------
|
||||
if(bgl::RAS_EXT_support._ARB_multitexture && bgl::QueryVersion(1, 1)) {
|
||||
m_blendermat = (SYS_GetCommandLineInt(syshandle, "blender_material", 0) != 0);
|
||||
int unitmax=0;
|
||||
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, (GLint*)&unitmax);
|
||||
bgl::max_texture_units = MAXTEX>unitmax?unitmax:MAXTEX;
|
||||
//std::cout << "using(" << bgl::max_texture_units << ") of(" << unitmax << ") texture units." << std::endl;
|
||||
} else {
|
||||
bgl::max_texture_units = 0;
|
||||
}
|
||||
#else
|
||||
m_blendermat=0;
|
||||
#endif//GL_ARB_multitexture
|
||||
// ----------------------------------
|
||||
|
||||
// create the canvas, rasterizer and rendertools
|
||||
m_canvas = new GPG_Canvas(window);
|
||||
if (!m_canvas)
|
||||
@@ -606,7 +628,8 @@ bool GPG_Application::startEngine(void)
|
||||
|
||||
// if (always_use_expand_framing)
|
||||
// sceneconverter->SetAlwaysUseExpandFraming(true);
|
||||
|
||||
if(m_blendermat)
|
||||
m_sceneconverter->SetMaterials(true);
|
||||
|
||||
KX_Scene* startscene = new KX_Scene(m_keyboard,
|
||||
m_mouse,
|
||||
|
||||
@@ -142,5 +142,8 @@ protected:
|
||||
NG_LoopBackNetworkDeviceInterface* m_networkdevice;
|
||||
/** Sound device. */
|
||||
SND_IAudioDevice* m_audiodevice;
|
||||
|
||||
bool m_blendermat;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -194,6 +194,7 @@ void usage(char* program)
|
||||
printf(" show_properties 0 Show debug properties\n");
|
||||
printf(" show_profile 0 Show profiling information\n");
|
||||
printf(" vertexarrays 1 Enable vertex arrays\n");
|
||||
printf(" blender_material 0 Enable material settings\n");
|
||||
printf("\n");
|
||||
printf("example: %s -p 10 10 320 200 -g noaudio c:\\loadtest.blend\n", program);
|
||||
printf("example: %s -g vertexarrays = 0 c:\\loadtest.blend\n", program);
|
||||
|
||||
116
source/gameengine/Ketsji/BL_Material.cpp
Normal file
116
source/gameengine/Ketsji/BL_Material.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
// ------------------------------------
|
||||
#include "BL_Material.h"
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_texture_types.h"
|
||||
#include "DNA_image_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "IMB_imbuf_types.h"
|
||||
#include "IMB_imbuf.h"
|
||||
|
||||
MTex* getImageFromMaterial(Material *mat, int index)
|
||||
{
|
||||
if(!mat) return 0;
|
||||
|
||||
if(!(index >=0 && index <=10) ) return 0;
|
||||
|
||||
MTex *m = mat->mtex[index];
|
||||
return m?m:0;
|
||||
}
|
||||
|
||||
int getNumTexChannels( Material *mat )
|
||||
{
|
||||
int count = -1;
|
||||
if(!mat) return -1;
|
||||
|
||||
for(count =0; (count < 10) && mat->mtex[count] != 0; count++) {}
|
||||
return count;
|
||||
}
|
||||
|
||||
BL_Material::BL_Material()
|
||||
{
|
||||
rgb[0] = 0;
|
||||
rgb[1] = 0;
|
||||
rgb[2] = 0;
|
||||
rgb[3] = 0;
|
||||
IdMode = 0;
|
||||
ras_mode = 0;
|
||||
tile = 0;
|
||||
matname = "NoMaterial";
|
||||
matcolor[0] = 0.5f;
|
||||
matcolor[1] = 0.5f;
|
||||
matcolor[2] = 0.5f;
|
||||
matcolor[3] = 0.5f;
|
||||
speccolor[0] = 1.f;
|
||||
speccolor[1] = 1.f;
|
||||
speccolor[2] = 1.f;
|
||||
transp = 0;
|
||||
hard = 50.f;
|
||||
spec_f = 0.5f;
|
||||
alpha = 1.f;
|
||||
emit = 0.f;
|
||||
mode = 0;
|
||||
material = 0;
|
||||
tface = 0;
|
||||
material_index = 0;
|
||||
amb=0.5f;
|
||||
num_enabled = 0;
|
||||
|
||||
int i;
|
||||
for(i=0; i<4; i++)
|
||||
uv[i] = MT_Point2(0.f,1.f);
|
||||
|
||||
for(i=0; i<MAXTEX; i++) // :(
|
||||
{
|
||||
mapping[i].mapping = 0;
|
||||
mapping[i].offsets[0] = 0.f;
|
||||
mapping[i].offsets[1] = 0.f;
|
||||
mapping[i].offsets[2] = 0.f;
|
||||
mapping[i].scale[0] = 1.f;
|
||||
mapping[i].scale[1] = 1.f;
|
||||
mapping[i].scale[2] = 1.f;
|
||||
mapping[i].projplane[0] = PROJX;
|
||||
mapping[i].projplane[1] = PROJY;
|
||||
mapping[i].projplane[2] = PROJZ;
|
||||
mapping[i].objconame = "";
|
||||
mtexname[i] = "NULL";
|
||||
imageId[i]="NULL";
|
||||
flag[i] = 0;
|
||||
texname[i] = "NULL";
|
||||
tilexrep[i] = 1;
|
||||
tileyrep[i] = 1;
|
||||
color_blend[i] = 1.f;
|
||||
blend_mode[i] = 0;
|
||||
img[i] = 0;
|
||||
cubemap[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void BL_Material::SetConversionRGB(unsigned int *nrgb) {
|
||||
rgb[0]=*nrgb++;
|
||||
rgb[1]=*nrgb++;
|
||||
rgb[2]=*nrgb++;
|
||||
rgb[3]=*nrgb;
|
||||
}
|
||||
|
||||
void BL_Material::GetConversionRGB(unsigned int *nrgb) {
|
||||
*nrgb++ = rgb[0];
|
||||
*nrgb++ = rgb[1];
|
||||
*nrgb++ = rgb[2];
|
||||
*nrgb = rgb[3];
|
||||
}
|
||||
|
||||
void BL_Material::SetConversionUV(MT_Point2 *nuv) {
|
||||
uv[0] = *nuv++;
|
||||
uv[1] = *nuv++;
|
||||
uv[2] = *nuv++;
|
||||
uv[3] = *nuv;
|
||||
}
|
||||
|
||||
void BL_Material::GetConversionUV(MT_Point2 *nuv){
|
||||
*nuv++ = uv[0];
|
||||
*nuv++ = uv[1];
|
||||
*nuv++ = uv[2];
|
||||
*nuv = uv[3];
|
||||
}
|
||||
|
||||
|
||||
156
source/gameengine/Ketsji/BL_Material.h
Normal file
156
source/gameengine/Ketsji/BL_Material.h
Normal file
@@ -0,0 +1,156 @@
|
||||
#ifndef __BL_MATERIAL_H__
|
||||
#define __BL_MATERIAL_H__
|
||||
|
||||
#include "STR_String.h"
|
||||
#include "MT_Point2.h"
|
||||
|
||||
// --
|
||||
struct MTex;
|
||||
struct Material;
|
||||
struct Image;
|
||||
struct TFace;
|
||||
struct MTex;
|
||||
struct Material;
|
||||
struct EnvMap;
|
||||
// --
|
||||
|
||||
/** max units
|
||||
this will default to users available units
|
||||
to build with more available, just increment this value
|
||||
although the more you add the slower the search time will be.
|
||||
we will go for three, which should be enough
|
||||
*/
|
||||
#define MAXTEX 3//match in RAS_TexVert
|
||||
|
||||
// different mapping modes
|
||||
class BL_Mapping
|
||||
{
|
||||
public:
|
||||
int mapping;
|
||||
float scale[3];
|
||||
float offsets[3];
|
||||
int projplane[3];
|
||||
STR_String objconame;
|
||||
};
|
||||
|
||||
// base material struct
|
||||
class BL_Material
|
||||
{
|
||||
private:
|
||||
unsigned int rgb[4];
|
||||
MT_Point2 uv[4];
|
||||
public:
|
||||
// -----------------------------------
|
||||
BL_Material();
|
||||
|
||||
int IdMode;
|
||||
unsigned int ras_mode;
|
||||
|
||||
STR_String texname[MAXTEX];
|
||||
unsigned int flag[MAXTEX];
|
||||
int tile,tilexrep[MAXTEX],tileyrep[MAXTEX];
|
||||
STR_String matname;
|
||||
STR_String mtexname[MAXTEX];
|
||||
|
||||
float matcolor[4];
|
||||
float speccolor[3];
|
||||
short transp, pad;
|
||||
|
||||
float hard, spec_f;
|
||||
float alpha, emit, color_blend[MAXTEX], ref;
|
||||
float amb;
|
||||
|
||||
int blend_mode[MAXTEX];
|
||||
|
||||
int mode;
|
||||
int num_enabled;
|
||||
|
||||
int material_index;
|
||||
|
||||
BL_Mapping mapping[MAXTEX];
|
||||
STR_String imageId[MAXTEX];
|
||||
|
||||
|
||||
Material* material;
|
||||
TFace* tface;
|
||||
Image* img[MAXTEX];
|
||||
EnvMap* cubemap[MAXTEX];
|
||||
|
||||
void SetConversionRGB(unsigned int *rgb);
|
||||
void GetConversionRGB(unsigned int *rgb);
|
||||
|
||||
void SetConversionUV(MT_Point2 *uv);
|
||||
void GetConversionUV(MT_Point2 *uv);
|
||||
|
||||
};
|
||||
|
||||
// BL_Material::IdMode
|
||||
enum BL_IdMode {
|
||||
DEFAULT_BLENDER=-1,
|
||||
TEXFACE,
|
||||
ONETEX,
|
||||
TWOTEX,
|
||||
GREATERTHAN2
|
||||
};
|
||||
|
||||
// BL_Material::blend_mode[index]
|
||||
enum BL_BlendMode
|
||||
{
|
||||
BLEND_MIX=1,
|
||||
BLEND_ADD,
|
||||
BLEND_SUB,
|
||||
BLEND_MUL,
|
||||
BLEND_SCR
|
||||
};
|
||||
|
||||
// -------------------------------------
|
||||
// BL_Material::flag[index]
|
||||
enum BL_flag
|
||||
{
|
||||
MIPMAP=1, // set to use mipmaps
|
||||
CALCALPHA=2, // additive
|
||||
USEALPHA=4, // use actual alpha channel
|
||||
TEXALPHA=8, // use alpha combiner functions
|
||||
TEXNEG=16, // negate blending
|
||||
HASIPO=32
|
||||
};
|
||||
|
||||
// BL_Material::ras_mode
|
||||
enum BL_ras_mode
|
||||
{
|
||||
POLY_VIS=1,
|
||||
COLLIDER=2,
|
||||
ZSORT=4,
|
||||
TRANSP=8,
|
||||
TRIANGLE=16,
|
||||
USE_LIGHT=32,
|
||||
WIRE=64
|
||||
};
|
||||
|
||||
// -------------------------------------
|
||||
// BL_Material::mapping[index]::mapping
|
||||
enum BL_MappingFlag
|
||||
{
|
||||
USEREFL=1,
|
||||
USEENV=2,
|
||||
USEOBJ=4
|
||||
};
|
||||
|
||||
// BL_Material::BL_Mapping::projplane
|
||||
enum BL_MappingProj
|
||||
{
|
||||
PROJN=0,
|
||||
PROJX,
|
||||
PROJY,
|
||||
PROJZ
|
||||
};
|
||||
|
||||
// ------------------------------------
|
||||
//extern void initBL_Material(BL_Material* mat);
|
||||
extern MTex* getImageFromMaterial(Material *mat, int index);
|
||||
extern int getNumTexChannels( Material *mat );
|
||||
// ------------------------------------
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
942
source/gameengine/Ketsji/BL_Shader.cpp
Normal file
942
source/gameengine/Ketsji/BL_Shader.cpp
Normal file
@@ -0,0 +1,942 @@
|
||||
// ------------------------------------
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#endif // WIN32
|
||||
#ifdef __APPLE__
|
||||
#include <OpenGL/gl.h>
|
||||
#include <OpenGL/glu.h>
|
||||
#else
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include "BL_Shader.h"
|
||||
#include "BL_Material.h"
|
||||
|
||||
#include "MT_assert.h"
|
||||
#include "MT_Matrix4x4.h"
|
||||
#include "MT_Matrix3x3.h"
|
||||
#include "KX_PyMath.h"
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "RAS_GLExtensionManager.h"
|
||||
|
||||
//using namespace bgl;
|
||||
#define spit(x) std::cout << x << std::endl;
|
||||
|
||||
const bool BL_Shader::Ok()const
|
||||
{
|
||||
return (mShader !=0 && mOk && mUse);
|
||||
}
|
||||
|
||||
BL_Shader::BL_Shader(int n, PyTypeObject *T)
|
||||
: PyObjectPlus(T),
|
||||
mShader(0),
|
||||
mVert(0),
|
||||
mFrag(0),
|
||||
mPass(1),
|
||||
mOk(0),
|
||||
mUse(0),
|
||||
vertProg(""),
|
||||
fragProg("")
|
||||
{
|
||||
// if !RAS_EXT_support._ARB_shader_objects this class will not be used
|
||||
|
||||
mBlending.src = -1;
|
||||
mBlending.dest = -1;
|
||||
mBlending.const_color[0] = 0.0;
|
||||
mBlending.const_color[1] = 0.0;
|
||||
mBlending.const_color[2] = 0.0;
|
||||
mBlending.const_color[3] = 1.0;
|
||||
|
||||
for (int i=0; i<MAXTEX; i++)
|
||||
{
|
||||
mSampler[i].type = 0;
|
||||
mSampler[i].pass = 0;
|
||||
mSampler[i].unit = -1;
|
||||
mSampler[i].loc = -1;
|
||||
mSampler[i].glTexture =0;
|
||||
}
|
||||
}
|
||||
|
||||
using namespace bgl;
|
||||
|
||||
BL_Shader::~BL_Shader()
|
||||
{
|
||||
#ifdef GL_ARB_shader_objects
|
||||
if( mShader ) {
|
||||
glDeleteObjectARB(mShader);
|
||||
mShader = 0;
|
||||
}
|
||||
if( mFrag ) {
|
||||
glDeleteObjectARB(mFrag);
|
||||
mFrag = 0;
|
||||
}
|
||||
if( mVert ) {
|
||||
glDeleteObjectARB(mVert);
|
||||
mVert = 0;
|
||||
}
|
||||
|
||||
vertProg = 0;
|
||||
fragProg = 0;
|
||||
mOk = 0;
|
||||
|
||||
glUseProgramObjectARB(0);
|
||||
#endif//GL_ARB_shader_objects
|
||||
}
|
||||
|
||||
|
||||
bool BL_Shader::LinkProgram()
|
||||
{
|
||||
#ifdef GL_ARB_shader_objects
|
||||
int numchars=0;
|
||||
char* log=0;
|
||||
int vertlen = 0, fraglen=0, proglen=0;
|
||||
|
||||
if(!vertProg || !fragProg){
|
||||
spit("Invalid GLSL sources");
|
||||
return false;
|
||||
}
|
||||
|
||||
// create our objects
|
||||
unsigned int tmpVert = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
|
||||
unsigned int tmpFrag = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
|
||||
unsigned int tmpProg = glCreateProgramObjectARB();
|
||||
|
||||
if(!tmpVert || !tmpFrag || !tmpProg){
|
||||
glDeleteObjectARB(tmpVert);
|
||||
glDeleteObjectARB(tmpFrag);
|
||||
glDeleteObjectARB(tmpProg);
|
||||
return false;
|
||||
}
|
||||
// set/compile vertex shader
|
||||
glShaderSourceARB(tmpVert, 1, (const char**)&vertProg, 0);
|
||||
glCompileShaderARB(tmpVert);
|
||||
glGetObjectParameterivARB(tmpVert, GL_OBJECT_INFO_LOG_LENGTH_ARB, &vertlen);
|
||||
|
||||
if( vertlen > 0 && !PrintInfo(vertlen,tmpVert, "Vertex Shader") ){
|
||||
spit("Vertex shader failed");
|
||||
glDeleteObjectARB(tmpVert);
|
||||
glDeleteObjectARB(tmpFrag);
|
||||
glDeleteObjectARB(tmpProg);
|
||||
mOk = 0;
|
||||
return false;
|
||||
}
|
||||
// set/compile fragment shader
|
||||
glShaderSourceARB(tmpFrag, 1,(const char**)&fragProg, 0);
|
||||
glCompileShaderARB(tmpFrag);
|
||||
glGetObjectParameterivARB(tmpFrag, GL_OBJECT_INFO_LOG_LENGTH_ARB, &fraglen);
|
||||
if(fraglen >0 && !PrintInfo(fraglen,tmpFrag, "Fragment Shader") ){
|
||||
spit("Fragment shader failed");
|
||||
glDeleteObjectARB(tmpVert);
|
||||
glDeleteObjectARB(tmpFrag);
|
||||
glDeleteObjectARB(tmpProg);
|
||||
mOk = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// set compiled vert/frag shader & link
|
||||
glAttachObjectARB(tmpProg, tmpVert);
|
||||
glAttachObjectARB(tmpProg, tmpFrag);
|
||||
glLinkProgramARB(tmpProg);
|
||||
|
||||
glGetObjectParameterivARB(tmpProg, GL_OBJECT_INFO_LOG_LENGTH_ARB, &proglen);
|
||||
if(proglen > 0){
|
||||
PrintInfo(proglen,tmpProg, "GLSL Shader");
|
||||
}
|
||||
else{
|
||||
spit("Program failed");
|
||||
glDeleteObjectARB(tmpVert);
|
||||
glDeleteObjectARB(tmpFrag);
|
||||
glDeleteObjectARB(tmpProg);
|
||||
mOk = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// set
|
||||
mShader = tmpProg;
|
||||
mVert = tmpVert;
|
||||
mFrag = tmpFrag;
|
||||
mOk = 1;
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif//GL_ARB_shader_objects
|
||||
}
|
||||
|
||||
bool BL_Shader::PrintInfo(int len, unsigned int handle, const char *type)
|
||||
{
|
||||
#ifdef GL_ARB_shader_objects
|
||||
int numchars=0;
|
||||
char *log = (char*)MEM_mallocN(sizeof(char)*len, "print_log");
|
||||
if(!log) {
|
||||
spit("BL_Shader::PrintInfo() MEM_mallocN failed");
|
||||
return false;
|
||||
}
|
||||
glGetInfoLogARB(handle, len, &numchars, log);
|
||||
|
||||
if(numchars >0){
|
||||
spit(type);
|
||||
spit(log);
|
||||
MEM_freeN(log);
|
||||
log=0;
|
||||
return false;
|
||||
}
|
||||
MEM_freeN(log);
|
||||
log=0;
|
||||
return true;
|
||||
#else
|
||||
return false
|
||||
#endif//GL_ARB_shader_objects
|
||||
}
|
||||
|
||||
|
||||
char *BL_Shader::GetVertPtr()
|
||||
{
|
||||
return vertProg?vertProg:0;
|
||||
}
|
||||
|
||||
char *BL_Shader::GetFragPtr()
|
||||
{
|
||||
return fragProg?fragProg:0;
|
||||
}
|
||||
|
||||
void BL_Shader::SetVertPtr( char *vert )
|
||||
{
|
||||
vertProg = vert;
|
||||
}
|
||||
|
||||
void BL_Shader::SetFragPtr( char *frag )
|
||||
{
|
||||
fragProg = frag;
|
||||
}
|
||||
|
||||
unsigned int BL_Shader::GetProg()
|
||||
{
|
||||
return mShader;
|
||||
}
|
||||
|
||||
unsigned int BL_Shader::GetVertexShader()
|
||||
{
|
||||
return mVert;
|
||||
}
|
||||
|
||||
unsigned int BL_Shader::GetFragmentShader()
|
||||
{
|
||||
return mFrag;
|
||||
}
|
||||
|
||||
const uSampler* BL_Shader::getSampler(int i)
|
||||
{
|
||||
MT_assert(i<=MAXTEX);
|
||||
return &mSampler[i];
|
||||
}
|
||||
|
||||
const uBlending *BL_Shader::getBlending( int pass )
|
||||
{
|
||||
return &mBlending;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void BL_Shader::InitializeSampler(
|
||||
int type,
|
||||
int unit,
|
||||
int pass,
|
||||
unsigned int texture)
|
||||
{
|
||||
MT_assert(unit<=MAXTEX);
|
||||
mSampler[unit].glTexture = texture;
|
||||
mSampler[unit].loc =-1;
|
||||
mSampler[unit].pass=0;
|
||||
mSampler[unit].type=type;
|
||||
mSampler[unit].unit=unit;
|
||||
}
|
||||
|
||||
PyObject* BL_Shader::_getattr(const STR_String& attr)
|
||||
{
|
||||
_getattr_up(PyObjectPlus);
|
||||
}
|
||||
|
||||
|
||||
PyMethodDef BL_Shader::Methods[] =
|
||||
{
|
||||
// creation
|
||||
KX_PYMETHODTABLE( BL_Shader, setSource ),
|
||||
KX_PYMETHODTABLE( BL_Shader, delSource ),
|
||||
KX_PYMETHODTABLE( BL_Shader, getVertexProg ),
|
||||
KX_PYMETHODTABLE( BL_Shader, getFragmentProg ),
|
||||
KX_PYMETHODTABLE( BL_Shader, setNumberOfPasses ),
|
||||
KX_PYMETHODTABLE( BL_Shader, validate),
|
||||
/// access functions
|
||||
KX_PYMETHODTABLE( BL_Shader, isValid),
|
||||
KX_PYMETHODTABLE( BL_Shader, setUniform1f ),
|
||||
KX_PYMETHODTABLE( BL_Shader, setUniform2f ),
|
||||
KX_PYMETHODTABLE( BL_Shader, setUniform3f ),
|
||||
KX_PYMETHODTABLE( BL_Shader, setUniform4f ),
|
||||
KX_PYMETHODTABLE( BL_Shader, setUniform1i ),
|
||||
KX_PYMETHODTABLE( BL_Shader, setUniform2i ),
|
||||
KX_PYMETHODTABLE( BL_Shader, setUniform3i ),
|
||||
KX_PYMETHODTABLE( BL_Shader, setUniform4i ),
|
||||
|
||||
KX_PYMETHODTABLE( BL_Shader, setUniformfv ),
|
||||
KX_PYMETHODTABLE( BL_Shader, setUniformiv ),
|
||||
|
||||
KX_PYMETHODTABLE( BL_Shader, setSampler ),
|
||||
KX_PYMETHODTABLE( BL_Shader, setUniformMatrix4 ),
|
||||
KX_PYMETHODTABLE( BL_Shader, setUniformMatrix3 ),
|
||||
// KX_PYMETHODTABLE( BL_Shader, setBlending ),
|
||||
|
||||
{NULL,NULL} //Sentinel
|
||||
};
|
||||
|
||||
|
||||
PyTypeObject BL_Shader::Type = {
|
||||
PyObject_HEAD_INIT(&PyType_Type)
|
||||
0,
|
||||
"BL_Shader",
|
||||
sizeof(BL_Shader),
|
||||
0,
|
||||
PyDestructor,
|
||||
0,
|
||||
__getattr,
|
||||
__setattr,
|
||||
0,
|
||||
__repr,
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
PyParentObject BL_Shader::Parents[] = {
|
||||
&PyObjectPlus::Type,
|
||||
&BL_Shader::Type,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
KX_PYMETHODDEF_DOC( BL_Shader, setSource," setSource(vertexProgram, fragmentProgram)" )
|
||||
{
|
||||
#ifdef GL_ARB_shader_objects
|
||||
if(mShader !=0 && mOk )
|
||||
{
|
||||
// already set...
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
char *v,*f;
|
||||
int apply=0;
|
||||
if( PyArg_ParseTuple(args, "ssi", &v, &f, &apply) )
|
||||
{
|
||||
vertProg = v;
|
||||
fragProg = f;
|
||||
if( LinkProgram() ) {
|
||||
glUseProgramObjectARB( mShader );
|
||||
mUse = apply!=0;
|
||||
Py_Return;
|
||||
}
|
||||
vertProg = 0;
|
||||
fragProg = 0;
|
||||
mUse = 0;
|
||||
glUseProgramObjectARB( 0 );
|
||||
PyErr_Format(PyExc_ValueError, "GLSL Error");
|
||||
}
|
||||
return NULL;
|
||||
#else
|
||||
Py_Return;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
KX_PYMETHODDEF_DOC( BL_Shader, delSource, "delSource( )" )
|
||||
{
|
||||
#ifdef GL_ARB_shader_objects
|
||||
glDeleteObjectARB(mShader);
|
||||
glDeleteObjectARB(mFrag);
|
||||
glDeleteObjectARB(mVert);
|
||||
mShader = 0;
|
||||
mFrag = 0;
|
||||
mVert = 0;
|
||||
vertProg = 0;
|
||||
fragProg = 0;
|
||||
mOk = 0;
|
||||
mUse = 0;
|
||||
glUseProgramObjectARB(0);
|
||||
#endif
|
||||
Py_Return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
KX_PYMETHODDEF_DOC( BL_Shader, isValid, "isValid()" )
|
||||
{
|
||||
return PyInt_FromLong( ( mShader !=0 && mOk ) );
|
||||
}
|
||||
|
||||
KX_PYMETHODDEF_DOC( BL_Shader, getVertexProg ,"getVertexProg( )" )
|
||||
{
|
||||
return PyString_FromString(vertProg?vertProg:"");
|
||||
}
|
||||
|
||||
KX_PYMETHODDEF_DOC( BL_Shader, getFragmentProg ,"getFragmentProg( )" )
|
||||
{
|
||||
return PyString_FromString(fragProg?fragProg:"");
|
||||
}
|
||||
|
||||
|
||||
KX_PYMETHODDEF_DOC( BL_Shader, validate, "validate()")
|
||||
{
|
||||
#ifdef GL_ARB_shader_objects
|
||||
if(mShader==0)
|
||||
{
|
||||
PyErr_Format(PyExc_TypeError, "invalid shader object");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int stat = 0;
|
||||
glValidateProgramARB(mShader);
|
||||
glGetObjectParameterivARB(mShader, GL_OBJECT_VALIDATE_STATUS_ARB, &stat);
|
||||
|
||||
return PyInt_FromLong((stat!=0));
|
||||
#else
|
||||
Py_Return;
|
||||
#endif//GL_ARB_shader_objects
|
||||
}
|
||||
|
||||
|
||||
KX_PYMETHODDEF_DOC( BL_Shader, setSampler, "setSampler(name, index)" )
|
||||
{
|
||||
#ifdef GL_ARB_shader_objects
|
||||
char *uniform="";
|
||||
int index=-1;
|
||||
if(PyArg_ParseTuple(args, "si", &uniform, &index))
|
||||
{
|
||||
if(mShader==0)
|
||||
{
|
||||
PyErr_Format(PyExc_ValueError, "invalid shader object");
|
||||
return NULL;
|
||||
}
|
||||
int loc= glGetUniformLocationARB(mShader, uniform);
|
||||
if( loc==-1 )
|
||||
{
|
||||
spit("Invalid uniform value: " << uniform << ".");
|
||||
Py_Return;
|
||||
}else
|
||||
{
|
||||
if(index <= MAXTEX)
|
||||
{
|
||||
mSampler[index].loc = loc;
|
||||
}else
|
||||
{
|
||||
spit("Invalid texture sample index: " << index);
|
||||
}
|
||||
Py_Return;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
#else
|
||||
Py_Return;
|
||||
#endif//GL_ARB_shader_objects
|
||||
}
|
||||
|
||||
KX_PYMETHODDEF_DOC( BL_Shader, setNumberOfPasses, "setNumberOfPasses( max-pass )" )
|
||||
{
|
||||
int pass = 1;
|
||||
if(!PyArg_ParseTuple(args, "i", &pass))
|
||||
return NULL;
|
||||
|
||||
mPass = pass;
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
/// access functions
|
||||
KX_PYMETHODDEF_DOC( BL_Shader, setUniform1f, "setUniform1f(name, fx)" )
|
||||
{
|
||||
#ifdef GL_ARB_shader_objects
|
||||
char *uniform="";
|
||||
float value=0;
|
||||
if(PyArg_ParseTuple(args, "sf", &uniform, &value ))
|
||||
{
|
||||
if( mShader==0 )
|
||||
{
|
||||
PyErr_Format(PyExc_ValueError, "invalid shader object");
|
||||
return NULL;
|
||||
}
|
||||
int loc= glGetUniformLocationARB(mShader, uniform);
|
||||
if( loc==-1 )
|
||||
{
|
||||
spit("Invalid uniform value: " << uniform << ".");
|
||||
Py_Return;
|
||||
}else
|
||||
{
|
||||
glUseProgramObjectARB( mShader );
|
||||
glUniform1fARB( loc, value );
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
}
|
||||
return NULL;
|
||||
#else
|
||||
Py_Return;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
KX_PYMETHODDEF_DOC( BL_Shader, setUniform2f , "setUniform2f(name, fx, fy)")
|
||||
{
|
||||
#ifdef GL_ARB_shader_objects
|
||||
char *uniform="";
|
||||
float array[2]={ 0,0 };
|
||||
if(PyArg_ParseTuple(args, "sff", &uniform, &array[0],&array[1] ))
|
||||
{
|
||||
if( mShader==0 )
|
||||
{
|
||||
PyErr_Format(PyExc_ValueError, "invalid shader object");
|
||||
return NULL;
|
||||
}
|
||||
int loc= glGetUniformLocationARB(mShader , uniform);
|
||||
if( loc==-1 )
|
||||
{
|
||||
spit("Invalid uniform value: " << uniform << ".");
|
||||
Py_Return;
|
||||
}else
|
||||
{
|
||||
glUseProgramObjectARB( mShader );
|
||||
glUniform2fARB(loc, array[0],array[1] );
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
}
|
||||
return NULL;
|
||||
#else
|
||||
Py_Return;
|
||||
#endif//GL_ARB_shader_objects
|
||||
}
|
||||
|
||||
|
||||
KX_PYMETHODDEF_DOC( BL_Shader, setUniform3f, "setUniform3f(name, fx,fy,fz) ")
|
||||
{
|
||||
#ifdef GL_ARB_shader_objects
|
||||
char *uniform="";
|
||||
float array[3]={0,0,0};
|
||||
if(PyArg_ParseTuple(args, "sfff", &uniform, &array[0],&array[1],&array[2]))
|
||||
{
|
||||
if(mShader==0)
|
||||
{
|
||||
PyErr_Format(PyExc_ValueError, "invalid shader object");
|
||||
return NULL;
|
||||
}
|
||||
int loc= glGetUniformLocationARB(mShader , uniform);
|
||||
if( loc==-1 )
|
||||
{
|
||||
spit("Invalid uniform value: " << uniform << ".");
|
||||
Py_Return;
|
||||
}else
|
||||
{
|
||||
glUseProgramObjectARB(mShader);
|
||||
glUniform3fARB(loc, array[0],array[1],array[2]);
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
}
|
||||
return NULL;
|
||||
#else
|
||||
Py_Return;
|
||||
#endif//GL_ARB_shader_objects
|
||||
}
|
||||
|
||||
|
||||
KX_PYMETHODDEF_DOC( BL_Shader, setUniform4f, "setUniform4f(name, fx,fy,fz, fw) ")
|
||||
{
|
||||
#ifdef GL_ARB_shader_objects
|
||||
char *uniform="";
|
||||
float array[4]={0,0,0,0};
|
||||
if(PyArg_ParseTuple(args, "sffff", &uniform, &array[0],&array[1],&array[2], &array[3]))
|
||||
{
|
||||
if(mShader==0)
|
||||
{
|
||||
PyErr_Format(PyExc_ValueError, "invalid shader object");
|
||||
return NULL;
|
||||
}
|
||||
int loc= glGetUniformLocationARB(mShader , uniform);
|
||||
if( loc==-1 )
|
||||
{
|
||||
spit("Invalid uniform value: " << uniform << ".");
|
||||
Py_Return;
|
||||
}else
|
||||
{
|
||||
glUseProgramObjectARB(mShader);
|
||||
glUniform4fARB(loc, array[0],array[1],array[2], array[3]);
|
||||
Py_Return;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
#else
|
||||
Py_Return;
|
||||
#endif//GL_ARB_shader_objects
|
||||
}
|
||||
|
||||
|
||||
KX_PYMETHODDEF_DOC( BL_Shader, setUniform1i, "setUniform1i(name, ix)" )
|
||||
{
|
||||
#ifdef GL_ARB_shader_objects
|
||||
char *uniform="";
|
||||
int value=0;
|
||||
if(PyArg_ParseTuple(args, "si", &uniform, &value ))
|
||||
{
|
||||
if( mShader==0 )
|
||||
{
|
||||
PyErr_Format(PyExc_ValueError, "invalid shader object");
|
||||
return NULL;
|
||||
}
|
||||
int loc= glGetUniformLocationARB(mShader, uniform);
|
||||
if( loc==-1 )
|
||||
{
|
||||
spit("Invalid uniform value: " << uniform << ".");
|
||||
Py_Return;
|
||||
}else
|
||||
{
|
||||
glUseProgramObjectARB( mShader );
|
||||
glUniform1iARB( loc, value );
|
||||
Py_Return;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
#else
|
||||
Py_Return;
|
||||
#endif//GL_ARB_shader_objects
|
||||
}
|
||||
|
||||
|
||||
KX_PYMETHODDEF_DOC( BL_Shader, setUniform2i , "setUniform2i(name, ix, iy)")
|
||||
{
|
||||
#ifdef GL_ARB_shader_objects
|
||||
char *uniform="";
|
||||
int array[2]={ 0,0 };
|
||||
if(PyArg_ParseTuple(args, "sii", &uniform, &array[0],&array[1] ))
|
||||
{
|
||||
if( mShader==0 )
|
||||
{
|
||||
PyErr_Format(PyExc_ValueError, "invalid shader object");
|
||||
return NULL;
|
||||
}
|
||||
int loc= glGetUniformLocationARB(mShader , uniform);
|
||||
if( loc==-1 )
|
||||
{
|
||||
spit("Invalid uniform value: " << uniform << ".");
|
||||
Py_Return;
|
||||
}else
|
||||
{
|
||||
glUseProgramObjectARB( mShader );
|
||||
glUniform2iARB(loc, array[0],array[1] );
|
||||
Py_Return;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
#else
|
||||
Py_Return;
|
||||
#endif//GL_ARB_shader_objects
|
||||
}
|
||||
|
||||
|
||||
KX_PYMETHODDEF_DOC( BL_Shader, setUniform3i, "setUniform3i(name, ix,iy,iz) ")
|
||||
{
|
||||
#ifdef GL_ARB_shader_objects
|
||||
char *uniform="";
|
||||
int array[3]={0,0,0};
|
||||
if(PyArg_ParseTuple(args, "siii", &uniform, &array[0],&array[1],&array[2]))
|
||||
{
|
||||
if(mShader==0)
|
||||
{
|
||||
PyErr_Format(PyExc_ValueError, "invalid shader object");
|
||||
return NULL;
|
||||
}
|
||||
int loc= glGetUniformLocationARB(mShader , uniform);
|
||||
if( loc==-1 )
|
||||
{
|
||||
spit("Invalid uniform value: " << uniform << ".");
|
||||
Py_Return;
|
||||
}else
|
||||
{
|
||||
glUseProgramObjectARB(mShader);
|
||||
glUniform3iARB(loc, array[0],array[1],array[2]);
|
||||
Py_Return;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
#else
|
||||
Py_Return;
|
||||
#endif//GL_ARB_shader_objects
|
||||
}
|
||||
|
||||
KX_PYMETHODDEF_DOC( BL_Shader, setUniform4i, "setUniform4i(name, ix,iy,iz, iw) ")
|
||||
{
|
||||
#ifdef GL_ARB_shader_objects
|
||||
char *uniform="";
|
||||
int array[4]={0,0,0, 0};
|
||||
if(PyArg_ParseTuple(args, "siiii", &uniform, &array[0],&array[1],&array[2], &array[3] ))
|
||||
{
|
||||
if(mShader==0)
|
||||
{
|
||||
PyErr_Format(PyExc_ValueError, "invalid shader object");
|
||||
return NULL;
|
||||
}
|
||||
int loc= glGetUniformLocationARB(mShader , uniform);
|
||||
if( loc==-1 )
|
||||
{
|
||||
spit("Invalid uniform value: " << uniform << ".");
|
||||
Py_Return;
|
||||
}else
|
||||
{
|
||||
glUseProgramObjectARB(mShader);
|
||||
glUniform4iARB(loc, array[0],array[1],array[2], array[3]);
|
||||
Py_Return;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
#else
|
||||
Py_Return;
|
||||
#endif//GL_ARB_shader_objects
|
||||
}
|
||||
|
||||
KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv , "setUniformfv( float (list2 or list3 or list4) )")
|
||||
{
|
||||
#ifdef GL_ARB_shader_objects
|
||||
char*uniform = "";
|
||||
PyObject *listPtr =0;
|
||||
float array_data[4] = {0.f,0.f,0.f,0.f};
|
||||
|
||||
if(PyArg_ParseTuple(args, "sO", &uniform, &listPtr))
|
||||
{
|
||||
if(mShader==0)
|
||||
{
|
||||
PyErr_Format(PyExc_ValueError, "invalid shader object");
|
||||
return NULL;
|
||||
}
|
||||
int loc= glGetUniformLocationARB(mShader , uniform);
|
||||
if( loc==-1 )
|
||||
{
|
||||
spit("Invalid uniform value: " << uniform << ".");
|
||||
Py_Return;
|
||||
}else
|
||||
{
|
||||
if(PySequence_Check(listPtr))
|
||||
{
|
||||
unsigned int list_size = PySequence_Size(listPtr);
|
||||
|
||||
for(unsigned int i=0; (i<list_size && i<=4); i++)
|
||||
{
|
||||
PyObject *item = PySequence_GetItem(listPtr, i);
|
||||
array_data[i] = (float)PyFloat_AsDouble(item);
|
||||
Py_DECREF(item);
|
||||
}
|
||||
switch(list_size)
|
||||
{
|
||||
case 2:
|
||||
{
|
||||
glUseProgramObjectARB(mShader);
|
||||
glUniform2fARB(loc, array_data[0],array_data[1]);
|
||||
Py_Return;
|
||||
} break;
|
||||
case 3:
|
||||
{
|
||||
glUseProgramObjectARB(mShader);
|
||||
glUniform3fARB(loc, array_data[0],array_data[1], array_data[2]);
|
||||
Py_Return;
|
||||
}break;
|
||||
case 4:
|
||||
{
|
||||
glUseProgramObjectARB(mShader);
|
||||
glUniform4fARB(loc, array_data[0],array_data[1], array_data[2], array_data[3]);
|
||||
Py_Return;
|
||||
}break;
|
||||
default:
|
||||
{
|
||||
PyErr_Format(PyExc_TypeError, "Invalid list size");
|
||||
return NULL;
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
#else
|
||||
Py_Return;
|
||||
#endif//GL_ARB_shader_objects
|
||||
|
||||
}
|
||||
|
||||
KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( int (list2 or list3 or list4) )")
|
||||
{
|
||||
#ifdef GL_ARB_shader_objects
|
||||
char*uniform = "";
|
||||
PyObject *listPtr =0;
|
||||
int array_data[4] = {0,0,0,0};
|
||||
|
||||
if(PyArg_ParseTuple(args, "sO", &uniform, &listPtr))
|
||||
{
|
||||
if(mShader==0)
|
||||
{
|
||||
PyErr_Format(PyExc_ValueError, "invalid shader object");
|
||||
return NULL;
|
||||
}
|
||||
int loc= glGetUniformLocationARB(mShader , uniform);
|
||||
if( loc==-1 )
|
||||
{
|
||||
spit("Invalid uniform value: " << uniform << ".");
|
||||
Py_Return;
|
||||
}else
|
||||
{
|
||||
if(PySequence_Check(listPtr))
|
||||
{
|
||||
unsigned int list_size = PySequence_Size(listPtr);
|
||||
|
||||
for(unsigned int i=0; (i<list_size && i<=4); i++)
|
||||
{
|
||||
PyObject *item = PySequence_GetItem(listPtr, i);
|
||||
array_data[i] = PyInt_AsLong(item);
|
||||
Py_DECREF(item);
|
||||
}
|
||||
switch(list_size)
|
||||
{
|
||||
case 2:
|
||||
{
|
||||
glUseProgramObjectARB(mShader);
|
||||
glUniform2iARB(loc, array_data[0],array_data[1]);
|
||||
Py_Return;
|
||||
} break;
|
||||
case 3:
|
||||
{
|
||||
glUseProgramObjectARB(mShader);
|
||||
glUniform3iARB(loc, array_data[0],array_data[1], array_data[2]);
|
||||
Py_Return;
|
||||
}break;
|
||||
case 4:
|
||||
{
|
||||
glUseProgramObjectARB(mShader);
|
||||
glUniform4iARB(loc, array_data[0],array_data[1], array_data[2], array_data[3]);
|
||||
Py_Return;
|
||||
}break;
|
||||
default:
|
||||
{
|
||||
PyErr_Format(PyExc_TypeError, "Invalid list size");
|
||||
return NULL;
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
#else
|
||||
Py_Return;
|
||||
#endif//GL_ARB_shader_objects
|
||||
}
|
||||
|
||||
|
||||
KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix4,
|
||||
"setUniformMatrix4(uniform-name, mat-4x4, transpose(row-major=true, col-major=false)" )
|
||||
{
|
||||
#ifdef GL_ARB_shader_objects
|
||||
float matr[16] = {
|
||||
1,0,0,0,
|
||||
0,1,0,0,
|
||||
0,0,1,0,
|
||||
0,0,0,1
|
||||
};
|
||||
|
||||
char *uniform="";
|
||||
PyObject *matrix=0;
|
||||
int transp=1; // MT_ is row major so transpose by default....
|
||||
if(PyArg_ParseTuple(args, "sO|i",&uniform, &matrix,&transp))
|
||||
{
|
||||
if(mShader==0)
|
||||
{
|
||||
PyErr_Format(PyExc_ValueError, "invalid shader object");
|
||||
return NULL;
|
||||
}
|
||||
int loc= glGetUniformLocationARB(mShader , uniform);
|
||||
if( loc==-1 )
|
||||
{
|
||||
spit("Invalid uniform value: " << uniform << ".");
|
||||
Py_Return;
|
||||
}else
|
||||
{
|
||||
if (PyObject_IsMT_Matrix(matrix, 4))
|
||||
{
|
||||
MT_Matrix4x4 mat;
|
||||
if (PyMatTo(matrix, mat))
|
||||
{
|
||||
mat.getValue(matr);
|
||||
glUseProgramObjectARB(mShader);
|
||||
glUniformMatrix4fvARB(loc, 1, (transp!=0)?GL_TRUE:GL_FALSE, matr);
|
||||
Py_Return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
#else
|
||||
Py_Return;
|
||||
#endif//GL_ARB_shader_objects
|
||||
}
|
||||
|
||||
|
||||
KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix3,
|
||||
"setUniformMatrix3(uniform-name, list[3x3], transpose(row-major=true, col-major=false)" )
|
||||
{
|
||||
#ifdef GL_ARB_shader_objects
|
||||
float matr[9] = {
|
||||
1,0,0,
|
||||
0,1,0,
|
||||
0,0,1,
|
||||
};
|
||||
|
||||
char *uniform="";
|
||||
PyObject *matrix=0;
|
||||
int transp=1; // MT_ is row major so transpose by default....
|
||||
if(PyArg_ParseTuple(args, "sO|i",&uniform, &matrix,&transp))
|
||||
{
|
||||
if(mShader==0)
|
||||
{
|
||||
PyErr_Format(PyExc_ValueError, "invalid shader object");
|
||||
return NULL;
|
||||
}
|
||||
int loc= glGetUniformLocationARB(mShader , uniform);
|
||||
if( loc==-1 )
|
||||
{
|
||||
spit("Invalid uniform value: " << uniform << ".");
|
||||
Py_Return;
|
||||
}else
|
||||
{
|
||||
if (PyObject_IsMT_Matrix(matrix, 3))
|
||||
{
|
||||
MT_Matrix3x3 mat;
|
||||
if (PyMatTo(matrix, mat))
|
||||
{
|
||||
mat.getValue(matr);
|
||||
glUseProgramObjectARB(mShader);
|
||||
glUniformMatrix3fvARB(loc, 1, (transp!=0)?GL_TRUE:GL_FALSE, matr);
|
||||
Py_Return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
#else
|
||||
Py_Return;
|
||||
#endif//GL_ARB_shader_objects
|
||||
}
|
||||
|
||||
|
||||
KX_PYMETHODDEF_DOC( BL_Shader, setBlending, "setBlending(src, dest)" )
|
||||
{
|
||||
int src, dest;
|
||||
if(PyArg_ParseTuple(args, "ii", &src, &dest))
|
||||
{
|
||||
mBlending.src = src;
|
||||
mBlending.dest = dest;
|
||||
Py_Return;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
117
source/gameengine/Ketsji/BL_Shader.h
Normal file
117
source/gameengine/Ketsji/BL_Shader.h
Normal file
@@ -0,0 +1,117 @@
|
||||
#ifndef __BL_SHADER_H__
|
||||
#define __BL_SHADER_H__
|
||||
|
||||
#include "PyObjectPlus.h"
|
||||
#include "BL_Material.h"
|
||||
|
||||
// -----------------------------------
|
||||
// user state management
|
||||
typedef struct uSampler
|
||||
{
|
||||
unsigned int type;
|
||||
int pass;
|
||||
int unit;
|
||||
int loc;
|
||||
unsigned int glTexture;
|
||||
}uSampler;
|
||||
|
||||
#define SAMP_2D 1
|
||||
#define SAMP_CUBE 2
|
||||
|
||||
|
||||
// -----------------------------------
|
||||
typedef struct uBlending
|
||||
{
|
||||
unsigned int pass;
|
||||
int src; // GL_ blend func values
|
||||
int dest;
|
||||
float const_color[4];
|
||||
}uBlending;
|
||||
// -----------------------------------
|
||||
|
||||
// ----------------
|
||||
class BL_Shader : public PyObjectPlus
|
||||
{
|
||||
Py_Header;
|
||||
private:
|
||||
unsigned int mShader,
|
||||
mVert,
|
||||
mFrag;
|
||||
int mPass;
|
||||
bool mOk;
|
||||
bool mUse;
|
||||
uSampler mSampler[MAXTEX];
|
||||
uBlending mBlending;
|
||||
char* vertProg;
|
||||
char* fragProg;
|
||||
bool LinkProgram();
|
||||
bool PrintInfo(int len, unsigned int handle, const char *type);
|
||||
|
||||
public:
|
||||
BL_Shader(int n, PyTypeObject *T=&Type);
|
||||
virtual ~BL_Shader();
|
||||
|
||||
char* GetVertPtr();
|
||||
char* GetFragPtr();
|
||||
void SetVertPtr( char *vert );
|
||||
void SetFragPtr( char *frag );
|
||||
|
||||
// ---
|
||||
int getNumPass() {return mPass;}
|
||||
bool use() {return mUse;}
|
||||
|
||||
// ---
|
||||
// access
|
||||
const uSampler* getSampler(int i);
|
||||
const uBlending* getBlending( int pass );
|
||||
const bool Ok()const;
|
||||
|
||||
unsigned int GetProg();
|
||||
unsigned int GetVertexShader();
|
||||
unsigned int GetFragmentShader();
|
||||
|
||||
void InitializeSampler(
|
||||
int type,
|
||||
int unit,
|
||||
int pass,
|
||||
unsigned int texture
|
||||
);
|
||||
|
||||
// -----------------------------------
|
||||
// python interface
|
||||
virtual PyObject* _getattr(const STR_String& attr);
|
||||
|
||||
KX_PYMETHOD_DOC( BL_Shader, setSource );
|
||||
KX_PYMETHOD_DOC( BL_Shader, delSource );
|
||||
KX_PYMETHOD_DOC( BL_Shader, getVertexProg );
|
||||
KX_PYMETHOD_DOC( BL_Shader, getFragmentProg );
|
||||
KX_PYMETHOD_DOC( BL_Shader, setNumberOfPasses );
|
||||
|
||||
// -----------------------------------
|
||||
KX_PYMETHOD_DOC( BL_Shader, isValid);
|
||||
KX_PYMETHOD_DOC( BL_Shader, validate);
|
||||
KX_PYMETHOD_DOC( BL_Shader, setUniform4f );
|
||||
KX_PYMETHOD_DOC( BL_Shader, setUniform3f );
|
||||
KX_PYMETHOD_DOC( BL_Shader, setUniform2f );
|
||||
KX_PYMETHOD_DOC( BL_Shader, setUniform1f );
|
||||
KX_PYMETHOD_DOC( BL_Shader, setUniform4i );
|
||||
KX_PYMETHOD_DOC( BL_Shader, setUniform3i );
|
||||
KX_PYMETHOD_DOC( BL_Shader, setUniform2i );
|
||||
KX_PYMETHOD_DOC( BL_Shader, setUniform1i );
|
||||
|
||||
KX_PYMETHOD_DOC( BL_Shader, setUniformfv );
|
||||
KX_PYMETHOD_DOC( BL_Shader, setUniformiv );
|
||||
|
||||
KX_PYMETHOD_DOC( BL_Shader, setUniformMatrix4 );
|
||||
KX_PYMETHOD_DOC( BL_Shader, setUniformMatrix3 );
|
||||
|
||||
// these come from within the material buttons
|
||||
// sampler2d/samplerCube work
|
||||
KX_PYMETHOD_DOC( BL_Shader, setSampler);
|
||||
// user blending funcs
|
||||
KX_PYMETHOD_DOC( BL_Shader, setBlending );
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif//__BL_SHADER_H__
|
||||
389
source/gameengine/Ketsji/BL_Texture.cpp
Normal file
389
source/gameengine/Ketsji/BL_Texture.cpp
Normal file
@@ -0,0 +1,389 @@
|
||||
// ------------------------------------
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#endif // WIN32
|
||||
#ifdef __APPLE__
|
||||
#include <OpenGL/gl.h>
|
||||
#include <OpenGL/glu.h>
|
||||
#else
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "BL_Material.h"
|
||||
#include "BL_Texture.h"
|
||||
#include "MT_assert.h"
|
||||
|
||||
#include "DNA_texture_types.h"
|
||||
#include "DNA_image_types.h"
|
||||
#include "IMB_imbuf_types.h"
|
||||
#include "BKE_image.h"
|
||||
//#include "IMB_imbuf.h"
|
||||
#include "BLI_blenlib.h"
|
||||
|
||||
#include "RAS_GLExtensionManager.h"
|
||||
using namespace bgl;
|
||||
|
||||
#define spit(x) std::cout << x << std::endl;
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
|
||||
|
||||
extern "C" {
|
||||
// envmaps
|
||||
#include "IMB_imbuf.h"
|
||||
void my_envmap_split_ima(EnvMap *env);
|
||||
void my_free_envmapdata(EnvMap *env);
|
||||
}
|
||||
|
||||
// (n&(n-1)) zeros the least significant bit of n
|
||||
static int is_pow2(int num) {
|
||||
return ((num)&(num-1))==0;
|
||||
}
|
||||
static int smaller_pow2(int num) {
|
||||
while (!is_pow2(num))
|
||||
num= num&(num-1);
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
|
||||
BL_Texture::BL_Texture()
|
||||
: mTexture(0),
|
||||
mError(0),
|
||||
mOk(0),
|
||||
mNeedsDeleted(0),
|
||||
mType(0),
|
||||
mName("")
|
||||
{
|
||||
// --
|
||||
}
|
||||
|
||||
BL_Texture::~BL_Texture()
|
||||
{
|
||||
// --
|
||||
}
|
||||
|
||||
void BL_Texture::DeleteTex()
|
||||
{
|
||||
if( mNeedsDeleted ) {
|
||||
glDeleteTextures(1, (GLuint*)&(*mTexture));
|
||||
mNeedsDeleted = 0;
|
||||
mOk = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool BL_Texture::InitFromImage( Image *img, bool mipmap)
|
||||
{
|
||||
if(!img || img->ok==0 ) {
|
||||
mError = true;
|
||||
mOk = false;
|
||||
return mOk;
|
||||
}
|
||||
if( img->ibuf==0 ) {
|
||||
load_image(img, IB_rect, "", 0);
|
||||
if(img->ibuf==0) {
|
||||
img->ok = 0;
|
||||
mError = true;
|
||||
mOk = false;
|
||||
return mOk;
|
||||
}
|
||||
}
|
||||
mTexture = &img->bindcode;
|
||||
mName = img->id.name;
|
||||
mType = BL_TEX2D;
|
||||
|
||||
// smoke em if we got em
|
||||
if (*mTexture != 0) {
|
||||
glBindTexture(GL_TEXTURE_2D, *mTexture );
|
||||
Validate();
|
||||
return mOk;
|
||||
}
|
||||
glGenTextures(1, (GLuint*)mTexture);
|
||||
InitGLTex(img->ibuf->rect, img->ibuf->x, img->ibuf->y, mipmap);
|
||||
Validate();
|
||||
return mOk;
|
||||
}
|
||||
|
||||
void BL_Texture::InitGLTex(unsigned int *pix,int x,int y,bool mipmap)
|
||||
{
|
||||
if (!is_pow2(x) || !is_pow2(y) ) {
|
||||
InitNonPow2Tex(pix, x,y,mipmap);
|
||||
return;
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, *mTexture );
|
||||
if( mipmap ) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, x, y, GL_RGBA, GL_UNSIGNED_BYTE, pix );
|
||||
}
|
||||
else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pix );
|
||||
}
|
||||
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
}
|
||||
|
||||
|
||||
void BL_Texture::InitNonPow2Tex(unsigned int *pix,int x,int y,bool mipmap)
|
||||
{
|
||||
int nx= smaller_pow2(x);
|
||||
int ny= smaller_pow2(y);
|
||||
|
||||
unsigned int *newPixels = (unsigned int *)malloc(nx*ny*sizeof(unsigned int));
|
||||
|
||||
gluScaleImage(GL_RGBA, x, y, GL_UNSIGNED_BYTE, pix, nx,ny, GL_UNSIGNED_BYTE, newPixels);
|
||||
glBindTexture(GL_TEXTURE_2D, *mTexture );
|
||||
|
||||
if( mipmap ) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, nx, ny, GL_RGBA, GL_UNSIGNED_BYTE, newPixels );
|
||||
}
|
||||
else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, nx, ny, 0, GL_RGBA, GL_UNSIGNED_BYTE, newPixels );
|
||||
}
|
||||
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
||||
free(newPixels);
|
||||
}
|
||||
|
||||
|
||||
bool BL_Texture::InitCubeMap( EnvMap *cubemap )
|
||||
{
|
||||
#ifdef GL_ARB_texture_cube_map
|
||||
if(!RAS_EXT_support._ARB_texture_cube_map) {
|
||||
spit("cubemaps not supported");
|
||||
mError = true;
|
||||
mOk = false;
|
||||
return mOk;
|
||||
}
|
||||
|
||||
else if(!cubemap || cubemap->ima->ok==0 ) {
|
||||
mError = true;
|
||||
mOk = false;
|
||||
return mOk;
|
||||
}
|
||||
|
||||
if( cubemap->ima->ibuf==0 ) {
|
||||
load_image(cubemap->ima, IB_rect, "", 0);
|
||||
if(cubemap->ima->ibuf==0) {
|
||||
cubemap->ima->ok = 0;
|
||||
mError = true;
|
||||
mOk = false;
|
||||
return mOk;
|
||||
}
|
||||
}
|
||||
|
||||
EnvMap *CubeMap = cubemap;
|
||||
mNeedsDeleted = 1;
|
||||
mBlankTexture = 0;
|
||||
mType = BL_TEXCUBE;
|
||||
mTexture = &mBlankTexture;
|
||||
mName = CubeMap->ima->id.name;
|
||||
|
||||
glGenTextures(1, (GLuint*)(mTexture));
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, *mTexture );
|
||||
bool needs_split = false;
|
||||
|
||||
if(!CubeMap->cube[0]) needs_split = true;
|
||||
|
||||
if(needs_split){
|
||||
// split it
|
||||
my_envmap_split_ima(CubeMap);
|
||||
}
|
||||
|
||||
int x = cubemap->ima->ibuf->x;
|
||||
int y = cubemap->ima->ibuf->y;
|
||||
unsigned int *data= (unsigned int *)malloc(x*y*sizeof(unsigned int));
|
||||
|
||||
// -----------------------------------
|
||||
x = CubeMap->cube[0]->ibuf->x;
|
||||
y = CubeMap->cube[0]->ibuf->y;
|
||||
|
||||
// check the first image, and assume the rest
|
||||
if (!is_pow2(x) || !is_pow2(y))
|
||||
{
|
||||
spit("invalid envmap size please render with CubeRes @ power of two");
|
||||
free(data);
|
||||
data = 0;
|
||||
mError = true;
|
||||
mOk = false;
|
||||
return mOk;
|
||||
}
|
||||
memcpy(data, CubeMap->cube[0]->ibuf->rect, (x*y*sizeof(unsigned int)));
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
|
||||
// -----------------------------------
|
||||
x = CubeMap->cube[1]->ibuf->x;
|
||||
y = CubeMap->cube[1]->ibuf->y;
|
||||
memcpy(data, CubeMap->cube[1]->ibuf->rect, (x*y*sizeof(unsigned int)));
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
|
||||
// -----------------------------------
|
||||
x = CubeMap->cube[2]->ibuf->x;
|
||||
y = CubeMap->cube[2]->ibuf->y;
|
||||
memcpy(data, CubeMap->cube[2]->ibuf->rect, (x*y*sizeof(unsigned int)));
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
|
||||
// -----------------------------------
|
||||
x = CubeMap->cube[3]->ibuf->x;
|
||||
y = CubeMap->cube[3]->ibuf->y;
|
||||
memcpy(data, CubeMap->cube[3]->ibuf->rect, (x*y*sizeof(unsigned int)));
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
|
||||
// -----------------------------------
|
||||
x = CubeMap->cube[4]->ibuf->x;
|
||||
y = CubeMap->cube[4]->ibuf->y;
|
||||
memcpy(data, CubeMap->cube[4]->ibuf->rect, (x*y*sizeof(unsigned int)));
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
|
||||
// -----------------------------------
|
||||
x = CubeMap->cube[5]->ibuf->x;
|
||||
y = CubeMap->cube[5]->ibuf->y;
|
||||
memcpy(data, CubeMap->cube[5]->ibuf->rect, (x*y*sizeof(unsigned int)));
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
|
||||
glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
|
||||
glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
||||
glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_REPEAT );
|
||||
glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_REPEAT );
|
||||
|
||||
if(data) {
|
||||
free(data);
|
||||
data = 0;
|
||||
}
|
||||
|
||||
if(needs_split) {
|
||||
// okay we allocated, swap back to orig and free used
|
||||
cubemap->ima = CubeMap->ima;
|
||||
my_free_envmapdata(CubeMap);
|
||||
}
|
||||
mOk = IsValid();
|
||||
return mOk;
|
||||
|
||||
#else
|
||||
|
||||
mError = true;
|
||||
mOk = false;
|
||||
return mOk;
|
||||
|
||||
#endif//GL_ARB_texture_cube_map
|
||||
}
|
||||
|
||||
|
||||
STR_String BL_Texture::GetName() const
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
|
||||
bool BL_Texture::IsValid()
|
||||
{
|
||||
return (mTexture && *mTexture!= 0)?glIsTexture(*mTexture)!=0:false;
|
||||
}
|
||||
|
||||
|
||||
void BL_Texture::Validate()
|
||||
{
|
||||
mOk = IsValid();
|
||||
}
|
||||
|
||||
|
||||
bool BL_Texture::Ok()
|
||||
{
|
||||
return ( mTexture?((!mError || mOk ) && *mTexture!= 0):0 );
|
||||
}
|
||||
|
||||
|
||||
unsigned int BL_Texture::GetTextureType() const
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
|
||||
|
||||
BL_Texture::operator const unsigned int () const
|
||||
{
|
||||
return mTexture? *mTexture:0;
|
||||
}
|
||||
|
||||
bool BL_Texture::SetGLTex(unsigned int tex)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
void my_envmap_split_ima(EnvMap *env)
|
||||
{
|
||||
ImBuf *ibuf;
|
||||
Image *ima;
|
||||
int dx, part;
|
||||
|
||||
my_free_envmapdata(env);
|
||||
|
||||
dx= env->ima->ibuf->y;
|
||||
dx/= 2;
|
||||
if(3*dx != env->ima->ibuf->x) {
|
||||
printf("Incorrect envmap size\n");
|
||||
env->ok= 0;
|
||||
env->ima->ok= 0;
|
||||
}
|
||||
else {
|
||||
for(part=0; part<6; part++) {
|
||||
ibuf= IMB_allocImBuf(dx, dx, 24, IB_rect, 0);
|
||||
ima= (Image*)MEM_callocN(sizeof(Image), "image");
|
||||
ima->ibuf= ibuf;
|
||||
ima->ok= 1;
|
||||
env->cube[part]= ima;
|
||||
}
|
||||
IMB_rectop(env->cube[0]->ibuf, env->ima->ibuf,
|
||||
0, 0, 0, 0, dx, dx, IMB_rectcpy, 0);
|
||||
IMB_rectop(env->cube[1]->ibuf, env->ima->ibuf,
|
||||
0, 0, dx, 0, dx, dx, IMB_rectcpy, 0);
|
||||
IMB_rectop(env->cube[2]->ibuf, env->ima->ibuf,
|
||||
0, 0, 2*dx, 0, dx, dx, IMB_rectcpy, 0);
|
||||
IMB_rectop(env->cube[3]->ibuf, env->ima->ibuf,
|
||||
0, 0, 0, dx, dx, dx, IMB_rectcpy, 0);
|
||||
IMB_rectop(env->cube[4]->ibuf, env->ima->ibuf,
|
||||
0, 0, dx, dx, dx, dx, IMB_rectcpy, 0);
|
||||
IMB_rectop(env->cube[5]->ibuf, env->ima->ibuf,
|
||||
0, 0, 2*dx, dx, dx, dx, IMB_rectcpy, 0);
|
||||
env->ok= 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void my_free_envmapdata(EnvMap *env)
|
||||
{
|
||||
Image *ima;
|
||||
unsigned int a, part;
|
||||
|
||||
for(part=0; part<6; part++) {
|
||||
ima= env->cube[part];
|
||||
if(ima) {
|
||||
if(ima->ibuf) IMB_freeImBuf(ima->ibuf);
|
||||
|
||||
for(a=0; a<BLI_ARRAY_NELEMS(ima->mipmap); a++) {
|
||||
if(ima->mipmap[a]) IMB_freeImBuf(ima->mipmap[a]);
|
||||
}
|
||||
MEM_freeN(ima);
|
||||
env->cube[part]= 0;
|
||||
}
|
||||
}
|
||||
env->ok= 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
unsigned int BL_Texture::mBlankTexture = 0;
|
||||
|
||||
53
source/gameengine/Ketsji/BL_Texture.h
Normal file
53
source/gameengine/Ketsji/BL_Texture.h
Normal file
@@ -0,0 +1,53 @@
|
||||
#ifndef __BL_TEXTURE_H__
|
||||
#define __BL_TEXTURE_H__
|
||||
#include <vector>
|
||||
// --
|
||||
struct Image;
|
||||
struct EnvMap;
|
||||
// --
|
||||
#include "STR_String.h"
|
||||
|
||||
class BL_Texture
|
||||
{
|
||||
private:
|
||||
// -----------------------------------
|
||||
unsigned int* mTexture;
|
||||
bool mError;
|
||||
bool mOk;
|
||||
bool mNeedsDeleted;
|
||||
unsigned int mType;
|
||||
STR_String mName;
|
||||
static unsigned int mBlankTexture;
|
||||
std::vector<EnvMap*>mCubeMem;
|
||||
// -----------------------------------
|
||||
void InitNonPow2Tex(unsigned int *p,int x,int y,bool mipmap );
|
||||
void InitGLTex(unsigned int *p,int x,int y,bool mipmap );
|
||||
|
||||
public:
|
||||
BL_Texture();
|
||||
~BL_Texture( );
|
||||
|
||||
operator const unsigned int () const;
|
||||
bool Ok();
|
||||
|
||||
STR_String GetName() const;
|
||||
|
||||
unsigned int GetTextureType() const;
|
||||
void DeleteTex();
|
||||
bool InitFromImage( Image *img, bool mipmap);
|
||||
bool InitCubeMap( EnvMap *cubemap );
|
||||
//
|
||||
bool SetGLTex(unsigned int tex);
|
||||
|
||||
void PopCubeMap();
|
||||
bool IsValid();
|
||||
void Validate();
|
||||
};
|
||||
|
||||
enum TexType{
|
||||
BL_TEX2D = 1,
|
||||
BL_TEXCUBE = 2
|
||||
};
|
||||
|
||||
|
||||
#endif//__BL_TEXTURE_H__
|
||||
949
source/gameengine/Ketsji/KX_BlenderMaterial.cpp
Normal file
949
source/gameengine/Ketsji/KX_BlenderMaterial.cpp
Normal file
@@ -0,0 +1,949 @@
|
||||
|
||||
// ------------------------------------
|
||||
// ...
|
||||
// ------------------------------------
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#endif // WIN32
|
||||
#ifdef __APPLE__
|
||||
#include <OpenGL/gl.h>
|
||||
#include <OpenGL/glu.h>
|
||||
#else
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#endif
|
||||
|
||||
#include "KX_BlenderMaterial.h"
|
||||
#include "BL_Material.h"
|
||||
#include "KX_Scene.h"
|
||||
#include "KX_Light.h"
|
||||
#include "KX_GameObject.h"
|
||||
|
||||
#include "MT_Vector3.h"
|
||||
#include "MT_Vector4.h"
|
||||
#include "MT_Matrix4x4.h"
|
||||
|
||||
#include "RAS_MeshObject.h"
|
||||
#include "RAS_IRasterizer.h"
|
||||
#include "RAS_OpenGLRasterizer/RAS_GLExtensionManager.h"
|
||||
#include "RAS_OpenGLRasterizer/ARB_multitexture.h"
|
||||
|
||||
extern "C" {
|
||||
#include "BDR_drawmesh.h"
|
||||
}
|
||||
|
||||
#include "STR_HashedString.h"
|
||||
|
||||
// ------------------------------------
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_material_types.h"
|
||||
#include "DNA_image_types.h"
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "BKE_mesh.h"
|
||||
// ------------------------------------
|
||||
using namespace bgl;
|
||||
#define spit(x) std::cout << x << std::endl;
|
||||
|
||||
//static PyObject *gTextureDict = 0;
|
||||
|
||||
KX_BlenderMaterial::KX_BlenderMaterial(
|
||||
KX_Scene *scene,
|
||||
BL_Material *data,
|
||||
bool skin,
|
||||
int lightlayer,
|
||||
void *clientobject,
|
||||
PyTypeObject *T
|
||||
)
|
||||
: PyObjectPlus(T),
|
||||
RAS_IPolyMaterial(
|
||||
STR_String( data->texname[0] ),
|
||||
STR_String( data->matname ), // needed for physics!
|
||||
data->tile,
|
||||
data->tilexrep[0],
|
||||
data->tileyrep[0],
|
||||
data->mode,
|
||||
((data->ras_mode &TRANSP)!=0),
|
||||
((data->ras_mode &ZSORT)!=0),
|
||||
lightlayer,
|
||||
((data->ras_mode &TRIANGLE)!=0),
|
||||
clientobject
|
||||
),
|
||||
mMaterial(data),
|
||||
mShader(0),
|
||||
mScene(scene),
|
||||
mPass(0)
|
||||
{
|
||||
///RAS_EXT_support._ARB_multitexture == true if were here
|
||||
|
||||
// --------------------------------
|
||||
// RAS_IPolyMaterial variables...
|
||||
m_flag |=RAS_BLENDERMAT;
|
||||
m_flag |=(mMaterial->IdMode>=ONETEX)?RAS_MULTITEX:0;
|
||||
m_flag |=(mMaterial->ras_mode & USE_LIGHT)!=0?RAS_MULTILIGHT:0;
|
||||
|
||||
// figure max
|
||||
#ifdef GL_ARB_multitexture
|
||||
int enabled = mMaterial->num_enabled;
|
||||
mMaterial->num_enabled = enabled>=bgl::max_texture_units?bgl::max_texture_units:enabled;
|
||||
#else
|
||||
mMaterial->num_enabled=0;
|
||||
#endif
|
||||
|
||||
m_enabled = mMaterial->num_enabled;
|
||||
|
||||
// test the sum of the various modes for equality
|
||||
// so we can ether accept or reject this material
|
||||
// as being equal, this is rather important to
|
||||
// prevent material bleeding
|
||||
for(int i=0; i<mMaterial->num_enabled; i++) {
|
||||
m_multimode +=
|
||||
(mMaterial->flag[i] +
|
||||
mMaterial->blend_mode[i]
|
||||
);
|
||||
}
|
||||
m_multimode += mMaterial->IdMode+mMaterial->ras_mode;
|
||||
|
||||
}
|
||||
|
||||
|
||||
KX_BlenderMaterial::~KX_BlenderMaterial()
|
||||
{
|
||||
// cleanup work
|
||||
OnExit();
|
||||
}
|
||||
|
||||
|
||||
TFace* KX_BlenderMaterial::GetTFace(void) const
|
||||
{
|
||||
// fonts on polys
|
||||
MT_assert(mMaterial->tface);
|
||||
return mMaterial->tface;
|
||||
}
|
||||
|
||||
void KX_BlenderMaterial::OnConstruction()
|
||||
{
|
||||
// for each unique material...
|
||||
#ifdef GL_ARB_multitexture
|
||||
/* will be used to switch textures
|
||||
if(!gTextureDict)
|
||||
gTextureDict = PyDict_New();
|
||||
*/
|
||||
#ifdef GL_ARB_shader_objects
|
||||
if( RAS_EXT_support._ARB_shader_objects )
|
||||
mShader = new BL_Shader( mMaterial->num_enabled );
|
||||
#endif
|
||||
|
||||
int i;
|
||||
for(i=0; i<mMaterial->num_enabled; i++) {
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB+i);
|
||||
#ifdef GL_ARB_texture_cube_map
|
||||
if( mMaterial->mapping[i].mapping & USEENV ) {
|
||||
if(!RAS_EXT_support._ARB_texture_cube_map) {
|
||||
spit("CubeMap textures not supported");
|
||||
continue;
|
||||
}
|
||||
if(!mTextures[i].InitCubeMap( mMaterial->cubemap[i] ) )
|
||||
spit("unable to initialize image("<<i<<") in "<<
|
||||
mMaterial->matname<< ", image will not be available");
|
||||
|
||||
if( RAS_EXT_support._ARB_shader_objects )
|
||||
mShader->InitializeSampler(SAMP_CUBE, i, 0, mTextures[i]);
|
||||
}
|
||||
|
||||
else {
|
||||
#endif//GL_ARB_texture_cube_map
|
||||
if( mMaterial->img[i] ) {
|
||||
if( ! mTextures[i].InitFromImage(mMaterial->img[i], (mMaterial->flag[i] &MIPMAP)!=0 ))
|
||||
spit("unable to initialize image("<<i<<") in "<<
|
||||
mMaterial->matname<< ", image will not be available");
|
||||
|
||||
if( RAS_EXT_support._ARB_shader_objects )
|
||||
mShader->InitializeSampler(SAMP_2D, i, 0, mTextures[i]);
|
||||
}
|
||||
#ifdef GL_ARB_texture_cube_map
|
||||
}
|
||||
#endif//GL_ARB_texture_cube_map
|
||||
/*PyDict_SetItemString(gTextureDict, mTextures[i].GetName().Ptr(), PyInt_FromLong(mTextures[i]));*/
|
||||
}
|
||||
#endif//GL_ARB_multitexture
|
||||
}
|
||||
|
||||
void KX_BlenderMaterial::OnExit()
|
||||
{
|
||||
#ifdef GL_ARB_multitexture
|
||||
|
||||
#ifdef GL_ARB_shader_objects
|
||||
if( RAS_EXT_support._ARB_shader_objects && mShader ) {
|
||||
//note, the shader here is allocated, per unique material
|
||||
//and this function is called per face
|
||||
glUseProgramObjectARB(0);
|
||||
delete mShader;
|
||||
mShader = 0;
|
||||
}
|
||||
#endif //GL_ARB_shader_objects
|
||||
|
||||
for(int i=0; i<mMaterial->num_enabled; i++) {
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB+i);
|
||||
|
||||
mTextures[i].DeleteTex();
|
||||
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
#ifdef GL_ARB_texture_cube_map
|
||||
if(RAS_EXT_support._ARB_texture_cube_map)
|
||||
glDisable(GL_TEXTURE_CUBE_MAP_ARB);
|
||||
#endif//GL_ARB_texture_cube_map
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_TEXTURE_GEN_S);
|
||||
glDisable(GL_TEXTURE_GEN_T);
|
||||
glDisable(GL_TEXTURE_GEN_R);
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
}
|
||||
|
||||
/*if (gTextureDict) {
|
||||
PyDict_Clear(gTextureDict);
|
||||
Py_DECREF(gTextureDict);
|
||||
gTextureDict = 0;
|
||||
}*/
|
||||
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
|
||||
#ifdef GL_ARB_texture_cube_map
|
||||
if(RAS_EXT_support._ARB_texture_cube_map)
|
||||
glDisable(GL_TEXTURE_CUBE_MAP_ARB);
|
||||
#endif//GL_ARB_texture_cube_map
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
#endif//GL_ARB_multitexture
|
||||
|
||||
// make sure multi texture units
|
||||
// revert back to blender...
|
||||
// --
|
||||
if( mMaterial->tface )
|
||||
set_tpage(mMaterial->tface);
|
||||
}
|
||||
|
||||
|
||||
void KX_BlenderMaterial::DisableTexData()
|
||||
{
|
||||
glDisable(GL_BLEND);
|
||||
#ifdef GL_ARB_multitexture
|
||||
int i=(MAXTEX>=bgl::max_texture_units?bgl::max_texture_units:MAXTEX)-1;
|
||||
for(; i>=0; i--) {
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB+i);
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
#ifdef GL_ARB_texture_cube_map
|
||||
if(RAS_EXT_support._ARB_texture_cube_map)
|
||||
glDisable(GL_TEXTURE_CUBE_MAP_ARB);
|
||||
#endif//GL_ARB_texture_cube_map
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_TEXTURE_GEN_S);
|
||||
glDisable(GL_TEXTURE_GEN_T);
|
||||
glDisable(GL_TEXTURE_GEN_R);
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
}
|
||||
#endif//GL_ARB_multitexture
|
||||
}
|
||||
|
||||
|
||||
void KX_BlenderMaterial::setShaderData( bool enable )
|
||||
{
|
||||
#ifdef GL_ARB_multitexture
|
||||
#ifdef GL_ARB_shader_objects
|
||||
|
||||
MT_assert(RAS_EXT_support._ARB_shader_objects && mShader);
|
||||
|
||||
int i;
|
||||
if( !enable || !mShader->Ok() ) {
|
||||
// frame cleanup.
|
||||
glUseProgramObjectARB( 0 );
|
||||
DisableTexData();
|
||||
return;
|
||||
}
|
||||
|
||||
DisableTexData();
|
||||
glUseProgramObjectARB( mShader->GetProg() );
|
||||
|
||||
// for each enabled unit
|
||||
for(i=0; i<mMaterial->num_enabled; i++) {
|
||||
|
||||
const uSampler *samp = mShader->getSampler(i);
|
||||
if( samp->loc == -1 || samp->glTexture == 0 ) continue;
|
||||
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB+i);
|
||||
|
||||
#ifdef GL_ARB_texture_cube_map
|
||||
if( mMaterial->mapping[i].mapping &USEENV ) {
|
||||
glBindTexture( GL_TEXTURE_CUBE_MAP_ARB, samp->glTexture /* mTextures[i]*/ );
|
||||
glEnable( GL_TEXTURE_CUBE_MAP_ARB );
|
||||
}
|
||||
else {
|
||||
#endif//GL_ARB_texture_cube_map
|
||||
glBindTexture( GL_TEXTURE_2D, samp->glTexture /*mTextures[i]*/ );
|
||||
glEnable( GL_TEXTURE_2D );
|
||||
#ifdef GL_ARB_texture_cube_map
|
||||
}
|
||||
#endif//GL_ARB_texture_cube_map
|
||||
// use a sampler
|
||||
glUniform1iARB(samp->loc, i );
|
||||
}
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
#endif//GL_ARB_shader_objects
|
||||
#endif//GL_ARB_multitexture
|
||||
}
|
||||
|
||||
|
||||
void KX_BlenderMaterial::setTexData( bool enable )
|
||||
{
|
||||
#ifdef GL_ARB_multitexture
|
||||
int i;
|
||||
|
||||
#ifdef GL_ARB_shader_objects
|
||||
if(RAS_EXT_support._ARB_shader_objects) {
|
||||
// switch back to fixed func
|
||||
glUseProgramObjectARB( 0 );
|
||||
}
|
||||
#endif//GL_ARB_shader_objects
|
||||
|
||||
if( !enable ) {
|
||||
// frame cleanup.
|
||||
DisableTexData();
|
||||
return;
|
||||
}
|
||||
|
||||
DisableTexData();
|
||||
|
||||
if( mMaterial->IdMode == DEFAULT_BLENDER ) {
|
||||
setDefaultBlending();
|
||||
return;
|
||||
}
|
||||
|
||||
if( mMaterial->IdMode == TEXFACE ) {
|
||||
|
||||
// no material connected to the object
|
||||
if( mTextures[0] ) {
|
||||
if( !mTextures[0].Ok() ) return;
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
glBindTexture( GL_TEXTURE_2D, mTextures[0] );
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
setTextureEnvironment( -1 ); // modulate
|
||||
setEnvMap( (mMaterial->mapping[0].mapping &USEREFL)!=0 );
|
||||
setDefaultBlending();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int lastblend = 0;
|
||||
|
||||
// for each enabled unit
|
||||
for(i=0; (i<mMaterial->num_enabled); i++) {
|
||||
if( !mTextures[i].Ok() ) continue;
|
||||
|
||||
glActiveTextureARB(GL_TEXTURE0_ARB+i);
|
||||
|
||||
#ifdef GL_ARB_texture_cube_map
|
||||
// use environment maps
|
||||
if( mMaterial->mapping[i].mapping &USEENV && RAS_EXT_support._ARB_texture_cube_map ) {
|
||||
glBindTexture( GL_TEXTURE_CUBE_MAP_ARB, mTextures[i] );
|
||||
glEnable(GL_TEXTURE_CUBE_MAP_ARB);
|
||||
setTextureEnvironment( i );
|
||||
|
||||
if( mMaterial->mapping[i].mapping &USEREFL )
|
||||
setEnvMap( true, true );
|
||||
else if(mMaterial->mapping[i].mapping &USEOBJ)
|
||||
setObjectMatrixData(i);
|
||||
else
|
||||
setTexMatrixData( i );
|
||||
}
|
||||
// 2d textures
|
||||
else {
|
||||
#endif//GL_ARB_texture_cube_map
|
||||
glBindTexture( GL_TEXTURE_2D, mTextures[i] );
|
||||
glEnable( GL_TEXTURE_2D );
|
||||
setTextureEnvironment( i );
|
||||
|
||||
if( mMaterial->mapping[i].mapping &USEREFL ){
|
||||
setEnvMap( true );
|
||||
}
|
||||
else if(mMaterial->mapping[i].mapping &USEOBJ){
|
||||
setObjectMatrixData(i);
|
||||
}
|
||||
else {
|
||||
setTexMatrixData( i );
|
||||
}
|
||||
|
||||
#ifdef GL_ARB_texture_cube_map
|
||||
}
|
||||
#endif//GL_ARB_texture_cube_map
|
||||
|
||||
// if either unit has set blending
|
||||
// and its the last pass
|
||||
lastblend += setBlending( i ); // dry run
|
||||
if(lastblend >0 && i==mMaterial->num_enabled-1)
|
||||
setBlending( i, true );
|
||||
else if(lastblend == 0 && i==mMaterial->num_enabled-1)
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
#endif//GL_ARB_multitexture
|
||||
}
|
||||
|
||||
void
|
||||
KX_BlenderMaterial::ActivatShaders(
|
||||
RAS_IRasterizer* rasty,
|
||||
TCachingInfo& cachingInfo)const
|
||||
{
|
||||
if (GetCachingInfo() != cachingInfo) {
|
||||
KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this);
|
||||
|
||||
if (!cachingInfo)
|
||||
tmp->setShaderData( false );
|
||||
|
||||
cachingInfo = GetCachingInfo();
|
||||
|
||||
if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED ) {
|
||||
tmp->setShaderData( true );
|
||||
rasty->EnableTextures(true);
|
||||
}
|
||||
else {
|
||||
tmp->setShaderData( false );
|
||||
rasty->EnableTextures(false);
|
||||
}
|
||||
|
||||
if(mMaterial->mode & RAS_IRasterizer::KX_TWOSIDE)
|
||||
rasty->SetCullFace(false);
|
||||
else
|
||||
rasty->SetCullFace(true);
|
||||
|
||||
if (((mMaterial->ras_mode &WIRE)!=0) || mMaterial->mode & RAS_IRasterizer::KX_LINES)
|
||||
rasty->SetLines(true);
|
||||
else
|
||||
rasty->SetLines(false);
|
||||
}
|
||||
|
||||
// shaders have access to the variables set here
|
||||
// via builtin GLSL variables
|
||||
// eg: gl_FrontMaterial.diffuse
|
||||
// --
|
||||
rasty->SetSpecularity(
|
||||
mMaterial->speccolor[0]*mMaterial->spec_f,
|
||||
mMaterial->speccolor[1]*mMaterial->spec_f,
|
||||
mMaterial->speccolor[2]*mMaterial->spec_f,
|
||||
mMaterial->spec_f
|
||||
);
|
||||
|
||||
rasty->SetShinyness( mMaterial->hard );
|
||||
|
||||
rasty->SetDiffuse(
|
||||
mMaterial->matcolor[0]*mMaterial->ref+mMaterial->emit,
|
||||
mMaterial->matcolor[1]*mMaterial->ref+mMaterial->emit,
|
||||
mMaterial->matcolor[2]*mMaterial->ref+mMaterial->emit,
|
||||
1.0f);
|
||||
|
||||
rasty->SetEmissive(
|
||||
mMaterial->matcolor[0]*mMaterial->emit,
|
||||
mMaterial->matcolor[1]*mMaterial->emit,
|
||||
mMaterial->matcolor[2]*mMaterial->emit,
|
||||
1.0
|
||||
);
|
||||
|
||||
// Lagan's patch...
|
||||
// added material factor
|
||||
rasty->SetAmbient(mMaterial->amb);
|
||||
|
||||
if (mMaterial->material)
|
||||
rasty->SetPolygonOffset(-mMaterial->material->zoffs, 0.0);
|
||||
}
|
||||
|
||||
void
|
||||
KX_BlenderMaterial::ActivateMat(
|
||||
RAS_IRasterizer* rasty,
|
||||
TCachingInfo& cachingInfo
|
||||
)const
|
||||
{
|
||||
if (GetCachingInfo() != cachingInfo) {
|
||||
KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this);
|
||||
|
||||
if (!cachingInfo)
|
||||
tmp->setTexData( false );
|
||||
|
||||
cachingInfo = GetCachingInfo();
|
||||
|
||||
if (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) {
|
||||
tmp->setTexData( true );
|
||||
rasty->EnableTextures(true);
|
||||
}
|
||||
else{
|
||||
tmp->setTexData( false );
|
||||
rasty->EnableTextures(false);
|
||||
}
|
||||
|
||||
if(mMaterial->mode & RAS_IRasterizer::KX_TWOSIDE)
|
||||
rasty->SetCullFace(false);
|
||||
else
|
||||
rasty->SetCullFace(true);
|
||||
|
||||
if (((mMaterial->ras_mode &WIRE)!=0) || mMaterial->mode & RAS_IRasterizer::KX_LINES)
|
||||
rasty->SetLines(true);
|
||||
else
|
||||
rasty->SetLines(false);
|
||||
}
|
||||
|
||||
rasty->SetSpecularity(
|
||||
mMaterial->speccolor[0]*mMaterial->spec_f,
|
||||
mMaterial->speccolor[1]*mMaterial->spec_f,
|
||||
mMaterial->speccolor[2]*mMaterial->spec_f,
|
||||
mMaterial->spec_f
|
||||
);
|
||||
|
||||
rasty->SetShinyness( mMaterial->hard );
|
||||
|
||||
rasty->SetDiffuse(
|
||||
mMaterial->matcolor[0]*mMaterial->ref+mMaterial->emit,
|
||||
mMaterial->matcolor[1]*mMaterial->ref+mMaterial->emit,
|
||||
mMaterial->matcolor[2]*mMaterial->ref+mMaterial->emit,
|
||||
1.0f);
|
||||
|
||||
rasty->SetEmissive(
|
||||
mMaterial->matcolor[0]*mMaterial->emit,
|
||||
mMaterial->matcolor[1]*mMaterial->emit,
|
||||
mMaterial->matcolor[2]*mMaterial->emit,
|
||||
1.0
|
||||
);
|
||||
|
||||
// Lagan's patch...
|
||||
// added material factor
|
||||
rasty->SetAmbient(mMaterial->amb);
|
||||
|
||||
if (mMaterial->material)
|
||||
rasty->SetPolygonOffset(-mMaterial->material->zoffs, 0.0);
|
||||
}
|
||||
|
||||
bool
|
||||
KX_BlenderMaterial::Activate(
|
||||
RAS_IRasterizer* rasty,
|
||||
TCachingInfo& cachingInfo
|
||||
)const
|
||||
{
|
||||
bool dopass = false;
|
||||
#ifdef GL_ARB_shader_objects
|
||||
if( RAS_EXT_support._ARB_shader_objects &&
|
||||
( mShader && mShader->Ok() ) ) {
|
||||
|
||||
if( (mPass++) < mShader->getNumPass() ) {
|
||||
ActivatShaders(rasty, cachingInfo);
|
||||
dopass = true;
|
||||
return dopass;
|
||||
}
|
||||
else {
|
||||
glUseProgramObjectARB( 0 );
|
||||
mPass = 0;
|
||||
dopass = false;
|
||||
return dopass;
|
||||
}
|
||||
}
|
||||
else {
|
||||
#endif//GL_ARB_shader_objects
|
||||
switch (mPass++)
|
||||
{
|
||||
case 0:
|
||||
ActivateMat(rasty, cachingInfo);
|
||||
dopass = true;
|
||||
break;
|
||||
default:
|
||||
mPass = 0;
|
||||
dopass = false;
|
||||
break;
|
||||
}
|
||||
#ifdef GL_ARB_shader_objects
|
||||
}
|
||||
#endif//GL_ARB_shader_objects
|
||||
return dopass;
|
||||
}
|
||||
|
||||
void KX_BlenderMaterial::setTextureEnvironment( int textureIndex )
|
||||
{
|
||||
#ifndef GL_ARB_texture_env_combine
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
return;
|
||||
#else
|
||||
if(textureIndex == -1 || !RAS_EXT_support._ARB_texture_env_combine){
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
|
||||
return;
|
||||
}
|
||||
|
||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
|
||||
|
||||
GLfloat blend_operand = GL_SRC_COLOR;
|
||||
GLfloat blend_operand_prev = GL_SRC_COLOR;
|
||||
|
||||
// all sources here are RGB by default
|
||||
GLenum combiner = GL_COMBINE_RGB_ARB;
|
||||
GLenum source0 = GL_SOURCE0_RGB_ARB;
|
||||
GLenum source1 = GL_SOURCE1_RGB_ARB;
|
||||
GLenum source2 = GL_SOURCE2_RGB_ARB;
|
||||
GLenum op0 = GL_OPERAND0_RGB_ARB;
|
||||
GLenum op1 = GL_OPERAND1_RGB_ARB;
|
||||
GLenum op2 = GL_OPERAND2_RGB_ARB;
|
||||
|
||||
// switch to alpha combiners
|
||||
if( (mMaterial->flag[textureIndex] &TEXALPHA) ) {
|
||||
combiner = GL_COMBINE_ALPHA_ARB;
|
||||
source0 = GL_SOURCE0_ALPHA_ARB;
|
||||
source1 = GL_SOURCE1_ALPHA_ARB;
|
||||
source2 = GL_SOURCE2_ALPHA_ARB;
|
||||
op0 = GL_OPERAND0_ALPHA_ARB;
|
||||
op1 = GL_OPERAND1_ALPHA_ARB;
|
||||
op2 = GL_OPERAND2_ALPHA_ARB;
|
||||
blend_operand = GL_SRC_ALPHA;
|
||||
blend_operand_prev = GL_SRC_ALPHA;
|
||||
|
||||
// invert
|
||||
if(mMaterial->flag[textureIndex] &TEXNEG) {
|
||||
blend_operand_prev = GL_ONE_MINUS_SRC_ALPHA;
|
||||
blend_operand = GL_ONE_MINUS_SRC_ALPHA;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(mMaterial->flag[textureIndex] &TEXNEG) {
|
||||
blend_operand_prev = GL_ONE_MINUS_SRC_COLOR;
|
||||
blend_operand = GL_ONE_MINUS_SRC_COLOR;
|
||||
}
|
||||
}
|
||||
// on Texture0 GL_PREVIOUS_ARB is the primary color
|
||||
// on Texture1 GL_PREVIOUS_ARB is Texture0 env
|
||||
switch( mMaterial->blend_mode[textureIndex] ) {
|
||||
case BLEND_MIX:
|
||||
{
|
||||
// ------------------------------
|
||||
GLfloat base_col[4];
|
||||
base_col[0] = base_col[1] = base_col[2] = 0.f;
|
||||
base_col[3] = 1.f-mMaterial->color_blend[textureIndex];
|
||||
glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,base_col );
|
||||
glTexEnvf( GL_TEXTURE_ENV, combiner, GL_INTERPOLATE_ARB);
|
||||
glTexEnvf( GL_TEXTURE_ENV, source0, GL_PREVIOUS_ARB);
|
||||
glTexEnvf( GL_TEXTURE_ENV, op0, blend_operand_prev );
|
||||
glTexEnvf( GL_TEXTURE_ENV, source1, GL_TEXTURE );
|
||||
glTexEnvf( GL_TEXTURE_ENV, op1, blend_operand);
|
||||
glTexEnvf( GL_TEXTURE_ENV, source2, GL_CONSTANT_ARB );
|
||||
glTexEnvf( GL_TEXTURE_ENV, op2, GL_SRC_ALPHA);
|
||||
}break;
|
||||
case BLEND_MUL:
|
||||
{
|
||||
// ------------------------------
|
||||
glTexEnvf( GL_TEXTURE_ENV, combiner, GL_MODULATE);
|
||||
glTexEnvf( GL_TEXTURE_ENV, source0, GL_PREVIOUS_ARB);
|
||||
glTexEnvf( GL_TEXTURE_ENV, op0, blend_operand_prev);
|
||||
glTexEnvf( GL_TEXTURE_ENV, source1, GL_TEXTURE );
|
||||
glTexEnvf( GL_TEXTURE_ENV, op1, blend_operand);
|
||||
}break;
|
||||
case BLEND_ADD:
|
||||
{
|
||||
// ------------------------------
|
||||
glTexEnvf( GL_TEXTURE_ENV, combiner, GL_ADD_SIGNED_ARB);
|
||||
glTexEnvf( GL_TEXTURE_ENV, source0, GL_PREVIOUS_ARB );
|
||||
glTexEnvf( GL_TEXTURE_ENV, op0, blend_operand_prev );
|
||||
glTexEnvf( GL_TEXTURE_ENV, source1, GL_TEXTURE );
|
||||
glTexEnvf( GL_TEXTURE_ENV, op1, blend_operand );
|
||||
}break;
|
||||
case BLEND_SUB:
|
||||
{
|
||||
// ------------------------------
|
||||
glTexEnvf( GL_TEXTURE_ENV, combiner, GL_SUBTRACT_ARB);
|
||||
glTexEnvf( GL_TEXTURE_ENV, source0, GL_PREVIOUS_ARB );
|
||||
glTexEnvf( GL_TEXTURE_ENV, op0, blend_operand_prev );
|
||||
glTexEnvf( GL_TEXTURE_ENV, source1, GL_TEXTURE );
|
||||
glTexEnvf( GL_TEXTURE_ENV, op1, blend_operand);
|
||||
}break;
|
||||
case BLEND_SCR:
|
||||
{
|
||||
// ------------------------------
|
||||
glTexEnvf( GL_TEXTURE_ENV, combiner, GL_ADD);
|
||||
glTexEnvf( GL_TEXTURE_ENV, source0, GL_PREVIOUS_ARB );
|
||||
glTexEnvf( GL_TEXTURE_ENV, op0, blend_operand_prev );
|
||||
glTexEnvf( GL_TEXTURE_ENV, source1, GL_TEXTURE );
|
||||
glTexEnvf( GL_TEXTURE_ENV, op1, blend_operand);
|
||||
} break;
|
||||
}
|
||||
#endif //!GL_ARB_texture_env_combine
|
||||
}
|
||||
|
||||
bool KX_BlenderMaterial::setBlending( int ind, bool enable)
|
||||
{
|
||||
if(!enable) {
|
||||
if(mMaterial->flag[ind] &CALCALPHA ) return true;
|
||||
else if(mMaterial->flag[ind] &USEALPHA ) return true;
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
// additive
|
||||
if(mMaterial->flag[ind] &CALCALPHA ) {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
return true;
|
||||
}
|
||||
|
||||
// use alpha channel
|
||||
else if(mMaterial->flag[ind] &USEALPHA ) {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool KX_BlenderMaterial::setDefaultBlending()
|
||||
{
|
||||
if( mMaterial->transp &TF_ADD) {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
return true;
|
||||
}
|
||||
|
||||
if( mMaterial->transp & TF_ALPHA ) {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
return true;
|
||||
}
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
return false;
|
||||
}
|
||||
|
||||
void KX_BlenderMaterial::setEnvMap(bool val, bool cube)
|
||||
{
|
||||
#ifdef GL_ARB_texture_cube_map
|
||||
if( cube && RAS_EXT_support._ARB_texture_cube_map )
|
||||
{
|
||||
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB );
|
||||
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
|
||||
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
|
||||
|
||||
glEnable(GL_TEXTURE_GEN_S);
|
||||
glEnable(GL_TEXTURE_GEN_T);
|
||||
glEnable(GL_TEXTURE_GEN_R);
|
||||
}
|
||||
else {
|
||||
#endif//GL_ARB_texture_cube_map
|
||||
if( val ) {
|
||||
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
|
||||
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
|
||||
|
||||
glEnable(GL_TEXTURE_GEN_S);
|
||||
glEnable(GL_TEXTURE_GEN_T);
|
||||
glEnable(GL_TEXTURE_GEN_R);
|
||||
}
|
||||
else {
|
||||
glDisable(GL_TEXTURE_GEN_S);
|
||||
glDisable(GL_TEXTURE_GEN_T);
|
||||
glDisable(GL_TEXTURE_GEN_R);
|
||||
}
|
||||
#ifdef GL_ARB_texture_cube_map
|
||||
}
|
||||
#endif//GL_ARB_texture_cube_map
|
||||
}
|
||||
|
||||
|
||||
void KX_BlenderMaterial::setTexMatrixData(int i)
|
||||
{
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadIdentity();
|
||||
|
||||
glScalef(
|
||||
mMaterial->mapping[i].scale[0],
|
||||
mMaterial->mapping[i].scale[1],
|
||||
mMaterial->mapping[i].scale[2]
|
||||
);
|
||||
glTranslatef(
|
||||
mMaterial->mapping[i].offsets[0],
|
||||
mMaterial->mapping[i].offsets[1],
|
||||
mMaterial->mapping[i].offsets[2]
|
||||
);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
}
|
||||
|
||||
static void GetProjPlane(BL_Material *mat, int index,int num, float*param)
|
||||
{
|
||||
param[0]=param[1]=param[2]=param[3]=0.f;
|
||||
if( mat->mapping[index].projplane[num] == PROJX )
|
||||
param[0] = 1.f;
|
||||
else if( mat->mapping[index].projplane[num] == PROJY )
|
||||
param[1] = 1.f;
|
||||
else if( mat->mapping[index].projplane[num] == PROJZ)
|
||||
param[2] = 1.f;
|
||||
}
|
||||
|
||||
|
||||
void KX_BlenderMaterial::setObjectMatrixData(int i)
|
||||
{
|
||||
// will work without cubemaps
|
||||
// but a cubemap will look the best
|
||||
KX_GameObject *obj =
|
||||
(KX_GameObject*)
|
||||
mScene->GetObjectList()->FindValue(mMaterial->mapping[i].objconame);
|
||||
|
||||
if(!obj)
|
||||
return;
|
||||
|
||||
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
|
||||
glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
|
||||
glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR );
|
||||
|
||||
GLenum plane = GL_EYE_PLANE;
|
||||
|
||||
// figure plane gen
|
||||
float proj[4]= {0.f,0.f,0.f,0.f};
|
||||
GetProjPlane(mMaterial, i, 0, proj);
|
||||
glTexGenfv(GL_S, plane, proj);
|
||||
|
||||
GetProjPlane(mMaterial, i, 1, proj);
|
||||
glTexGenfv(GL_T, plane, proj);
|
||||
|
||||
GetProjPlane(mMaterial, i, 2, proj);
|
||||
glTexGenfv(GL_R, plane, proj);
|
||||
|
||||
glEnable(GL_TEXTURE_GEN_S);
|
||||
glEnable(GL_TEXTURE_GEN_T);
|
||||
glEnable(GL_TEXTURE_GEN_R);
|
||||
|
||||
float matr[16];
|
||||
glGetFloatv(GL_MODELVIEW_MATRIX, matr);
|
||||
MT_Matrix4x4 mvmat(matr);
|
||||
|
||||
glMatrixMode(GL_TEXTURE);
|
||||
glLoadIdentity();
|
||||
glScalef(
|
||||
mMaterial->mapping[i].scale[0],
|
||||
mMaterial->mapping[i].scale[1],
|
||||
mMaterial->mapping[i].scale[2]
|
||||
);
|
||||
|
||||
MT_Point3 pos = obj->NodeGetWorldPosition();
|
||||
MT_Vector4 matmul = MT_Vector4(pos[0], pos[1], pos[2], 1.f);
|
||||
MT_Vector4 t = mvmat*matmul;
|
||||
|
||||
glTranslatef( (float)(-t[0]), (float)(-t[1]), (float)(-t[2]) );
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------
|
||||
void KX_BlenderMaterial::UpdateIPO(
|
||||
MT_Vector4 rgba,
|
||||
MT_Vector3 specrgb,
|
||||
MT_Scalar hard,
|
||||
MT_Scalar spec,
|
||||
MT_Scalar ref,
|
||||
MT_Scalar emit,
|
||||
MT_Scalar alpha
|
||||
)
|
||||
{
|
||||
// only works one deep now
|
||||
mMaterial->speccolor[0] = (float)(specrgb)[0];
|
||||
mMaterial->speccolor[1] = (float)(specrgb)[1];
|
||||
mMaterial->speccolor[2] = (float)(specrgb)[2];
|
||||
mMaterial->matcolor[0] = (float)(rgba[0]);
|
||||
mMaterial->matcolor[1] = (float)(rgba[1]);
|
||||
mMaterial->matcolor[2] = (float)(rgba[2]);
|
||||
mMaterial->alpha = (float)(alpha);
|
||||
mMaterial->hard = (float)(hard);
|
||||
mMaterial->emit = (float)(emit);
|
||||
mMaterial->spec_f = (float)(spec);
|
||||
}
|
||||
|
||||
|
||||
PyMethodDef KX_BlenderMaterial::Methods[] =
|
||||
{
|
||||
KX_PYMETHODTABLE( KX_BlenderMaterial, getShader ),
|
||||
KX_PYMETHODTABLE( KX_BlenderMaterial, getMaterialIndex ),
|
||||
// KX_PYMETHODTABLE( KX_BlenderMaterial, getTexture ),
|
||||
// KX_PYMETHODTABLE( KX_BlenderMaterial, setTexture ),
|
||||
|
||||
{NULL,NULL} //Sentinel
|
||||
};
|
||||
|
||||
|
||||
PyTypeObject KX_BlenderMaterial::Type = {
|
||||
PyObject_HEAD_INIT(&PyType_Type)
|
||||
0,
|
||||
"KX_BlenderMaterial",
|
||||
sizeof(KX_BlenderMaterial),
|
||||
0,
|
||||
PyDestructor,
|
||||
0,
|
||||
__getattr,
|
||||
__setattr,
|
||||
0,
|
||||
__repr,
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
PyParentObject KX_BlenderMaterial::Parents[] = {
|
||||
&PyObjectPlus::Type,
|
||||
&KX_BlenderMaterial::Type,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
PyObject* KX_BlenderMaterial::_getattr(const STR_String& attr)
|
||||
{
|
||||
// nodda ?
|
||||
_getattr_up(PyObjectPlus);
|
||||
}
|
||||
|
||||
int KX_BlenderMaterial::_setattr(const STR_String& attr, PyObject *pyvalue)
|
||||
{
|
||||
return PyObjectPlus::_setattr(attr, pyvalue);
|
||||
}
|
||||
|
||||
KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()")
|
||||
{
|
||||
#ifdef GL_ARB_shader_objects
|
||||
if(!RAS_EXT_support._ARB_shader_objects) {
|
||||
PyErr_Format(PyExc_SystemError, "GLSL not supported");
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
Py_INCREF(mShader);
|
||||
return mShader;
|
||||
}
|
||||
#else
|
||||
Py_Return;
|
||||
#endif//GL_ARB_shader_objects
|
||||
}
|
||||
|
||||
KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getMaterialIndex, "getMaterialIndex()")
|
||||
{
|
||||
return PyInt_FromLong( mMaterial->material_index );
|
||||
}
|
||||
|
||||
KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getTexture, "getTexture( index )" )
|
||||
{
|
||||
// TODO: enable python switching
|
||||
return NULL;
|
||||
}
|
||||
|
||||
KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setTexture , "setTexture( index, tex)")
|
||||
{
|
||||
// TODO: enable python switching
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user