Italian 3DS_importer

After some requests, I re-posting, the 3DS_importer by Federico B.
Please Up-grade the script if you understand, python.

The Home page of the author

http://thera.teppisti.it/

[email protected]


#!BPY

""" Registration info for Blender menus:
Name: '3DS'
Blender: 232
Group: 'Import'
Tip: 'Export to 3DS (.3ds) format.'
"""

#//////////////////////////////////// IMPORT3DS /////////////////////////////////*
#/////
#/////	SCRIPT: IMPORT3DS.PY
#/////	VERSION: 0.9
#/////	
#/////	AUTHOR:		Federico B. 2003 - [email protected]
#/////	WEB:		http://thera.teppisti.it
#/////	
#/////	Thanks to GameTutorials.com for the 42 tutorial and to its author
#/////	(wich this work is based on) and to http://web.hypersurf.com/~sully/OpenGL/DemoBox.html.
#/////	Thanks to Reevan Mckay for his scritp full of usefull info.
#/////	And especially, thanks to Blender.it and his comunity for his support and help 
#/////
#/////	REQUIRMENTS:	Python full istallation (www.python.org) and Blender
#/////
#/////	DONE:			The Script now import 3d mesh, material, textures and textures coords, 
#/////					light and camera supp. The standard out is logged in a file blende_out.txt
#/////					in the blender dir. Now it's possible insert the script in the blender script
#/////					dir to use automatic load up in blender import menu.
#/////
#/////	TODO:			Finish light and add keyframe support. For now texture are loaded but not
#/////					correctly assigned to the mesh faces
#/////
#/////	LICENSE:		The script is under GPL and feel free to use it but remember that
#/////					3ds file format is covered by its own license.
#/////
#//////////////////////////////////// IMPORT3DS /////////////////////////////////*

import array
import struct

#import string
#from string import *
import sys

import exceptions

import Blender
from Blender import NMesh, Material, Texture, Scene, Lamp, Image
from Blender.Draw import *
from Blender.BGL import *

import math
from math import sin, cos, sqrt
from math import cos, acos, sin, asin
from math import pi as PI

import exceptions
from exceptions import *

#>------ Primary CChunk, at the beginning of each file
PRIMARY 	=		long("0x4D4D",16);

#>------ Main CChunks
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=			long("0xAFFF",16);		#This stored the texture info
OBJECT 	=			long("0x4000",16);		#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

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

#//////////////////////////////////// C3DMODEL /////////////////////////////////*
#/////
#/////	This class holds the data of an intere model
#/////
#//////////////////////////////////// C3DMODEL /////////////////////////////////*
class C3DModel(object):
	numOfObjects 	= 0;		# The number of objects in the model
	numOfMaterials 	= 0;		# The number of materials for the model
	numOfLights		= 0;
	numOfCameras	= 0;
	pMaterials		= [];		# The list of material information (Textures and colors)
	pObjects		= [];		# The object list for our model
	pLights			= []
	pCameras		= [];
	
#//////////////////////////////////// C3DOBJECT /////////////////////////////////*
#/////
#/////	This class holds the data of a part of a model
#/////
#//////////////////////////////////// C3DOBJECT /////////////////////////////////*  
class C3DObject(object):
	numOfVerts	= 0;			# The number of verts in the model
	numOfFaces	= 0;			# The number of faces in the model
	numTexVertex= 0;			# The number of texture coordinates
	materialID	= [];			# The textures ID to use, which is the index into our texture array
	bHasTexture	= False;		# This is TRUE if there is a texture map for this object
	strName		= "";			# The name of the object
	pVerts		= [];			# The object's vertices
	pNormals	= [];			# The object's normals
	pTexVerts	= [];			# The texture's UV coordinates
	pFaces 		= [];			# The faces information of the object
	
#//////////////////////////////////// CINDICES /////////////////////////////////*
#/////
#/////	This class holds the indeces of a face
#/////
#//////////////////////////////////// CINDICES /////////////////////////////////*  
class CIndices(object):
	a	= 0;
	b	= 0;
	c	= 0;
	bVisible = 0;	# This will hold point1, 2, and 3 index's into the vertex array plus a visible flag
	
#//////////////////////////////////// CFACE /////////////////////////////////*
#/////
#/////	This class colde the data of a face
#/////
#//////////////////////////////////// CFACE /////////////////////////////////*  
class CFace(object):
	vertIndex	= CIndices();	# indicies for the verts that make up this triangle
	coordIndex	= CIndices();	# indicies for the tex coords to texture this face
	
#//////////////////////////////////// CMATERIALINFO /////////////////////////////////*
#/////
#/////	This class holds materilas and texture info
#/////
#//////////////////////////////////// CMATERIALINFO /////////////////////////////////*  
class CMaterialInfo(object):
	strName		=	"";			# The texture name
	strFile		=	"";			# The texture file name (If this is set it's a texture map)
	color		=	[];			# The color of the object (R, G, B)
	ambient		=	[];			# The ambient color
	specular	=	[];			# The speculat color
	numOfFaces	=	0;			# number of Faces covered by the material
	pFaces		=	[];			# Array of Faces covered by the material
	
#//////////////////////////////////// CLIGHT /////////////////////////////////*
#/////
#/////	This class holds materilas and texture info
#/////
#//////////////////////////////////// CLIGHT /////////////////////////////////*  
class CLight(object):	
	position	=	[];
	color		=	[];
	
#//////////////////////////////////// CLIGHT /////////////////////////////////*
#/////
#/////	This class holds materilas and texture info
#/////
#//////////////////////////////////// CLIGHT /////////////////////////////////*  
class CCamera(object):	
	Position	=	[];
	Target		=	[];
	Angle		=	0.0;
	Focus		=	0.0;
	near		=	0.0;
	far			=	0.0;

#//////////////////////////////////// CCHUNK /////////////////////////////////*
#/////
#/////	This class is the basico unit of 3ds subdivision
#/////
#//////////////////////////////////// CCHUNK /////////////////////////////////*  
class CChunk(object):
	ID 			= 0;		# The CChunk's ID
	length 		= 0;		# The length of the CChunk
	bytesRead 	= 0;		# The amount of bytes read within that CChunk

