Tuesday merger of bf-blender into orange branch.

This commit is contained in:
2006-01-10 22:10:14 +00:00
139 changed files with 23322 additions and 755 deletions

View 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...
}
}

View 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

View 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

View 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;
}

View 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

View 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);
}

View 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

View 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
{
}

View 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

View 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()
{
}

View 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;
}

View 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){}
};

View 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);
}
}

View 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

View 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'))

View 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
'''

View 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
View 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)

View 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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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)

View 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")

View 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)

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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

View File

@@ -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 */

View File

@@ -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);

View File

@@ -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

View File

@@ -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;
}
}
}

View File

@@ -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) {

View File

@@ -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);
}
}

View File

@@ -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++];

View File

@@ -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);

View File

@@ -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);

View File

@@ -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

View File

@@ -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)*/

View File

@@ -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 {

View File

@@ -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

View File

@@ -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;

View File

@@ -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 *

View File

@@ -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

View File

@@ -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 );

View File

@@ -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,

View File

@@ -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)".

View File

@@ -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.

View File

@@ -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

View File

@@ -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):

View File

@@ -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++){

View File

@@ -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;*/
}

View File

@@ -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

View File

@@ -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");

View File

@@ -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);

View File

@@ -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 */

View File

@@ -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))

View File

@@ -784,3 +784,4 @@ void ob_clear_constraints(void)
BIF_undo_push("Clear Constraint(s)");
}

View File

@@ -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);
}

View File

@@ -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];
}

View File

@@ -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;
}
}
}
}

View File

@@ -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);

View File

@@ -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]);

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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);
}
}

View File

@@ -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;
}
} */
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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();
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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()
{

View File

@@ -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();

View File

@@ -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)

View File

@@ -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();
};

View File

@@ -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);
}
}
}

View File

@@ -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

View File

@@ -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.

View File

@@ -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',

View File

@@ -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
//

View File

@@ -184,6 +184,7 @@ public:
#ifndef NO_EXP_PYTHON_EMBEDDING
#include "PyObjectPlus.h"
#include "object.h"

View File

@@ -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)

View File

@@ -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 !

View File

@@ -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();

View File

@@ -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)
{

View File

@@ -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,

View File

@@ -142,5 +142,8 @@ protected:
NG_LoopBackNetworkDeviceInterface* m_networkdevice;
/** Sound device. */
SND_IAudioDevice* m_audiodevice;
bool m_blendermat;
};

View File

@@ -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);

View 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];
}

View 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

View 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;
}

View 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__

View 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;

View 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__

View 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