sidebar features
sidebar content

Go Back   Blender Artists Forums > General Forums > Python & Plugins

Reply
 
Thread Tools
reD_Fox's Avatar
reD_Fox reD_Fox is offline
Member
 
Join Date: Mar 2002
Location: Abilene, KS
Posts: 115
Over a year ago, I drafted an initial proposal for a "Blender Python Consortium" and the creation of an associated central online repository for blender scripts. You can find my post here (although I warn you it's a little long):
http://blenderartists.org/forum/showthread?t=45591

Last month, I took some time to slap together a prototype incorporating many of the essential features of my vision for such a repository, and I am continuing to gather and draft ideas for an eventual system. I posted the prototype to the bf-python mailing list the beginning of this month. So far most of the feedback has been positive.

Now, I am posting the prototype to the community.
http://www.hhofministries.org/bpyc

If you are a script author:
Please, help me by signing up for an account and uploading your scripts to the repository. Along the way, jot down some notes (trouble spots, bad pages, missing features, etc.), and submit them to me as feedback (you can post it here, if you want). For best results, read the scripts FAQ first. I need to know what you need to best host, update, and maintain your scripts in the repository in a way that the users can easily find, install, and locate updates.

For everyone else (and authors too):
Download the BPyMan script, and test out its limited possibilities. Hopefully more authors will get their scripts in the repository, so you will have a better selection (there are only two scripts in there right now). I am also gathering ideas for what is needed in an ideal "package manager" for Blender's scripts. So post those here too.

Some quick points:
1. The repository is author maintained (the authors are responsible for the maintenance of and updates to their scripts in the repository).
2. This is just a prototype. Test it like the real thing, but let me know when it breaks. Also, this is a temporary online location.
3. Documentation is limited, I didn't have a lot of time. Did I mention that this was a prototype? I'm a nice guy. Contact me if you can't figure something out. Everything (e-mail, names, etc.) will remain formal and confidential, as well as prompt and friendly.

That's it! Try it out and post your musings here.

Thanks!
Levi
............................................
BPyC script repository:
http://www.hhofministries.org/bpyc

Last edited by reD_Fox; 12-Sep-06 at 23:02.
#1   Old 12-Sep-06, 22:57   
Reply With Quote


patrick7 patrick7 is offline
Member
 
Join Date: Mar 2006
Posts: 65
wow. really neat stuff.

i think if the GUI was made so that it went bottom/up instead of top/down that it would work better within blender as the GUI (at least on mine) always aligns everything to the bottom first (the bottom left of the panel being 0,0) because with a small panel i almost missed that there was a GUI!

otherwise again neat stuff. I think this could be a great application for everyone and should be standard!! The only thing I can think of is I wonder how it handles scripts containing multiple scripts that are distributed with a zip (eg the hotspots script) and I wonder if it could made to pull scripts from other servers via yours so that yours would be like traffic control but wouldn't have to worry about licensing and copyrights and things like that.. in other words maybe a bit like a torrent server.. you would send to the users the link that would get them the script but not the actual script?
#2   Old 13-Sep-06, 19:05   
Reply With Quote
oilbane oilbane is offline
Member
 
Join Date: Dec 2005
Posts: 6
# THIS SCRIPT IS BROKEN INTO 4 PARTS IT IS TOO BIG TO FIT IN ONE POST
# THIS PART 1
# script work with blender 2.42, python 2.4 and winXP
# this script is messy but it works for me :>
# -- the list box, new button, and the sel button is used for
# storing selections in face selection mode
# select 1 of 3 in the list box then select some faces
# and click the new button the face will unselect
# you can then reselect the face by clicking the sel button
# -- the shell tool works like the shell tool in Silo
# -- the bridge face tool works the the bridge face tool in wings

import Blender
from Blender import *
from Blender.Draw import *
from Blender.Mathutils import *
from Blender.BGL import *
Ang= Mathutils.AngleBetweenVecs
global dist
SMALL_NUM=0.00001
dist = Create(0.2)
left = Create(0.0)
right = Create(1.0)
num = Create(2)


EVENT_NOEVENT = 1
EVENT_BEVEL = 2
EVENT_UPDATE = 3
EVENT_RECURS = 4
EVENT_EXIT = 5

Menu1 = None
Menu1_Value = 1
ToggleEvent=[0,0,0]
MeshSelectST = [0,0,0]

def event(evt, val):
if (evt == Blender.Draw.ESCKEY and not val):
Blender.Draw.Exit()


def Flatten_Mesh():
global ToggleEvent

if Blender.Window.EditMode() == 0:
Blender.Draw.PupMenu("run this script in edit mode")
return
user_object = Blender.Scene.GetCurrent().getActiveObject()
if user_object.getType() != "Mesh":
Blender.Draw.PupMenu("this object is not a mesh")
return

Blender.Window.EditMode(0)
SelectedVerts = []

Mesh = user_object.getData()

for verts in Mesh.verts:
if verts.sel == 1:
SelectedVerts.append(verts)

if len(SelectedVerts) > 1:
if ToggleEvent[0] == 1:
vertSum =0
for vert in SelectedVerts: vertSum += vert[0]
vertSum = vertSum / len(SelectedVerts)
for vert in SelectedVerts: vert[0] = vertSum
if ToggleEvent[1] == 1:
vertSum =0
for vert in SelectedVerts: vertSum += vert[1]
vertSum = vertSum / len(SelectedVerts)
for vert in SelectedVerts: vert[1] = vertSum
if ToggleEvent[2] == 1:
vertSum =0
for vert in SelectedVerts: vertSum += vert[2]
vertSum = vertSum / len(SelectedVerts)
for vert in SelectedVerts: vert[2] = vertSum
Mesh.update()
Blender.Window.EditMode(1)
#3   Old 13-Sep-06, 19:29   
Reply With Quote
oilbane oilbane is offline
Member
 
Join Date: Dec 2005
Posts: 6
# PART 2
def AddMesh():
global MeshSelectST,Menu1_Value
SEL = Blender.NMesh.FaceFlags['SELECT']


if Blender.Window.EditMode() == 0:
Blender.Draw.PupMenu("run this script in edit mode")
return
user_object = Blender.Scene.GetCurrent().getActiveObject()
if user_object.getType() != "Mesh":
Blender.Draw.PupMenu("this object is not a mesh")
return

Blender.Window.EditMode(0)
SelectedFases = []

Mesh = user_object.getData()

Mesh = Blender.NMesh.GetRaw(Mesh.name)

for faces in Mesh.faces:
if faces.sel == 1:
SelectedFases.append(faces)
faces.sel = 0
MeshSelectST[Menu1_Value -1] = SelectedFases
Mesh.update()
Blender.Window.EditMode(1)

def SelectStoreMesh():

global MeshSelectST,Menu1_Value

if Blender.Window.EditMode() == 0:
Blender.Draw.PupMenu("run this script in edit mode")
return
user_object = Blender.Scene.GetCurrent().getActiveObject()
if user_object.getType() != "Mesh":
Blender.Draw.PupMenu("this object is not a mesh")
return

Blender.Window.EditMode(0)



Mesh = user_object.getData()
Mesh = Blender.NMesh.GetRaw(Mesh.name)


StoredMesh = MeshSelectST[Menu1_Value -1]
if StoredMesh != 0:
for faces in Mesh.faces:
Boolean1 = False
for sel_faces in StoredMesh:
if len(faces.v) == len(sel_faces.v):
if len(faces.v) == 3:
if faces.v[0].co == sel_faces.v[0].co and faces.v[1].co == sel_faces.v[1].co and faces.v[2].co == sel_faces.v[2].co:
Boolean1 = True
if len(faces.v) == 4:
if faces.v[0].co == sel_faces.v[0].co and faces.v[1].co == sel_faces.v[1].co and faces.v[2].co == sel_faces.v[2].co and faces.v[3].co == sel_faces.v[3].co:
Boolean1 = True
if Boolean1 == True:
faces.sel = 1
Mesh.update()
Blender.Window.EditMode(1)

BIG_NUM = 1<<30

global CULL_METHOD
CULL_METHOD = 0
#4   Old 13-Sep-06, 19:30   
Reply With Quote
oilbane oilbane is offline
Member
 
Join Date: Dec 2005
Posts: 6
# PART 3
class edge:
def __init__(self, v1,v2):
self.v1 = v1
self.v2 = v2


self.length = (v1.co - v2.co).length

self.removed = 0
self.match = None


class edgeLoop:
def __init__(self, loop):


self.centre = Mathutils.Vector()
f = 1.0/len(loop)
for v in loop:
self.centre += v.co * f





self.edges = []
vIdx = 0
while vIdx < len(loop):
self.edges.append( edge(loop[vIdx-1], loop[vIdx]) )
vIdx += 1


for eIdx in range(len(self.edges)-1):
self.edges[eIdx].next = self.edges[eIdx+1]
self.edges[eIdx].prev = self.edges[eIdx-1]

self.edges[-1].next = self.edges[0]
self.edges[-1].prev = self.edges[-2]




self.normal = Mathutils.Vector()
for e in self.edges:
n = Mathutils.CrossVecs(self.centre-e.v1.co, self.centre-e.v2.co)

n.normalize()
self.normal += n
self.normal.normalize()

for e in self.edges:

n1 = e.v1.co
n2 = e.v2.co
n3 = e.prev.v1.co

a = n1-n2
b = n1-n3
normal1 = Mathutils.CrossVecs(a,b)
normal1.normalize()

n1 = e.v2.co
n3 = e.next.v2.co
n2 = e.v1.co

a = n1-n2
b = n1-n3

normal2 = Mathutils.CrossVecs(a,b)
normal2.normalize()


normal1 += normal1 + normal2
normal1.normalize()

e.normal = normal1





def backup(self):

self.backupEdges = self.edges[:]

def restore(self):
self.edges = self.backupEdges[:]
for e in self.edges:
e.removed = 0

def reverse(self):
self.edges.reverse()
for e in self.edges:
e.normal = -e.normal
e.v1, e.v2 = e.v2, e.v1
self.normal = -self.normal


def removeSmallest(self, cullNum, otherLoopLen):
global CULL_METHOD
if CULL_METHOD == 0:

eloopCopy = self.edges[:]
eloopCopy.sort(lambda e1, e2: cmp(e1.length, e2.length ))
eloopCopy = eloopCopy[:cullNum]
for e in eloopCopy:
e.removed = 1
self.edges.remove( e )

else:

culled = 0

step = int(otherLoopLen / float(cullNum))

currentEdge = self.edges[0]
while culled < cullNum:


while currentEdge.removed == 1:

currentEdge = currentEdge.next
smallestEdge = currentEdge

for i in range(step):
currentEdge = currentEdge.next
while currentEdge.removed == 1:
currentEdge = currentEdge.next
if smallestEdge.length > currentEdge.length:
smallestEdge = currentEdge


smallestEdge.removed = 1
self.edges.remove(smallestEdge)

culled+=1
#5   Old 13-Sep-06, 19:31   
Reply With Quote
oilbane oilbane is offline
Member
 
Join Date: Dec 2005
Posts: 6
# PART 4
def faceEdges(me, f):
if len(f) == 3:
return [\
me.findEdge(f[0], f[1]),\
me.findEdge(f[1], f[2]),\
me.findEdge(f[2], f[0])\
]
elif len(f) == 4:
return [\
me.findEdge(f[0], f[1]),\
me.findEdge(f[1], f[2]),\
me.findEdge(f[2], f[3]),\
me.findEdge(f[3], f[0])\
]


def getSelectedEdges(me, ob):
SEL_FLAG = NMesh.EdgeFlags['SELECT']
FGON_FLAG = NMesh.EdgeFlags['FGON']

edges = [e for e in me.edges if e.flag & SEL_FLAG if (e.flag & FGON_FLAG) == 0 ]


edgeFromSelFaces = []
for f in me.faces:
if len(f) >2 and f.sel:
edgeFromSelFaces.extend(faceEdges(me, f))


for e in edgeFromSelFaces:
if edgeFromSelFaces.count(e) > 1:
me.removeEdge(e.v1, e.v2)


fIdx = len(me.faces)
while fIdx:
fIdx-=1
if len(me.faces[fIdx]) > 2:
if me.faces[fIdx].sel:
me.faces.pop(fIdx)
return [e for e in edges if edgeFromSelFaces.count(e) < 2]



def getVertLoops(selEdges):
mainVertLoops = []
while selEdges:
e = selEdges.pop()
contextVertLoop= [e.v1, e.v2]

eIdx = 1


while eIdx:
eIdx = len(selEdges)
while eIdx:
eIdx-=1

if contextVertLoop[0] == selEdges[eIdx].v1:
contextVertLoop.insert(0, selEdges.pop(eIdx).v2)
elif contextVertLoop[0] == selEdges[eIdx].v2:
contextVertLoop.insert(0, selEdges.pop(eIdx).v1)


elif contextVertLoop[-1] == selEdges[eIdx].v1:
contextVertLoop.append(selEdges.pop(eIdx).v2)
elif contextVertLoop[-1] == selEdges[eIdx].v2:
contextVertLoop.append(selEdges.pop(eIdx).v1)
else:
continue


break

if contextVertLoop[0].index == contextVertLoop[-1].index:
contextVertLoop.pop()
mainVertLoops.append(contextVertLoop)

return mainVertLoops


def skin2EdgeLoops(eloop1, eloop2, me, ob, MODE):
if len(eloop1.edges) != len(eloop2.edges):
if len(eloop1.edges) < len(eloop2.edges):
eloop1, eloop2 = eloop2, eloop1

eloop1.backup()
CULL_FACES = len(eloop1.edges) - len(eloop2.edges)
eloop1.removeSmallest(CULL_FACES, len(eloop1.edges))
else:
CULL_FACES = 0

skinVector = eloop1.centre - eloop2.centre

loopDist = skinVector.length


angleBetweenLoopNormals = Mathutils.AngleBetweenVecs(eloop1.normal, eloop2.normal)

if angleBetweenLoopNormals > 90:
eloop2.reverse()


bestEloopDist = BIG_NUM
bestOffset = 0
eLoopIdxs = range(len(eloop1.edges))
for offset in range(len(eloop1.edges)):
totEloopDist = 0

offsetIndexLs = eLoopIdxs[offset:] + eLoopIdxs[: offset]

for e1Idx, e2Idx in enumerate(offsetIndexLs):
totEloopDist += ((eloop1.edges[e1Idx].v1.co - eloop2.edges[e2Idx].v1.co).length / loopDist)
totEloopDist += ((eloop1.edges[e1Idx].v2.co - eloop2.edges[e2Idx].v2.co).length / loopDist)

if totEloopDist > bestEloopDist:
break

if totEloopDist < bestEloopDist:
bestOffset = offset
bestEloopDist = totEloopDist

eloop2.edges = eloop2.edges[bestOffset:] + eloop2.edges[:bestOffset]



for loopIdx in range(len(eloop2.edges)):
e1 = eloop1.edges[loopIdx]
e2 = eloop2.edges[loopIdx]

e1.match = e2; e2.match = e1

f = NMesh.Face([e1.v1, e1.v2, e2.v2, e2.v1])

f.sel = 1
me.faces.append(f)

if CULL_FACES:
FAN_FILLED_FACES = 0

contextEdge = eloop1.edges[0]
while FAN_FILLED_FACES < CULL_FACES:
while contextEdge.next.removed == 0:
contextEdge = contextEdge.next

vertFanPivot = contextEdge.match.v2

while contextEdge.next.removed == 1:

f = NMesh.Face([contextEdge.next.v1, contextEdge.next.v2, vertFanPivot] )


f.sel = 1
me.faces.append(f)

contextEdge.next.removed = 1

contextEdge = contextEdge.next
FAN_FILLED_FACES += 1

eloop1.restore()

Last edited by oilbane; 13-Sep-06 at 19:39.
#6   Old 13-Sep-06, 19:32   
Reply With Quote
Koba Koba is offline
Member
 
Join Date: Jan 2004
Posts: 1,096
Hi...when I heard "BPyMan" I was reminded of Samadam's script (which it is now an outgrowth of). Anyhow, I've long felt that there should be a central repository for Blender Python (something where you can select the scripts from within Blender) so I wish you the best of luck!

Hopefully, one day we will have a fully fledged way of managing Python scripts off the internet while working.

Koba
............................................
[Sanity is not statistical]
#7   Old 13-Sep-06, 19:33   
Reply With Quote
oilbane oilbane is offline
Member
 
Join Date: Dec 2005
Posts: 6
# part 5
def main():
global CULL_METHOD

is_editmode = Window.EditMode()
if is_editmode: Window.EditMode(0)
ob = Scene.GetCurrent().getActiveObject()
if ob == None or ob.getType() != 'Mesh':
return

me = ob.getData()
if not me.edges:
Draw.PupMenu('Error, add edge data first')
if is_editmode: Window.EditMode(1)
return


selEdges = getSelectedEdges(me, ob)
vertLoops = getVertLoops(selEdges)

if len(vertLoops) > 2:
choice = Draw.PupMenu('Loft '+str(len(vertLoops))+' edge loops%t|loop|segment')
if choice == -1:
if is_editmode: Window.EditMode(1)
return
elif len(vertLoops) < 2:
PupMenu('Error, No Vertloops found%t|if you have a valid selection, go in and out of face edit mode to update the selection state.')
if is_editmode: Window.EditMode(1)
return
else:
choice = 2


if False in [len(v) == len(vertLoops[0]) for v in vertLoops]:
CULL_METHOD = PupMenu('Small to large edge loop distrobution method%t|remove edges evenly|remove smallest edges edges')
if CULL_METHOD == -1:
if is_editmode: Window.EditMode(1)
return

if CULL_METHOD ==1:
CULL_METHOD = 0
else:
CULL_METHOD = 1


time1 = sys.time()
edgeLoops = []
for vloop in vertLoops:
edgeLoops.append(edgeLoop(vloop))


edgeOrderedList = [edgeLoops.pop()]

bestSoFar = BIG_NUM
bestIdxSoFar = None
for edLoopIdx, edLoop in enumerate(edgeLoops):
l =(edgeOrderedList[-1].centre - edLoop.centre).length
if l < bestSoFar:
bestIdxSoFar = edLoopIdx
bestSoFar = l

edgeOrderedList.append( edgeLoops.pop(bestIdxSoFar) )

while edgeLoops:
bestSoFar = BIG_NUM
bestIdxSoFar = None
first_or_last = 0
for edLoopIdx, edLoop in enumerate(edgeLoops):
l1 =(edgeOrderedList[-1].centre - edLoop.centre).length

if l1 < bestSoFar:
bestIdxSoFar = edLoopIdx
bestSoFar = l1
first_or_last = 1

l2 =(edgeOrderedList[0].centre - edLoop.centre).length
if l2 < bestSoFar:
bestIdxSoFar = edLoopIdx
bestSoFar = l2
first_or_last = 0
if first_or_last:
edgeOrderedList.append( edgeLoops.pop(bestIdxSoFar) )
else:
edgeOrderedList.insert(0, edgeLoops.pop(bestIdxSoFar) )

for i in range(len(edgeOrderedList)-1):
skin2EdgeLoops(edgeOrderedList[i], edgeOrderedList[i+1], me, ob, 0)
if choice == 1 and len(edgeOrderedList) > 2:
skin2EdgeLoops(edgeOrderedList[0], edgeOrderedList[-1], me, ob, 0)

me.update(1, 1, 0)
if is_editmode: Window.EditMode(1)
#8   Old 13-Sep-06, 19:41   
Reply With Quote
reD_Fox's Avatar
reD_Fox reD_Fox is offline
Member
 
Join Date: Mar 2002
Location: Abilene, KS
Posts: 115
Quote:
Originally Posted by patrick7
i think if the GUI was made so that it went bottom/up instead of top/down that it would work better within blender as the GUI (at least on mine) always aligns everything to the bottom first (the bottom left of the panel being 0,0) because with a small panel i almost missed that there was a GUI!
Yeah. I just used SamAdam/theeth's original GUI. I didn't have a lot of time. Run it full screen!

Quote:
Originally Posted by patrick7
The only thing I can think of is I wonder how it handles scripts containing multiple scripts that are distributed with a zip (eg the hotspots script) and I wonder if it could made to pull scripts from other servers via yours so that yours would be like traffic control but wouldn't have to worry about licensing and copyrights and things like that.. in other words maybe a bit like a torrent server.. you would send to the users the link that would get them the script but not the actual script?
It should handle multiple files pretty well. There are a few kinks (it makes sure that none of the files in the repository have the same name), but the capability is there. The multiple server thing is a new idea for me. Thanks!

To Koba: Thanks! I hope so too.

oilbane: Sorry, maybe it wasn't clear. Do not post your script here. Sign up for an account with the prototype, follow the guidelines in the BPyC faq, and upload your files to the repository. Then, you can add simple documentation and point others to your script. Also, whenever you update your script, add a new version for the updated files, and users of the BPyMan script will be able to update your script on their machine. PM me or contact me if you have trouble, and I can walk you through the process. Thanks!

Levi
............................................
BPyC script repository:
http://www.hhofministries.org/bpyc

Last edited by reD_Fox; 14-Sep-06 at 03:04.
#9   Old 13-Sep-06, 20:14   
Reply With Quote
lucidMonkey's Avatar
lucidMonkey lucidMonkey is offline
Donating Member
 
Join Date: Feb 2004
Location: Everywhere
Posts: 863
oilbane: try CODE tags next time

reD_Fox: it would be cool if the best and still relevant of what exists now were rounded up.

http://blender.org/cms/Python_Scripts.3.0.html
http://alienhelpdesk.com/index.php?id=39
http://members.iinet.net.au/~cpbarton/ideasman/index_old.html
http://uselessdreamer.byethost32.com/
http://jmsoler.free.fr/didacticiel/b.../eng_index.htm
http://www.harkyman.com/scripts.html
there are definately more...


Hope that helps...
............................................
Blend On!

Last edited by lucidMonkey; 14-Sep-06 at 02:27.
#10   Old 14-Sep-06, 02:21   
Reply With Quote
reD_Fox's Avatar
reD_Fox reD_Fox is offline
Member
 
Join Date: Mar 2002
Location: Abilene, KS
Posts: 115
Quote:
Originally Posted by lucidMonkey View Post
reD_Fox: it would be cool if the best and still relevant of what exists now were rounded up.
Yeah, it would. As you probably know, an effort to gather a list of links to scripts is being organized at http://blenderartists.org/forum/showthread.php?t=74659

It is a similar concept, but I'm planning for a more long-term solution. Also, I won't be doing any of the "rounding up" myself. It has been my philosophy that it is better to put that power in the hands of the authors than to depend on a select few to do it.

However, I am a little disheartened at the lack of response from authors (but it's only been a couple of days). I'll see if I can personally contact a few of them in the next few days.

oilbane: I got your e-mail and sent you a reply, are you still having trouble?

Thanks!
Levi
............................................
BPyC script repository:
http://www.hhofministries.org/bpyc
#11   Old 14-Sep-06, 22:48   
Reply With Quote
reD_Fox's Avatar
reD_Fox reD_Fox is offline
Member
 
Join Date: Mar 2002
Location: Abilene, KS
Posts: 115
After talking a bit with patrick7, I realized that it may be good to post a few directions here, so that people know something about the process involved with putting their scripts in the repository. You can sign up for an account, see if it works for you, and if it doesn't, you can delete your script and no one will be the wiser.
  1. Create an account so that people know whose script it is.
  2. After you have activated your account: login, go to your profile, and add a script.
  3. Then, add a version to that script.
  4. Edit the version to add your files to that version.
  5. Download and test!
Note that your script won't show up in the repository for download until you've completed step 4. Also, you might try starting with an older version of your script, download it using the BPyMan, and then make a new version to see what happens for the user when a new version of a script is available. Feel free to play around with the system. It's not exactly "public" yet, so you can get away with quite a bit of messing around. Don't worry, you won't break it. (But if you do, you'll have just helped me find a bug.) If the FAQ doesn't answer your questions, contact me and I'll see if I can help.

Levi
............................................
BPyC script repository:
http://www.hhofministries.org/bpyc
#12   Old 18-Sep-06, 23:09   
Reply With Quote
Reply

Bookmarks

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
VirtualUndo Script - Anyone want to Help? mthoenes Python & Plugins 26 12-Nov-06 17:09
NEW: Aligner/Displacer/Randomizer Script RobertT Python & Plugins 19 07-Nov-06 16:24
New Script List theeth Python & Plugins 28 07-Mar-06 00:56
.blend append and link script zenoscope Python & Plugins 0 16-Jan-06 12:25
auto UV mapping python script -> speeds up level texturin lizard809 Game Engine Support and Discussion 7 25-Mar-03 01:38


All times are GMT. The time now is 22:50.


Powered by vBulletin® Version 3.7.3
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Logo and website design copyright © 2006 by froodee design bureau. All rights reserved.
Other Blender Sites
new icon Blender Homepage »
The official Blender homepage
new icon BlenderNation »
Fresh Blender News, Every Day
new icon Blenderart Magazine »
Blender articles, tutorials and images.
Blender Headlines
Featured Artwork
Short animation: Barrel by Phlopper
Woolly mammoth by sebastian_k
Photorealistic classic furniture by eMirage
Social BlenderArtists