#//////////////////////////////////// CLOAD3DS /////////////////////////////////*
#/////
#/////	#This class load 3ds info and construct a 3d model from it
#/////
#//////////////////////////////////// CLOAD3DS /////////////////////////////////*  
class CLoad3ds(object): 

	#///////////////////////////////// __INIT__ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	#/////
	#/////	Constructor of the class
	#/////
	#///////////////////////////////// __INIT__ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	def __init__(self):
		
		self.m_FilePointer = [];
		
		self.currentChunk	= CChunk();
		self.tempChunk 		= CChunk();
	
	#///////////////////////////////// FREAD \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	#/////
	#/////	This function emulate C++ fread
	#/////
	#///////////////////////////////// FREAD \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	def fread( self, Type, Size, Count ):
		try:
			value = ( struct.unpack( "%s%s" % (Count,Type), self.m_FilePointer.read(Size)));
		except IOError:
			print("IO Error, failed to read the next byte in the stream.");
		return (Size*Count, value[0])
	
	#///////////////////////////////// SKIP \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	#/////
	#/////	This function permit to skip some bytes
	#/////
	#///////////////////////////////// SKIP \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	def skip(self, n):
	
		try:
			self.m_FilePointer.read(n)
		except IOError:
			print("IO Error, failed to read the next byte in the stream.");
			
		return n;
		
	#///////////////////////////////// IMPORT3DS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	#/////
	#/////	Main function of the class, open file and import the 3ds into our 
	#/////	C3DModel class
	#/////
	#///////////////////////////////// IMPORT3DS \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	def Import3DS( self, pModel, strFileName ):
	
		self.currentChunk = CChunk();
		# Open the 3DS file
		try:
			self.m_FilePointer = open(strFileName, "rb");
		except IOError:
			# Make sure we have a valid file pointer (we found the file)
			print("Unable to find the file %s!" % (strFileName));
			return;
			
		# Once we have the file open, we need to read the very first data chunk
		# to see if it's a 3DS file.  That way we don't read an invalid file.
		# If it is a 3DS file, then the first chunk ID will be equal to PRIMARY (some hex num)
		
		# Read the first chuck of the file to see if it's a 3DS file
		self.ReadChunk(self.currentChunk);
		
		# Make sure this is a 3DS file
		if (self.currentChunk.ID != PRIMARY):
			print("Unable to load PRIMARY chuck from file: %s!" % (strFileName));
			print "%s" % self.currentChunk.ID
			return;
			
		# Now we actually start reading in the data.  ProcessNextChunk() is recursive
		# Begin loading objects, by calling this recursive function
		self.ProcessNextChunk(pModel, self.currentChunk);
		# After we have read the whole 3DS file, we want to calculate our own vertex normals.
		# self.ComputeNormals(pModel);		
		# Clean up after everything
		self.CleanUp();
		return;
		
	#///////////////////////////////// CLEAN UP \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	#/////
	#/////	This function cleans up our allocated memory and closes the file
	#/////
	#///////////////////////////////// CLEAN UP \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	def CleanUp( self ):
	
		self.m_FilePointer.close();		# Close the current file pointer
	
	#/////////////////////////// PROCESS NEXT CHUNK \\\\\\\\\\\\\\\\\\\\\\\\\\\*
	#/////
	#/////	This function reads the main sections of the .3DS file, then dives 
	#/////	deeper with recursion
	#/////
	#/////////////////////////// PROCESS NEXT CHUNK \\\\\\\\\\\\\\\\\\\\\\\\\\\*
	def ProcessNextChunk( self, pModel, pPreviousChunk ):
	
		print "CHUNK <--"
		
		self.currentChunk = CChunk();			# The current chunk to load
		
		version	 = 0;							# This will hold the file version
    	
		# Below we check our chunk ID each time we read a new chunk.  Then, if
		# we want to extract the information from that chunk, we do so.
		# If we don't want a chunk, we just read past it.  
    	
		# Continue to read the sub chunks until we have reached the length.
		# After we read ANYTHING we add the bytes read to the chunk and then check
		# check against the length.
		while pPreviousChunk.bytesRead < pPreviousChunk.length:
		
			# Read next Chunk
			self.ReadChunk(self.currentChunk);
    	
			# Check the chunk ID
			if self.currentChunk.ID == VERSION:	# This holds the version of the file
				
				# If the file was made in 3D Studio Max, this chunk has an int that 
				# holds the file version.  Since there might be new additions to the 3DS file
				# format in 4.0, we give a warning to that problem.
				# However, if the file wasn't made by 3D Studio Max, we don't 100% what the
				# version length will be so we'll simply ignore the value
    	
				# Read the file version and add the bytes read to our bytesRead variable
				value = self.fread("H", 2, 1);
				self.currentChunk.bytesRead += value[0]; version = value[1];
				
				print "VERSION %s, file version %s" % (VERSION,version)
				
				self.currentChunk.bytesRead += self.skip(self.currentChunk.length - self.currentChunk.bytesRead);
				
				# If the file version is over 3, give a warning that there could be a problem
				if  (version > int("0x03",16)):
					print( "This 3DS file is over version 3 so it may load incorrectly");
    	
			elif self.currentChunk.ID == OBJECTINFO:	# This holds the version of the mesh
			
				# This chunk holds the version of the mesh.  It is also the head of the MATERIAL
				# and OBJECT chunks.  From here on we start reading in the material and object info.
    	
				# Read the next chunk
				self.ReadChunk(self.tempChunk);
    	
				# Get the version of the mesh
				value = self.fread("H", 2, 1);
				self.tempChunk.bytesRead += value[0]; version = value[1]
				
				print "OBJECTINFO %s, mesh version %s" % (OBJECTINFO,version)
				
				# skip some trash
				self.tempChunk.bytesRead += self.skip(self.tempChunk.length - self.tempChunk.bytesRead);
				
				# Increase the bytesRead by the bytes read from the last chunk
				self.currentChunk.bytesRead += self.tempChunk.bytesRead;
    	
				# Go to the next chunk, which is the object has a texture, it should be MATERIAL, then OBJECT.
				self.ProcessNextChunk(pModel, self.currentChunk);

			elif self.currentChunk.ID == MATERIAL:				# This holds the material information
			 	
				print "MATERIAL"
			
				# This chunk is the header for the material info chunks
				
				# Increase the number of materials
				pModel.numOfMaterials += 1;
				
				# This is used to add to our material list
				newTexture	 = CMaterialInfo();
				
				# Add a empty texture structure to our texture list.
				# If you are unfamiliar with STL's "vector" class, all push_back()
				# does is add a new node onto the list.  I used the vector class
				# so I didn't need to write my own link list functions.  
				pModel.pMaterials.append(newTexture);
    	
				# Proceed to the material loading function
				self.ProcessNextMaterialChunk(pModel, self.currentChunk);
    	
			elif self.currentChunk.ID == OBJECT:					# This holds the name of the object being read
				
				print "OBJECT"
			
				# This chunk is the header for the object info chunks.  It also
				# holds the name of the object.
    	
				# Increase the object count
				pModel.numOfObjects += 1;
				
				# A new object to add to our object list
				newObject = C3DObject(); 
			
				# Get the name of the object and store it, then add the read bytes to our byte counter.
				value = self.GetString();
				self.currentChunk.bytesRead += value[0]; newObject.strName = value[1];
				
				# Add a new CObject node to our list of objects (like a link list)
				pModel.pObjects.append(newObject);
				
				print "OBJECT %s, object name %s" % (OBJECT,value[1])
				
				# Now proceed to read in the rest of the object information
				self.ProcessNextObjectChunk(pModel, newObject, self.currentChunk);
		
			elif self.currentChunk.ID == EDITKEYFRAME:
			
				print "EDITKEYFRAME"
			
				# Because I wanted to make this a SIMPLE tutorial as possible, I did not include
				# the key frame information.  This chunk is the header for all the animation info.
				# In a later tutorial this will be the subject and explained thoroughly.
			
				#ProcessNextKeyFrameChunk(pModel, self.currentChunk);
			
				# Read past this chunk and add the bytes read to the byte counter
				self.currentChunk.bytesRead += self.skip(self.currentChunk.length - self.currentChunk.bytesRead);
			
			else : 
			
				print "CHUNK ELSE at %s " % self.m_FilePointer.tell()
			
				# If we didn't care about a chunk, then we get here.  We still need
				# to read past the unknown or ignored chunk and add the bytes read to the byte counter.
				self.currentChunk.bytesRead += self.skip(self.currentChunk.length - self.currentChunk.bytesRead);
				
			# Add the bytes read from the last chunk to the previous chunk passed in.
			pPreviousChunk.bytesRead += self.currentChunk.bytesRead;
			
		# Free the current CChunk and set it back to the previous CChunk (since it started that way)
		self.currentChunk = pPreviousChunk;

	#///////////////////////////////// PROCESS NEXT OBJECT CHUNK \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	#/////
	#/////	This function handles all the information about the objects in the file
	#/////
	#///////////////////////////////// PROCESS NEXT OBJECT CHUNK \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	def ProcessNextObjectChunk(self, pModel, pObject, pPreviousChunk):
	
		print "--> OBJECT CHUNK  <--"
		# The current chunk to work with
		self.currentChunk = CChunk();
	
		# Continue to read these chunks until we read the end of this sub chunk
		while pPreviousChunk.bytesRead < pPreviousChunk.length:
		
			# Read the next chunk
			self.ReadChunk(self.currentChunk);
			
			# Check which chunk we just read
			if self.currentChunk.ID == OBJECT_MESH:			# This lets us know that we are reading a new object
				print "--> OBJECT_MESH"
				# We found a new object, so let's read in it's info using recursion
				self.ProcessNextObjectChunk(pModel, pObject, self.currentChunk);
				
			elif self.currentChunk.ID == OBJECT_LIGHT:
				print "--> OBJECT_LIGHT"
				# Increase the light count
				pModel.numOfLights += 1;
				
				newLight = CLight(); 
				
				self.ReadLight(newLight, self.currentChunk)
							
				pModel.pLights.append(newLight);
				
			elif self.currentChunk.ID == OBJECT_CAMERA:
				print "--> OBJECT_CAMERA"
				pModel.numOfCameras += 1;
				
				newCamera = CCamera();
				
				pModel.pCameras.append(newCamera);
				
				self.ReadCamera(newCamera, self.currentChunk);
				
			elif self.currentChunk.ID == OBJECT_CAM_RANGES:
				
				print "--> OBJECT_CAM_RANGES"
				self.ReadCameraRanges(pModel, self.currentChunk);
				
			elif self.currentChunk.ID == OBJECT_VERTICES:		# This is the objects vertices
				print "--> OBJECT_VERTICES"
				self.ReadVertices(pObject, self.currentChunk);
			
			elif self.currentChunk.ID == OBJECT_FACES:			# This is the objects face information
				print "--> OBJECT_FACES"
				self.ReadVertexIndices(pObject, self.currentChunk);
			
			elif self.currentChunk.ID == OBJECT_MATERIAL:		# This holds the material name that the object has
				
				print "--> OBJECT_MATERIAL"
				# This chunk holds the name of the material that the object has assigned to it.
				# This could either be just a color or a texture map.  This chunk also holds
				# the faces that the texture is assigned to (In the case that there is multiple
				# textures assigned to one object, or it just has a texture on a part of the object.
				# Since most of my game objects just have the texture around the whole object, and 
				# they aren't multitextured, I just want the material name.
			
				# We now will read the name of the material assigned to this object
				self.ReadObjectMaterial(pModel, pObject, self.currentChunk);			
			
			elif self.currentChunk.ID == OBJECT_UV:				# This holds the UV texture coordinates for the object
				print "--> OBJECT_UV"
				# This chunk holds all of the UV coordinates for our object.  Let's read them in.
				self.ReadUVCoordinates(pObject, self.currentChunk);
			
			else:  
				print "--> OBJECTCHUNK ELSE at %s " % self.m_FilePointer.tell()
				# Read past the ignored or unknown chunks
				self.currentChunk.bytesRead += self.skip(self.currentChunk.length - self.currentChunk.bytesRead);
				
			# Add the bytes read from the last chunk to the previous chunk passed in.
			pPreviousChunk.bytesRead += self.currentChunk.bytesRead;
		
		# Free the current CChunk and set it back to the previous CChunk (since it started that way)
		self.currentChunk = pPreviousChunk;

	#///////////////////////////////// PROCESS NEXT MATERIAL CHUNK \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	#/////
	#/////	This function handles all the information about the material (Texture)
	#/////
	#///////////////////////////////// PROCESS NEXT MATERIAL CHUNK \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	def ProcessNextMaterialChunk(self, pModel, pPreviousChunk):
	
		print "--> MATERIAL CHUNK <--";
		
		# The current chunk to work with
		self.currentChunk = CChunk();
		
		# Continue to read these chunks until we read the end of this sub chunk
		while pPreviousChunk.bytesRead < pPreviousChunk.length:
		
			# Read the next chunk
			self.ReadChunk(self.currentChunk);
		
			# Check which chunk we just read in
			
			if self.currentChunk.ID == MATNAME:		# This chunk holds the name of the material
				
				print "--> MATNAME"
				# Here we read in the material name
				value = self.GetString();
				self.currentChunk.bytesRead += value[0]; pModel.pMaterials[pModel.numOfMaterials - 1].strName = value[1];
				print "--> MATNAME %s, material name %s" % (MATNAME,value[1]);
			
			elif self.currentChunk.ID == MATAMBIENT:			# This holds the R G B color of our object
				print "--> MATAMBIENT";
				self.ReadAmbientChunk((pModel.pMaterials[pModel.numOfMaterials - 1]), self.currentChunk);
				
			elif self.currentChunk.ID == MATDIFFUSE:			# This holds the R G B color of our object
			
				print "--> MATDIFFUSE";
				self.ReadColorChunk((pModel.pMaterials[pModel.numOfMaterials - 1]), self.currentChunk);
			
			elif self.currentChunk.ID == MATSPECULAR:			# This holds the R G B color of our object
				print "--> MATSPECULAR";
				self.ReadSpecularChunk((pModel.pMaterials[pModel.numOfMaterials - 1]), self.currentChunk);
			
			elif self.currentChunk.ID == MATSHINESS:
				# ---> da inserire un campo apposta per il colore
				print "--> MATSHINESS";
				self.currentChunk.bytesRead += self.skip(self.currentChunk.length - self.currentChunk.bytesRead);
			
			elif self.currentChunk.ID == MATMAP:
			
				print "--> MATMAP";
				# Proceed to read in the material information
				self.ProcessNextMaterialChunk(pModel, self.currentChunk);
				
			elif self.currentChunk.ID == MATMAPFILE:			# This stores the file name of the material
				
				print "--> MATMAPFILE"
				# Here we read in the material's file name
				value = self.GetString();
				self.currentChunk.bytesRead += value[0]; pModel.pMaterials[pModel.numOfMaterials - 1].strFile = value[1];
				print "--> MATMAPFILE %s, material file name %s" % (MATMAPFILE,value[1]);
				
			else:
				
				print "--> MATERIAL ELSE at %s " % self.m_FilePointer.tell();
				# Read past the ignored or unknown chunks
				self.currentChunk.bytesRead += self.skip(self.currentChunk.length - self.currentChunk.bytesRead);
			
			# Add the bytes read from the last chunk to the previous chunk passed in.
			pPreviousChunk.bytesRead += self.currentChunk.bytesRead;
			
		# Free the current chunk and set it back to the previous chunk (since it started that way)
		self.currentChunk = pPreviousChunk;
    
	#///////////////////////////////// READ CHUNK \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	#/////
	#/////	This function reads in a chunk ID and it's length in bytes
	#/////
	#///////////////////////////////// READ CHUNK \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	def ReadChunk(self, pChunk):
	
		# This reads the chunk ID which is 2 bytes.
		# The chunk ID is like OBJECT or MATERIAL.  It tells what data is
		# able to be read in within the chunks section.  
		value = self.fread( "H", 2, 1 );
		pChunk.bytesRead = value[0];	pChunk.ID = value[1];
		
		# Then, we read the length of the chunk which is 4 bytes.
		# This is how we know how much to read in, or read past.
		value = self.fread( "L", 4, 1 );
		pChunk.bytesRead += value[0];	pChunk.length = value[1];
		
		
	#///////////////////////////////// GET STRING \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	#/////
	#/////	This function reads in a string of characters
	#/////
	#///////////////////////////////// GET STRING \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	def GetString(self):
	
		string=""

		while (1):
			char=self.m_FilePointer.read(1)
			if (char=='\0'):
				return ( (len(string)+1), string)
			else:
				string=string+char

	#///////////////////////////////// READ LIGHT \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	#/////
	#/////	This function reads in the Light chunk
	#/////
	#///////////////////////////////// READ LIGHT \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	def ReadLight(self, pLight, pChunk):
	
		print "-->READLIGHT"
	
		# Read the Position for the light
		value = self.fread("f",4,1);
		pChunk.bytesRead += value[0]; pLight.position.append(value[1])
		value = self.fread("f",4,1);
		pChunk.bytesRead += value[0]; pLight.position.append(value[1])
		value = self.fread("f",4,1);
		pChunk.bytesRead += value[0]; pLight.position.append(value[1])
		
	#///////////////////////////////// READ COLOR \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	#/////
	#/////	This function reads in the RGB color data
	#/////
	#///////////////////////////////// READ COLOR \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	def ReadColorChunk(self, pMaterial, pChunk):
	
		# Read the color chunk info
		self.ReadChunk(self.tempChunk);
	
		# Read in the R  color (3 bytes - 0 through 255)
		value = self.fread("B",1,1);
		self.tempChunk.bytesRead += 1; pMaterial.color.append(value[1]);
		value = self.fread("B",1,1);
		self.tempChunk.bytesRead += 1; pMaterial.color.append(value[1]);
		value = self.fread("B",1,1);
		self.tempChunk.bytesRead += 1; pMaterial.color.append(value[1]);
				
		# Add the bytes read to our chunk
		pChunk.bytesRead += self.tempChunk.bytesRead;
		
	#///////////////////////////////// READ AMBIENT \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	#/////
	#/////	This function reads in the RGB color data
	#/////
	#///////////////////////////////// READ AMBIENT \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	def ReadAmbientChunk(self, pMaterial, pChunk):
	
		# Read the color chunk info
		self.ReadChunk(self.tempChunk);
	
		# Read in the R  color (3 bytes - 0 through 255)
		value = self.fread("B",1,1);
		self.tempChunk.bytesRead += 1; pMaterial.ambient.append(value[1]);
		value = self.fread("B",1,1);
		self.tempChunk.bytesRead += 1; pMaterial.ambient.append(value[1]);
		value = self.fread("B",1,1);
		self.tempChunk.bytesRead += 1; pMaterial.ambient.append(value[1]);
				
		# Add the bytes read to our chunk
		pChunk.bytesRead += self.tempChunk.bytesRead;
		
	#///////////////////////////////// READ SPECULAR \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	#/////
	#/////	This function reads in the RGB color data
	#/////
	#///////////////////////////////// READ SPECULAR \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	def ReadSpecularChunk(self, pMaterial, pChunk):
	
		# Read the color chunk info
		self.ReadChunk(self.tempChunk);
	
		# Read in the R  color (3 bytes - 0 through 255)
		value = self.fread("B",1,1);
		self.tempChunk.bytesRead += 1; pMaterial.specular.append(value[1]);
		value = self.fread("B",1,1);
		self.tempChunk.bytesRead += 1; pMaterial.specular.append(value[1]);
		value = self.fread("B",1,1);
		self.tempChunk.bytesRead += 1; pMaterial.specular.append(value[1]);
				
		# Add the bytes read to our chunk
		pChunk.bytesRead += self.tempChunk.bytesRead;
		
	#///////////////////////////////// READ CAMERA \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	#/////
	#/////	This function reads in the camera data
	#/////
	#///////////////////////////////// READ CAMERA \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	def ReadCamera(self, pCamera, pChunk):

		print "--> READCAMERA";
		# camera x
		value = self.fread("f", 4, 1);
		pChunk.bytesRead += value[0]; pCamera.Position.append(value[1]);
		# camera y
		value = self.fread("f", 4, 1);
		pChunk.bytesRead += value[0]; pCamera.Position.append(value[1]);
		# camera z
		value = self.fread("f", 4, 1);
		pChunk.bytesRead += value[0]; pCamera.Position.append(value[1]);
		# tartget x
		value = self.fread("f", 4, 1);
		pChunk.bytesRead += value[0]; pCamera.Target.append(value[1]);
		# target y
		value = self.fread("f", 4, 1);
		pChunk.bytesRead += value[0]; pCamera.Target.append(value[1]);
		# target z
		value = self.fread("f", 4, 1);
		pChunk.bytesRead += value[0]; pCamera.Target.append(value[1]);
		# bank angle
		value = self.fread("f", 4, 1);
		pChunk.bytesRead += value[0]; pCamera.Angle = value[1];
		# focus
		value = self.fread("f", 4, 1);
		pChunk.bytesRead += value[0]; pCamera.Focus = value[1];

	#///////////////////////////////// READ CAMERA RANGES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	#/////
	#/////	This function reads in the camra ranges data
	#/////
	#///////////////////////////////// READ CAMERA RANGES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	def ReadCameraRanges(self,pModel, pChunk):
	
		# camera near range
		value = self.fread("f", 4, 1);
		pChunk.bytesRead += value[0]; 
		(pModel.pCameras[len(pModel.pCameras)-1]).near = value[1];
		# camera far range
		value = self.fread("f", 4, 1);
		pChunk.bytesRead += value[0];
		(pModel.pCameras[len(pModel.pCameras)-1]).far = value[1];

		
	#///////////////////////////////// READ VERTEX INDECES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	#/////
	#/////	This function reads in the indices for the vertex array
	#/////
	#///////////////////////////////// READ VERTEX INDECES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	def ReadVertexIndices(self, pObject, pPreviousChunk):
	
		print "--> READVERTEXINDICES"
		
		# In order to read in the vertex indices for the object, we need to first
		# read in the number of them, then read them in.  Remember,
		# we only want 3 of the 4 values read in for each face.  The fourth is
		# a visibility flag for 3D Studio Max that doesn't mean anything to us.
	
		# Read in the number of faces that are in this object (int)
		value = self.fread("H",2,1);
		pPreviousChunk.bytesRead += value[0]; pObject.numOfFaces = value[1];
		
		# Alloc enough memory for the faces and initialize the structure
		pObject.pFaces = [];
	
		# Go through all of the faces in this object
		for i in xrange(pObject.numOfFaces):
			
			# Read the first vertice index for the current face 
			value = self.fread("H",2,1);
			pPreviousChunk.bytesRead += value[0]; a = value[1]
			
			# Read the second vertice index for the current face 
			value = self.fread("H",2,1);
			pPreviousChunk.bytesRead += value[0]; b = value[1]
			
			# Read the third vertice index for the current face 
			value = self.fread("H",2,1);
			pPreviousChunk.bytesRead += value[0]; c = value[1]
			
			# Visibility flag
			value = self.fread("H",2,1);
			pPreviousChunk.bytesRead += value[0]; bVisible = value[1]
			
			# Store the index in our face structure.
			indices = CIndices();
			indices.a = a; indices.b = b; indices.c = c; indices.bVisible = bVisible;
			
			face = CFace();
			face.vertIndex = indices;
			
			pObject.pFaces.append(face);

	#///////////////////////////////// READ UV COORDINATES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	#/////
	#/////	This function reads in the UV coordinates for the object
	#/////
	#///////////////////////////////// READ UV COORDINATES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	def ReadUVCoordinates(self, pObject, pPreviousChunk):
	
		print "--> READUVCOORDINATES"
		
		# In order to read in the UV indices for the object, we need to first
		# read in the amount there are, then read them in.
	
		# Read in the number of UV coordinates there are (int)
		value = self.fread("H", 2, 1);
		pPreviousChunk.bytesRead += value[0]; pObject.numTexVertex = value[1]
		
		# Allocate memory to hold the UV coordinates
		pObject.pTexVerts = []
	
		# Read in the texture coodinates (an array 2 float)
		
		for i in xrange(pObject.numTexVertex):
		
			value = self.fread("f", 4, 1);
			pPreviousChunk.bytesRead += value[0]; vert1 = value[1]
			
			value = self.fread("f", 4, 1);
			pPreviousChunk.bytesRead += value[0]; vert2 = value[1]
			
			TexVector = CVector2(vert1,vert2);
			pObject.pTexVerts.append( TexVector );
			
		
	#///////////////////////////////// READ VERTICES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	#/////
	#/////	This function reads in the vertices for the object
	#/////
	#///////////////////////////////// READ VERTICES \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	def ReadVertices(self, pObject, pPreviousChunk):

		print "--> READVERTICES"
		# Like most chunks, before we read in the actual vertices, we need
		# to find out how many there are to read in.  Once we have that number
		# we then self.fread() them into our vertice array.
	
		# Read in the number of vertices (int)
		value = self.fread("H",2,1);
		pPreviousChunk.bytesRead += value[0]; pObject.numOfVerts = value[1];
		
		pObject.pVerts = [];
		
		for i in xrange(pObject.numOfVerts):

			# Read in the vertices
			value = self.fread("f",4,1);
			pPreviousChunk.bytesRead += value[0]; vert1 = value[1];
			
			value = self.fread("f",4,1);
			pPreviousChunk.bytesRead += value[0]; vert2 = value[1];
			
			value = self.fread("f",4,1);
			pPreviousChunk.bytesRead += value[0]; vert3 = value[1];
						
			VertVector = CVector3(vert1,vert2,vert3);
			pObject.pVerts.append( VertVector );
			
		# Now we should have all of the vertices read in.  Because 3D Studio Max
		# Models with the Z-Axis pointing up (strange and ugly I know!), we need
		# to flip the y values with the z values in our vertices.  That way it
		# will be normal, with Y pointing up.  If you prefer to work with Z pointing
		# up, then just delete this next loop.  Also, because we swap the Y and Z
		# we need to negate the Z to make it come out correctly.
	
		# Go through all of the vertices that we just read and swap the Y and Z values
		for i in xrange(pObject.numOfVerts):

			# Store off the Y value
			fTempY = pObject.pVerts[i].y;
	
			# Set the Y value to the Z value
			pObject.pVerts[i].y = pObject.pVerts[i].z;
	
			# Set the Z value to the Y value, 
			# but negative Z because 3D Studio max does the opposite.
			pObject.pVerts[i].z = -fTempY;
			

	#///////////////////////////////// READ OBJECT MATERIAL \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	#/////
	#/////	This function reads in the material name assigned to the object and sets the materialID
	#/////
	#///////////////////////////////// READ OBJECT MATERIAL \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*
	def ReadObjectMaterial(self, pModel, pObject, pPreviousChunk):
	
		print"--> READOBJECTMATERIAL"
	
		strMaterial = "";	    # This is used to hold the objects material name
	
		# *What is a material?*  - A material is either the color or the texture map of the object.
		# It can also hold other information like the brightness, shine, etc... Stuff we don't
		# really care about.  We just want the color, or the texture map file name really.
	
		# Here we read the material name that is assigned to the current object.
		# strMaterial should now have a string of the material name, like "Material #2" etc..
		value = self.GetString();
		print "--> %s " % value[1]
		pPreviousChunk.bytesRead += value[0]; strMaterial = value[1]
		
		
		nFaces = 0;			#This is used to hold the number of faces for the material
		pFaces = [];		#The array of faces
		
		# Look if our material is applied to some faces rather than the whole object
		value = self.fread("H",2,1);
		pPreviousChunk.bytesRead += value[0]; nFaces = value[1];	
		
		if( nFaces > 0):
				
			# Loop nFaces times to read all the face indexes
			for i in xrange(nFaces):
				value = self.fread("H",2,1);
				pPreviousChunk.bytesRead += value[0];		
				pFaces.append(value[1]);
		else:
			nFaces = 0;	
		# Now that we have a material name, we need to go through all of the materials
		# and check the name against each material.  When we find a material in our material
		# list that matches this name we just read in, then we assign the materialID
		# of the object to that material index.  You will notice that we passed in the
		# model to this function.  This is because we need the number of textures.
		# Yes though, we could have just passed in the model and not the object too.
	
		# Go through all of the textures
		for i in range(pModel.numOfMaterials):
	
			# If the material we just read in matches the current texture name
			if strMaterial == pModel.pMaterials[i].strName:
	
				# Add to the material ids list of this object the current index 'i'
				pObject.materialID.append(i);
				
				# Assing to our material the numbers of faces is applied to and it's face array
				pModel.pMaterials[i].numOfFaces = nFaces;
				
				if( nFaces > 0): 
					# Add to the material a face array of face index
					pModel.pMaterials[i].pFaces = pFaces;
	
				# Now that we found the material, check if it's a texture map.
				# If the strFile has a string length of 1 and over it's a texture
				if len(pModel.pMaterials[i].strFile) > 0:
	
					# Set the object's flag to say it has a texture map to bind.
					pObject.bHasTexture = True;	
					
				break;
	
		# Read past the rest of the chunk since we don't care about shared vertices
		# You will notice we subtract the bytes already read in this chunk from the total length.
		pPreviousChunk.bytesRead += self.skip(pPreviousChunk.length - pPreviousChunk.bytesRead);
	
			
#/////////////////////////////////// CVECTOR3 ///////////////////////////////////*
#/////
#///// This  is the vector class
#/////
#/////////////////////////////////// CVECTOR ////////////////////////////////////*
class CVector3(object):

    def __init__(self,x,y,z):
      self.x = x
      self.y = y
      self.z = z
      
#/////////////////////////////////// CVECTOR2 ///////////////////////////////////*
#/////
#///// This  is the vector class
#/////
#/////////////////////////////////// CVECTOR2 ///////////////////////////////////*
class CVector2(object):

    def __init__(self,x,y):
      self.x = x
      self.y = y

	
EVENT_PATHCHANGE=		1;
EVENT_IMPORT=			2;
EVENT_IMPORT_MATS=		3;
EVENT_QUIT=				4;

bMaterials = False

#//////////////////////////////////// TOBLENDER /////////////////////////////////*
#/////
#/////	Import the info held by Model3d to blender
#/////
#//////////////////////////////////// TOBLENDER /////////////////////////////////*
def ToBlender(Model3d,FileName):

	FilePath = FileName[0:(len(FileName)-len(Blender.sys.basename(FileName)))];
	#Get out the  current scene
	scene = Scene.getCurrent()
	
	#//////////////////////// LOAD ANY LIGHT \\\\\\\\\\\\\\\\\\\\\\\\

	for i in xrange(Model3d.numOfLights):
	
		lite = Blender.Lamp.New('Lamp');
		
		# I cant fogur out where light color is stored :(
		#lite.col( Model3d.pLights[i].color[0], 
		#		  Model3d.pLights[i].color[1], 
		#		  Model3d.pLights[i].color[2]);
	
		lamp = Blender.Object.New('Lamp');
		lamp.setLocation( Model3d.pLights[i].position[0],
						  Model3d.pLights[i].position[1],
						  Model3d.pLights[i].position[2]);
		# Make the lamp a real light object
		lamp.link(lite);
		# add the lamp to the scene
		scene.link(lamp);
		
	
	#//////////////////////// LOAD ANY CAMERA \\\\\\\\\\\\\\\\\\\\\\\\\

	for i in xrange(Model3d.numOfCameras):
	
		cam = Blender.Camera.New('ortho');
		cam.setClipEnd(Model3d.pCameras[i].far);
		cam.setClipStart(Model3d.pCameras[i].near);
		camera = Blender.Object.New('Camera');
		camera.setLocation( Model3d.pCameras[i].Position[0],
							Model3d.pCameras[i].Position[1],
							Model3d.pCameras[i].Position[2]);
		# make the camera a real camera object
		camera.link(cam);
		# add camera to the scene
		scene.link(camera)
	
	#///////////////// LOAD ANY TEXTURE AND MATERIAL \\\\\\\\\\\\\\\\\\\
		
	if bMaterials == True:
		
		mats = []
		
		for i in xrange(0,Model3d.numOfMaterials):
		
			mat = Material.New(Model3d.pMaterials[i].strName);
			# Add color material
			mat.rgbCol =( float(Model3d.pMaterials[i].color[0]),
						  float(Model3d.pMaterials[i].color[1]),
						  float(Model3d.pMaterials[i].color[2]) );
			# Add the specular color
			mat.specCol =( float(Model3d.pMaterials[i].specular[0]),
						   float(Model3d.pMaterials[i].specular[1]),
						   float(Model3d.pMaterials[i].specular[2]) );
			# Add the ambient color (i'm not very sure about this)
			mat.mirCol =( float(Model3d.pMaterials[i].ambient[0]),
						  float(Model3d.pMaterials[i].ambient[1]),
						  float(Model3d.pMaterials[i].ambient[2]) );
			
			# If the material has a texture load in the image
			if (len(Model3d.pMaterials[i].strFile) > 0):
				try:
					imgName = str(FilePath+Model3d.pMaterials[i].strFile);
					img = Image.Load(imgName);
					tex = Blender.Texture.New();
					tex.setType('Image');
					tex.image = img
					mat.setTexture(0, tex);
				except:
					print "failed to load %s texture" % (FilePath+Model3d.pMaterials[i].strFile);
			mats.append(mat);

	#/////////////////////// FOR EVERY OBJECT \\\\\\\\\\\\\\\\\\\\\\\\\
	
	for i in xrange(0,Model3d.numOfObjects):
	
		# Make sure we have valid objects just in case. (size() is in the vector class)
		if(len(Model3d.pObjects) <= 0):
			break;
			
		# Get the current object that we are displaying
		pObject = C3DObject();
		pObject = Model3d.pObjects[i]; 
		
		currMesh = Blender.NMesh.New()
		
		#////////////////////// ADD VERTICES \\\\\\\\\\\\\\\\\\\\\\\\\
		
		# Go through all of the vertices of the object and assign them
		# to the current mesh
		for j in xrange(0,pObject.numOfVerts):
			
			vert = NMesh.Vert(pObject.pVerts[j].x,
							  pObject.pVerts[j].y,
							  pObject.pVerts[j].z);
				
			currMesh.verts.append(vert)
		
		#////////////// ADD MATERIALS AND TEXTURES \\\\\\\\\\\\\\\\\
		
		if bMaterials == True:

			# If Object has a texture Set the flag for the uv texture
			if pObject.bHasTexture == True:
				currMesh.hasFaceUV(1);
				
				# Add Vertex uvco coordinates
				for j in xrange(0,pObject.numTexVertex):
					
					currMesh.verts[j].uvco  = ( pObject.pTexVerts[j].x,pObject.pTexVerts[j].y );
			
			# Add the materials to the mesh
			for m in xrange(0,len(mats)):
				for ids in xrange(0,len(pObject.materialID)):
					if( mats[m].name == Model3d.pMaterials[pObject.materialID[ids]].strName):
						print "Appling to mesh " + str(mats[m].name) + " material"
						currMesh.materials.append(mats[m]);
						
		#/////////////////////// ADD FACES \\\\\\\\\\\\\\\\\\\\\\\\\
		
		# Loop again in faces to assign the face indeces
		for j in xrange(0,pObject.numOfFaces):
			
			face = NMesh.Face();
			face.v.append (currMesh.verts[pObject.pFaces[j].vertIndex.a]);
			face.v.append (currMesh.verts[pObject.pFaces[j].vertIndex.b]);
			face.v.append (currMesh.verts[pObject.pFaces[j].vertIndex.c]);
			currMesh.faces.append(face);

		#////////////// FINALLY CREATE THE MESH \\\\\\\\\\\\\\\\\
			
		# Done, unpdate and draw
		NMesh.PutRaw(currMesh,str(pObject.strName),1)
		
	Blender.Redraw();
			
#//////////////////////////////////// EXITGUI /////////////////////////////////*
#/////
#/////	Exit form the gui
#/////
#//////////////////////////////////// EXITGUI /////////////////////////////////*
def ExitGUI ():
	Exit()
	
#//////////////////////////////////// EVENTGUI /////////////////////////////////*
#/////
#/////	Process events
#/////
#//////////////////////////////////// EVENTGUI /////////////////////////////////*
def	EventGUI (event):
	global bMaterials
	if (event==EVENT_IMPORT):
                bMaterials = False
                Blender.Window.FileSelector(Import, "3DS Import")
	elif (event==EVENT_IMPORT_MATS):
                bMaterials = True
                Blender.Window.FileSelector(Import, "3DS Import")
	elif (event==EVENT_QUIT):
                ExitGUI()
		
#//////////////////////////////////// DRAWGUI /////////////////////////////////*
#/////
#/////	Draw the gui in blender
#/////
#//////////////////////////////////// DRAWGUI /////////////////////////////////*
def DrawGUI():
	
	glClearColor(0.6,0.6,0.6,0)
	glClear(GL_COLOR_BUFFER_BIT)
	Button ("Import",EVENT_IMPORT,32,48,100,32)
	Button ("Import with mats",EVENT_IMPORT_MATS,252,48,100,32)	
	Button ("Cancel",EVENT_QUIT,132,10,100,32)

		
#//////////////////////////////////// IMPORT /////////////////////////////////*
#/////
#/////	Load the 3ds file, parse it and import everything in blender
#/////
#//////////////////////////////////// IMPORT /////////////////////////////////*
def Import(FileName):

	LOGDIR = '.'
	logfile = '3ds_blend_log.txt'
	try:
		st_f=open(LOGDIR + logfile, 'a+', 0) 
	except IOError:
		try:
			st_f = open(LOGDIR + logfile, 'w+', 0)
		except IOError:
			st_f = open(LOGDIR + logfile, 'w+', 0)
	sys.stderr=sys.stdout=st_f

	try:
		Loader = CLoad3ds();
		Model3d= C3DModel()
		Loader.Import3DS(Model3d,FileName);
		ToBlender(Model3d,FileName)
	except IOError:
		Draw()
		print "error while loading/processing 3ds file make sure path is correct"

#//////////////////////////////////// REGISTERGUI /////////////////////////////////*
#/////
#/////
#/////
#//////////////////////////////////// REGISTERGUI /////////////////////////////////*
def RegisterGUI ():
	Register (DrawGUI,None,EventGUI)

#////////////////////////////////////  MAIN SCRIPT /////////////////////////////////*
#/////
#/////	Start the script
#/////
#////////////////////////////////////  MAIN SCRIPT /////////////////////////////////*
RegisterGUI()

Group: ‘Import’
Tip: ‘Export to 3DS (.3ds) format.’

Can you submit this for 2.37?

It is actually an import script. Messing with it now. I’ll see what I get, and post my results here.

I can’t seem to get any object with textures ti actualy import the textures at all.

Hi, I reworked 0.8 and didnt realize that 0.9 was done. Grrr- anyhow Im happy with my progress…
It applies Objects matricies and makes sure it will never overwrite existing data with PutRaw

Also leaves the imported data selected


See Below for an update

:o :o
Why you, have not update the script?
And why, you have removed all the credits?
Why, you have removed all the comments?
Why??

I didnt remove the credits, This was from 0.81, it didnt have the extended credets that 0.9 have.

Yep- its updatedCheckout…

  • the uniqueName function (importers should never overwrite existing data), PutRaw without checking can be nasty.
    *List comprehension for assugning verts, uvs, colors etc.
  • Imported objects are left selected (rather then the last one)

Other changes that arnt necessarly an improvement are a single loop for all tatatypes and Applying of the Objects Matrix.
3ds has applied matrix, but when importing many objects it can help when some have centres and rotations- Can make them Linked objects etc more more easerly.

As for removing comments, I did remove some, but not all.

  • Cambo

:-? :-?
OK, but:
I Hope to see the improvements on the first script and not to see a back improvement.
And the original version of this and the (V.8)script is made by Fedrico B.
http://thera.teppisti.it/
[email protected]
:wink:

All said and done I was just adding a few things I did for my OBJ importer and using a few simple speedups. - Didnt mean to steal your thunder- Your new script with Classes looks very good.

Can we get a 3ds importer licenced under GPL? - Thats what we need for distrobution with Blender.

3ds would be a good format to have blender import, and included with Blender.

  • Cam

:expressionless:
I’m sorry for this flame, but I think, you can do, all you think!
and dont stop please the coding of the script.
Thanks for yours job!

yes, please.
keep it up.
import & export should not be a problem in a pro app as blender is, imo your work is really usefull.

Okay, have fixed the image importing and assigning to faces!

Have added a very comprehensive image loading method.
This is necessary nice 3ds files often include windows case insensitive path names.

Images are looked for where they should be, but if not found it Looks in the 3ds file dir.

  • This is what was done, I extended this to build a list of files in.
  • 3ds files dir
  • Blend files dir
  • Textures dir (set in the Blender preferences) - Uses if it exists.

These files are searched through and a case insesiticve comparison is made, so Images will almost always be found.

get it here- (EDIT Below)
XXXXXX

Willian updated this, materials were inporting wrongly,

http://members.iinet.net.au/~cpbarton/import-3ds_0-82.py
Clipi - Does this work for you?

Thanks, I have made some tests and works well!

I am having a problem with the script; I am taking a digital terrain model from AutoCAD and saving it as a .3ds for importing into Blender. Everything looks great when I import it, but when I switch to face-select mode, many of the face-centers are not appearing in the center of the face.

I know it has something to do with the xyz coordinates of my original mesh in AutoCAD; this is because I checked the coords of one of the verticies in AutoCAD, and it was at an approximate location of x=12,000,000 y=3,000,000.

So I moved the entire mesh from that location to x=0, y=0.

After I moved the entire mesh, the import as a .3ds no longer messed up the face centers.

I loaded 2.36 and tried it with the old 3ds import script (v.07) and the exact same thing happened.

I also tried this using a dxf, and the problem didn’t occur.

I don’t know if this is a bug with blender, or a problem with the import script.

here are the files if you want to see what i am talking about
-Brian

http://www.geocities.com/treacy_brian/3ds_problem.zip

Right BrianT, got some errors when trying to import 3ds files, myself. My 2.41 blender listed the error message in the console and never understood why. so I gave up in the end and moved to export as .dxf which it seemed to work just fine. I am not sure but I think that the problem might be that the .3ds import is made under a python script while the .dxf file is imported “as is”. So for the moment i’ll stick with.dxf