2003-04-26 11:56:44 +00:00
|
|
|
/* exotic.c
|
2002-10-12 11:37:38 +00:00
|
|
|
*
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
* ***** BEGIN GPL/BL DUAL 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. The Blender
|
|
|
|
* Foundation also sells licenses for use in proprietary software under
|
|
|
|
* the Blender License. See http://www.blender.org/BL/ for information
|
|
|
|
* about this.
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* The Original Code is: all of this file.
|
|
|
|
*
|
2004-10-15 13:04:21 +00:00
|
|
|
* Contributor(s):
|
|
|
|
* - Martin DeMello
|
|
|
|
* Added dxf_read_arc, dxf_read_ellipse and dxf_read_lwpolyline
|
|
|
|
* Copyright (C) 2004 by Etheract Software Labs
|
2002-10-12 11:37:38 +00:00
|
|
|
*
|
|
|
|
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
|
|
|
*
|
|
|
|
* eigen videoscape formaat:
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* lamp:
|
|
|
|
* 3DG2
|
|
|
|
aantal_lampen
|
|
|
|
|
|
|
|
type
|
|
|
|
spsi spbl
|
|
|
|
r, g, b, energy
|
|
|
|
locx, locy, locz
|
|
|
|
vecx, vecy, vecz
|
|
|
|
|
|
|
|
|
|
|
|
curve / nurbs:
|
|
|
|
3DG3
|
|
|
|
5 of 11 (curve of surf)
|
|
|
|
aantal_nurbs
|
|
|
|
extr1 extr2
|
|
|
|
|
|
|
|
mat[0][0] mat[0][1] mat[0][2] mat[0][3]
|
|
|
|
mat[1][0] mat[1][1] mat[1][2] mat[1][3]
|
|
|
|
...
|
|
|
|
|
|
|
|
type
|
|
|
|
pntsu, pntsv
|
|
|
|
resolu, resolv
|
|
|
|
orderu, orderv
|
|
|
|
flagu, flagv
|
|
|
|
|
|
|
|
(als type==nurb) x y z w
|
|
|
|
x y z w
|
|
|
|
...
|
|
|
|
(als type==bez) xyz xyz xyz h1 h2 h3
|
|
|
|
xyz xyz xyz h1 h2 h3
|
|
|
|
...
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <ctype.h> /* isdigit, isspace */
|
|
|
|
#include <math.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <string.h>
|
2002-11-25 12:02:15 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
#ifndef WIN32
|
|
|
|
#include <unistd.h>
|
|
|
|
#else
|
|
|
|
#include "BLI_winstuff.h"
|
|
|
|
#include <io.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
#include "DNA_object_types.h"
|
|
|
|
#include "DNA_mesh_types.h"
|
2004-03-20 22:55:42 +00:00
|
|
|
#include "DNA_meshdata_types.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
#include "DNA_material_types.h"
|
|
|
|
#include "DNA_lamp_types.h"
|
|
|
|
#include "DNA_curve_types.h"
|
|
|
|
#include "DNA_image_types.h"
|
|
|
|
#include "DNA_camera_types.h"
|
|
|
|
#include "DNA_scene_types.h"
|
|
|
|
#include "DNA_view3d_types.h"
|
|
|
|
#include "DNA_userdef_types.h"
|
|
|
|
|
|
|
|
#include "BKE_bad_level_calls.h"
|
|
|
|
#include "BKE_utildefines.h"
|
|
|
|
#include "BLI_blenlib.h"
|
|
|
|
#include "BLI_arithb.h"
|
|
|
|
#include "BLI_editVert.h"
|
|
|
|
|
|
|
|
#include "BKE_global.h"
|
|
|
|
#include "BKE_main.h"
|
|
|
|
#include "BKE_mesh.h"
|
|
|
|
#include "BKE_library.h"
|
|
|
|
#include "BKE_global.h"
|
|
|
|
#include "BKE_object.h"
|
|
|
|
#include "BKE_material.h"
|
|
|
|
#include "BKE_exotic.h"
|
|
|
|
/* #include "BKE_error.h" */
|
|
|
|
#include "BKE_screen.h"
|
|
|
|
#include "BKE_displist.h"
|
|
|
|
#include "BKE_curve.h"
|
|
|
|
|
2003-11-23 14:28:46 +00:00
|
|
|
#include "BPY_extern.h"
|
2002-10-12 11:37:38 +00:00
|
|
|
|
Biiig commit! Thanks to 2-3 weeks of cvs freeze...
Render:
- New; support for dual CPU render (SDL thread)
Currently only works with alternating scanlines, but gives excellent
performance. For both normal render as unified implemented.
Note the "mutex" locks on z-transp buffer render and imbuf loads.
- This has been made possible by major cleanups in render code, especially
getting rid of globals (example Tin Tr Tg Tb Ta for textures) or struct
OSA or using Materials or Texture data to write to.
- Made normal render fully 4x32 floats too, and removed all old optimizes
with chars or shorts.
- Made normal render and unified render use same code for sky and halo
render, giving equal (and better) results for halo render. Old render
now also uses PostProcess options (brightness, mul, gamma)
- Added option ("FBuf") in F10 Output Panel, this keeps a 4x32 bits buffer
after render. Using PostProcess menu you will note an immediate re-
display of image too (32 bits RGBA)
- Added "Hue" and "Saturation" sliders to PostProcess options
- Render module is still not having a "nice" API, but amount of dependencies
went down a lot. Next todo: remove abusive "previewrender" code.
The last main global in Render (struct Render) now can be re-used for fully
controlling a render, to allow multiple "instances" of render to open.
- Renderwindow now displays a smal bar on top with the stats, and keeps the
stats after render too. Including "spare" page support.
Not only easier visible that way, but also to remove the awkward code that
was drawing stats in the Info header (extreme slow on some ATIs too)
- Cleaned up blendef.h and BKE_utildefines.h, these two had overlapping
defines.
- I might have forgotten stuff... and will write a nice doc on the architecture!
2004-12-27 19:28:52 +00:00
|
|
|
#include "blendef.h"
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
static int is_dxf(char *str);
|
|
|
|
static void dxf_read(char *filename);
|
2004-03-30 03:10:34 +00:00
|
|
|
static int is_stl(char *str);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2004-03-30 03:10:34 +00:00
|
|
|
static int is_stl_ascii(char *str)
|
|
|
|
{
|
|
|
|
FILE *fpSTL;
|
2004-07-23 20:50:44 +00:00
|
|
|
unsigned char buffer[1000];
|
|
|
|
int numread, i;
|
|
|
|
|
|
|
|
fpSTL = fopen(str, "rb");
|
|
|
|
if ( (numread = fread( (void *) buffer, sizeof(char), 1000, fpSTL)) <= 0 )
|
|
|
|
{ fclose(fpSTL); return 0; }
|
|
|
|
|
|
|
|
for (i=0; i < numread; ++i) {
|
|
|
|
/* if bit 8 is set we assume binary */
|
|
|
|
if (buffer[i] & 0x80)
|
|
|
|
{ fclose(fpSTL); return 0; }
|
|
|
|
}
|
|
|
|
|
|
|
|
buffer[5] = '\0';
|
|
|
|
if ( !(strstr(buffer, "solid")) && !(strstr(buffer, "SOLID")) )
|
|
|
|
{ fclose(fpSTL); return 0; }
|
2004-03-30 03:10:34 +00:00
|
|
|
|
|
|
|
fclose(fpSTL);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int is_stl(char *str)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
i = strlen(str) - 3;
|
|
|
|
if ( (str[i] !='s') && (str[i] !='S'))
|
|
|
|
return 0;
|
|
|
|
i++;
|
|
|
|
if ( (str[i] !='t') && (str[i] !='T'))
|
|
|
|
return 0;
|
|
|
|
i++;
|
|
|
|
if ( (str[i] !='l') && (str[i] !='L'))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define READSTLVERT { \
|
|
|
|
if (fread(mvert->co, sizeof(float), 3, fpSTL) != 3) { \
|
|
|
|
char error_msg[255]; \
|
|
|
|
MEM_freeN(vertdata); \
|
|
|
|
MEM_freeN(facedata); \
|
|
|
|
fclose(fpSTL); \
|
|
|
|
sprintf(error_msg, "Problems reading face %d!", i); \
|
|
|
|
error(error_msg); \
|
|
|
|
return; \
|
|
|
|
} \
|
|
|
|
else { \
|
|
|
|
if (G.order==B_ENDIAN) { \
|
|
|
|
SWITCH_INT(mvert->co[0]); \
|
|
|
|
SWITCH_INT(mvert->co[1]); \
|
|
|
|
SWITCH_INT(mvert->co[2]); \
|
|
|
|
} \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
2004-04-12 19:29:52 +00:00
|
|
|
static void simple_vertex_normal_blend(short *no, short *ble)
|
|
|
|
{
|
|
|
|
if(no[0]==0 && no[1]==0 && no[2]==0) {
|
|
|
|
VECCOPY(no, ble);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
no[0]= (2*no[0] + ble[0])/3;
|
|
|
|
no[1]= (2*no[1] + ble[1])/3;
|
|
|
|
no[2]= (2*no[2] + ble[2])/3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void mesh_add_normals_flags(Mesh *me)
|
|
|
|
{
|
|
|
|
MVert *v1, *v2, *v3, *v4;
|
|
|
|
MFace *mface;
|
|
|
|
float nor[3];
|
|
|
|
int a;
|
|
|
|
short sno[3];
|
|
|
|
|
|
|
|
mface= me->mface;
|
|
|
|
for(a=0; a<me->totface; a++, mface++) {
|
|
|
|
if(mface->v3) {
|
|
|
|
mface->edcode= ME_V1V2 | ME_V2V3; // only draw 2 for speed
|
|
|
|
|
|
|
|
v1= me->mvert+mface->v1;
|
|
|
|
v2= me->mvert+mface->v2;
|
|
|
|
v3= me->mvert+mface->v3;
|
|
|
|
v4= me->mvert+mface->v4;
|
|
|
|
|
|
|
|
CalcNormFloat(v1->co, v2->co, v3->co, nor);
|
|
|
|
sno[0]= 32767.0*nor[0];
|
|
|
|
sno[1]= 32767.0*nor[1];
|
|
|
|
sno[2]= 32767.0*nor[2];
|
|
|
|
|
|
|
|
simple_vertex_normal_blend(v1->no, sno);
|
|
|
|
simple_vertex_normal_blend(v2->no, sno);
|
|
|
|
simple_vertex_normal_blend(v3->no, sno);
|
|
|
|
if(mface->v4) {
|
|
|
|
simple_vertex_normal_blend(v4->no, sno);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-03-30 03:10:34 +00:00
|
|
|
static void read_stl_mesh_binary(char *str)
|
|
|
|
{
|
|
|
|
FILE *fpSTL;
|
|
|
|
Object *ob;
|
|
|
|
Mesh *me;
|
|
|
|
MVert *mvert, *vertdata;
|
|
|
|
MFace *mface, *facedata;
|
|
|
|
unsigned int numfacets = 0, i, j, vertnum;
|
|
|
|
unsigned int maxmeshsize, nummesh, lastmeshsize;
|
|
|
|
unsigned int totvert, totface;
|
|
|
|
|
|
|
|
fpSTL= fopen(str, "rb");
|
|
|
|
if(fpSTL==NULL) {
|
|
|
|
error("Can't read file");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
fseek(fpSTL, 80, SEEK_SET);
|
|
|
|
fread(&numfacets, 4*sizeof(char), 1, fpSTL);
|
|
|
|
if (G.order==B_ENDIAN) {
|
|
|
|
SWITCH_INT(numfacets);
|
|
|
|
}
|
|
|
|
|
|
|
|
maxmeshsize = MESH_MAX_VERTS/3;
|
|
|
|
|
|
|
|
nummesh = (numfacets / maxmeshsize) + 1;
|
|
|
|
lastmeshsize = numfacets % maxmeshsize;
|
|
|
|
|
|
|
|
if (numfacets) {
|
|
|
|
for (j=0; j < nummesh; ++j) {
|
|
|
|
/* new object */
|
|
|
|
if (j == nummesh-1) {
|
|
|
|
totface = lastmeshsize;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
totface = maxmeshsize;
|
|
|
|
}
|
|
|
|
totvert = 3 * totface;
|
|
|
|
|
|
|
|
vertdata = MEM_callocN(totvert*sizeof(MVert), "mverts");
|
|
|
|
facedata = MEM_callocN(totface*sizeof(MFace), "mface");
|
|
|
|
|
|
|
|
vertnum = 0;
|
|
|
|
mvert= vertdata;
|
|
|
|
mface = facedata;
|
|
|
|
for (i=0; i < totface; i++) {
|
|
|
|
fseek(fpSTL, 12, SEEK_CUR); /* skip the face normal */
|
|
|
|
READSTLVERT;
|
|
|
|
mvert++;
|
|
|
|
READSTLVERT;
|
|
|
|
mvert++;
|
|
|
|
READSTLVERT;
|
|
|
|
mvert++;
|
|
|
|
|
|
|
|
mface->v1 = vertnum++;
|
|
|
|
mface->v2 = vertnum++;
|
|
|
|
mface->v3 = vertnum++;
|
|
|
|
mface++;
|
|
|
|
|
|
|
|
fseek(fpSTL, 2, SEEK_CUR);
|
|
|
|
}
|
|
|
|
|
|
|
|
ob= add_object(OB_MESH);
|
|
|
|
me= ob->data;
|
|
|
|
me->mvert = vertdata;
|
|
|
|
me->mface = facedata;
|
|
|
|
me->totface = totface;
|
|
|
|
me->totvert = totvert;
|
|
|
|
|
2004-04-22 22:33:57 +00:00
|
|
|
mesh_add_normals_flags(me);
|
EditMesh refactory + undo recode
The changelog is very long... it's on the web too:
http://www.blender3d.org/cms/Mesh_editing_rewrite.425.0.html
EditMesh refactor notes (user)
**** New selection modes
When entering Edit Mode for a Mesh, you now have the choice for three selection modes. These are shown as icons in the 3D header (hotkey is being searched for!).
- Vertex Select
Select vertices as usual, fully compatible with how previous version work
- Edge Select
Vertices are not drawn anymore, and selections happen by default on the edges. It is a true edge select, meaning that you can select three out of four edges in a face, without automatic having the 4th edge selected.
- Face Select
Instead of vertices, now selection 'points' are drawn in the face centers. Selected faces also get a colored outline, like for edges. This also is true face select, for each face individual regardless selection status of its vertices or edges.
While holding SHIFT, and press a selection mode, you can also combine the above choices. Now selection becomes mixed, and will behave as expected.
For example; in Edge+Face select mode, selecting the 4 edges of a face will select the face too.
The selection modes and optional drawing modes (like transparant faces, normals, or solid drawing) all work together. All of Blender's mesh editing tools now react to the correct selection mode as well.
Most noticeable it's in:
**** Extrude
Extruding in Edge or Face Select mode allows much more precise control over what's extruded and what should be excluded. Try for example a checker pattern selection, and extrude it.
New is the fixed translation when faces are extruded. This always follows the (averaged) face normal(s) of the old face(s), enabling much easier working in 3D views . A single 'G' (Grab) or 'R' (Rotate) or 'S' (Scale) will change transform modus as usual.
**** Other things to note
- Hiding edges/faces will also behave different based on Select Mode.
- while editing, normals of faces are updated always now
- Border select (BKEY) has 2 different rules for edges; when one edge is fully inside of the border, it will only select edges that are fully inside. Otherwise it selects each edge intersecting with the border.
- in face mode, adding vertices, edges or a circle is invisible...
- "Add monkey" now works as a normal primitive (rotated and on 3d cursor)
- Mesh undo was fully recoded, hopefully solving issues now with Vertex Keys and Groups
- Going in and out of editmode was fully recoded. Especially on larger models you'll notice substantial speed gain.
**** Todo
Add 'FaceSelect mode' functionality in EditMode, including zbuffered selection, display and editing of UV texture.
EditMesh refactor notes (coder)
**** Usage of flags in general
The "->f" flags are reserved for the editmesh.c and editmesh_lib.c core functions. Actually only selection status is there now.
The "->f1" and "->f2" flags are free to use. They're available in vertex/edge/face structs. Since they're free, check carefully when calling other functions that use these flags... for example extrude() or subdivide() use them.
**** Selection flags
EditVert: eve->f & SELECT
EditEdge: eed->f & SELECT
EditFace: efa->f & SELECT
- Selection is only possible when not-hidden!
- Selection flags are always up-to-date, BUT:
if selection mode >= SELECT_EDGE vertex selection flags can be incorrect
if selection mode == SELECT_FACE vertex/edge selection flags can be incorrect
This because of shared vertices or edges.
- use for selecting vertices:
eve->f &= SELECT
- use for selecting edges always:
void EM_select_edge(eed, 1) // 1 = select, 0 = deselect
- use for selecting faces always:
void EM_select_face(efa, 1) // 1 = select, 0 = deselect
- To set the 'f' flags in all of the data:
void EM_set_flag_all(int flag);
void EM_clear_flag_all(int flag);
- the old faceselectedOR() and faceselectedAND() are still there, but only
to be used for evaluating its vertices
**** Code hints for handling selection
If the selectmode is 'face'; vertex or edge selections need to be flushed upward. Same is true for 'edge' selection mode. This means that you'll have to keep track of all selections while coding... selecting the four vertices in a face doesn't automatically select the face anymore.
However, by using the above calls, at least selections flush downward (to vertex level). You then can call:
void EM_selectmode_flush(void);
Which flushes selections back upward, based on the selectmode setting. This function does the following:
- if selectmode 'vertex': select edges/faces based on its selected vertices
- if selectmode 'edge': select faces based its selected edges
This works fine in nice controlled situations.
However, only changing the vertex selections then still doesn't select a face in face mode! If you really can't avoid only working with vertex selections, you can use this call:
void EM_select_flush(void);
Now selection is flushed upward regardless current selectmode. That can be destructive for special cases however, like checkerboard selected faces. So use this only when you know everything else was deselected (or deselect it). Example: adding primitives.
**** Hide flags
EditVert: eve->h
EditEdge: eed->h
EditFace: efa->h
- all hide flags are always up-to-date
- hidden vertices/edges/faces are always deselected. so when you operate on selection only, there's no need to check for hide flag.
**** Unified undo for editmode
New file: editmode_undo.h
A pretty nice function pointer handler style undo. Just code three functions, and your undo will fly! The c file has a good reference.
Also note that the old undo system has been replaced. It currently uses minimal dependencies on Meshes themselves (no abuse of going in/out editmode), and is restricted nicely to editmode functions.
**** Going in/out editmode
As speedup now all vertices/faces/edges are allocated in three big chunks. In vertices/faces/edges now tags are set to denote such data cannot be freed.
ALso the hashtable (lookup) for edges uses no mallocs at all anymore, but is part of the EditEdge itself.
2004-09-23 20:52:51 +00:00
|
|
|
|
2004-03-30 03:10:34 +00:00
|
|
|
tex_space_mesh(me);
|
|
|
|
}
|
|
|
|
waitcursor(1);
|
|
|
|
}
|
|
|
|
fclose(fpSTL);
|
|
|
|
|
|
|
|
}
|
|
|
|
#undef READSTLVERT
|
|
|
|
|
|
|
|
#define STLALLOCERROR { \
|
|
|
|
char error_msg[255]; \
|
|
|
|
fclose(fpSTL); \
|
|
|
|
sprintf(error_msg, "Can't allocate storage for %d faces!", \
|
|
|
|
numtenthousand * 10000); \
|
|
|
|
error(error_msg); \
|
|
|
|
return; \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define STLBAILOUT(message) { \
|
|
|
|
char error_msg[255]; \
|
|
|
|
fclose(fpSTL); \
|
|
|
|
free(vertdata); \
|
|
|
|
sprintf(error_msg, "Line %d: %s", linenum, message); \
|
|
|
|
error(message); \
|
|
|
|
return; \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define STLREADLINE { \
|
|
|
|
if (!fgets(buffer, 2048, fpSTL)) STLBAILOUT("Can't read line!"); \
|
|
|
|
linenum++; \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define STLREADVERT { \
|
|
|
|
STLREADLINE; \
|
|
|
|
if ( !(cp = strstr(buffer, "vertex")) && \
|
|
|
|
!(cp = strstr(buffer, "VERTEX")) ) STLBAILOUT("Bad vertex!"); \
|
|
|
|
vp = vertdata + 3 * totvert; \
|
|
|
|
if (sscanf(cp + 6, "%f %f %f", vp, vp+1, vp+2) != 3) \
|
|
|
|
STLBAILOUT("Bad vertex!"); \
|
|
|
|
++totvert; \
|
|
|
|
}
|
|
|
|
static void read_stl_mesh_ascii(char *str)
|
|
|
|
{
|
|
|
|
FILE *fpSTL;
|
|
|
|
char buffer[2048], *cp;
|
|
|
|
Object *ob;
|
|
|
|
Mesh *me;
|
|
|
|
MVert *mvert;
|
|
|
|
MFace *mface;
|
|
|
|
float *vertdata, *vp;
|
|
|
|
unsigned int numtenthousand, linenum;
|
|
|
|
unsigned int i, vertnum;
|
|
|
|
unsigned int totvert, totface;
|
|
|
|
|
|
|
|
/* ASCII stl sucks ... we don't really know how many faces there
|
|
|
|
are until the file is done, so lets allocate faces 10000 at a time */
|
|
|
|
|
|
|
|
fpSTL= fopen(str, "r");
|
|
|
|
if(fpSTL==NULL) {
|
|
|
|
error("Can't read file");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* we'll use the standard malloc/realloc for now ...
|
|
|
|
* lets allocate enough storage to hold 10000 triangles,
|
|
|
|
* i.e. 30000 verts, i.e., 90000 floats.
|
|
|
|
*/
|
|
|
|
numtenthousand = 1;
|
|
|
|
vertdata = malloc(numtenthousand*3*30000*sizeof(float));
|
|
|
|
if (!vertdata) STLALLOCERROR;
|
|
|
|
|
|
|
|
linenum = 1;
|
|
|
|
/* Get rid of the first line */
|
|
|
|
STLREADLINE;
|
|
|
|
|
|
|
|
totvert = 0;
|
|
|
|
totface = 0;
|
|
|
|
while(1) {
|
|
|
|
/* Read in the next line */
|
|
|
|
STLREADLINE;
|
|
|
|
|
|
|
|
/* lets check if this is the end of the file */
|
|
|
|
if ( strstr(buffer, "endsolid") || strstr(buffer, "ENDSOLID") )
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* Well, guess that wasn't the end, so lets make
|
|
|
|
* sure we have enough storage for some more faces
|
|
|
|
*/
|
|
|
|
if ( (totface) && ( (totface % 10000) == 0 ) ) {
|
|
|
|
++numtenthousand;
|
|
|
|
vertdata = realloc(vertdata,
|
|
|
|
numtenthousand*3*30000*sizeof(float));
|
|
|
|
if (!vertdata) STLALLOCERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Don't read normal, but check line for proper syntax anyway
|
|
|
|
*/
|
|
|
|
if ( !(cp = strstr(buffer, "facet")) &&
|
|
|
|
!(cp = strstr(buffer, "FACET")) ) STLBAILOUT("Bad normal line!");
|
|
|
|
if ( !(strstr(cp+5, "normal")) &&
|
|
|
|
!(strstr(cp+5, "NORMAL")) ) STLBAILOUT("Bad normal line!");
|
|
|
|
|
|
|
|
/* Read in what should be the outer loop line
|
|
|
|
*/
|
|
|
|
STLREADLINE;
|
|
|
|
if ( !(cp = strstr(buffer, "outer")) &&
|
|
|
|
!(cp = strstr(buffer, "OUTER")) ) STLBAILOUT("Bad outer loop!");
|
|
|
|
if ( !(strstr(cp+5, "loop")) &&
|
|
|
|
!(strstr(cp+5, "LOOP")) ) STLBAILOUT("Bad outer loop!");
|
|
|
|
|
|
|
|
/* Read in the face */
|
|
|
|
STLREADVERT;
|
|
|
|
STLREADVERT;
|
|
|
|
STLREADVERT;
|
|
|
|
|
|
|
|
/* Read in what should be the endloop line
|
|
|
|
*/
|
|
|
|
STLREADLINE;
|
|
|
|
if ( !strstr(buffer, "endloop") && !strstr(buffer, "ENDLOOP") )
|
|
|
|
STLBAILOUT("Bad endloop!");
|
|
|
|
|
|
|
|
/* Read in what should be the endfacet line
|
|
|
|
*/
|
|
|
|
STLREADLINE;
|
|
|
|
if ( !strstr(buffer, "endfacet") && !strstr(buffer, "ENDFACET") )
|
|
|
|
STLBAILOUT("Bad endfacet!");
|
|
|
|
|
|
|
|
/* Made it this far? Increment face count */
|
|
|
|
++totface;
|
|
|
|
}
|
|
|
|
fclose(fpSTL);
|
|
|
|
|
|
|
|
/* OK, lets create our mesh */
|
|
|
|
ob = add_object(OB_MESH);
|
|
|
|
me = ob->data;
|
|
|
|
me->mvert = MEM_callocN(totvert*sizeof(MVert), "mverts");
|
|
|
|
me->mface = MEM_callocN(totface*sizeof(MFace), "mface");
|
|
|
|
me->totface = totface;
|
|
|
|
me->totvert = totvert;
|
|
|
|
|
|
|
|
/* Copy vert coords and create topology */
|
|
|
|
mvert = me->mvert;
|
|
|
|
mface = me->mface;
|
|
|
|
vertnum = 0;
|
|
|
|
for (i=0; i < totface; ++i) {
|
|
|
|
memcpy(mvert->co, vertdata+3*vertnum, 3*sizeof(float) );
|
|
|
|
mface->v1 = vertnum;
|
|
|
|
mvert++;
|
|
|
|
vertnum++;
|
|
|
|
|
|
|
|
memcpy(mvert->co, vertdata+3*vertnum, 3*sizeof(float) );
|
|
|
|
mface->v2 = vertnum;
|
|
|
|
mvert++;
|
|
|
|
vertnum++;
|
|
|
|
|
|
|
|
memcpy(mvert->co, vertdata+3*vertnum, 3*sizeof(float) );
|
|
|
|
mface->v3 = vertnum;
|
|
|
|
mvert++;
|
|
|
|
vertnum++;
|
|
|
|
|
|
|
|
mface++;
|
|
|
|
}
|
|
|
|
free(vertdata);
|
|
|
|
|
2004-04-22 22:33:57 +00:00
|
|
|
mesh_add_normals_flags(me);
|
EditMesh refactory + undo recode
The changelog is very long... it's on the web too:
http://www.blender3d.org/cms/Mesh_editing_rewrite.425.0.html
EditMesh refactor notes (user)
**** New selection modes
When entering Edit Mode for a Mesh, you now have the choice for three selection modes. These are shown as icons in the 3D header (hotkey is being searched for!).
- Vertex Select
Select vertices as usual, fully compatible with how previous version work
- Edge Select
Vertices are not drawn anymore, and selections happen by default on the edges. It is a true edge select, meaning that you can select three out of four edges in a face, without automatic having the 4th edge selected.
- Face Select
Instead of vertices, now selection 'points' are drawn in the face centers. Selected faces also get a colored outline, like for edges. This also is true face select, for each face individual regardless selection status of its vertices or edges.
While holding SHIFT, and press a selection mode, you can also combine the above choices. Now selection becomes mixed, and will behave as expected.
For example; in Edge+Face select mode, selecting the 4 edges of a face will select the face too.
The selection modes and optional drawing modes (like transparant faces, normals, or solid drawing) all work together. All of Blender's mesh editing tools now react to the correct selection mode as well.
Most noticeable it's in:
**** Extrude
Extruding in Edge or Face Select mode allows much more precise control over what's extruded and what should be excluded. Try for example a checker pattern selection, and extrude it.
New is the fixed translation when faces are extruded. This always follows the (averaged) face normal(s) of the old face(s), enabling much easier working in 3D views . A single 'G' (Grab) or 'R' (Rotate) or 'S' (Scale) will change transform modus as usual.
**** Other things to note
- Hiding edges/faces will also behave different based on Select Mode.
- while editing, normals of faces are updated always now
- Border select (BKEY) has 2 different rules for edges; when one edge is fully inside of the border, it will only select edges that are fully inside. Otherwise it selects each edge intersecting with the border.
- in face mode, adding vertices, edges or a circle is invisible...
- "Add monkey" now works as a normal primitive (rotated and on 3d cursor)
- Mesh undo was fully recoded, hopefully solving issues now with Vertex Keys and Groups
- Going in and out of editmode was fully recoded. Especially on larger models you'll notice substantial speed gain.
**** Todo
Add 'FaceSelect mode' functionality in EditMode, including zbuffered selection, display and editing of UV texture.
EditMesh refactor notes (coder)
**** Usage of flags in general
The "->f" flags are reserved for the editmesh.c and editmesh_lib.c core functions. Actually only selection status is there now.
The "->f1" and "->f2" flags are free to use. They're available in vertex/edge/face structs. Since they're free, check carefully when calling other functions that use these flags... for example extrude() or subdivide() use them.
**** Selection flags
EditVert: eve->f & SELECT
EditEdge: eed->f & SELECT
EditFace: efa->f & SELECT
- Selection is only possible when not-hidden!
- Selection flags are always up-to-date, BUT:
if selection mode >= SELECT_EDGE vertex selection flags can be incorrect
if selection mode == SELECT_FACE vertex/edge selection flags can be incorrect
This because of shared vertices or edges.
- use for selecting vertices:
eve->f &= SELECT
- use for selecting edges always:
void EM_select_edge(eed, 1) // 1 = select, 0 = deselect
- use for selecting faces always:
void EM_select_face(efa, 1) // 1 = select, 0 = deselect
- To set the 'f' flags in all of the data:
void EM_set_flag_all(int flag);
void EM_clear_flag_all(int flag);
- the old faceselectedOR() and faceselectedAND() are still there, but only
to be used for evaluating its vertices
**** Code hints for handling selection
If the selectmode is 'face'; vertex or edge selections need to be flushed upward. Same is true for 'edge' selection mode. This means that you'll have to keep track of all selections while coding... selecting the four vertices in a face doesn't automatically select the face anymore.
However, by using the above calls, at least selections flush downward (to vertex level). You then can call:
void EM_selectmode_flush(void);
Which flushes selections back upward, based on the selectmode setting. This function does the following:
- if selectmode 'vertex': select edges/faces based on its selected vertices
- if selectmode 'edge': select faces based its selected edges
This works fine in nice controlled situations.
However, only changing the vertex selections then still doesn't select a face in face mode! If you really can't avoid only working with vertex selections, you can use this call:
void EM_select_flush(void);
Now selection is flushed upward regardless current selectmode. That can be destructive for special cases however, like checkerboard selected faces. So use this only when you know everything else was deselected (or deselect it). Example: adding primitives.
**** Hide flags
EditVert: eve->h
EditEdge: eed->h
EditFace: efa->h
- all hide flags are always up-to-date
- hidden vertices/edges/faces are always deselected. so when you operate on selection only, there's no need to check for hide flag.
**** Unified undo for editmode
New file: editmode_undo.h
A pretty nice function pointer handler style undo. Just code three functions, and your undo will fly! The c file has a good reference.
Also note that the old undo system has been replaced. It currently uses minimal dependencies on Meshes themselves (no abuse of going in/out editmode), and is restricted nicely to editmode functions.
**** Going in/out editmode
As speedup now all vertices/faces/edges are allocated in three big chunks. In vertices/faces/edges now tags are set to denote such data cannot be freed.
ALso the hashtable (lookup) for edges uses no mallocs at all anymore, but is part of the EditEdge itself.
2004-09-23 20:52:51 +00:00
|
|
|
|
2004-03-30 03:10:34 +00:00
|
|
|
tex_space_mesh(me);
|
|
|
|
waitcursor(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef STLALLOCERROR
|
|
|
|
#undef STLBAILOUT
|
|
|
|
#undef STLREADLINE
|
|
|
|
#undef STLREADVERT
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
static void read_videoscape_mesh(char *str)
|
|
|
|
{
|
|
|
|
Object *ob;
|
|
|
|
Mesh *me;
|
|
|
|
MVert *mvert;
|
|
|
|
MFace *mface;
|
|
|
|
Material *ma;
|
|
|
|
FILE *fp;
|
|
|
|
float *vertdata, *vd, min[3], max[3], cent[3], ftemp;
|
|
|
|
unsigned int color[32], col;
|
|
|
|
int totcol, a, b, verts, tottria=0, totquad=0, totedge=0, poly, nr0, nr, first;
|
2003-12-16 01:27:37 +00:00
|
|
|
int end;
|
2002-10-12 11:37:38 +00:00
|
|
|
char s[50];
|
|
|
|
|
|
|
|
fp= fopen(str, "rb");
|
|
|
|
if(fp==NULL) {
|
|
|
|
error("Can't read file");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
fscanf(fp, "%40s", s);
|
|
|
|
|
|
|
|
fscanf(fp, "%d\n", &verts);
|
|
|
|
if(verts<=0) {
|
|
|
|
fclose(fp);
|
|
|
|
error("Read error");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-03-14 21:21:09 +00:00
|
|
|
if(verts>MESH_MAX_VERTS) {
|
2002-10-12 11:37:38 +00:00
|
|
|
error("too many vertices");
|
|
|
|
fclose(fp);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
INIT_MINMAX(min, max);
|
|
|
|
vd= vertdata= MEM_mallocN(sizeof(float)*3*verts, "videoscapelezer");
|
|
|
|
|
|
|
|
for(a=0; a<verts; a++) {
|
|
|
|
fscanf(fp, "%f %f %f", vd, vd+1, vd+2);
|
|
|
|
DO_MINMAX(vd, min, max);
|
|
|
|
vd+=3;
|
|
|
|
}
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* count faces and colors */
|
2002-10-12 11:37:38 +00:00
|
|
|
for(a=0; a<32; a++) color[a]= 0;
|
|
|
|
totcol= 0;
|
|
|
|
end= 1;
|
|
|
|
while(end>0) {
|
|
|
|
end= fscanf(fp,"%d", &poly);
|
|
|
|
if(end<=0) break;
|
|
|
|
|
|
|
|
if(poly==3) tottria++;
|
|
|
|
else if(poly==4) totquad++;
|
|
|
|
else totedge+= poly;
|
|
|
|
|
|
|
|
for(a=0;a<poly;a++) {
|
|
|
|
end= fscanf(fp,"%d", &nr);
|
|
|
|
if(end<=0) break;
|
|
|
|
}
|
|
|
|
if(end<=0) break;
|
|
|
|
|
|
|
|
end= fscanf(fp,"%i\n", &col);
|
|
|
|
col &= 0xF0F0F0;
|
|
|
|
for(a=0; a<totcol; a++) {
|
|
|
|
if(color[a]==col) break;
|
|
|
|
}
|
|
|
|
if(a>=totcol && totcol<32) {
|
|
|
|
color[totcol]= col;
|
|
|
|
totcol++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-03-14 21:21:09 +00:00
|
|
|
if(totedge+tottria+totquad>MESH_MAX_VERTS) {
|
2002-10-12 11:37:38 +00:00
|
|
|
printf(" var1: %d, var2: %d, var3: %d \n", totedge, tottria, totquad);
|
|
|
|
error("too many faces");
|
|
|
|
MEM_freeN(vertdata);
|
|
|
|
fclose(fp);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* new object */
|
2002-10-12 11:37:38 +00:00
|
|
|
ob= add_object(OB_MESH);
|
|
|
|
me= ob->data;
|
|
|
|
me->totvert= verts;
|
|
|
|
me->totface= totedge+tottria+totquad;
|
|
|
|
|
|
|
|
me->mvert= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
|
|
|
|
if(me->totface) me->mface= MEM_callocN(me->totface*sizeof(MFace), "mface");
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* colors */
|
2002-10-12 11:37:38 +00:00
|
|
|
if(totcol) {
|
|
|
|
ob->mat= MEM_callocN(sizeof(void *)*totcol, "ob->mat");
|
|
|
|
me->mat= MEM_callocN(sizeof(void *)*totcol, "me->mat");
|
|
|
|
me->totcol= totcol;
|
|
|
|
ob->totcol= (unsigned char) me->totcol;
|
|
|
|
ob->actcol= 1;
|
|
|
|
}
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* materials */
|
2002-10-12 11:37:38 +00:00
|
|
|
for(a=0; a<totcol; a++) {
|
|
|
|
ma= G.main->mat.first;
|
|
|
|
while(ma) {
|
|
|
|
if(ma->mtex[0]==0) {
|
|
|
|
col= rgb_to_cpack(ma->r, ma->g, ma->b);
|
|
|
|
if(color[a]==col) {
|
|
|
|
me->mat[a]= ma;
|
|
|
|
ma->id.us++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ma= ma->id.next;
|
|
|
|
}
|
|
|
|
if(ma==0) {
|
|
|
|
ma= add_material("ext");
|
|
|
|
me->mat[a]= ma;
|
|
|
|
cpack_to_rgb(color[a], cent, cent+1, cent+2);
|
|
|
|
ma->r= cent[0];
|
|
|
|
ma->g= cent[1];
|
|
|
|
ma->b= cent[2];
|
|
|
|
automatname(ma);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* verts */
|
|
|
|
|
|
|
|
cent[0]= (min[0]+max[0])/2.0f;
|
|
|
|
cent[1]= (min[1]+max[1])/2.0f;
|
|
|
|
cent[2]= (min[2]+max[2])/2.0f;
|
|
|
|
VECCOPY(ob->loc, cent);
|
|
|
|
|
|
|
|
a= me->totvert;
|
|
|
|
vd= vertdata;
|
|
|
|
mvert= me->mvert;
|
|
|
|
while(a--) {
|
|
|
|
VecSubf(mvert->co, vd, cent);
|
|
|
|
mvert++;
|
|
|
|
vd+= 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* faces */
|
|
|
|
if(me->totface) {
|
|
|
|
rewind(fp);
|
|
|
|
|
|
|
|
fscanf(fp, "%40s", s);
|
|
|
|
fscanf(fp, "%d\n", &verts);
|
|
|
|
/* fake read */
|
|
|
|
for(a=0;a<verts;a++) {
|
|
|
|
fscanf(fp, "%f %f %f", &ftemp, &ftemp, &ftemp);
|
|
|
|
}
|
|
|
|
|
|
|
|
a= me->totface;
|
|
|
|
mface= me->mface;
|
|
|
|
while(a--) {
|
|
|
|
end= fscanf(fp,"%d", &poly);
|
|
|
|
if(end<=0) break;
|
|
|
|
|
|
|
|
if(poly==3 || poly==4) {
|
|
|
|
fscanf(fp,"%d", &nr);
|
|
|
|
mface->v1= MIN2(nr, me->totvert-1);
|
|
|
|
fscanf(fp,"%d", &nr);
|
|
|
|
mface->v2= MIN2(nr, me->totvert-1);
|
|
|
|
fscanf(fp,"%d", &nr);
|
|
|
|
mface->v3= MIN2(nr, me->totvert-1);
|
|
|
|
if(poly==4) {
|
|
|
|
if( fscanf(fp,"%d", &nr) <=0 ) break;
|
|
|
|
mface->v4= MIN2(nr, me->totvert-1);
|
|
|
|
}
|
|
|
|
mface->edcode= 3;
|
|
|
|
|
|
|
|
test_index_mface(mface, poly);
|
|
|
|
|
|
|
|
mface++;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if( fscanf(fp,"%d", &nr0) <=0) break;
|
|
|
|
first= nr0;
|
|
|
|
for(b=1; b<poly; b++) {
|
|
|
|
end= fscanf(fp,"%d", &nr);
|
|
|
|
if(end<=0) break;
|
|
|
|
nr= MIN2(nr, me->totvert-1);
|
|
|
|
mface->v1= nr;
|
|
|
|
mface->v2= nr0;
|
|
|
|
nr0= nr;
|
|
|
|
mface++;
|
|
|
|
a--;
|
|
|
|
}
|
|
|
|
mface->v1= first;
|
|
|
|
mface->v2= nr;
|
|
|
|
mface->edcode= 1;
|
|
|
|
mface++;
|
|
|
|
if(end<=0) break;
|
|
|
|
}
|
|
|
|
end= fscanf(fp,"%i", &col);
|
|
|
|
col &= 0xF0F0F0;
|
|
|
|
if(end<=0) break;
|
|
|
|
|
|
|
|
for(b=0; b<totcol; b++) {
|
|
|
|
if(color[b]==col) {
|
|
|
|
(mface-1)->mat_nr= b;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose(fp);
|
|
|
|
MEM_freeN(vertdata);
|
|
|
|
|
|
|
|
G.obedit= ob;
|
|
|
|
make_editMesh();
|
|
|
|
load_editMesh();
|
EditMesh refactory + undo recode
The changelog is very long... it's on the web too:
http://www.blender3d.org/cms/Mesh_editing_rewrite.425.0.html
EditMesh refactor notes (user)
**** New selection modes
When entering Edit Mode for a Mesh, you now have the choice for three selection modes. These are shown as icons in the 3D header (hotkey is being searched for!).
- Vertex Select
Select vertices as usual, fully compatible with how previous version work
- Edge Select
Vertices are not drawn anymore, and selections happen by default on the edges. It is a true edge select, meaning that you can select three out of four edges in a face, without automatic having the 4th edge selected.
- Face Select
Instead of vertices, now selection 'points' are drawn in the face centers. Selected faces also get a colored outline, like for edges. This also is true face select, for each face individual regardless selection status of its vertices or edges.
While holding SHIFT, and press a selection mode, you can also combine the above choices. Now selection becomes mixed, and will behave as expected.
For example; in Edge+Face select mode, selecting the 4 edges of a face will select the face too.
The selection modes and optional drawing modes (like transparant faces, normals, or solid drawing) all work together. All of Blender's mesh editing tools now react to the correct selection mode as well.
Most noticeable it's in:
**** Extrude
Extruding in Edge or Face Select mode allows much more precise control over what's extruded and what should be excluded. Try for example a checker pattern selection, and extrude it.
New is the fixed translation when faces are extruded. This always follows the (averaged) face normal(s) of the old face(s), enabling much easier working in 3D views . A single 'G' (Grab) or 'R' (Rotate) or 'S' (Scale) will change transform modus as usual.
**** Other things to note
- Hiding edges/faces will also behave different based on Select Mode.
- while editing, normals of faces are updated always now
- Border select (BKEY) has 2 different rules for edges; when one edge is fully inside of the border, it will only select edges that are fully inside. Otherwise it selects each edge intersecting with the border.
- in face mode, adding vertices, edges or a circle is invisible...
- "Add monkey" now works as a normal primitive (rotated and on 3d cursor)
- Mesh undo was fully recoded, hopefully solving issues now with Vertex Keys and Groups
- Going in and out of editmode was fully recoded. Especially on larger models you'll notice substantial speed gain.
**** Todo
Add 'FaceSelect mode' functionality in EditMode, including zbuffered selection, display and editing of UV texture.
EditMesh refactor notes (coder)
**** Usage of flags in general
The "->f" flags are reserved for the editmesh.c and editmesh_lib.c core functions. Actually only selection status is there now.
The "->f1" and "->f2" flags are free to use. They're available in vertex/edge/face structs. Since they're free, check carefully when calling other functions that use these flags... for example extrude() or subdivide() use them.
**** Selection flags
EditVert: eve->f & SELECT
EditEdge: eed->f & SELECT
EditFace: efa->f & SELECT
- Selection is only possible when not-hidden!
- Selection flags are always up-to-date, BUT:
if selection mode >= SELECT_EDGE vertex selection flags can be incorrect
if selection mode == SELECT_FACE vertex/edge selection flags can be incorrect
This because of shared vertices or edges.
- use for selecting vertices:
eve->f &= SELECT
- use for selecting edges always:
void EM_select_edge(eed, 1) // 1 = select, 0 = deselect
- use for selecting faces always:
void EM_select_face(efa, 1) // 1 = select, 0 = deselect
- To set the 'f' flags in all of the data:
void EM_set_flag_all(int flag);
void EM_clear_flag_all(int flag);
- the old faceselectedOR() and faceselectedAND() are still there, but only
to be used for evaluating its vertices
**** Code hints for handling selection
If the selectmode is 'face'; vertex or edge selections need to be flushed upward. Same is true for 'edge' selection mode. This means that you'll have to keep track of all selections while coding... selecting the four vertices in a face doesn't automatically select the face anymore.
However, by using the above calls, at least selections flush downward (to vertex level). You then can call:
void EM_selectmode_flush(void);
Which flushes selections back upward, based on the selectmode setting. This function does the following:
- if selectmode 'vertex': select edges/faces based on its selected vertices
- if selectmode 'edge': select faces based its selected edges
This works fine in nice controlled situations.
However, only changing the vertex selections then still doesn't select a face in face mode! If you really can't avoid only working with vertex selections, you can use this call:
void EM_select_flush(void);
Now selection is flushed upward regardless current selectmode. That can be destructive for special cases however, like checkerboard selected faces. So use this only when you know everything else was deselected (or deselect it). Example: adding primitives.
**** Hide flags
EditVert: eve->h
EditEdge: eed->h
EditFace: efa->h
- all hide flags are always up-to-date
- hidden vertices/edges/faces are always deselected. so when you operate on selection only, there's no need to check for hide flag.
**** Unified undo for editmode
New file: editmode_undo.h
A pretty nice function pointer handler style undo. Just code three functions, and your undo will fly! The c file has a good reference.
Also note that the old undo system has been replaced. It currently uses minimal dependencies on Meshes themselves (no abuse of going in/out editmode), and is restricted nicely to editmode functions.
**** Going in/out editmode
As speedup now all vertices/faces/edges are allocated in three big chunks. In vertices/faces/edges now tags are set to denote such data cannot be freed.
ALso the hashtable (lookup) for edges uses no mallocs at all anymore, but is part of the EditEdge itself.
2004-09-23 20:52:51 +00:00
|
|
|
free_editMesh(G.editMesh);
|
2002-10-12 11:37:38 +00:00
|
|
|
G.obedit= 0;
|
|
|
|
tex_space_mesh(me);
|
|
|
|
waitcursor(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void read_radiogour(char *str)
|
|
|
|
{
|
|
|
|
Object *ob;
|
|
|
|
Mesh *me;
|
|
|
|
MVert *mvert;
|
|
|
|
MFace *mface;
|
|
|
|
FILE *fp;
|
|
|
|
float *vertdata, *vd, min[3], max[3], cent[3], ftemp;
|
|
|
|
unsigned int *colv, *colf, *colvertdata;
|
|
|
|
int itemp, a, b, verts, tottria=0, totquad=0, totedge=0, poly, nr0, nr, first;
|
2003-12-16 01:27:37 +00:00
|
|
|
int end;
|
2002-10-12 11:37:38 +00:00
|
|
|
char s[50];
|
|
|
|
|
|
|
|
fp= fopen(str, "rb");
|
|
|
|
if(fp==NULL) {
|
|
|
|
error("Can't read file");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
fscanf(fp, "%40s", s);
|
|
|
|
|
|
|
|
fscanf(fp, "%d\n", &verts);
|
|
|
|
if(verts<=0) {
|
|
|
|
fclose(fp);
|
|
|
|
error("Read error");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-03-14 21:21:09 +00:00
|
|
|
if(verts>MESH_MAX_VERTS) {
|
2002-10-12 11:37:38 +00:00
|
|
|
error("too many vertices");
|
|
|
|
fclose(fp);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
INIT_MINMAX(min, max);
|
|
|
|
vd= vertdata= MEM_mallocN(sizeof(float)*3*verts, "videoscapelezer");
|
|
|
|
colv= colvertdata= MEM_mallocN(verts*sizeof(float), "coldata");
|
|
|
|
|
|
|
|
for(a=0; a<verts; a++) {
|
|
|
|
fscanf(fp, "%f %f %f %i", vd, vd+1, vd+2, colv);
|
|
|
|
DO_MINMAX(vd, min, max);
|
|
|
|
vd+=3;
|
|
|
|
colv++;
|
|
|
|
}
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* count faces */
|
2002-10-12 11:37:38 +00:00
|
|
|
end= 1;
|
|
|
|
while(end>0) {
|
|
|
|
end= fscanf(fp,"%d", &poly);
|
|
|
|
if(end<=0) break;
|
|
|
|
|
|
|
|
if(poly==3) tottria++;
|
|
|
|
else if(poly==4) totquad++;
|
|
|
|
else totedge+= poly;
|
|
|
|
|
|
|
|
for(a=0;a<poly;a++) {
|
|
|
|
end= fscanf(fp,"%d", &nr);
|
|
|
|
if(end<=0) break;
|
|
|
|
}
|
|
|
|
if(end<=0) break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2004-03-14 21:21:09 +00:00
|
|
|
if(totedge+tottria+totquad>MESH_MAX_VERTS) {
|
2002-10-12 11:37:38 +00:00
|
|
|
printf(" var1: %d, var2: %d, var3: %d \n", totedge, tottria, totquad);
|
|
|
|
error("too many faces");
|
|
|
|
MEM_freeN(vertdata);
|
|
|
|
MEM_freeN(colvertdata);
|
|
|
|
fclose(fp);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* new object */
|
2002-10-12 11:37:38 +00:00
|
|
|
ob= add_object(OB_MESH);
|
|
|
|
me= ob->data;
|
|
|
|
me->totvert= verts;
|
|
|
|
me->totface= totedge+tottria+totquad;
|
|
|
|
me->flag= 0;
|
|
|
|
me->mvert= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
|
|
|
|
if(me->totface) me->mface= MEM_callocN(me->totface*sizeof(MFace), "mface");
|
|
|
|
|
|
|
|
/* verts */
|
|
|
|
|
|
|
|
cent[0]= (min[0]+max[0])/2.0f;
|
|
|
|
cent[1]= (min[1]+max[1])/2.0f;
|
|
|
|
cent[2]= (min[2]+max[2])/2.0f;
|
|
|
|
VECCOPY(ob->loc, cent);
|
|
|
|
|
|
|
|
a= me->totvert;
|
|
|
|
vd= vertdata;
|
|
|
|
mvert= me->mvert;
|
|
|
|
while(a--) {
|
|
|
|
VecSubf(mvert->co, vd, cent);
|
|
|
|
mvert++;
|
|
|
|
vd+= 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* faces */
|
|
|
|
if(me->totface) {
|
|
|
|
rewind(fp);
|
|
|
|
|
|
|
|
fscanf(fp, "%40s", s);
|
|
|
|
fscanf(fp, "%d\n", &verts);
|
|
|
|
for(a=0;a<verts;a++) {
|
|
|
|
fscanf(fp, "%f %f %f %i", &ftemp, &ftemp, &ftemp, &itemp);
|
|
|
|
}
|
|
|
|
|
|
|
|
a= me->totface;
|
|
|
|
mface= me->mface;
|
|
|
|
while(a--) {
|
|
|
|
end= fscanf(fp,"%d", &poly);
|
|
|
|
if(end<=0) break;
|
|
|
|
|
|
|
|
if(poly==3 || poly==4) {
|
|
|
|
fscanf(fp,"%d", &nr);
|
|
|
|
mface->v1= MIN2(nr, me->totvert-1);
|
|
|
|
fscanf(fp,"%d", &nr);
|
|
|
|
mface->v2= MIN2(nr, me->totvert-1);
|
|
|
|
fscanf(fp,"%d", &nr);
|
|
|
|
mface->v3= MIN2(nr, me->totvert-1);
|
|
|
|
if(poly==4) {
|
|
|
|
if( fscanf(fp,"%d", &nr) <=0 ) break;
|
|
|
|
mface->v4= MIN2(nr, me->totvert-1);
|
|
|
|
}
|
|
|
|
mface->edcode= 3;
|
|
|
|
|
|
|
|
test_index_mface(mface, poly);
|
|
|
|
|
|
|
|
mface++;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if( fscanf(fp,"%d", &nr0) <=0) break;
|
|
|
|
first= nr0;
|
|
|
|
for(b=1; b<poly; b++) {
|
|
|
|
end= fscanf(fp,"%d", &nr);
|
|
|
|
if(end<=0) break;
|
|
|
|
nr= MIN2(nr, me->totvert-1);
|
|
|
|
mface->v1= nr;
|
|
|
|
mface->v2= nr0;
|
|
|
|
nr0= nr;
|
|
|
|
mface++;
|
|
|
|
a--;
|
|
|
|
}
|
|
|
|
mface->v1= first;
|
|
|
|
mface->v2= nr;
|
|
|
|
mface->edcode= 1;
|
|
|
|
mface->flag= ME_SMOOTH;
|
|
|
|
|
|
|
|
mface++;
|
|
|
|
if(end<=0) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* mcol is 4 colors per face */
|
2002-10-12 11:37:38 +00:00
|
|
|
me->mcol= MEM_mallocN(4*sizeof(int)*me->totface, "mcol");
|
|
|
|
colf= (unsigned int *)me->mcol;
|
|
|
|
|
|
|
|
a= me->totface;
|
|
|
|
mface= me->mface;
|
|
|
|
while(a--) {
|
|
|
|
|
|
|
|
colf[0]= colvertdata[mface->v1];
|
|
|
|
colf[1]= colvertdata[mface->v2];
|
|
|
|
colf[2]= colvertdata[mface->v3];
|
|
|
|
colf[3]= colvertdata[mface->v4];
|
|
|
|
|
|
|
|
colf+= 4;
|
|
|
|
mface++;
|
|
|
|
}
|
|
|
|
|
|
|
|
MEM_freeN(colvertdata);
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose(fp);
|
|
|
|
MEM_freeN(vertdata);
|
|
|
|
|
|
|
|
G.obedit= ob;
|
|
|
|
make_editMesh();
|
|
|
|
load_editMesh();
|
EditMesh refactory + undo recode
The changelog is very long... it's on the web too:
http://www.blender3d.org/cms/Mesh_editing_rewrite.425.0.html
EditMesh refactor notes (user)
**** New selection modes
When entering Edit Mode for a Mesh, you now have the choice for three selection modes. These are shown as icons in the 3D header (hotkey is being searched for!).
- Vertex Select
Select vertices as usual, fully compatible with how previous version work
- Edge Select
Vertices are not drawn anymore, and selections happen by default on the edges. It is a true edge select, meaning that you can select three out of four edges in a face, without automatic having the 4th edge selected.
- Face Select
Instead of vertices, now selection 'points' are drawn in the face centers. Selected faces also get a colored outline, like for edges. This also is true face select, for each face individual regardless selection status of its vertices or edges.
While holding SHIFT, and press a selection mode, you can also combine the above choices. Now selection becomes mixed, and will behave as expected.
For example; in Edge+Face select mode, selecting the 4 edges of a face will select the face too.
The selection modes and optional drawing modes (like transparant faces, normals, or solid drawing) all work together. All of Blender's mesh editing tools now react to the correct selection mode as well.
Most noticeable it's in:
**** Extrude
Extruding in Edge or Face Select mode allows much more precise control over what's extruded and what should be excluded. Try for example a checker pattern selection, and extrude it.
New is the fixed translation when faces are extruded. This always follows the (averaged) face normal(s) of the old face(s), enabling much easier working in 3D views . A single 'G' (Grab) or 'R' (Rotate) or 'S' (Scale) will change transform modus as usual.
**** Other things to note
- Hiding edges/faces will also behave different based on Select Mode.
- while editing, normals of faces are updated always now
- Border select (BKEY) has 2 different rules for edges; when one edge is fully inside of the border, it will only select edges that are fully inside. Otherwise it selects each edge intersecting with the border.
- in face mode, adding vertices, edges or a circle is invisible...
- "Add monkey" now works as a normal primitive (rotated and on 3d cursor)
- Mesh undo was fully recoded, hopefully solving issues now with Vertex Keys and Groups
- Going in and out of editmode was fully recoded. Especially on larger models you'll notice substantial speed gain.
**** Todo
Add 'FaceSelect mode' functionality in EditMode, including zbuffered selection, display and editing of UV texture.
EditMesh refactor notes (coder)
**** Usage of flags in general
The "->f" flags are reserved for the editmesh.c and editmesh_lib.c core functions. Actually only selection status is there now.
The "->f1" and "->f2" flags are free to use. They're available in vertex/edge/face structs. Since they're free, check carefully when calling other functions that use these flags... for example extrude() or subdivide() use them.
**** Selection flags
EditVert: eve->f & SELECT
EditEdge: eed->f & SELECT
EditFace: efa->f & SELECT
- Selection is only possible when not-hidden!
- Selection flags are always up-to-date, BUT:
if selection mode >= SELECT_EDGE vertex selection flags can be incorrect
if selection mode == SELECT_FACE vertex/edge selection flags can be incorrect
This because of shared vertices or edges.
- use for selecting vertices:
eve->f &= SELECT
- use for selecting edges always:
void EM_select_edge(eed, 1) // 1 = select, 0 = deselect
- use for selecting faces always:
void EM_select_face(efa, 1) // 1 = select, 0 = deselect
- To set the 'f' flags in all of the data:
void EM_set_flag_all(int flag);
void EM_clear_flag_all(int flag);
- the old faceselectedOR() and faceselectedAND() are still there, but only
to be used for evaluating its vertices
**** Code hints for handling selection
If the selectmode is 'face'; vertex or edge selections need to be flushed upward. Same is true for 'edge' selection mode. This means that you'll have to keep track of all selections while coding... selecting the four vertices in a face doesn't automatically select the face anymore.
However, by using the above calls, at least selections flush downward (to vertex level). You then can call:
void EM_selectmode_flush(void);
Which flushes selections back upward, based on the selectmode setting. This function does the following:
- if selectmode 'vertex': select edges/faces based on its selected vertices
- if selectmode 'edge': select faces based its selected edges
This works fine in nice controlled situations.
However, only changing the vertex selections then still doesn't select a face in face mode! If you really can't avoid only working with vertex selections, you can use this call:
void EM_select_flush(void);
Now selection is flushed upward regardless current selectmode. That can be destructive for special cases however, like checkerboard selected faces. So use this only when you know everything else was deselected (or deselect it). Example: adding primitives.
**** Hide flags
EditVert: eve->h
EditEdge: eed->h
EditFace: efa->h
- all hide flags are always up-to-date
- hidden vertices/edges/faces are always deselected. so when you operate on selection only, there's no need to check for hide flag.
**** Unified undo for editmode
New file: editmode_undo.h
A pretty nice function pointer handler style undo. Just code three functions, and your undo will fly! The c file has a good reference.
Also note that the old undo system has been replaced. It currently uses minimal dependencies on Meshes themselves (no abuse of going in/out editmode), and is restricted nicely to editmode functions.
**** Going in/out editmode
As speedup now all vertices/faces/edges are allocated in three big chunks. In vertices/faces/edges now tags are set to denote such data cannot be freed.
ALso the hashtable (lookup) for edges uses no mallocs at all anymore, but is part of the EditEdge itself.
2004-09-23 20:52:51 +00:00
|
|
|
free_editMesh(G.editMesh);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
G.obedit= 0;
|
|
|
|
tex_space_mesh(me);
|
|
|
|
|
|
|
|
waitcursor(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void read_videoscape_lamp(char *str)
|
|
|
|
{
|
|
|
|
Object *ob;
|
|
|
|
Lamp *la;
|
|
|
|
FILE *fp;
|
|
|
|
float vec[3], *q1;
|
|
|
|
int tot, val;
|
|
|
|
char s[50];
|
|
|
|
|
|
|
|
fp= fopen(str, "rb");
|
|
|
|
if(fp==NULL) {
|
|
|
|
error("Can't read file");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
fscanf(fp, "%40s", s);
|
|
|
|
fscanf(fp, "%d\n", &tot);
|
|
|
|
|
|
|
|
while(tot--) {
|
|
|
|
ob= add_object(OB_LAMP);
|
|
|
|
la= ob->data;
|
|
|
|
|
|
|
|
fscanf(fp, "%d\n", &val);
|
|
|
|
la->type= val;
|
|
|
|
if(la->type==1) la->type= LA_SPOT;
|
|
|
|
else if(la->type==2) la->type= LA_SUN;
|
|
|
|
|
|
|
|
fscanf(fp, "%f %f\n", &la->spotsize, &la->spotblend);
|
|
|
|
|
|
|
|
fscanf(fp, "%f %f %f %f\n", &la->r, &la->g, &la->b, &la->energy);
|
|
|
|
|
|
|
|
fscanf(fp, "%f %f %f\n", ob->loc, ob->loc+1, ob->loc+2);
|
|
|
|
val= fscanf(fp, "%f %f %f\n", vec, vec+1, vec+2);
|
|
|
|
q1= vectoquat(vec, 5, 2);
|
|
|
|
QuatToEul(q1, ob->rot);
|
|
|
|
|
|
|
|
if(val<=0) break;
|
|
|
|
|
|
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void read_videoscape_nurbs(char *str)
|
|
|
|
{
|
|
|
|
Object *ob;
|
|
|
|
Curve *cu;
|
|
|
|
Nurb *nu;
|
|
|
|
BezTriple *bezt;
|
|
|
|
BPoint *bp;
|
|
|
|
FILE *fp;
|
|
|
|
float tmat[4][4], omat[3][3], imat[3][3], mat[3][3];
|
|
|
|
int a, tot, type, val;
|
|
|
|
char s[50];
|
|
|
|
|
|
|
|
fp= fopen(str, "rb");
|
|
|
|
if(fp==NULL) {
|
|
|
|
error("Can't read file");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
fscanf(fp, "%40s", s);
|
|
|
|
fscanf(fp, "%d\n", &type);
|
|
|
|
|
|
|
|
if(type==5) ob= add_object(OB_SURF);
|
|
|
|
else ob= add_object(OB_CURVE);
|
|
|
|
cu= ob->data;
|
|
|
|
|
|
|
|
fscanf(fp, "%d\n", &tot);
|
|
|
|
fscanf(fp, "%d %d\n", &type, &val);
|
|
|
|
|
|
|
|
cu->ext1= 0.002f*type;
|
|
|
|
cu->ext2= 0.002f*val;
|
|
|
|
|
|
|
|
for(a=0; a<4; a++) fscanf(fp, "%e %e %e %e\n", tmat[a], tmat[a]+1, tmat[a]+2, tmat[a]+3);
|
|
|
|
|
|
|
|
VECCOPY(ob->loc, tmat[3]);
|
|
|
|
|
|
|
|
Mat3CpyMat4(omat, tmat);
|
|
|
|
Mat3ToEul(omat, ob->rot);
|
|
|
|
EulToMat3(ob->rot, mat);
|
|
|
|
Mat3Inv(imat, mat);
|
|
|
|
Mat3MulMat3(tmat, imat, omat);
|
|
|
|
|
|
|
|
while(tot--) {
|
|
|
|
nu= (Nurb*)MEM_callocN(sizeof(Nurb),"nu from exotic");
|
|
|
|
BLI_addtail(&cu->nurb, nu);
|
|
|
|
|
|
|
|
fscanf(fp, "%d\n", &type);
|
|
|
|
nu->type= type;
|
|
|
|
|
|
|
|
fscanf(fp, "%d %d\n", &type, &val);
|
|
|
|
nu->pntsu= type; nu->pntsv= val;
|
|
|
|
fscanf(fp, "%d %d\n", &type, &val);
|
|
|
|
nu->resolu= type; nu->resolv= val;
|
|
|
|
fscanf(fp, "%d %d\n", &type, &val);
|
|
|
|
nu->orderu= type; nu->orderv= val;
|
|
|
|
fscanf(fp, "%d %d\n", &type, &val);
|
|
|
|
nu->flagu= type; nu->flagv= val;
|
|
|
|
|
|
|
|
if( (nu->type & 7)==CU_BEZIER) {
|
|
|
|
a= nu->pntsu;
|
|
|
|
nu->bezt= bezt= MEM_callocN(a*sizeof(BezTriple), "bezt from exotic");
|
|
|
|
while(a--) {
|
|
|
|
fscanf(fp, "%f %f %f ", bezt->vec[0], bezt->vec[0]+1, bezt->vec[0]+2);
|
|
|
|
Mat4MulVecfl(tmat, bezt->vec[0]);
|
|
|
|
fscanf(fp, "%f %f %f ", bezt->vec[1], bezt->vec[1]+1, bezt->vec[1]+2);
|
|
|
|
Mat4MulVecfl(tmat, bezt->vec[1]);
|
|
|
|
fscanf(fp, "%f %f %f ", bezt->vec[2], bezt->vec[2]+1, bezt->vec[2]+2);
|
|
|
|
Mat4MulVecfl(tmat, bezt->vec[2]);
|
|
|
|
fscanf(fp, "%d %d\n", &type, &val);
|
|
|
|
bezt->h1= type;
|
|
|
|
bezt->h2= val;
|
|
|
|
bezt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
a= nu->pntsu*nu->pntsv;
|
|
|
|
if(a) {
|
|
|
|
nu->bp= bp= MEM_callocN(a*sizeof(BPoint), "bp from exotic");
|
|
|
|
while(a--) {
|
|
|
|
fscanf(fp, "%f %f %f %f\n", bp->vec, bp->vec+1, bp->vec+2, bp->vec+3);
|
|
|
|
Mat4MulVecfl(tmat, bp->vec);
|
|
|
|
bp++;
|
|
|
|
}
|
|
|
|
|
|
|
|
val= KNOTSU(nu);
|
|
|
|
nu->knotsu= MEM_mallocN(sizeof(float)*val, "knots");
|
|
|
|
for(a=0; a<val; a++) fscanf(fp, "%f\n", nu->knotsu+a);
|
|
|
|
|
|
|
|
if(nu->pntsv>1) {
|
|
|
|
val= KNOTSV(nu);
|
|
|
|
nu->knotsv= MEM_mallocN(sizeof(float)*val, "knots");
|
|
|
|
for(a=0; a<val; a++) fscanf(fp, "%f\n", nu->knotsv+a);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
BLI_remlink(&cu->nurb, nu);
|
|
|
|
MEM_freeN(nu);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
makeDispList(ob);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void read_videoscape(char *str)
|
|
|
|
{
|
|
|
|
int file, type;
|
Phew, a lot of work, and no new features...
Main target was to make the inner rendering loop using no globals anymore.
This is essential for proper usage while raytracing, it caused a lot of
hacks in the raycode as well, which even didn't work correctly for all
situations (textures especially).
Done this by creating a new local struct RenderInput, which replaces usage
of the global struct Render R. The latter now only is used to denote
image size, viewmatrix, and the like.
Making the inner render loops using no globals caused 1000s of vars to
be changed... but the result definitely is much nicer code, which enables
making 'real' shaders in a next stage.
It also enabled me to remove the hacks from ray.c
Then i went to the task of removing redundant code. Especially the calculus
of texture coords took place (identical) in three locations.
Most obvious is the change in the unified render part, which is much less
code now; it uses the same rendering routines as normal render now.
(Note; not for halos yet!)
I also removed 6 files called 'shadowbuffer' something. This was experimen-
tal stuff from NaN days. And again saved a lot of double used code.
Finally I went over the blenkernel and blender/src calls to render stuff.
Here the same local data is used now, resulting in less dependency.
I also moved render-texture to the render module, this was still in Kernel.
(new file: texture.c)
So! After this commit I will check on the autofiles, to try to fix that.
MSVC people have to do it themselves.
This commit will need quite some testing help, but I'm around!
2003-12-21 21:52:51 +00:00
|
|
|
unsigned int val;
|
|
|
|
unsigned short numlen;
|
2002-10-12 11:37:38 +00:00
|
|
|
char name[FILE_MAXDIR+FILE_MAXFILE], head[FILE_MAXFILE], tail[FILE_MAXFILE];
|
|
|
|
|
|
|
|
strcpy(name, str);
|
|
|
|
|
|
|
|
while( TRUE ) {
|
|
|
|
file= open(name, O_BINARY|O_RDONLY);
|
|
|
|
if(file<=0) break;
|
|
|
|
else {
|
|
|
|
read(file, &type, 4);
|
|
|
|
close(file);
|
|
|
|
|
|
|
|
if(type==DDG1) read_videoscape_mesh(name);
|
|
|
|
else if(type==DDG2) read_videoscape_lamp(name);
|
|
|
|
else if(type==DDG3) read_videoscape_nurbs(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
val = BLI_stringdec(name, head, tail, &numlen);
|
|
|
|
BLI_stringenc(name, head, tail, numlen, val + 1);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ***************** INVENTOR ******************* */
|
|
|
|
|
|
|
|
|
2004-12-12 11:19:27 +00:00
|
|
|
#define IV_MAXSTACK 3000000
|
2002-10-12 11:37:38 +00:00
|
|
|
#define IV_MAXFIELD 10
|
|
|
|
#define IV_MAXCOL 16
|
|
|
|
|
|
|
|
static float *iv_data_stack;
|
|
|
|
static float ivcolors[IV_MAXCOL][3];
|
|
|
|
static Object *ivsurf;
|
|
|
|
static ListBase ivbase;
|
|
|
|
|
|
|
|
struct IvNode {
|
|
|
|
struct IvNode *next, *prev;
|
|
|
|
char *nodename;
|
|
|
|
char *fieldname[IV_MAXFIELD];
|
|
|
|
int datalen[IV_MAXFIELD];
|
|
|
|
float *data[IV_MAXFIELD];
|
|
|
|
};
|
|
|
|
|
|
|
|
static int iv_curcol=0;
|
|
|
|
|
|
|
|
static int iv_colornumber(struct IvNode *iv)
|
|
|
|
{
|
|
|
|
float *fp, fr = 0.0, fg = 0.0, fb = 0.0;
|
|
|
|
int a;
|
|
|
|
char *cp;
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* search back to last material */
|
2002-10-12 11:37:38 +00:00
|
|
|
while(iv) {
|
|
|
|
if( strcmp(iv->nodename, "Material")==0) {
|
|
|
|
fp= iv->data[0];
|
|
|
|
if(fp==0) fp= iv->data[1];
|
|
|
|
if(fp) {
|
|
|
|
fr= fp[0];
|
|
|
|
fg= fp[1];
|
|
|
|
fb= fp[2];
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if( strcmp(iv->nodename, "BaseColor")==0) {
|
|
|
|
fp= iv->data[0];
|
|
|
|
fr= fp[0];
|
|
|
|
fg= fp[1];
|
|
|
|
fb= fp[2];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if( strcmp(iv->nodename, "PackedColor")==0) {
|
|
|
|
cp= (char *)iv->data[0];
|
|
|
|
fr= cp[3]/255.0f;
|
|
|
|
fg= cp[2]/255.0f;
|
|
|
|
fb= cp[1]/255.0f;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
iv= iv->prev;
|
|
|
|
|
|
|
|
}
|
|
|
|
if(iv==0) return 0;
|
|
|
|
if(iv->datalen[0]<3) return 0;
|
|
|
|
|
|
|
|
for(a=0; a<iv_curcol; a++) {
|
|
|
|
|
|
|
|
if(ivcolors[a][0]== fr)
|
|
|
|
if(ivcolors[a][1]== fg)
|
|
|
|
if(ivcolors[a][2]== fb) return a+1
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(a>=IV_MAXCOL) a= IV_MAXCOL-1;
|
|
|
|
iv_curcol= a+1;
|
|
|
|
ivcolors[a][0]= fr;
|
|
|
|
ivcolors[a][1]= fg;
|
|
|
|
ivcolors[a][2]= fb;
|
|
|
|
|
|
|
|
return iv_curcol;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int iv_finddata(struct IvNode *iv, char *field, int fieldnr)
|
|
|
|
{
|
2003-04-26 11:56:44 +00:00
|
|
|
/* search for "field", count data size and make datablock. return skipdata */
|
2002-10-12 11:37:38 +00:00
|
|
|
float *fp;
|
|
|
|
int len, stackcount, skipdata=0;
|
|
|
|
char *cpa, terminator, str[64];
|
|
|
|
long i;
|
|
|
|
|
|
|
|
len= strlen(field);
|
|
|
|
|
|
|
|
cpa= iv->nodename+1;
|
|
|
|
while( *cpa != '}' ) {
|
|
|
|
|
|
|
|
if( *cpa == *field ) {
|
|
|
|
if( strncmp(cpa, field, len)==0 ) {
|
|
|
|
iv->fieldname[fieldnr]= cpa;
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* read until first character */
|
2002-10-12 11:37:38 +00:00
|
|
|
cpa+= len;
|
|
|
|
skipdata+= len;
|
|
|
|
*cpa= 0;
|
|
|
|
cpa++;
|
|
|
|
skipdata++;
|
|
|
|
|
|
|
|
while( *cpa==32 || *cpa==13 || *cpa==10 || *cpa==9) cpa++;
|
|
|
|
if( *cpa=='[' ) {
|
|
|
|
terminator= ']';
|
|
|
|
cpa++;
|
|
|
|
skipdata++;
|
|
|
|
}
|
|
|
|
else terminator= 13;
|
|
|
|
|
|
|
|
stackcount= 0;
|
|
|
|
fp= iv_data_stack;
|
|
|
|
|
|
|
|
while( *cpa!=terminator && *cpa != '}' ) {
|
|
|
|
|
|
|
|
/* in fact, isdigit should include the dot and minus */
|
|
|
|
if( (isdigit(*cpa) || *cpa=='.' || *cpa=='-') && (isspace(cpa[-1]) || cpa[-1]==0 || cpa[-1]==',') ) {
|
|
|
|
if(cpa[1]=='x') {
|
|
|
|
memcpy(str, cpa, 16);
|
|
|
|
str[16]= 0;
|
|
|
|
|
|
|
|
sscanf(str, "%x", (int *)fp);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* atof doesn't stop after the first float
|
|
|
|
* in a long string at Windows... so we copy
|
|
|
|
* the float to a new string then atof... */
|
2004-07-22 00:15:50 +00:00
|
|
|
char *cpa_temp = strpbrk(cpa, ", \n");
|
|
|
|
i = cpa_temp - cpa;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
if (i>63) *fp= 0.0;
|
|
|
|
else {
|
|
|
|
memcpy(str, cpa, i);
|
|
|
|
str[i]=0;
|
|
|
|
|
|
|
|
*fp= (float) atof(str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
stackcount++;
|
|
|
|
if(stackcount>=IV_MAXSTACK) {
|
|
|
|
printf("stackoverflow in IV read\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
fp++;
|
|
|
|
}
|
|
|
|
cpa++;
|
|
|
|
skipdata++;
|
|
|
|
}
|
|
|
|
|
|
|
|
iv->datalen[fieldnr]= stackcount;
|
|
|
|
if(stackcount) {
|
|
|
|
iv->data[fieldnr]= MEM_mallocN(sizeof(float)*stackcount, "iv_finddata");
|
|
|
|
memcpy(iv->data[fieldnr], iv_data_stack, sizeof(float)*stackcount);
|
|
|
|
}
|
|
|
|
else iv->data[fieldnr]= 0;
|
|
|
|
|
|
|
|
return skipdata;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cpa++;
|
|
|
|
skipdata++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return skipdata;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void read_iv_index(float *data, float *baseadr, float *index, int nr, int coordtype)
|
|
|
|
{
|
2003-04-26 11:56:44 +00:00
|
|
|
/* write in data: baseadr with offset index (and number nr) */
|
2002-10-12 11:37:38 +00:00
|
|
|
float *fp;
|
|
|
|
int ofs;
|
|
|
|
|
|
|
|
while(nr--) {
|
|
|
|
ofs= (int) *index;
|
|
|
|
fp= baseadr+coordtype*ofs;
|
|
|
|
VECCOPY(data, fp);
|
|
|
|
data+= 3;
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void read_inventor(char *str, struct ListBase *listb)
|
|
|
|
{
|
|
|
|
struct IvNode *iv, *ivp, *ivn;
|
|
|
|
char *maindata, *md, *cpa;
|
|
|
|
float *index, *data, *fp;
|
2002-10-30 00:37:19 +00:00
|
|
|
int file, filelen, count, lll, face, nr = 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
int skipdata, ok, a, b, tot, first, colnr, coordtype, polytype, *idata;
|
|
|
|
struct DispList *dl;
|
|
|
|
|
|
|
|
ivbase.first= ivbase.last= 0;
|
|
|
|
iv_curcol= 0;
|
|
|
|
ivsurf= 0;
|
|
|
|
|
|
|
|
file= open(str, O_BINARY|O_RDONLY);
|
|
|
|
if(file== -1) {
|
|
|
|
error("Can't read file\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
filelen= BLI_filesize(file);
|
|
|
|
|
|
|
|
maindata= MEM_mallocN(filelen, "leesInventor");
|
|
|
|
read(file, maindata, filelen);
|
|
|
|
close(file);
|
|
|
|
|
|
|
|
iv_data_stack= MEM_mallocN(sizeof(float)*IV_MAXSTACK, "ivstack");
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* preprocess: remove comments */
|
2002-10-12 11:37:38 +00:00
|
|
|
md= maindata+20;
|
|
|
|
count= 20;
|
|
|
|
while(count<filelen) {
|
|
|
|
if( *md=='#' ) { /* comment */
|
|
|
|
while( *md!=13 && *md!=10) { /* enters */
|
|
|
|
*md= 32;
|
|
|
|
md++;
|
|
|
|
count++;
|
|
|
|
if(count>=filelen) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
md++;
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* now time to collect: which are the nodes and fields? */
|
2002-10-12 11:37:38 +00:00
|
|
|
md= maindata;
|
|
|
|
count= 0;
|
|
|
|
while(count<filelen) {
|
2003-04-26 11:56:44 +00:00
|
|
|
if( *md=='{' ) { /* read back */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
cpa= md-1;
|
2003-04-26 11:56:44 +00:00
|
|
|
while( *cpa==32 || *cpa==13 || *cpa==10 || *cpa==9) { /* remove spaces/enters/tab */
|
2002-10-12 11:37:38 +00:00
|
|
|
*cpa= 0;
|
|
|
|
cpa--;
|
|
|
|
}
|
|
|
|
|
|
|
|
while( *cpa>32 && *cpa<128) cpa--;
|
|
|
|
cpa++;
|
|
|
|
*md= 0;
|
|
|
|
|
|
|
|
ok= 0;
|
|
|
|
skipdata= 0;
|
|
|
|
iv= MEM_callocN(sizeof(struct IvNode), "leesInventor");
|
|
|
|
iv->nodename= cpa;
|
|
|
|
|
|
|
|
if(strcmp(cpa, "Coordinate3")==0 || strcmp(cpa, "Coordinate4")==0) {
|
|
|
|
skipdata= iv_finddata(iv, "point", 0);
|
|
|
|
ok= 1;
|
|
|
|
}
|
|
|
|
else if(strcmp(cpa, "VertexProperty")==0) {
|
|
|
|
skipdata= iv_finddata(iv, "vertex", 0);
|
|
|
|
ok= 1;
|
|
|
|
}
|
|
|
|
else if(strcmp(cpa, "IndexedLineSet")==0) {
|
|
|
|
skipdata= iv_finddata(iv, "coordIndex", 0);
|
|
|
|
ok= 1;
|
|
|
|
}
|
|
|
|
else if(strcmp(cpa, "IndexedTriangleMesh")==0) {
|
|
|
|
skipdata= iv_finddata(iv, "coordIndex", 0);
|
|
|
|
ok= 1;
|
|
|
|
}
|
|
|
|
else if(strcmp(cpa, "IndexedFaceSet")==0) {
|
|
|
|
skipdata= iv_finddata(iv, "coordIndex", 0);
|
|
|
|
ok= 1;
|
|
|
|
}
|
|
|
|
else if(strcmp(cpa, "FaceSet")==0) {
|
|
|
|
skipdata= iv_finddata(iv, "numVertices", 0);
|
|
|
|
ok= 1;
|
|
|
|
}
|
|
|
|
else if(strcmp(cpa, "Material")==0) {
|
|
|
|
iv_finddata(iv, "diffuseColor", 0);
|
|
|
|
iv_finddata(iv, "ambientColor", 1);
|
|
|
|
ok= 1;
|
|
|
|
}
|
|
|
|
else if(strcmp(cpa, "BaseColor")==0) {
|
|
|
|
iv_finddata(iv, "rgb", 0);
|
|
|
|
ok= 1;
|
|
|
|
}
|
|
|
|
else if(strcmp(cpa, "PackedColor")==0) {
|
|
|
|
iv_finddata(iv, "rgba", 0);
|
|
|
|
ok= 1;
|
|
|
|
}
|
|
|
|
else if(strcmp(cpa, "QuadMesh")==0) {
|
|
|
|
iv_finddata(iv, "verticesPerColumn", 0);
|
|
|
|
iv_finddata(iv, "verticesPerRow", 1);
|
|
|
|
|
|
|
|
ok= 1;
|
|
|
|
}
|
|
|
|
else if(strcmp(cpa, "IndexedTriangleStripSet")==0) {
|
|
|
|
skipdata= iv_finddata(iv, "coordIndex", 0);
|
|
|
|
ok= 1;
|
|
|
|
}
|
|
|
|
else if(strcmp(cpa, "TriangleStripSet")==0) {
|
|
|
|
skipdata= iv_finddata(iv, "numVertices", 0);
|
|
|
|
ok= 1;
|
|
|
|
}
|
|
|
|
else if(strcmp(cpa, "IndexedNurbsSurface")==0 || strcmp(cpa, "NurbsSurface")==0) {
|
|
|
|
iv_finddata(iv, "numUControlPoints", 0);
|
|
|
|
iv_finddata(iv, "numVControlPoints", 1);
|
|
|
|
iv_finddata(iv, "uKnotVector", 2);
|
|
|
|
iv_finddata(iv, "vKnotVector", 3);
|
|
|
|
ok= 1;
|
|
|
|
}
|
|
|
|
else {
|
2003-04-26 11:56:44 +00:00
|
|
|
/* to the end */
|
2002-10-12 11:37:38 +00:00
|
|
|
while( *md != '}') {
|
|
|
|
md++;
|
|
|
|
count++;
|
|
|
|
if(count<filelen) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(ok) {
|
|
|
|
BLI_addtail(&ivbase, iv);
|
|
|
|
md+= skipdata;
|
|
|
|
count+= skipdata;
|
|
|
|
}
|
|
|
|
else MEM_freeN(iv);
|
|
|
|
|
|
|
|
}
|
|
|
|
md++;
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* join nodes */
|
2002-10-12 11:37:38 +00:00
|
|
|
iv= ivbase.first;
|
|
|
|
|
|
|
|
while(iv) {
|
|
|
|
ivn= iv->next;
|
|
|
|
|
|
|
|
if( strncmp(iv->nodename, "Indexed", 7)==0) {
|
2003-04-26 11:56:44 +00:00
|
|
|
/* seek back: same name? */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
ivp= iv->prev;
|
|
|
|
while(ivp) {
|
|
|
|
if(strcmp(iv->nodename, ivp->nodename)==0) break;
|
|
|
|
|
|
|
|
if(strcmp(ivp->nodename, "Coordinate3")==0 ||
|
|
|
|
strcmp(ivp->nodename, "Coordinate4")==0 ||
|
|
|
|
strcmp(ivp->nodename, "VertexProperty")==0) {
|
|
|
|
ivp= 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
ivp= ivp->prev;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ivp) {
|
2003-04-26 11:56:44 +00:00
|
|
|
/* add iv to ivp */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
tot= iv->datalen[0] + ivp->datalen[0];
|
|
|
|
if(tot) {
|
|
|
|
data= MEM_mallocN(tot*sizeof(float), "samenvoeg iv");
|
|
|
|
memcpy(data, ivp->data[0], sizeof(float)*ivp->datalen[0]);
|
|
|
|
memcpy(data+ivp->datalen[0], iv->data[0], sizeof(float)*iv->datalen[0]);
|
|
|
|
|
|
|
|
ivp->datalen[0]+= iv->datalen[0];
|
|
|
|
MEM_freeN(ivp->data[0]);
|
|
|
|
ivp->data[0]= data;
|
|
|
|
|
|
|
|
BLI_remlink(&ivbase, iv);
|
|
|
|
MEM_freeN(iv->data[0]);
|
|
|
|
MEM_freeN(iv);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
iv= ivn;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* convert Nodes to DispLists */
|
2002-10-12 11:37:38 +00:00
|
|
|
iv= ivbase.first;
|
|
|
|
while(iv) {
|
|
|
|
|
|
|
|
/* printf(" Node: %s\n", iv->nodename); */
|
|
|
|
/* if(iv->fieldname[0]) printf(" Field: %s len %d\n", iv->fieldname[0], iv->datalen[0]); */
|
|
|
|
coordtype= 3;
|
|
|
|
|
|
|
|
if( strcmp(iv->nodename, "IndexedLineSet")==0 ) {
|
|
|
|
|
|
|
|
colnr= iv_colornumber(iv);
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* seek back to data */
|
2002-10-12 11:37:38 +00:00
|
|
|
ivp= iv;
|
|
|
|
while(ivp->prev) {
|
|
|
|
ivp= ivp->prev;
|
|
|
|
if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
|
|
|
|
coordtype= 3;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
|
|
|
|
coordtype= 4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(ivp) {
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* count the nr of lines */
|
2002-10-12 11:37:38 +00:00
|
|
|
tot= 0;
|
|
|
|
index= iv->data[0];
|
2002-10-30 00:37:19 +00:00
|
|
|
lll = iv->datalen[0]-1;
|
|
|
|
for(a=0; a<lll; a++) {
|
2002-10-12 11:37:38 +00:00
|
|
|
if(index[0]!= -1 && index[1]!= -1) tot++;
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
tot*= 2; /* nr of vertices */
|
2002-10-12 11:37:38 +00:00
|
|
|
dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor1");
|
|
|
|
BLI_addtail(listb, dl);
|
|
|
|
dl->type= DL_SEGM;
|
|
|
|
dl->nr= 2;
|
|
|
|
dl->parts= tot/2;
|
|
|
|
dl->col= colnr;
|
|
|
|
data= (float *)(dl+1);
|
|
|
|
|
|
|
|
index= iv->data[0];
|
2002-10-30 00:37:19 +00:00
|
|
|
for(a=0; a<lll; a++) {
|
2002-10-12 11:37:38 +00:00
|
|
|
if(index[0]!= -1 && index[1]!= -1) {
|
|
|
|
read_iv_index(data, ivp->data[0], index, 2, coordtype);
|
|
|
|
data+= 6;
|
|
|
|
}
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( strcmp(iv->nodename, "FaceSet")==0 ) {
|
|
|
|
|
|
|
|
colnr= iv_colornumber(iv);
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* seek back to data */
|
2002-10-12 11:37:38 +00:00
|
|
|
ivp= iv;
|
|
|
|
while(ivp->prev) {
|
|
|
|
ivp= ivp->prev;
|
|
|
|
if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
|
|
|
|
coordtype= 3;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
|
|
|
|
coordtype= 4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ivp) {
|
2003-04-26 11:56:44 +00:00
|
|
|
/* count triangles */
|
2002-10-12 11:37:38 +00:00
|
|
|
tot= 0;
|
|
|
|
|
|
|
|
index= iv->data[0];
|
|
|
|
polytype= (int) index[0];
|
|
|
|
|
|
|
|
for(a=0; a<iv->datalen[0]; a++) {
|
2003-04-26 11:56:44 +00:00
|
|
|
if(index[0]== polytype) tot++; /* one kind? */
|
2002-10-12 11:37:38 +00:00
|
|
|
index++;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
tot*= polytype; /* nr of vertices */
|
2002-10-12 11:37:38 +00:00
|
|
|
dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor4");
|
|
|
|
BLI_addtail(listb, dl);
|
|
|
|
dl->type= DL_POLY;
|
|
|
|
dl->nr= polytype;
|
|
|
|
dl->parts= tot/polytype;
|
|
|
|
dl->col= colnr;
|
|
|
|
data= (float *)(dl+1);
|
|
|
|
|
|
|
|
index= ivp->data[0];
|
|
|
|
first= 1;
|
|
|
|
for(a=0; a<iv->datalen[0]; a++) {
|
|
|
|
|
|
|
|
VECCOPY(data, index);
|
|
|
|
data+= 3;
|
|
|
|
index+= 3;
|
|
|
|
|
|
|
|
VECCOPY(data, index);
|
|
|
|
data+= 3;
|
|
|
|
index+= 3;
|
|
|
|
|
|
|
|
VECCOPY(data, index);
|
|
|
|
data+= 3;
|
|
|
|
index+= 3;
|
|
|
|
|
|
|
|
if(polytype==4) {
|
|
|
|
VECCOPY(data, index);
|
|
|
|
data+= 3;
|
|
|
|
index+= 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( strcmp(iv->nodename, "TriangleStripSet")==0 ) {
|
|
|
|
|
|
|
|
colnr= iv_colornumber(iv);
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* seek back to data */
|
2002-10-12 11:37:38 +00:00
|
|
|
ivp= iv;
|
|
|
|
while(ivp->prev) {
|
|
|
|
ivp= ivp->prev;
|
|
|
|
if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
|
|
|
|
coordtype= 3;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
|
|
|
|
coordtype= 4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ivp) {
|
2003-04-26 11:56:44 +00:00
|
|
|
/* count triangles */
|
2002-10-12 11:37:38 +00:00
|
|
|
tot= 0;
|
|
|
|
face= 0;
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
index= iv->data[0]; /* strip size */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
for(a=0; a<iv->datalen[0]; a++) {
|
|
|
|
tot+= (int) index[0];
|
|
|
|
face+= ((int) index[0]) - 2;
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
|
|
|
|
dl= MEM_callocN(sizeof(struct DispList), "leesInventor4");
|
|
|
|
dl->verts= MEM_callocN( tot*3*sizeof(float), "dl verts");
|
|
|
|
dl->index= MEM_callocN( face*3*sizeof(int), "dl index");
|
|
|
|
|
|
|
|
dl->type= DL_INDEX3;
|
|
|
|
dl->nr= tot;
|
|
|
|
dl->parts= face;
|
|
|
|
|
|
|
|
BLI_addtail(listb, dl);
|
|
|
|
dl->col= colnr;
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
index= iv->data[0]; /* strip size */
|
2002-10-12 11:37:38 +00:00
|
|
|
fp= ivp->data[0]; /* vertices */
|
|
|
|
data= dl->verts;
|
|
|
|
idata= dl->index;
|
|
|
|
first= 0;
|
|
|
|
|
|
|
|
for(a=0; a<iv->datalen[0]; a++) {
|
|
|
|
|
|
|
|
/* vertices */
|
|
|
|
for(b=0; b<index[0]; b++) {
|
|
|
|
VECCOPY(data, fp);
|
|
|
|
data+= 3;
|
|
|
|
fp+= coordtype;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* indices */
|
2002-10-30 00:37:19 +00:00
|
|
|
lll = index[0] - 2;
|
|
|
|
for(b=0; b<lll; b++) {
|
2002-10-12 11:37:38 +00:00
|
|
|
idata[0]= first;
|
|
|
|
idata[1]= first+1;
|
|
|
|
idata[2]= first+2;
|
|
|
|
first++;
|
|
|
|
idata+= 3;
|
|
|
|
}
|
|
|
|
first+= 2;
|
|
|
|
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( strcmp(iv->nodename, "IndexedFaceSet")==0 ) {
|
|
|
|
|
|
|
|
colnr= iv_colornumber(iv);
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* seek back to data */
|
2002-10-12 11:37:38 +00:00
|
|
|
ivp= iv;
|
|
|
|
while(ivp->prev) {
|
|
|
|
ivp= ivp->prev;
|
|
|
|
if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
|
|
|
|
coordtype= 3;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
|
|
|
|
coordtype= 4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(ivp) {
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* count triangles */
|
2002-10-12 11:37:38 +00:00
|
|
|
face= 0;
|
|
|
|
index= iv->data[0];
|
2002-11-12 20:12:40 +00:00
|
|
|
lll = iv->datalen[0]-2;
|
|
|
|
for(a=0; a<lll; a++) {
|
2002-10-12 11:37:38 +00:00
|
|
|
if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) face++;
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/*number of vertices */
|
2002-10-12 11:37:38 +00:00
|
|
|
tot= ivp->datalen[0]/coordtype;
|
|
|
|
|
|
|
|
if(tot) {
|
|
|
|
dl= MEM_callocN(sizeof(struct DispList), "leesInventor5");
|
|
|
|
BLI_addtail(listb, dl);
|
|
|
|
dl->type= DL_INDEX3;
|
|
|
|
dl->nr= tot;
|
|
|
|
dl->parts= face;
|
|
|
|
dl->col= colnr;
|
|
|
|
|
|
|
|
dl->verts= MEM_callocN( tot*3*sizeof(float), "dl verts");
|
|
|
|
dl->index= MEM_callocN(sizeof(int)*3*face, "dl index");
|
|
|
|
|
|
|
|
/* vertices */
|
|
|
|
fp= ivp->data[0];
|
|
|
|
data= dl->verts;
|
|
|
|
for(b=tot; b>0; b--) {
|
|
|
|
VECCOPY(data, fp);
|
|
|
|
data+= 3;
|
|
|
|
fp+= coordtype;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* indices */
|
|
|
|
index= iv->data[0];
|
|
|
|
idata= dl->index;
|
|
|
|
first= 1;
|
2002-10-30 00:37:19 +00:00
|
|
|
lll=iv->datalen[0]-2;
|
|
|
|
for(a=0; a<lll; a++) {
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) {
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* this trick is to fill poly's with more than 3 vertices correctly */
|
2002-10-12 11:37:38 +00:00
|
|
|
if(first) {
|
|
|
|
nr= (int) index[0];
|
|
|
|
first= 0;
|
|
|
|
}
|
|
|
|
idata[0]= nr;
|
|
|
|
idata[1]= (int) index[1];
|
|
|
|
idata[2]= (int) index[2];
|
|
|
|
idata+= 3;
|
|
|
|
}
|
|
|
|
else first= 1;
|
|
|
|
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( strcmp(iv->nodename, "IndexedTriangleMesh")==0 ||
|
|
|
|
strcmp(iv->nodename, "IndexedTriangleStripSet")==0 ) {
|
|
|
|
|
|
|
|
colnr= iv_colornumber(iv);
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* seek back to data */
|
2002-10-12 11:37:38 +00:00
|
|
|
ivp= iv;
|
|
|
|
while(ivp->prev) {
|
|
|
|
ivp= ivp->prev;
|
|
|
|
if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
|
|
|
|
coordtype= 3;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
|
|
|
|
coordtype= 4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(ivp) {
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* count triangles */
|
2002-10-12 11:37:38 +00:00
|
|
|
face= 0;
|
|
|
|
index= iv->data[0];
|
2002-10-30 00:37:19 +00:00
|
|
|
lll=iv->datalen[0]-2;
|
|
|
|
for(a=0; a<lll; a++) {
|
2002-10-12 11:37:38 +00:00
|
|
|
if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) face++;
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* nr of vertices */
|
2002-10-12 11:37:38 +00:00
|
|
|
tot= ivp->datalen[0]/coordtype;
|
|
|
|
|
|
|
|
dl= MEM_callocN(sizeof(struct DispList), "leesInventor6");
|
|
|
|
BLI_addtail(listb, dl);
|
|
|
|
dl->type= DL_INDEX3;
|
|
|
|
dl->nr= tot;
|
|
|
|
dl->parts= face;
|
|
|
|
dl->col= colnr;
|
|
|
|
|
|
|
|
dl->verts= MEM_callocN( tot*3*sizeof(float), "dl verts");
|
|
|
|
dl->index= MEM_callocN(sizeof(int)*3*face, "dl index");
|
|
|
|
|
|
|
|
/* vertices */
|
|
|
|
fp= ivp->data[0];
|
|
|
|
data= dl->verts;
|
|
|
|
for(b=tot; b>0; b--) {
|
|
|
|
VECCOPY(data, fp);
|
|
|
|
data+= 3;
|
|
|
|
fp+= coordtype;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* indices */
|
|
|
|
index= iv->data[0];
|
|
|
|
idata= dl->index;
|
|
|
|
|
2002-10-30 00:37:19 +00:00
|
|
|
lll=iv->datalen[0]-2;
|
|
|
|
for(a=lll; a>0; a--) {
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) {
|
|
|
|
idata[0]= (int) index[0];
|
|
|
|
idata[1]= (int) index[1];
|
|
|
|
idata[2]= (int) index[2];
|
|
|
|
idata+= 3;
|
|
|
|
}
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( strcmp(iv->nodename, "QuadMesh")==0 ) {
|
|
|
|
|
|
|
|
colnr= iv_colornumber(iv);
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* seek back to data */
|
2002-10-12 11:37:38 +00:00
|
|
|
ivp= iv;
|
|
|
|
while(ivp->prev) {
|
|
|
|
ivp= ivp->prev;
|
|
|
|
if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
|
|
|
|
coordtype= 3;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if( strcmp(ivp->nodename, "VertexProperty")==0 ) {
|
|
|
|
coordtype= 3;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
|
|
|
|
coordtype= 4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ivp) {
|
|
|
|
tot= (int) (floor(*(iv->data[0])+0.5) * floor(*(iv->data[1])+0.5));
|
|
|
|
|
|
|
|
if(tot>0) {
|
|
|
|
dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor8");
|
|
|
|
BLI_addtail(listb, dl);
|
|
|
|
dl->type= DL_SURF;
|
|
|
|
dl->parts= (int) floor(*(iv->data[0])+0.5);
|
|
|
|
dl->nr= (int) floor(*(iv->data[1])+0.5);
|
|
|
|
dl->col= colnr;
|
|
|
|
data= (float *)(dl+1);
|
|
|
|
memcpy(data, ivp->data[0], tot*3*sizeof(float));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(strcmp(iv->nodename, "IndexedNurbsSurface")==0 || strcmp(iv->nodename, "NurbsSurface")==0) {
|
|
|
|
|
|
|
|
colnr= iv_colornumber(iv);
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* sek back to data */
|
2002-10-12 11:37:38 +00:00
|
|
|
ivp= iv;
|
|
|
|
while(ivp->prev) {
|
|
|
|
ivp= ivp->prev;
|
|
|
|
if( strcmp(ivp->nodename, "Coordinate3")==0 ) {
|
|
|
|
coordtype= 3;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if( strcmp(ivp->nodename, "Coordinate4")==0 ) {
|
|
|
|
coordtype= 4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(ivp) {
|
|
|
|
a= (int) *(iv->data[0]);
|
|
|
|
b= (int) *(iv->data[1]);
|
|
|
|
|
|
|
|
tot= a*b;
|
|
|
|
|
|
|
|
if( (a>=4 || b>=4) && tot>6) {
|
|
|
|
Object *ob;
|
|
|
|
Curve *cu;
|
|
|
|
Nurb *nu;
|
|
|
|
BPoint *bp;
|
|
|
|
|
|
|
|
if(ivsurf==0) {
|
|
|
|
ob= add_object(OB_SURF);
|
|
|
|
ivsurf= ob;
|
|
|
|
}
|
|
|
|
else ob= ivsurf;
|
|
|
|
cu= ob->data;
|
|
|
|
nu = (Nurb*) MEM_callocN(sizeof(Nurb),"addNurbprim") ;
|
|
|
|
BLI_addtail(&cu->nurb, nu);
|
|
|
|
nu->type= CU_NURBS;
|
|
|
|
|
|
|
|
nu->pntsu= a;
|
|
|
|
nu->pntsv= b;
|
|
|
|
nu->resolu= 2*a;
|
|
|
|
nu->resolv= 2*b;
|
|
|
|
|
|
|
|
nu->flagu= 0;
|
|
|
|
nu->flagv= 0;
|
|
|
|
|
|
|
|
nu->bp = bp =
|
|
|
|
(BPoint*)MEM_callocN(tot * sizeof(BPoint), "addNurbprim3");
|
|
|
|
a= tot;
|
|
|
|
data= ivp->data[0];
|
|
|
|
while(a--) {
|
|
|
|
VECCOPY(bp->vec, data);
|
|
|
|
if(coordtype==4) {
|
|
|
|
bp->vec[3]= data[3];
|
|
|
|
VecMulf(bp->vec, 1.0f/data[3]);
|
|
|
|
}
|
|
|
|
else bp->vec[3]= 1.0;
|
|
|
|
data+= coordtype;
|
|
|
|
bp++;
|
|
|
|
}
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* iv->datalen[2] / [3] is number of knots */
|
2002-10-12 11:37:38 +00:00
|
|
|
nu->orderu= iv->datalen[2] - nu->pntsu;
|
|
|
|
nu->orderv= iv->datalen[3] - nu->pntsv;
|
|
|
|
|
|
|
|
nu->knotsu= MEM_mallocN( sizeof(float)*(iv->datalen[2]), "knots");
|
|
|
|
memcpy(nu->knotsu, iv->data[2], sizeof(float)*(iv->datalen[2]));
|
|
|
|
nu->knotsv= MEM_mallocN( sizeof(float)*(iv->datalen[3]), "knots");
|
|
|
|
memcpy(nu->knotsv, iv->data[3], sizeof(float)*(iv->datalen[3]));
|
|
|
|
|
|
|
|
switchdirectionNurb(nu);
|
|
|
|
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
dl= MEM_callocN(sizeof(struct DispList)+tot*3*sizeof(float), "leesInventor3");
|
|
|
|
BLI_addtail(listb, dl);
|
|
|
|
dl->type= DL_SURF;
|
|
|
|
dl->nr= (int) *(iv->data[0]);
|
|
|
|
dl->parts= (int) *(iv->data[1]);
|
|
|
|
dl->col= colnr;
|
|
|
|
data= (float *)(dl+1);
|
|
|
|
|
|
|
|
a= tot;
|
|
|
|
fp= ivp->data[0];
|
|
|
|
while(a--) {
|
|
|
|
VECCOPY(data, fp);
|
|
|
|
fp+= coordtype;
|
|
|
|
data+= 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
iv= iv->next;
|
|
|
|
}
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* free */
|
2002-10-12 11:37:38 +00:00
|
|
|
iv= ivbase.first;
|
|
|
|
while(iv) {
|
|
|
|
for(a=0; a<IV_MAXFIELD; a++) {
|
|
|
|
if(iv->data[a]) MEM_freeN(iv->data[a]);
|
|
|
|
}
|
|
|
|
iv= iv->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
BLI_freelistN(&ivbase);
|
|
|
|
MEM_freeN(maindata);
|
|
|
|
MEM_freeN(iv_data_stack);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ************************************************************ */
|
|
|
|
|
|
|
|
static void displist_to_mesh(DispList *dlfirst)
|
|
|
|
{
|
|
|
|
Object *ob;
|
|
|
|
Mesh *me;
|
|
|
|
Material *ma;
|
|
|
|
DispList *dl;
|
|
|
|
MVert *mvert;
|
|
|
|
MFace *mface;
|
|
|
|
float *data, vec[3], min[3], max[3];
|
2004-09-18 20:15:37 +00:00
|
|
|
int a, b, startve, *idata, totedge=0, tottria=0, totquad=0, totvert=0, totface, totcol=0, colnr;
|
2002-10-12 11:37:38 +00:00
|
|
|
int p1, p2, p3, p4;
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* count first */
|
2002-10-12 11:37:38 +00:00
|
|
|
INIT_MINMAX(min, max);
|
|
|
|
|
|
|
|
dl= dlfirst;
|
|
|
|
while(dl) {
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* PATCH 1 (polyfill) can't be done, there's no listbase here. do that first! */
|
2002-10-12 11:37:38 +00:00
|
|
|
/* PATCH 2 */
|
|
|
|
if(dl->type==DL_SEGM && dl->nr>2) {
|
|
|
|
data= (float *)(dl+1);
|
|
|
|
if(data[0]==data[3*(dl->nr-1)]) {
|
|
|
|
if(data[1]==data[3*(dl->nr-1)+1]) {
|
|
|
|
if(data[2]==data[3*(dl->nr-1)+2]) {
|
|
|
|
dl->type= DL_POLY;
|
|
|
|
dl->nr--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* colors */
|
2002-10-12 11:37:38 +00:00
|
|
|
if(dl->col > totcol) totcol= dl->col;
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* size and count */
|
2002-10-12 11:37:38 +00:00
|
|
|
if(dl->type==DL_SURF) {
|
|
|
|
a= dl->nr;
|
|
|
|
b= dl->parts;
|
|
|
|
if(dl->flag & 1) a++;
|
|
|
|
if(dl->flag & 2) b++;
|
|
|
|
|
|
|
|
totquad+= a*b;
|
|
|
|
|
|
|
|
totvert+= dl->nr*dl->parts;
|
|
|
|
|
|
|
|
data= (float *)(dl+1);
|
|
|
|
for(a= dl->nr*dl->parts; a>0; a--) {
|
|
|
|
DO_MINMAX(data, min, max);
|
|
|
|
data+= 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(dl->type==DL_POLY) {
|
|
|
|
if(dl->nr==3 || dl->nr==4) {
|
|
|
|
if(dl->nr==3) tottria+= dl->parts;
|
|
|
|
else totquad+= dl->parts;
|
|
|
|
|
|
|
|
totvert+= dl->nr*dl->parts;
|
|
|
|
|
|
|
|
data= (float *)(dl+1);
|
|
|
|
for(a= dl->nr*dl->parts; a>0; a--) {
|
|
|
|
DO_MINMAX(data, min, max);
|
|
|
|
data+= 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(dl->nr>4) {
|
|
|
|
|
|
|
|
tottria+= dl->nr*dl->parts;
|
|
|
|
totvert+= dl->nr*dl->parts;
|
|
|
|
|
|
|
|
data= (float *)(dl+1);
|
|
|
|
for(a= dl->nr*dl->parts; a>0; a--) {
|
|
|
|
DO_MINMAX(data, min, max);
|
|
|
|
data+= 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(dl->type==DL_INDEX3) {
|
|
|
|
tottria+= dl->parts;
|
|
|
|
totvert+= dl->nr;
|
|
|
|
|
|
|
|
data= dl->verts;
|
|
|
|
for(a= dl->nr; a>0; a--) {
|
|
|
|
DO_MINMAX(data, min, max);
|
|
|
|
data+= 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(dl->type==DL_SEGM) {
|
|
|
|
|
|
|
|
tottria+= (dl->nr-1)*dl->parts;
|
|
|
|
totvert+= dl->nr*dl->parts;
|
|
|
|
|
|
|
|
data= (float *)(dl+1);
|
|
|
|
for(a= dl->nr*dl->parts; a>0; a--) {
|
|
|
|
DO_MINMAX(data, min, max);
|
|
|
|
data+= 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dl= dl->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(totvert==0) {
|
|
|
|
return;
|
|
|
|
}
|
2004-03-14 21:21:09 +00:00
|
|
|
if(totvert>MESH_MAX_VERTS || tottria>=MESH_MAX_VERTS) {
|
|
|
|
if (totvert>=MESH_MAX_VERTS) {
|
2002-10-12 11:37:38 +00:00
|
|
|
error("Too many vertices (%d)", totvert);
|
|
|
|
} else {
|
|
|
|
error("Too many faces (%d)", tottria);
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(totcol>16) {
|
|
|
|
error("Found more than 16 different colors");
|
|
|
|
totcol= 16;
|
|
|
|
}
|
|
|
|
|
|
|
|
vec[0]= (min[0]+max[0])/2;
|
|
|
|
vec[1]= (min[1]+max[1])/2;
|
|
|
|
vec[2]= (min[2]+max[2])/2;
|
|
|
|
|
|
|
|
ob= add_object(OB_MESH);
|
|
|
|
VECCOPY(ob->loc, vec);
|
|
|
|
where_is_object(ob);
|
|
|
|
|
|
|
|
me= ob->data;
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* colors */
|
2002-10-12 11:37:38 +00:00
|
|
|
if(totcol) {
|
|
|
|
ob->mat= MEM_callocN(sizeof(void *)*totcol, "ob->mat");
|
|
|
|
me->mat= MEM_callocN(sizeof(void *)*totcol, "me->mat");
|
|
|
|
me->totcol= totcol;
|
|
|
|
ob->totcol= (unsigned char) me->totcol;
|
|
|
|
ob->actcol= 1;
|
|
|
|
}
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* materials */
|
2002-10-12 11:37:38 +00:00
|
|
|
for(a=0; a<totcol; a++) {
|
|
|
|
ma= G.main->mat.first;
|
|
|
|
while(ma) {
|
|
|
|
if(ma->mtex[0]==0) {
|
|
|
|
if(ivcolors[a][0]==ma->r && ivcolors[a][1]==ma->g && ivcolors[a][2]==ma->b) {
|
|
|
|
me->mat[a]= ma;
|
|
|
|
ma->id.us++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ma= ma->id.next;
|
|
|
|
}
|
|
|
|
if(ma==0) {
|
|
|
|
ma= add_material("ext");
|
|
|
|
me->mat[a]= ma;
|
|
|
|
ma->r= ivcolors[a][0];
|
|
|
|
ma->g= ivcolors[a][1];
|
|
|
|
ma->b= ivcolors[a][2];
|
|
|
|
automatname(ma);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-18 20:15:37 +00:00
|
|
|
totface= totquad+tottria+totedge;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2004-09-18 20:15:37 +00:00
|
|
|
printf("Import: %d vertices %d faces\n", totvert, totface);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
if(totvert) me->mvert= MEM_callocN(totvert*sizeof(MVert), "mvert");
|
2004-09-18 20:15:37 +00:00
|
|
|
if(totface) me->mface= MEM_callocN(totface*sizeof(MFace), "mface");
|
2002-10-12 11:37:38 +00:00
|
|
|
me->totvert= totvert;
|
2004-09-18 20:15:37 +00:00
|
|
|
me->totface= totface;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
mvert= me->mvert;
|
|
|
|
mface= me->mface;
|
|
|
|
|
|
|
|
startve= 0;
|
|
|
|
|
|
|
|
dl= dlfirst;
|
|
|
|
while(dl) {
|
|
|
|
|
|
|
|
colnr= (dl->col>15 ? 15: dl->col);
|
|
|
|
if(colnr) colnr--;
|
|
|
|
|
|
|
|
if(dl->type==DL_SURF) {
|
|
|
|
data= (float *)(dl+1);
|
|
|
|
|
|
|
|
for(a=dl->parts*dl->nr; a>0; a--) {
|
|
|
|
mvert->co[0]= data[0] -vec[0];
|
|
|
|
mvert->co[1]= data[1] -vec[1];
|
|
|
|
mvert->co[2]= data[2] -vec[2];
|
|
|
|
|
|
|
|
data+=3;
|
|
|
|
mvert++;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(a=0; a<dl->parts; a++) {
|
|
|
|
|
|
|
|
DL_SURFINDEX(dl->flag & 1, dl->flag & 2, dl->nr, dl->parts);
|
|
|
|
p1+= startve;
|
|
|
|
p2+= startve;
|
|
|
|
p3+= startve;
|
|
|
|
p4+= startve;
|
|
|
|
|
|
|
|
for(; b<dl->nr; b++) {
|
|
|
|
|
|
|
|
mface->v1= p1;
|
|
|
|
mface->v2= p2;
|
|
|
|
mface->v3= p4;
|
|
|
|
mface->v4= p3;
|
|
|
|
|
|
|
|
mface->mat_nr= colnr;
|
|
|
|
test_index_mface(mface, 4);
|
|
|
|
|
|
|
|
mface++;
|
|
|
|
|
|
|
|
p4= p3;
|
|
|
|
p3++;
|
|
|
|
p2= p1;
|
|
|
|
p1++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
startve += dl->parts*dl->nr;
|
|
|
|
|
|
|
|
}
|
|
|
|
else if(dl->type==DL_POLY) {
|
|
|
|
|
|
|
|
if(dl->nr==3 || dl->nr==4) {
|
|
|
|
data= (float *)(dl+1);
|
|
|
|
|
|
|
|
for(a=dl->parts*dl->nr; a>0; a--) {
|
|
|
|
mvert->co[0]= data[0] -vec[0];
|
|
|
|
mvert->co[1]= data[1] -vec[1];
|
|
|
|
mvert->co[2]= data[2] -vec[2];
|
|
|
|
data+=3;
|
|
|
|
mvert++;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(a=0; a<dl->parts; a++) {
|
|
|
|
if(dl->nr==3) {
|
|
|
|
mface->v1= startve+a*dl->nr;
|
|
|
|
mface->v2= startve+a*dl->nr+1;
|
|
|
|
mface->v3= startve+a*dl->nr+2;
|
|
|
|
mface->mat_nr= colnr;
|
|
|
|
test_index_mface(mface, 3);
|
|
|
|
mface++;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
mface->v1= startve+a*dl->nr;
|
|
|
|
mface->v2= startve+a*dl->nr+1;
|
|
|
|
mface->v3= startve+a*dl->nr+2;
|
|
|
|
mface->v4= startve+a*dl->nr+3;
|
|
|
|
mface->mat_nr= colnr;
|
|
|
|
test_index_mface(mface, 4);
|
|
|
|
mface++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
startve += dl->parts*dl->nr;
|
|
|
|
}
|
|
|
|
else if(dl->nr>4) {
|
|
|
|
data= (float *)(dl+1);
|
|
|
|
|
|
|
|
for(a=dl->parts*dl->nr; a>0; a--) {
|
|
|
|
mvert->co[0]= data[0] -vec[0];
|
|
|
|
mvert->co[1]= data[1] -vec[1];
|
|
|
|
mvert->co[2]= data[2] -vec[2];
|
|
|
|
|
|
|
|
data+=3;
|
|
|
|
mvert++;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(b=0; b<dl->parts; b++) {
|
|
|
|
for(a=0; a<dl->nr; a++) {
|
|
|
|
mface->v1= startve+a;
|
|
|
|
|
|
|
|
if(a==dl->nr-1) mface->v2= startve;
|
|
|
|
else mface->v2= startve+a+1;
|
|
|
|
|
|
|
|
mface->mat_nr= colnr;
|
|
|
|
test_index_mface(mface, 2);
|
|
|
|
|
|
|
|
mface++;
|
|
|
|
}
|
|
|
|
startve += dl->nr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(dl->type==DL_INDEX3) {
|
|
|
|
data= dl->verts;
|
|
|
|
|
|
|
|
for(a=dl->nr; a>0; a--) {
|
|
|
|
mvert->co[0]= data[0] -vec[0];
|
|
|
|
mvert->co[1]= data[1] -vec[1];
|
|
|
|
mvert->co[2]= data[2] -vec[2];
|
|
|
|
data+=3;
|
|
|
|
mvert++;
|
|
|
|
}
|
|
|
|
|
|
|
|
idata= dl->index;
|
|
|
|
for(b=dl->parts; b>0; b--) {
|
|
|
|
mface->v1= startve+idata[0];
|
|
|
|
mface->v2= startve+idata[1];
|
|
|
|
mface->v3= startve+idata[2];
|
|
|
|
mface->mat_nr= colnr;
|
|
|
|
|
|
|
|
if (mface->v1>me->totvert-1) mface->v1= me->totvert-1;
|
|
|
|
if (mface->v2>me->totvert-1) mface->v2= me->totvert-1;
|
|
|
|
if (mface->v3>me->totvert-1) mface->v3= me->totvert-1;
|
|
|
|
|
|
|
|
test_index_mface(mface, 3);
|
|
|
|
mface++;
|
|
|
|
idata+= 3;
|
|
|
|
}
|
|
|
|
startve += dl->nr;
|
|
|
|
}
|
|
|
|
else if(dl->type==DL_SEGM) {
|
|
|
|
data= (float *)(dl+1);
|
|
|
|
|
|
|
|
for(a=dl->parts*dl->nr; a>0; a--) {
|
|
|
|
mvert->co[0]= data[0] -vec[0];
|
|
|
|
mvert->co[1]= data[1] -vec[1];
|
|
|
|
mvert->co[2]= data[2] -vec[2];
|
|
|
|
data+=3;
|
|
|
|
mvert++;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(b=0; b<dl->parts; b++) {
|
|
|
|
for(a=0; a<dl->nr-1; a++) {
|
|
|
|
mface->v1= startve+a;
|
|
|
|
mface->v2= startve+a+1;
|
|
|
|
mface->mat_nr= colnr;
|
|
|
|
test_index_mface(mface, 2);
|
|
|
|
mface++;
|
|
|
|
}
|
|
|
|
startve += dl->nr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dl= dl->next;
|
|
|
|
}
|
|
|
|
|
2004-04-12 19:29:52 +00:00
|
|
|
mesh_add_normals_flags(me);
|
2002-10-12 11:37:38 +00:00
|
|
|
tex_space_mesh(me);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static void displist_to_objects(ListBase *lbase)
|
|
|
|
{
|
|
|
|
DispList *dl, *first, *prev, *next;
|
|
|
|
ListBase tempbase;
|
|
|
|
int maxaantal, curcol, totvert=0, vert;
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* irst this: is still active */
|
2002-10-12 11:37:38 +00:00
|
|
|
if(ivsurf) {
|
|
|
|
where_is_object(ivsurf);
|
|
|
|
docentre_new();
|
|
|
|
}
|
|
|
|
|
|
|
|
dl= lbase->first;
|
|
|
|
while(dl) {
|
|
|
|
next= dl->next;
|
|
|
|
|
|
|
|
/* PATCH 1: polyfill */
|
|
|
|
if(dl->type==DL_POLY && dl->nr>4) {
|
2003-04-26 11:56:44 +00:00
|
|
|
/* solution: put them together in separate listbase */
|
2002-10-12 11:37:38 +00:00
|
|
|
;
|
|
|
|
}
|
2003-04-26 11:56:44 +00:00
|
|
|
/* PATCH 2: poly's of 2 points */
|
2002-10-12 11:37:38 +00:00
|
|
|
if(dl->type==DL_POLY && dl->nr==2) dl->type= DL_SEGM;
|
|
|
|
|
|
|
|
dl= next;
|
|
|
|
}
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* count vertices */
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
dl= lbase->first;
|
|
|
|
while(dl) {
|
|
|
|
|
|
|
|
if(dl->type==DL_SURF) totvert+= dl->nr*dl->parts;
|
|
|
|
else if(dl->type==DL_POLY) {
|
|
|
|
if(dl->nr==3 || dl->nr==4) totvert+= dl->nr*dl->parts;
|
|
|
|
else if(dl->nr>4) totvert+= dl->nr*dl->parts;
|
|
|
|
}
|
|
|
|
else if(dl->type==DL_INDEX3) totvert+= dl->nr;
|
|
|
|
else if(dl->type==DL_SEGM) totvert+= dl->nr*dl->parts;
|
|
|
|
|
|
|
|
dl= dl->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(totvert==0) {
|
|
|
|
|
|
|
|
if(ivsurf==0) error("Found no data");
|
|
|
|
if(lbase->first) BLI_freelistN(lbase);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
maxaantal= 32000;
|
|
|
|
|
|
|
|
if(totvert>maxaantal) {
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* try to put colors together */
|
2002-10-12 11:37:38 +00:00
|
|
|
curcol= 0;
|
|
|
|
tempbase.first= tempbase.last= 0;
|
|
|
|
|
|
|
|
while(lbase->first) {
|
|
|
|
dl= lbase->first;
|
|
|
|
while(dl) {
|
|
|
|
next= dl->next;
|
|
|
|
if(dl->col==curcol) {
|
|
|
|
BLI_remlink(lbase, dl);
|
|
|
|
BLI_addtail(&tempbase, dl);
|
|
|
|
dl->col= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
dl= next;
|
|
|
|
}
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* in tempbase are all 'curcol' */
|
2002-10-12 11:37:38 +00:00
|
|
|
totvert= 0;
|
|
|
|
dl= first= tempbase.first;
|
|
|
|
while(dl) {
|
|
|
|
vert= 0;
|
|
|
|
|
|
|
|
if(dl->type==DL_SURF) vert= dl->nr*dl->parts;
|
|
|
|
else if(dl->type==DL_POLY) {
|
|
|
|
if(dl->nr==3 || dl->nr==4) vert= dl->nr*dl->parts;
|
|
|
|
else if(dl->nr>4) vert= dl->nr*dl->parts;
|
|
|
|
}
|
|
|
|
else if(dl->type==DL_INDEX3) totvert+= dl->nr;
|
|
|
|
else if(dl->type==DL_SEGM) vert= dl->nr*dl->parts;
|
|
|
|
|
|
|
|
totvert+= vert;
|
|
|
|
if(totvert > maxaantal || dl->next==0) {
|
|
|
|
if(dl->next==0) {
|
|
|
|
displist_to_mesh(first);
|
|
|
|
}
|
|
|
|
else if(dl->prev) {
|
|
|
|
prev= dl->prev;
|
|
|
|
prev->next= 0;
|
|
|
|
displist_to_mesh(first);
|
|
|
|
prev->next= dl;
|
|
|
|
first= dl;
|
|
|
|
totvert= 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dl= dl->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
freedisplist(&tempbase);
|
|
|
|
|
|
|
|
curcol++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else displist_to_mesh(lbase->first);
|
|
|
|
|
|
|
|
freedisplist(lbase);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
int BKE_read_exotic(char *name)
|
|
|
|
{
|
|
|
|
ListBase lbase={0, 0};
|
|
|
|
int file, len;
|
|
|
|
char str[32];
|
|
|
|
int *s0 = (int*) str;
|
|
|
|
int retval = 0;
|
|
|
|
|
|
|
|
// make sure we're not trying to read a directory....
|
|
|
|
|
|
|
|
len= strlen(name);
|
|
|
|
if (name[len-1] !='/' && name[len-1] != '\\') {
|
|
|
|
file = open(name, O_BINARY|O_RDONLY);
|
|
|
|
|
|
|
|
if (file <= 0) {
|
|
|
|
error("Can't open file: %s", name);
|
|
|
|
} else {
|
|
|
|
read(file, str, 31);
|
|
|
|
close(file);
|
|
|
|
|
|
|
|
if ((*s0 != FORM) && (strncmp(str, "BLEN", 4) != 0)) {
|
|
|
|
|
|
|
|
waitcursor(1);
|
|
|
|
|
|
|
|
if(*s0==GOUR) {
|
|
|
|
if(G.obedit) {
|
|
|
|
error("Unable to perform function in EditMode");
|
|
|
|
} else {
|
|
|
|
read_radiogour(name);
|
|
|
|
retval = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ELEM4(*s0, DDG1, DDG2, DDG3, DDG4) {
|
|
|
|
if(G.obedit) {
|
|
|
|
error("Unable to perform function in EditMode");
|
|
|
|
} else {
|
|
|
|
read_videoscape(name);
|
|
|
|
retval = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(strncmp(str, "#Inventor V1.0", 14)==0) {
|
|
|
|
if( strncmp(str+15, "ascii", 5)==0) {
|
|
|
|
read_inventor(name, &lbase);
|
|
|
|
displist_to_objects(&lbase);
|
|
|
|
retval = 1;
|
|
|
|
} else {
|
|
|
|
error("Can only read Inventor 1.0 ascii");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if((strncmp(str, "#VRML V1.0 asc", 14)==0)) {
|
|
|
|
read_inventor(name, &lbase);
|
|
|
|
displist_to_objects(&lbase);
|
|
|
|
retval = 1;
|
|
|
|
}
|
|
|
|
else if(is_dxf(name)) {
|
|
|
|
dxf_read(name);
|
|
|
|
retval = 1;
|
|
|
|
}
|
2004-03-30 03:10:34 +00:00
|
|
|
else if(is_stl(name)) {
|
|
|
|
if (is_stl_ascii(name))
|
|
|
|
read_stl_mesh_ascii(name);
|
|
|
|
else
|
|
|
|
read_stl_mesh_binary(name);
|
|
|
|
retval = 1;
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
// TODO: this should not be in the kernel...
|
|
|
|
else { // unknown format, call Python importloader
|
|
|
|
if (BPY_call_importloader(name)) {
|
|
|
|
retval = 1;
|
|
|
|
} else {
|
|
|
|
error("Unknown file type or error, check console");
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
waitcursor(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (retval == 1) {
|
|
|
|
strcpy(G.sce, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (retval);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ************************ WRITE ************************** */
|
|
|
|
|
|
|
|
|
|
|
|
char videosc_dir[160]= {0, 0};
|
|
|
|
|
2004-03-30 03:10:34 +00:00
|
|
|
#define WRITEVERT(verts, ind) { \
|
|
|
|
VECCOPY(vert, verts[(ind)].co); \
|
|
|
|
Mat4MulVecfl(ob->obmat, vert); \
|
|
|
|
if (G.order==B_ENDIAN) { \
|
|
|
|
SWITCH_INT(vert[0]); \
|
|
|
|
SWITCH_INT(vert[1]); \
|
|
|
|
SWITCH_INT(vert[2]); \
|
|
|
|
} \
|
|
|
|
fwrite(vert, sizeof(float), 3, fpSTL); \
|
|
|
|
}
|
|
|
|
|
|
|
|
static int write_mesh_stl(FILE *fpSTL, Object *ob, Mesh *me)
|
|
|
|
{
|
|
|
|
MVert *mvert;
|
|
|
|
MFace *mface;
|
|
|
|
int i, numfacets = 0;
|
|
|
|
float zero[3] = {0.0f, 0.0f, 0.0f};
|
|
|
|
float vert[3];
|
|
|
|
|
|
|
|
mvert = me->mvert;
|
|
|
|
mface = me->mface;
|
|
|
|
|
|
|
|
for (i=0; i<me->totface; i++) {
|
|
|
|
|
|
|
|
if (mface->v4 || mface->v3) {
|
|
|
|
fwrite(zero, sizeof(float), 3, fpSTL); /* <-- v. normal lazy */
|
|
|
|
WRITEVERT(mvert, mface->v1);
|
|
|
|
WRITEVERT(mvert, mface->v2);
|
|
|
|
WRITEVERT(mvert, mface->v3);
|
|
|
|
fprintf(fpSTL, " "); /* <-- spec puts 2 spaces after facet */
|
|
|
|
numfacets++;
|
|
|
|
|
|
|
|
if(mface->v4) { /* quad = 2 tri's */
|
|
|
|
fwrite(zero, sizeof(float), 3, fpSTL);
|
|
|
|
WRITEVERT(mvert, mface->v1);
|
|
|
|
WRITEVERT(mvert, mface->v3);
|
|
|
|
WRITEVERT(mvert, mface->v4);
|
|
|
|
fprintf(fpSTL, " ");
|
|
|
|
numfacets++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mface++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return numfacets;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int write_displistmesh_stl(FILE *fpSTL, Object *ob, DispListMesh *dlm)
|
|
|
|
{
|
|
|
|
|
|
|
|
MFace *mface;
|
|
|
|
int i, numfacets = 0;
|
|
|
|
float zero[3] = {0.0f, 0.0f, 0.0f};
|
|
|
|
float vert[3];
|
|
|
|
|
|
|
|
for (i=0; i<dlm->totface; i++) {
|
|
|
|
mface = &dlm->mface[i];
|
|
|
|
|
|
|
|
fwrite(zero, sizeof(float), 3, fpSTL);
|
|
|
|
WRITEVERT(dlm->mvert, mface->v1);
|
|
|
|
WRITEVERT(dlm->mvert, mface->v2);
|
|
|
|
WRITEVERT(dlm->mvert, mface->v3);
|
|
|
|
fprintf(fpSTL, " ");
|
|
|
|
numfacets++;
|
|
|
|
|
|
|
|
if(mface->v4) { /* quad = 2 tri's */
|
|
|
|
fwrite(zero, sizeof(float), 3, fpSTL);
|
|
|
|
WRITEVERT(dlm->mvert, mface->v1);
|
|
|
|
WRITEVERT(dlm->mvert, mface->v3);
|
|
|
|
WRITEVERT(dlm->mvert, mface->v4);
|
|
|
|
fprintf(fpSTL, " ");
|
|
|
|
numfacets++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return numfacets;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int write_object_stl(FILE *fpSTL, Object *ob, Mesh *me)
|
|
|
|
{
|
|
|
|
int numfacets = 0;
|
|
|
|
|
|
|
|
if(mesh_uses_displist(me)) {
|
|
|
|
ListBase *dlbase=0;
|
|
|
|
DispList *dl;
|
|
|
|
float *data;
|
|
|
|
dlbase = &me->disp;
|
|
|
|
|
|
|
|
if (dlbase==0) return 0;
|
|
|
|
|
|
|
|
dl= dlbase->first;
|
|
|
|
while(dl) {
|
|
|
|
data= dl->verts;
|
|
|
|
|
|
|
|
switch(dl->type) {
|
|
|
|
case DL_MESH:
|
|
|
|
numfacets
|
|
|
|
+= write_displistmesh_stl(fpSTL, ob, dl->mesh);
|
|
|
|
break;
|
|
|
|
#if 0
|
|
|
|
default:
|
|
|
|
numfacets
|
|
|
|
+= write_displist_stl(fpSTL, ob, dl);
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
dl= dl->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
numfacets += write_mesh_stl(fpSTL, ob, me);
|
|
|
|
}
|
|
|
|
return numfacets;
|
|
|
|
}
|
|
|
|
|
|
|
|
void write_stl(char *str)
|
|
|
|
{
|
|
|
|
Object *ob;
|
|
|
|
Mesh *me;
|
|
|
|
Base *base;
|
|
|
|
FILE *fpSTL;
|
|
|
|
int numfacets = 0;
|
|
|
|
|
|
|
|
if(BLI_testextensie(str,".blend")) str[ strlen(str)-6]= 0;
|
|
|
|
if(BLI_testextensie(str,".ble")) str[ strlen(str)-4]= 0;
|
|
|
|
if(BLI_testextensie(str,".stl")==0) strcat(str, ".stl");
|
|
|
|
|
New scripts:
- hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms);
- bevel_center by Loic Berthe, suggested for inclusion by jms;
- doc_browser, by Daniel Dunbar (Zr)
Thanks to them for the new contributions!
(I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?)
BPython related:
- Added scriptlink methods to object, lamp, camera and world.
- Object: added object.makeTrack and object.clearTrack (old track method).
- sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither.
- doc updates and fixes.
- made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data.
- Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...)
- Draw: added mouse wheel events.
- Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate".
The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
|
|
|
if (!during_script()) {
|
|
|
|
if (BLI_exists(str))
|
|
|
|
if(saveover(str)==0)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-03-30 03:10:34 +00:00
|
|
|
fpSTL= fopen(str, "wb");
|
|
|
|
|
|
|
|
if(fpSTL==NULL) {
|
New scripts:
- hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms);
- bevel_center by Loic Berthe, suggested for inclusion by jms;
- doc_browser, by Daniel Dunbar (Zr)
Thanks to them for the new contributions!
(I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?)
BPython related:
- Added scriptlink methods to object, lamp, camera and world.
- Object: added object.makeTrack and object.clearTrack (old track method).
- sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither.
- doc updates and fixes.
- made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data.
- Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...)
- Draw: added mouse wheel events.
- Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate".
The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
|
|
|
if (!during_script()) error("Can't write file");
|
2004-03-30 03:10:34 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
strcpy(videosc_dir, str);
|
|
|
|
|
|
|
|
waitcursor(1);
|
|
|
|
|
|
|
|
/* The header part of the STL */
|
|
|
|
/* First 80 characters are a title or whatever you want.
|
|
|
|
Lets make the first 32 of those spam and the rest the filename.
|
|
|
|
Those first 80 characters will be followed by 4 bytes
|
|
|
|
which will be overwritten later with an integer holding
|
|
|
|
how many facets are written (we set them to ' ' for now).
|
|
|
|
*/
|
|
|
|
fprintf(fpSTL, "Binary STL output from Blender: %-48.48s ", str);
|
|
|
|
|
|
|
|
/* Write all selected mesh objects */
|
|
|
|
base= G.scene->base.first;
|
|
|
|
while(base) {
|
|
|
|
if (base->flag & SELECT) {
|
|
|
|
ob = base->object;
|
|
|
|
if (ob->type == OB_MESH) {
|
|
|
|
me = ob->data;
|
|
|
|
if (me)
|
|
|
|
numfacets += write_object_stl(fpSTL, ob, me);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
base= base->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* time to write the number of facets in the 4 bytes
|
|
|
|
starting at byte 81
|
|
|
|
*/
|
|
|
|
fseek(fpSTL, 80, SEEK_SET);
|
|
|
|
|
|
|
|
if (G.order==B_ENDIAN) {
|
|
|
|
SWITCH_INT(numfacets);
|
|
|
|
}
|
|
|
|
fwrite(&numfacets, 4*sizeof(char), 1, fpSTL);
|
|
|
|
|
|
|
|
fclose(fpSTL);
|
|
|
|
|
|
|
|
waitcursor(0);
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
static void write_videoscape_mesh(Object *ob, char *str)
|
|
|
|
{
|
2004-03-28 08:46:35 +00:00
|
|
|
EditMesh *em = G.editMesh;
|
2002-10-12 11:37:38 +00:00
|
|
|
Mesh *me;
|
|
|
|
Material *ma;
|
|
|
|
MVert *mvert;
|
|
|
|
MFace *mface;
|
|
|
|
FILE *fp;
|
|
|
|
EditVert *eve;
|
2004-09-18 20:15:37 +00:00
|
|
|
EditFace *evl;
|
2002-10-12 11:37:38 +00:00
|
|
|
unsigned int kleur[32];
|
|
|
|
float co[3];
|
|
|
|
int a;
|
|
|
|
long tot;
|
|
|
|
char *cp;
|
|
|
|
|
|
|
|
if(ob && ob->type==OB_MESH);
|
|
|
|
else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
kleur[0]= 0x00C0C0C0;
|
|
|
|
if(G.order==L_ENDIAN) SWITCH_INT(kleur[0]);
|
|
|
|
|
|
|
|
cp= (char *)kleur;
|
|
|
|
for(a=0; a<ob->totcol; a++, cp+=4) {
|
|
|
|
|
|
|
|
ma= give_current_material(ob, a+1);
|
|
|
|
if(ma) {
|
|
|
|
cp[0]= (unsigned char) (255.0*ma->emit);
|
|
|
|
cp[1]= (unsigned char) (255.0*ma->b);
|
|
|
|
cp[2]= (unsigned char) (255.0*ma->g);
|
|
|
|
cp[3]= (unsigned char) (255.0*ma->r);
|
|
|
|
}
|
|
|
|
else kleur[a]= 0x00C0C0C0;
|
|
|
|
|
|
|
|
if(G.order==L_ENDIAN) SWITCH_INT(kleur[a]);
|
|
|
|
|
|
|
|
if(a>30) break;
|
|
|
|
}
|
|
|
|
|
|
|
|
fp= fopen(str, "wb");
|
|
|
|
if(fp==NULL) return;
|
|
|
|
|
|
|
|
fprintf(fp,"3DG1\n");
|
|
|
|
|
|
|
|
if(G.obedit) {
|
|
|
|
|
|
|
|
fprintf(fp, "%d\n", G.totvert);
|
|
|
|
|
|
|
|
tot= 0;
|
2004-03-28 08:46:35 +00:00
|
|
|
eve= em->verts.first;
|
2002-10-12 11:37:38 +00:00
|
|
|
while(eve) {
|
|
|
|
VECCOPY(co, eve->co);
|
|
|
|
Mat4MulVecfl(ob->obmat, co);
|
|
|
|
fprintf(fp, "%f %f %f\n", co[0], co[1], co[2] );
|
|
|
|
eve->vn= (struct EditVert *)tot;
|
|
|
|
tot++;
|
|
|
|
eve= eve->next;
|
|
|
|
}
|
2004-03-28 08:46:35 +00:00
|
|
|
evl= em->faces.first;
|
2002-10-12 11:37:38 +00:00
|
|
|
while(evl) {
|
|
|
|
|
|
|
|
if(evl->v4==0) {
|
|
|
|
fprintf(fp, "3 %p %p %p 0x%x\n", evl->v1->vn, evl->v2->vn, evl->v3->vn, kleur[evl->mat_nr]);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fprintf(fp, "4 %p %p %p %p 0x%x\n", evl->v1->vn, evl->v2->vn, evl->v3->vn, evl->v4->vn, kleur[evl->mat_nr]);
|
|
|
|
}
|
|
|
|
evl= evl->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
DispList *dl;
|
|
|
|
float *extverts=0;
|
|
|
|
|
|
|
|
dl= find_displist(&ob->disp, DL_VERTS);
|
|
|
|
if(dl) extverts= dl->verts;
|
|
|
|
|
|
|
|
me= ob->data;
|
|
|
|
|
|
|
|
fprintf(fp, "%d\n", me->totvert);
|
|
|
|
|
|
|
|
mvert= me->mvert;
|
|
|
|
mface= me->mface;
|
|
|
|
for(a=0; a<me->totvert; a++, mvert++) {
|
|
|
|
if(extverts) {
|
|
|
|
VECCOPY(co, extverts);
|
|
|
|
extverts+= 3;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
VECCOPY(co, mvert->co);
|
|
|
|
}
|
|
|
|
Mat4MulVecfl(ob->obmat, co);
|
|
|
|
fprintf(fp, "%f %f %f\n", co[0], co[1], co[2] );
|
|
|
|
}
|
|
|
|
for(a=0; a<me->totface; a++, mface++) {
|
|
|
|
if(mface->v3==0) {
|
|
|
|
fprintf(fp, "2 %d %d 0x%x\n", mface->v1, mface->v2, kleur[mface->mat_nr]);
|
|
|
|
}
|
|
|
|
else if(mface->v4==0) {
|
|
|
|
fprintf(fp, "3 %d %d %d 0x%x\n", mface->v1, mface->v2, mface->v3, kleur[mface->mat_nr]);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fprintf(fp, "4 %d %d %d %d 0x%x\n", mface->v1, mface->v2, mface->v3, mface->v4, kleur[mface->mat_nr]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose(fp);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void write_videoscape(char *str)
|
|
|
|
{
|
|
|
|
Base *base;
|
|
|
|
int file, val, lampdone=0;
|
Phew, a lot of work, and no new features...
Main target was to make the inner rendering loop using no globals anymore.
This is essential for proper usage while raytracing, it caused a lot of
hacks in the raycode as well, which even didn't work correctly for all
situations (textures especially).
Done this by creating a new local struct RenderInput, which replaces usage
of the global struct Render R. The latter now only is used to denote
image size, viewmatrix, and the like.
Making the inner render loops using no globals caused 1000s of vars to
be changed... but the result definitely is much nicer code, which enables
making 'real' shaders in a next stage.
It also enabled me to remove the hacks from ray.c
Then i went to the task of removing redundant code. Especially the calculus
of texture coords took place (identical) in three locations.
Most obvious is the change in the unified render part, which is much less
code now; it uses the same rendering routines as normal render now.
(Note; not for halos yet!)
I also removed 6 files called 'shadowbuffer' something. This was experimen-
tal stuff from NaN days. And again saved a lot of double used code.
Finally I went over the blenkernel and blender/src calls to render stuff.
Here the same local data is used now, resulting in less dependency.
I also moved render-texture to the render module, this was still in Kernel.
(new file: texture.c)
So! After this commit I will check on the autofiles, to try to fix that.
MSVC people have to do it themselves.
This commit will need quite some testing help, but I'm around!
2003-12-21 21:52:51 +00:00
|
|
|
unsigned short numlen;
|
2002-10-12 11:37:38 +00:00
|
|
|
char head[FILE_MAXFILE], tail[FILE_MAXFILE];
|
|
|
|
|
|
|
|
if(BLI_testextensie(str,".trace")) str[ strlen(str)-6]= 0;
|
|
|
|
if(BLI_testextensie(str,".blend")) str[ strlen(str)-6]= 0;
|
|
|
|
if(BLI_testextensie(str,".ble")) str[ strlen(str)-4]= 0;
|
|
|
|
if(BLI_testextensie(str,".obj")==0) strcat(str, ".obj");
|
|
|
|
|
|
|
|
file= open(str,O_BINARY|O_RDONLY);
|
|
|
|
close(file);
|
New scripts:
- hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms);
- bevel_center by Loic Berthe, suggested for inclusion by jms;
- doc_browser, by Daniel Dunbar (Zr)
Thanks to them for the new contributions!
(I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?)
BPython related:
- Added scriptlink methods to object, lamp, camera and world.
- Object: added object.makeTrack and object.clearTrack (old track method).
- sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither.
- doc updates and fixes.
- made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data.
- Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...)
- Draw: added mouse wheel events.
- Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate".
The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
|
|
|
if(file>-1) if(!during_script() && saveover(str)==0) return;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
strcpy(videosc_dir, str);
|
|
|
|
|
|
|
|
base= G.scene->base.first;
|
|
|
|
while(base) {
|
|
|
|
if((base->flag & SELECT) && (base->lay & G.scene->lay)) {
|
|
|
|
if(base->object->type==OB_MESH) {
|
|
|
|
write_videoscape_mesh(base->object, str);
|
|
|
|
val = BLI_stringdec(str, head, tail, &numlen);
|
|
|
|
BLI_stringenc(str, head, tail, numlen, val + 1);
|
|
|
|
}
|
|
|
|
else if(base->object->type==OB_CURVE || base->object->type==OB_SURF) {
|
|
|
|
/* write_videoscape_nurbs(base->object, str); */
|
|
|
|
/* val = stringdec(str, head, tail, &numlen); */
|
|
|
|
/* stringenc(str, head, tail, numlen, val + 1); */
|
|
|
|
}
|
|
|
|
else if(lampdone==0 && base->object->type==OB_LAMP) {
|
|
|
|
/* lampdone= 1; */
|
|
|
|
/* write_videoscape_lamps(str); */
|
|
|
|
/* val = stringdec(str, head, tail, &numlen); */
|
|
|
|
/* stringenc(str, head, tail, numlen, val + 1); */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
base= base->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-04-26 11:56:44 +00:00
|
|
|
/* remove when higher numbers exist */
|
2002-10-12 11:37:38 +00:00
|
|
|
while(remove(str)==0) {
|
|
|
|
|
|
|
|
val = BLI_stringdec(str, head, tail, &numlen);
|
|
|
|
BLI_stringenc(str, head, tail, numlen, val + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ******************************* WRITE VRML ***************************** */
|
|
|
|
|
|
|
|
static void replace_chars(char *str1, char *str2)
|
|
|
|
{
|
|
|
|
int a= strlen(str2);
|
|
|
|
|
|
|
|
str1[a]= 0;
|
|
|
|
while(a--) {
|
|
|
|
if(str2[a]=='.' || str2[a]==' ') str1[a]= '_';
|
|
|
|
else str1[a]= str2[a];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void write_material_vrml(FILE *fp, Material *ma)
|
|
|
|
{
|
|
|
|
char str[32];
|
|
|
|
|
|
|
|
replace_chars(str, ma->id.name+2);
|
|
|
|
|
|
|
|
fprintf(fp, "\tDEF %s\n", str);
|
|
|
|
fprintf(fp, "\tMaterial {\n");
|
|
|
|
|
|
|
|
fprintf(fp, "\t\tdiffuseColor %f %f %f\n", ma->r, ma->g, ma->b);
|
|
|
|
fprintf(fp, "\t\tspecularColor %f %f %f\n", ma->specr, ma->specg, ma->specb);
|
|
|
|
fprintf(fp, "\t\tshininess %f \n", ((float)ma->har)/100.0);
|
|
|
|
fprintf(fp, "\t\ttransparency %f \n", 1.0-ma->alpha);
|
|
|
|
|
|
|
|
fprintf(fp, "\t}\n");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int *mcol_to_vcol(Mesh *me)
|
|
|
|
{
|
|
|
|
MFace *mface;
|
|
|
|
unsigned int *mcol, *mcoln, *mcolmain;
|
|
|
|
int a;
|
|
|
|
|
|
|
|
if(me->totface==0 || me->mcol==0) return 0;
|
|
|
|
|
|
|
|
mcoln= mcolmain= MEM_mallocN(sizeof(int)*me->totvert, "mcoln");
|
|
|
|
mcol = (unsigned int *)me->mcol;
|
|
|
|
mface= me->mface;
|
|
|
|
|
|
|
|
for(a=me->totface; a>0; a--, mface++) {
|
|
|
|
mcoln[mface->v1]= mcol[0];
|
|
|
|
mcoln[mface->v2]= mcol[1];
|
|
|
|
if(mface->v3) mcoln[mface->v3]= mcol[2];
|
|
|
|
if(mface->v4) mcoln[mface->v4]= mcol[3];
|
|
|
|
|
|
|
|
mcol+= 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
return mcolmain;
|
|
|
|
}
|
|
|
|
|
|
|
|
void mcol_to_rgba(unsigned int col, float *r, float *g, float *b, float *a)
|
|
|
|
{
|
|
|
|
char *cp;
|
|
|
|
|
|
|
|
cp = (char *)&col;
|
|
|
|
|
|
|
|
*r= cp[3];
|
|
|
|
*r /= 255.0;
|
|
|
|
|
|
|
|
*g= cp[2];
|
|
|
|
*g /= 255.0;
|
|
|
|
|
|
|
|
*b= cp[1];
|
|
|
|
*b /= 255.0;
|
|
|
|
|
|
|
|
*a= cp[0];
|
|
|
|
*a /= 255.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void write_mesh_vrml(FILE *fp, Mesh *me)
|
|
|
|
{
|
|
|
|
Material *ma;
|
|
|
|
MVert *mvert;
|
|
|
|
MFace *mface;
|
|
|
|
TFace *tface;
|
|
|
|
Image *ima;
|
2003-06-30 18:09:08 +00:00
|
|
|
int a, b, totcol, texind;
|
2002-10-12 11:37:38 +00:00
|
|
|
char str[32];
|
|
|
|
|
|
|
|
replace_chars(str, me->id.name+2);
|
|
|
|
|
|
|
|
fprintf(fp, "\tDEF %s\n", str);
|
|
|
|
fprintf(fp, "\tSeparator {\n");
|
|
|
|
|
|
|
|
if(me->tface) {
|
|
|
|
ima= ((TFace *)me->tface)->tpage;
|
|
|
|
if(ima) {
|
|
|
|
fprintf(fp, "\t\tTexture2 {\n");
|
|
|
|
fprintf(fp, "\t\t\tfilename %s\n", ima->name);
|
|
|
|
fprintf(fp, "\t\t\twrapS REPEAT \n");
|
|
|
|
fprintf(fp, "\t\t\twrapT REPEAT \n");
|
|
|
|
fprintf(fp, "\t\t}\n");
|
|
|
|
}
|
|
|
|
tface_to_mcol(me);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(me->mcol) {
|
|
|
|
unsigned int *mcol, *mcolmain;
|
|
|
|
float r, g, b, cola;
|
|
|
|
|
|
|
|
fprintf(fp, "\t\tMaterial {\n");
|
|
|
|
fprintf(fp, "\t\t\tdiffuseColor [\n");
|
|
|
|
|
|
|
|
a= me->totvert;
|
|
|
|
mcol= mcolmain= mcol_to_vcol(me);
|
|
|
|
if(mcol) {
|
|
|
|
while(a--) {
|
|
|
|
mcol_to_rgba(*mcol, &r, &g, &b, &cola);
|
|
|
|
fprintf(fp, "\t\t\t\t %f %f %f,\n", r, g, b);
|
|
|
|
mcol++;
|
|
|
|
}
|
|
|
|
MEM_freeN(mcolmain);
|
|
|
|
}
|
|
|
|
fprintf(fp, "\t\t\t]\n");
|
|
|
|
fprintf(fp, "\t\t}\n");
|
|
|
|
|
|
|
|
fprintf(fp, "\t\tMaterialBinding { value PER_VERTEX_INDEXED }\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fprintf(fp, "\t\tCoordinate3 {\n");
|
|
|
|
fprintf(fp, "\t\t\tpoint [\n");
|
|
|
|
|
|
|
|
a= me->totvert;
|
|
|
|
mvert= me->mvert;
|
|
|
|
while(a--) {
|
|
|
|
fprintf(fp, "\t\t\t\t %f %f %f,\n", mvert->co[0], mvert->co[1], mvert->co[2]);
|
|
|
|
mvert++;
|
|
|
|
}
|
|
|
|
fprintf(fp, "\t\t\t]\n");
|
|
|
|
fprintf(fp, "\t\t}\n");
|
|
|
|
|
|
|
|
|
|
|
|
totcol= me->totcol;
|
|
|
|
if(totcol==0) totcol= 1;
|
2003-06-30 18:09:08 +00:00
|
|
|
texind= 0; // index for uv coords
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
for(b=0; b<totcol; b++) {
|
|
|
|
|
|
|
|
if(me->mcol==0) {
|
|
|
|
if(me->mat) {
|
|
|
|
ma= me->mat[b];
|
|
|
|
if(ma) {
|
|
|
|
replace_chars(str, ma->id.name+2);
|
|
|
|
|
|
|
|
fprintf(fp, "\t\tUSE %s\n\n", str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(me->tface) {
|
|
|
|
fprintf(fp, "\t\tTextureCoordinate2 {\n");
|
|
|
|
fprintf(fp, "\t\t\tpoint [\n");
|
|
|
|
|
|
|
|
a= me->totface;
|
|
|
|
mface= me->mface;
|
|
|
|
tface= me->tface;
|
|
|
|
while(a--) {
|
|
|
|
if(mface->mat_nr==b) {
|
|
|
|
fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[0][0], tface->uv[0][1]);
|
2003-07-03 12:31:19 +00:00
|
|
|
fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[1][0], tface->uv[1][1]);
|
2002-10-12 11:37:38 +00:00
|
|
|
if(mface->v3) fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[2][0], tface->uv[2][1]);
|
2003-07-03 12:31:19 +00:00
|
|
|
if(mface->v4) fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[3][0], tface->uv[3][1]);
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
mface++;
|
|
|
|
tface++;
|
|
|
|
}
|
|
|
|
fprintf(fp, "\t\t\t]\n");
|
|
|
|
fprintf(fp, "\t\t}\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(fp, "\t\tIndexedFaceSet {\n");
|
|
|
|
fprintf(fp, "\t\t\tcoordIndex [\n");
|
|
|
|
|
|
|
|
a= me->totface;
|
|
|
|
mface= me->mface;
|
|
|
|
while(a--) {
|
|
|
|
if(mface->mat_nr==b) {
|
|
|
|
if(mface->v4) fprintf(fp, "\t\t\t\t %d, %d, %d, %d, -1,\n", mface->v1, mface->v2, mface->v3, mface->v4);
|
|
|
|
else if(mface->v3) fprintf(fp, "\t\t\t\t %d, %d, %d, -1,\n", mface->v1, mface->v2, mface->v3);
|
|
|
|
}
|
|
|
|
mface++;
|
|
|
|
}
|
|
|
|
fprintf(fp, "\t\t\t]\n");
|
|
|
|
|
2003-06-30 18:09:08 +00:00
|
|
|
if(me->tface) {
|
|
|
|
fprintf(fp, "\t\t\ttextureCoordIndex [\n");
|
|
|
|
|
|
|
|
a= me->totface;
|
|
|
|
mface= me->mface;
|
|
|
|
while(a--) {
|
|
|
|
if(mface->mat_nr==b) {
|
|
|
|
if(mface->v4) {
|
|
|
|
fprintf(fp, "\t\t\t\t %d, %d, %d, %d, -1,\n", texind, texind+1, texind+2, texind+3);
|
|
|
|
texind+= 4;
|
|
|
|
}
|
|
|
|
else if(mface->v3) {
|
|
|
|
fprintf(fp, "\t\t\t\t %d, %d, %d, -1,\n", texind, texind+1, texind+2);
|
|
|
|
texind+= 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mface++;
|
|
|
|
}
|
|
|
|
fprintf(fp, "\t\t\t]\n");
|
|
|
|
}
|
|
|
|
fprintf(fp, "\t\t}\n");
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(fp, "\t}\n");
|
|
|
|
|
|
|
|
if(me->tface) {
|
|
|
|
MEM_freeN(me->mcol);
|
|
|
|
me->mcol= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static void write_camera_vrml(FILE *fp, Object *ob)
|
|
|
|
{
|
|
|
|
Camera *cam;
|
|
|
|
|
|
|
|
if(ob==0) return;
|
|
|
|
Mat4Invert(ob->imat, ob->obmat);
|
|
|
|
|
|
|
|
fprintf(fp, "\tMatrixTransform {\n");
|
|
|
|
|
|
|
|
fprintf(fp, "\tmatrix \n");
|
|
|
|
|
|
|
|
fprintf(fp, "\t\t%f %f %f %f\n", ob->imat[0][0], ob->imat[0][1], ob->imat[0][2], ob->imat[0][3]);
|
|
|
|
fprintf(fp, "\t\t%f %f %f %f\n", ob->imat[1][0], ob->imat[1][1], ob->imat[1][2], ob->imat[1][3]);
|
|
|
|
fprintf(fp, "\t\t%f %f %f %f\n", ob->imat[2][0], ob->imat[2][1], ob->imat[2][2], ob->imat[2][3]);
|
|
|
|
fprintf(fp, "\t\t%f %f %f %f\n", ob->imat[3][0], ob->imat[3][1], ob->imat[3][2], ob->imat[3][3]);
|
|
|
|
|
|
|
|
fprintf(fp, "\t}\n");
|
|
|
|
|
|
|
|
cam= ob->data;
|
|
|
|
|
|
|
|
fprintf(fp, "\tPerspectiveCamera {\n");
|
|
|
|
fprintf(fp, "\t\tfocalDistance %f\n", cam->lens/10.0);
|
|
|
|
|
|
|
|
fprintf(fp, "\t}\n");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static void write_object_vrml(FILE *fp, Object *ob)
|
|
|
|
{
|
|
|
|
ID *id;
|
|
|
|
char str[32];
|
|
|
|
|
|
|
|
fprintf(fp, "\tSeparator {\n");
|
|
|
|
fprintf(fp, "\t\tMatrixTransform {\n");
|
|
|
|
|
|
|
|
fprintf(fp, "\t\tmatrix \n");
|
|
|
|
|
|
|
|
fprintf(fp, "\t\t\t%f %f %f %f\n", ob->obmat[0][0], ob->obmat[0][1], ob->obmat[0][2], ob->obmat[0][3]);
|
|
|
|
fprintf(fp, "\t\t\t%f %f %f %f\n", ob->obmat[1][0], ob->obmat[1][1], ob->obmat[1][2], ob->obmat[1][3]);
|
|
|
|
fprintf(fp, "\t\t\t%f %f %f %f\n", ob->obmat[2][0], ob->obmat[2][1], ob->obmat[2][2], ob->obmat[2][3]);
|
|
|
|
fprintf(fp, "\t\t\t%f %f %f %f\n", ob->obmat[3][0], ob->obmat[3][1], ob->obmat[3][2], ob->obmat[3][3]);
|
|
|
|
|
|
|
|
fprintf(fp, "\t\t}\n");
|
|
|
|
|
|
|
|
id= ob->data;
|
|
|
|
|
|
|
|
replace_chars(str, id->name+2);
|
|
|
|
|
|
|
|
fprintf(fp, "\t\tUSE %s\n", str);
|
|
|
|
fprintf(fp, "\t}\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void write_vrml(char *str)
|
|
|
|
{
|
|
|
|
Mesh *me;
|
|
|
|
Material *ma;
|
|
|
|
Base *base;
|
|
|
|
FILE *fp;
|
|
|
|
|
|
|
|
if(BLI_testextensie(str,".blend")) str[ strlen(str)-6]= 0;
|
|
|
|
if(BLI_testextensie(str,".ble")) str[ strlen(str)-4]= 0;
|
|
|
|
if(BLI_testextensie(str,".wrl")==0) strcat(str, ".wrl");
|
|
|
|
|
New scripts:
- hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms);
- bevel_center by Loic Berthe, suggested for inclusion by jms;
- doc_browser, by Daniel Dunbar (Zr)
Thanks to them for the new contributions!
(I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?)
BPython related:
- Added scriptlink methods to object, lamp, camera and world.
- Object: added object.makeTrack and object.clearTrack (old track method).
- sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither.
- doc updates and fixes.
- made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data.
- Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...)
- Draw: added mouse wheel events.
- Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate".
The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
|
|
|
if(!during_script() && saveover(str)==0) return;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
fp= fopen(str, "w");
|
|
|
|
|
New scripts:
- hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms);
- bevel_center by Loic Berthe, suggested for inclusion by jms;
- doc_browser, by Daniel Dunbar (Zr)
Thanks to them for the new contributions!
(I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?)
BPython related:
- Added scriptlink methods to object, lamp, camera and world.
- Object: added object.makeTrack and object.clearTrack (old track method).
- sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither.
- doc updates and fixes.
- made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data.
- Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...)
- Draw: added mouse wheel events.
- Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate".
The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
|
|
|
if(fp==NULL && !during_script()) {
|
2002-10-12 11:37:38 +00:00
|
|
|
error("Can't write file");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
strcpy(videosc_dir, str);
|
|
|
|
|
|
|
|
waitcursor(1);
|
|
|
|
|
|
|
|
/* FIRST: write all the datablocks */
|
|
|
|
|
|
|
|
fprintf(fp, "#VRML V1.0 ascii\n\n# Blender V2.0\n\n# 'Switch' is used as a hack, to ensure it is not part of the drawing\n\n");
|
|
|
|
fprintf(fp, "Separator {\n");
|
|
|
|
fprintf(fp, "Switch {\n");
|
|
|
|
|
|
|
|
ma= G.main->mat.first;
|
|
|
|
while(ma) {
|
|
|
|
if(ma->id.us) {
|
|
|
|
write_material_vrml(fp, ma);
|
|
|
|
}
|
|
|
|
ma= ma->id.next;
|
|
|
|
}
|
|
|
|
|
|
|
|
me= G.main->mesh.first;
|
|
|
|
while(me) {
|
|
|
|
if(me->id.us) {
|
|
|
|
write_mesh_vrml(fp, me);
|
|
|
|
}
|
|
|
|
me= me->id.next;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* THEN:Hidden Objects */
|
|
|
|
fprintf(fp, "\n\t# Hidden Objects, in invisible layers\n\n");
|
|
|
|
base= G.scene->base.first;
|
|
|
|
while(base) {
|
|
|
|
if(base->object->type== OB_MESH) {
|
|
|
|
if( (base->lay & G.scene->lay)==0 ) {
|
|
|
|
write_object_vrml(fp, base->object);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
base= base->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(fp, "}\n");
|
|
|
|
fprintf(fp, "\n# Visible Objects\n\n");
|
|
|
|
fprintf(fp, "Separator {\n");
|
|
|
|
|
|
|
|
/* The camera */
|
|
|
|
|
|
|
|
write_camera_vrml(fp, G.scene->camera);
|
|
|
|
|
|
|
|
/* THEN:The Objects */
|
|
|
|
|
|
|
|
base= G.scene->base.first;
|
|
|
|
while(base) {
|
|
|
|
if(base->object->type== OB_MESH) {
|
|
|
|
if(base->lay & G.scene->lay) {
|
|
|
|
write_object_vrml(fp, base->object);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
base= base->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf(fp, "}\n");
|
|
|
|
fprintf(fp, "}\n");
|
|
|
|
|
|
|
|
fclose(fp);
|
|
|
|
|
|
|
|
waitcursor(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ******************************* WRITE DXF ***************************** */
|
|
|
|
|
|
|
|
#define write_group(id,data) fprintf(fp, "%d\n%s\n", id, data)
|
|
|
|
|
|
|
|
/* A completely wacky function to try and make good
|
|
|
|
indexed (AutoCAD index) values out of straight rgb
|
|
|
|
ones... crazy */
|
|
|
|
|
|
|
|
static int rgb_to_dxf_col (float rf, float gf, float bf)
|
|
|
|
{
|
|
|
|
int r= (int) (rf*255.0f);
|
|
|
|
int g= (int) (gf*255.0f);
|
|
|
|
int b= (int) (bf*255.0f);
|
|
|
|
float h,s,v;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
/* Grayscale value */
|
|
|
|
if (((int)r/10)==((int)g/10) && ((int)g/10)==((int)b/10)) ret= 250+((int)r/51);
|
|
|
|
/* A nice chroma value */
|
|
|
|
else {
|
|
|
|
rgb_to_hsv (rf,gf,bf,&h,&s,&v);
|
|
|
|
|
|
|
|
ret= (int) (10.0f + (h*239.0f));
|
|
|
|
CLAMP(ret,10,249);
|
|
|
|
|
|
|
|
/* If its whitish make the index odd */
|
|
|
|
if (s<.5 || v>.5) if(ret%2) ret++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* And its completely wacky complement */
|
|
|
|
|
|
|
|
static void dxf_col_to_rgb (int cid, float *rf, float *gf, float *bf)
|
|
|
|
{
|
|
|
|
float h, s, v;
|
|
|
|
|
|
|
|
/* Grayscale values */
|
|
|
|
if (cid>=250 && cid <= 255) {
|
|
|
|
*rf= *gf= *bf= (float) ((cid-250)*51)/255;
|
|
|
|
CLAMP(*rf, 0.0, 1.0);
|
|
|
|
CLAMP(*gf, 0.0, 1.0);
|
|
|
|
CLAMP(*bf, 0.0, 1.0);
|
|
|
|
|
|
|
|
/* Pure values */
|
|
|
|
} else if (cid<10) {
|
|
|
|
switch (cid) {
|
|
|
|
case 1:
|
|
|
|
*rf=1.0;
|
|
|
|
*gf=0.0;
|
|
|
|
*bf=0.0;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
*rf=1.0;
|
|
|
|
*gf=1.0;
|
|
|
|
*bf=0.0;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
*gf=1.0;
|
|
|
|
*rf=0.0;
|
|
|
|
*bf=0.0;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
*rf=0.0;
|
|
|
|
*gf=1.0;
|
|
|
|
*bf=1.0;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
*rf=0.0;
|
|
|
|
*gf=0.0;
|
|
|
|
*bf=1.0;
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
*rf=1.0;
|
|
|
|
*gf=0.0;
|
|
|
|
*bf=1.0;
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
default:
|
|
|
|
*rf= *gf= *bf= 1.0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Get chroma values */
|
|
|
|
|
|
|
|
h= (float) (cid-10)/239;
|
|
|
|
CLAMP(h, 0.0, 1.0);
|
|
|
|
|
|
|
|
/* If its odd make it a bit whitish */
|
|
|
|
if (cid%2) { s=.75; v= 0.25;
|
|
|
|
} else { s= 0.25; v= 0.75;}
|
|
|
|
|
|
|
|
hsv_to_rgb (h, s, v, rf, gf, bf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void write_mesh_dxf(FILE *fp, Mesh *me)
|
|
|
|
{
|
|
|
|
Material *ma;
|
|
|
|
MVert *mvert;
|
|
|
|
MFace *mface;
|
|
|
|
int a;
|
|
|
|
char str[32];
|
|
|
|
|
|
|
|
replace_chars(str, me->id.name+2);
|
|
|
|
|
|
|
|
write_group(0, "BLOCK");
|
|
|
|
|
|
|
|
write_group(2, str); /* The name */
|
|
|
|
|
|
|
|
write_group(8, "Meshes"); /* DXF Layer */
|
|
|
|
write_group(70, "64"); /* DXF block flags */
|
|
|
|
|
|
|
|
write_group(10, "0.0"); /* X of base */
|
|
|
|
write_group(20, "0.0"); /* Y of base */
|
|
|
|
write_group(30, "0.0"); /* Z of base */
|
|
|
|
|
|
|
|
write_group(3, str); /* The name (again) */
|
|
|
|
|
|
|
|
write_group(0, "POLYLINE"); /* Start the mesh */
|
|
|
|
write_group(66, "1"); /* Vertices follow flag */
|
|
|
|
write_group(8,"Meshes"); /* DXF Layer */
|
|
|
|
|
|
|
|
if (me->totcol) {
|
|
|
|
ma= me->mat[0];
|
|
|
|
if(ma) {
|
|
|
|
sprintf(str,"%d",rgb_to_dxf_col(ma->r,ma->g,ma->b));
|
|
|
|
write_group(62, str); /* Color index */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
write_group(70, "64"); /* Polymesh mesh flag */
|
|
|
|
|
|
|
|
fprintf(fp, "71\n%d\n", me->totvert); /* Total vertices */
|
|
|
|
fprintf(fp, "72\n%d\n", me->totface); /* Total faces */
|
|
|
|
|
|
|
|
/* Write the vertices */
|
|
|
|
a= me->totvert;
|
|
|
|
mvert= me->mvert;
|
|
|
|
while(a--) {
|
|
|
|
write_group(0, "VERTEX"); /* Start a new vertex */
|
|
|
|
write_group(8, "Meshes"); /* DXF Layer */
|
|
|
|
fprintf (fp, "10\n%f\n", mvert->co[0]); /* X cord */
|
|
|
|
fprintf (fp, "20\n%f\n", mvert->co[1]); /* Y cord */
|
|
|
|
fprintf (fp, "30\n%f\n", mvert->co[2]); /* Z cord */
|
|
|
|
write_group(70, "192"); /* Polymesh vertex flag */
|
|
|
|
|
|
|
|
mvert++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Write the face entries */
|
|
|
|
a= me->totface;
|
|
|
|
mface= me->mface;
|
|
|
|
while(a--) {
|
|
|
|
if (mface->v4 || mface->v3) {
|
|
|
|
write_group(0, "VERTEX"); /* Start a new face */
|
|
|
|
write_group(8, "Meshes");
|
|
|
|
|
|
|
|
/* Write a face color */
|
|
|
|
if (me->totcol) {
|
|
|
|
ma= me->mat[mface->mat_nr];
|
|
|
|
if(ma) {
|
|
|
|
sprintf(str,"%d",rgb_to_dxf_col(ma->r,ma->g,ma->b));
|
|
|
|
write_group(62, str); /* Color index */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else write_group(62, "254"); /* Color Index */
|
|
|
|
|
|
|
|
/* Not sure what this really corresponds too */
|
|
|
|
write_group(10, "0.0"); /* X of base */
|
|
|
|
write_group(20, "0.0"); /* Y of base */
|
|
|
|
write_group(30, "0.0"); /* Z of base */
|
|
|
|
|
|
|
|
write_group(70, "128"); /* Polymesh face flag */
|
|
|
|
|
|
|
|
if(mface->v4) {
|
|
|
|
fprintf (fp, "71\n%d\n", mface->v1+1);
|
|
|
|
fprintf (fp, "72\n%d\n", mface->v2+1);
|
|
|
|
fprintf (fp, "73\n%d\n", mface->v3+1);
|
|
|
|
fprintf (fp, "74\n%d\n", mface->v4+1);
|
|
|
|
} else if(mface->v3) {
|
|
|
|
fprintf (fp, "71\n%d\n", mface->v1+1);
|
|
|
|
fprintf (fp, "72\n%d\n", mface->v2+1);
|
|
|
|
fprintf (fp, "73\n%d\n", mface->v3+1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mface++;
|
|
|
|
}
|
|
|
|
|
|
|
|
write_group(0, "SEQEND");
|
|
|
|
|
|
|
|
write_group(0, "ENDBLK");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void write_object_dxf(FILE *fp, Object *ob, int layer)
|
|
|
|
{
|
|
|
|
ID *id;
|
|
|
|
char str[32];
|
|
|
|
|
|
|
|
id= ob->data;
|
|
|
|
|
|
|
|
write_group(0, "INSERT"); /* Start an insert group */
|
|
|
|
|
|
|
|
sprintf(str, "%d", layer);
|
|
|
|
write_group(8, str);
|
|
|
|
|
|
|
|
replace_chars(str, id->name+2);
|
|
|
|
write_group(2, str);
|
|
|
|
|
|
|
|
fprintf (fp, "10\n%f\n", ob->loc[0]); /* X of base */
|
|
|
|
fprintf (fp, "20\n%f\n", ob->loc[1]); /* Y of base */
|
|
|
|
fprintf (fp, "30\n%f\n", ob->loc[2]); /* Z of base */
|
|
|
|
|
|
|
|
fprintf (fp, "41\n%f\n", ob->size[0]); /* X scale */
|
|
|
|
fprintf (fp, "42\n%f\n", ob->size[1]); /* Y scale */
|
|
|
|
fprintf (fp, "43\n%f\n", ob->size[2]); /* Z scale */
|
|
|
|
|
|
|
|
fprintf (fp, "50\n%f\n", (float) ob->rot[2]*180/M_PI); /* Can only write the Z rot */
|
|
|
|
}
|
|
|
|
|
|
|
|
void write_dxf(char *str)
|
|
|
|
{
|
|
|
|
Mesh *me;
|
|
|
|
Base *base;
|
|
|
|
FILE *fp;
|
|
|
|
|
|
|
|
if(BLI_testextensie(str,".blend")) str[ strlen(str)-6]= 0;
|
|
|
|
if(BLI_testextensie(str,".ble")) str[ strlen(str)-4]= 0;
|
|
|
|
if(BLI_testextensie(str,".dxf")==0) strcat(str, ".dxf");
|
|
|
|
|
New scripts:
- hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms);
- bevel_center by Loic Berthe, suggested for inclusion by jms;
- doc_browser, by Daniel Dunbar (Zr)
Thanks to them for the new contributions!
(I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?)
BPython related:
- Added scriptlink methods to object, lamp, camera and world.
- Object: added object.makeTrack and object.clearTrack (old track method).
- sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither.
- doc updates and fixes.
- made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data.
- Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...)
- Draw: added mouse wheel events.
- Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate".
The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
|
|
|
if (!during_script()) {
|
|
|
|
if (BLI_exists(str))
|
|
|
|
if(saveover(str)==0)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
fp= fopen(str, "w");
|
|
|
|
|
New scripts:
- hotkeys, obdatacopier and renameobjectbyblock, all from Jean-Michel Soler (jms);
- bevel_center by Loic Berthe, suggested for inclusion by jms;
- doc_browser, by Daniel Dunbar (Zr)
Thanks to them for the new contributions!
(I included doc_browser at 'Misc' because only users interested in script writing would actually use it, but it could also be under 'Help'. Opinions?)
BPython related:
- Added scriptlink methods to object, lamp, camera and world.
- Object: added object.makeTrack and object.clearTrack (old track method).
- sys: made sys.exists(path) return 0 for not found; 1 for file, 2 for dir and -1 for neither.
- doc updates and fixes.
- made ONLOAD event work. G.f's SCENESCRIPT bit was being zeroed in set_app_data.
- Blender: updated functions Load and Save to support the builtin importers and exporters besides .blend (dxf, videoscape, vrml 1.0, stl, ...)
- Draw: added mouse wheel events.
- Scene: added scene.play to play back animations (like ALT+A and SHIFT+ALT+A). Makes a good counter, too, when the 'win' attribute is set to a space that doesn't "animate".
The scene.play() addition and the fix to ONLOAD scriptlinks is part of the work for a Blender demo mode. It already works, but I'll still add support for Radiosity calculations and fix a thing in main(): it executes onload scripts too early (BIF_Init), giving funny results in alt+a animations and renderings when firing up Blender. Loading after the program is up has no such problems. When I finish I'll post examples of demo mode scripts.
2004-07-03 05:17:04 +00:00
|
|
|
if(fp==NULL && !during_script()) {
|
2002-10-12 11:37:38 +00:00
|
|
|
error("Can't write file");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
strcpy(videosc_dir, str);
|
|
|
|
|
|
|
|
waitcursor(1);
|
|
|
|
|
|
|
|
/* The header part of the DXF */
|
|
|
|
|
|
|
|
write_group(0, "SECTION");
|
|
|
|
write_group(2, "HEADER");
|
|
|
|
write_group(0, "ENDSEC");
|
|
|
|
|
|
|
|
/* The blocks part of the DXF */
|
|
|
|
|
|
|
|
write_group(0, "SECTION");
|
|
|
|
write_group(2, "BLOCKS");
|
|
|
|
|
|
|
|
/* Write all the meshes */
|
|
|
|
me= G.main->mesh.first;
|
|
|
|
while(me) {
|
|
|
|
if(me->id.us) {
|
|
|
|
write_mesh_dxf(fp, me);
|
|
|
|
}
|
|
|
|
me= me->id.next;
|
|
|
|
}
|
|
|
|
|
|
|
|
write_group(0, "ENDSEC");
|
|
|
|
|
|
|
|
/* The entities part of the DXF */
|
|
|
|
|
|
|
|
write_group(0, "SECTION");
|
|
|
|
write_group(2, "ENTITIES");
|
|
|
|
|
|
|
|
/* Write all the mesh objects */
|
|
|
|
base= G.scene->base.first;
|
|
|
|
while(base) {
|
|
|
|
if(base->object->type== OB_MESH) {
|
|
|
|
write_object_dxf(fp, base->object, base->lay);
|
|
|
|
}
|
|
|
|
base= base->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
write_group(0, "ENDSEC");
|
|
|
|
|
|
|
|
/* Thats all */
|
|
|
|
|
|
|
|
write_group(0, "EOF");
|
|
|
|
fclose(fp);
|
|
|
|
|
|
|
|
waitcursor(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int dxf_line;
|
|
|
|
static FILE *dxf_fp;
|
|
|
|
|
|
|
|
/* exotic.c(2863) : note C6311: c:/Program Files/Microsoft Visual
|
|
|
|
* Studio/VC98/include\ctype.h(268) : see previous definition of
|
|
|
|
* 'iswspace' */
|
|
|
|
#define ton_iswspace(c) (c==' '||c=='\n'||c=='\t')
|
|
|
|
|
|
|
|
static void clean_wspace (char *str)
|
|
|
|
{
|
|
|
|
char *from, *to;
|
|
|
|
char t;
|
|
|
|
|
|
|
|
from= str;
|
|
|
|
to=str;
|
|
|
|
|
|
|
|
while (*from!=0) {
|
|
|
|
t= *from;
|
|
|
|
*to= t;
|
|
|
|
|
|
|
|
if(!ton_iswspace(*from)) to++;
|
|
|
|
from++;
|
|
|
|
}
|
|
|
|
*to=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int all_wspace(char *str)
|
|
|
|
{
|
|
|
|
while(*str != 0) {
|
|
|
|
if (!ton_iswspace(*str)) return 0;
|
|
|
|
str++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int all_digits(char *str)
|
|
|
|
{
|
|
|
|
while(*str != 0) {
|
|
|
|
if (!isdigit(*str)) return 0;
|
|
|
|
str++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dxf_get_layer_col(char *layer)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dxf_get_layer_num(char *layer)
|
|
|
|
{
|
|
|
|
int ret = 1;
|
|
|
|
|
|
|
|
if (all_digits(layer) && atoi(layer)<(1<<20)) ret= atoi(layer);
|
|
|
|
if (ret == 0) ret = 1;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void dos_clean(char *str)
|
|
|
|
{
|
|
|
|
while (*str) {
|
|
|
|
if (*str == 0x0d) {
|
|
|
|
*str='\n';
|
|
|
|
*(++str)= 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
str++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-11-26 19:59:11 +00:00
|
|
|
static void myfgets(char *str, int len, FILE *fp)
|
|
|
|
{
|
|
|
|
char c;
|
|
|
|
|
|
|
|
while(len>0 && (c=getc(dxf_fp)) ) {
|
|
|
|
*str= c;
|
|
|
|
str++;
|
|
|
|
len--;
|
2004-12-22 19:19:39 +00:00
|
|
|
/* three types of enters, \n \r and \r\n */
|
|
|
|
if(c == '\n') break;
|
|
|
|
if(c=='\r') {
|
|
|
|
c= getc(dxf_fp); // read the linefeed from stream
|
|
|
|
if(c != 10) ungetc(c, dxf_fp); // put back, if it's not one...
|
|
|
|
break;
|
|
|
|
}
|
2004-11-26 19:59:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
static int read_groupf(char *str)
|
|
|
|
{
|
|
|
|
short c;
|
|
|
|
int ret=-1;
|
|
|
|
char tmp[256];
|
|
|
|
|
|
|
|
strcpy(str, " ");
|
|
|
|
|
|
|
|
while ((c=getc(dxf_fp)) && ton_iswspace(c));
|
|
|
|
ungetc(c, dxf_fp);
|
|
|
|
if (c==EOF) return -1;
|
|
|
|
|
2004-11-26 19:59:11 +00:00
|
|
|
myfgets(tmp, 255, dxf_fp);
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
dos_clean(tmp);
|
|
|
|
|
|
|
|
if(sscanf(tmp, "%d\n", &ret)!=1) return -2;
|
|
|
|
|
2004-11-26 19:59:11 +00:00
|
|
|
myfgets(tmp, 255, dxf_fp);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
dos_clean(tmp);
|
|
|
|
|
|
|
|
if (!all_wspace(tmp)) {
|
|
|
|
if (sscanf(tmp, "%s\n", str)!=1) return -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
clean_wspace(str);
|
|
|
|
dxf_line+=2;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define id_test(id) if(id<0) {char errmsg[128];fclose(dxf_fp); if(id==-1) sprintf(errmsg, "Error inputting dxf, near line %d", dxf_line); else if(id==-2) sprintf(errmsg, "Error reading dxf, near line %d", dxf_line);error(errmsg); return;}
|
|
|
|
|
|
|
|
#define read_group(id,str) {id= read_groupf(str); id_test(id);}
|
|
|
|
|
|
|
|
#define group_is(idtst,str) (id==idtst&&strcmp(val,str)==0)
|
|
|
|
#define group_isnt(idtst,str) (id!=idtst||strcmp(val,str)!=0)
|
|
|
|
#define id_check(idtst,str) if(group_isnt(idtst,str)) { fclose(dxf_fp); error("Error parsing dxf, near line %d", dxf_line); return;}
|
|
|
|
|
|
|
|
static int id;
|
|
|
|
static char val[256];
|
|
|
|
|
|
|
|
static short error_exit=0;
|
|
|
|
static short hasbumped=0;
|
|
|
|
|
|
|
|
static int is_dxf(char *str)
|
|
|
|
{
|
|
|
|
dxf_line=0;
|
|
|
|
|
|
|
|
dxf_fp= fopen(str, "r");
|
|
|
|
if (dxf_fp==NULL) return 0;
|
|
|
|
|
|
|
|
id= read_groupf(val);
|
|
|
|
if ((id==0 && strcmp(val, "SECTION")==0)||id==999) return 1;
|
|
|
|
|
|
|
|
fclose(dxf_fp);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* NOTES ON THE READER */
|
|
|
|
/*
|
|
|
|
--
|
|
|
|
It turns out that most DXF writers like (LOVE) to
|
|
|
|
write meshes as a long string of 3DFACE entities.
|
|
|
|
This means the natural way to read a DXF file
|
|
|
|
(every entity corresponds to an object) is completely
|
|
|
|
unusable, reading in 10,000 faces each as an
|
|
|
|
object just doesn't cut it. Thus the 3DFACE
|
|
|
|
entry reader holds state, and only finalizes to
|
|
|
|
an object when a) the layer name changes, b) the
|
|
|
|
entry type changes, c) we are done reading.
|
|
|
|
|
|
|
|
PS... I decided to do the same thing with LINES,
|
|
|
|
apparently the same thing happens sometimes as
|
|
|
|
well.
|
|
|
|
|
|
|
|
PPS... I decided to do the same thing with everything.
|
|
|
|
Now it is all really nasty and should be rewritten.
|
2004-10-15 13:04:21 +00:00
|
|
|
--
|
|
|
|
|
|
|
|
Added circular and elliptical arcs and lwpolylines.
|
|
|
|
These are all self-contained and have the size known
|
|
|
|
in advance, and so I haven't used the held state. -- martin
|
2002-10-12 11:37:38 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
static void dxf_add_mat (Object *ob, Mesh *me, float color[3], char *layer)
|
|
|
|
{
|
|
|
|
Material *ma;
|
|
|
|
|
|
|
|
if (!me) return;
|
|
|
|
|
|
|
|
if(ob) ob->mat= MEM_callocN(sizeof(void *)*1, "ob->mat");
|
|
|
|
if(ob) ob->totcol= 1;
|
|
|
|
if(ob) ob->actcol= 1;
|
|
|
|
|
|
|
|
me->totcol= 1;
|
|
|
|
me->mat= MEM_callocN(sizeof(void *)*1, "me->mat");
|
|
|
|
|
|
|
|
if (color[0]<0) {
|
|
|
|
if (strlen(layer)) dxf_col_to_rgb(dxf_get_layer_col(layer), &color[0], &color[1], &color[2]);
|
|
|
|
color[0]= color[1]= color[2]= 0.8f;
|
|
|
|
}
|
|
|
|
|
|
|
|
ma= G.main->mat.first;
|
|
|
|
while(ma) {
|
|
|
|
if(ma->mtex[0]==0) {
|
|
|
|
if(color[0]==ma->r && color[1]==ma->g && color[2]==ma->b) {
|
|
|
|
me->mat[0]= ma;
|
|
|
|
ma->id.us++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ma= ma->id.next;
|
|
|
|
}
|
|
|
|
if(ma==0) {
|
|
|
|
ma= add_material("ext");
|
|
|
|
me->mat[0]= ma;
|
|
|
|
ma->r= color[0];
|
|
|
|
ma->g= color[1];
|
|
|
|
ma->b= color[2];
|
|
|
|
automatname(ma);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* General DXF vars */
|
|
|
|
static float cent[3]={0.0, 0.0, 0.0};
|
|
|
|
static char layname[32]="";
|
|
|
|
static char entname[32]="";
|
|
|
|
static float color[3]={-1.0, -1.0, -1.0};
|
|
|
|
static float *vcenter;
|
|
|
|
static float zerovec[3]= {0.0, 0.0, 0.0};
|
|
|
|
|
|
|
|
#define reset_vars cent[0]= cent[1]= cent[2]=0.0; strcpy(layname, ""); color[0]= color[1]= color[2]= -1.0
|
|
|
|
|
2004-10-15 13:04:21 +00:00
|
|
|
|
|
|
|
static void dxf_get_mesh(Mesh** m, Object** o, int noob)
|
|
|
|
{
|
|
|
|
Mesh *me = NULL;
|
|
|
|
Object *ob;
|
|
|
|
|
|
|
|
if (!noob) {
|
|
|
|
*o = add_object(OB_MESH);
|
|
|
|
ob = *o;
|
|
|
|
|
|
|
|
if (strlen(entname)) new_id(&G.main->object, (ID *)ob, entname);
|
|
|
|
else if (strlen(layname)) new_id(&G.main->object, (ID *)ob,
|
|
|
|
layname);
|
|
|
|
|
|
|
|
if (strlen(layname)) ob->lay= dxf_get_layer_num(layname);
|
|
|
|
else ob->lay= G.scene->lay;
|
|
|
|
|
|
|
|
*m = ob->data;
|
|
|
|
me= *m;
|
|
|
|
|
|
|
|
vcenter= ob->loc;
|
|
|
|
} else {
|
|
|
|
*o = NULL;
|
|
|
|
*m = add_mesh(); G.totmesh++;
|
|
|
|
|
|
|
|
me = *m;
|
|
|
|
ob = *o;
|
|
|
|
|
|
|
|
((ID *)me)->us=0;
|
|
|
|
|
|
|
|
if (strlen(entname)) new_id(&G.main->mesh, (ID *)me, entname);
|
|
|
|
else if (strlen(layname)) new_id(&G.main->mesh, (ID *)me, layname);
|
|
|
|
|
|
|
|
vcenter = zerovec;
|
|
|
|
}
|
|
|
|
me->totvert=0;
|
|
|
|
me->totface=0;
|
|
|
|
me->mvert=NULL;
|
|
|
|
me->mface=NULL;
|
|
|
|
}
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
static void dxf_read_point(int noob) {
|
|
|
|
/* Blender vars */
|
|
|
|
Object *ob;
|
|
|
|
Mesh *me;
|
|
|
|
MVert *mvert;
|
|
|
|
|
|
|
|
reset_vars;
|
|
|
|
|
|
|
|
read_group(id, val);
|
|
|
|
while(id!=0) {
|
|
|
|
if (id==8) {
|
|
|
|
BLI_strncpy(layname, val, sizeof(layname));
|
|
|
|
} else if (id==10) {
|
|
|
|
cent[0]= (float) atof(val);
|
|
|
|
} else if (id==20) {
|
|
|
|
cent[1]= (float) atof(val);
|
|
|
|
} else if (id==30) {
|
|
|
|
cent[2]= (float) atof(val);
|
|
|
|
} else if (id==60) {
|
|
|
|
/* short invisible= atoi(val); */
|
|
|
|
} else if (id==62) {
|
|
|
|
int colorid= atoi(val);
|
|
|
|
|
|
|
|
CLAMP(colorid, 1, 255);
|
|
|
|
dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]);
|
|
|
|
}
|
|
|
|
read_group(id, val);
|
|
|
|
}
|
|
|
|
|
2004-10-15 13:04:21 +00:00
|
|
|
dxf_get_mesh(&me, &ob, noob);
|
|
|
|
me->totvert= 1;
|
2002-10-12 11:37:38 +00:00
|
|
|
me->mvert= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
|
|
|
|
|
|
|
|
dxf_add_mat (ob, me, color, layname);
|
|
|
|
|
|
|
|
mvert= me->mvert;
|
|
|
|
mvert->co[0]= mvert->co[1]= mvert->co[2]= 0;
|
|
|
|
|
|
|
|
if (ob) VECCOPY(ob->loc, cent);
|
|
|
|
|
|
|
|
if (!noob) {
|
|
|
|
G.obedit= ob;
|
|
|
|
make_editMesh();
|
|
|
|
load_editMesh();
|
EditMesh refactory + undo recode
The changelog is very long... it's on the web too:
http://www.blender3d.org/cms/Mesh_editing_rewrite.425.0.html
EditMesh refactor notes (user)
**** New selection modes
When entering Edit Mode for a Mesh, you now have the choice for three selection modes. These are shown as icons in the 3D header (hotkey is being searched for!).
- Vertex Select
Select vertices as usual, fully compatible with how previous version work
- Edge Select
Vertices are not drawn anymore, and selections happen by default on the edges. It is a true edge select, meaning that you can select three out of four edges in a face, without automatic having the 4th edge selected.
- Face Select
Instead of vertices, now selection 'points' are drawn in the face centers. Selected faces also get a colored outline, like for edges. This also is true face select, for each face individual regardless selection status of its vertices or edges.
While holding SHIFT, and press a selection mode, you can also combine the above choices. Now selection becomes mixed, and will behave as expected.
For example; in Edge+Face select mode, selecting the 4 edges of a face will select the face too.
The selection modes and optional drawing modes (like transparant faces, normals, or solid drawing) all work together. All of Blender's mesh editing tools now react to the correct selection mode as well.
Most noticeable it's in:
**** Extrude
Extruding in Edge or Face Select mode allows much more precise control over what's extruded and what should be excluded. Try for example a checker pattern selection, and extrude it.
New is the fixed translation when faces are extruded. This always follows the (averaged) face normal(s) of the old face(s), enabling much easier working in 3D views . A single 'G' (Grab) or 'R' (Rotate) or 'S' (Scale) will change transform modus as usual.
**** Other things to note
- Hiding edges/faces will also behave different based on Select Mode.
- while editing, normals of faces are updated always now
- Border select (BKEY) has 2 different rules for edges; when one edge is fully inside of the border, it will only select edges that are fully inside. Otherwise it selects each edge intersecting with the border.
- in face mode, adding vertices, edges or a circle is invisible...
- "Add monkey" now works as a normal primitive (rotated and on 3d cursor)
- Mesh undo was fully recoded, hopefully solving issues now with Vertex Keys and Groups
- Going in and out of editmode was fully recoded. Especially on larger models you'll notice substantial speed gain.
**** Todo
Add 'FaceSelect mode' functionality in EditMode, including zbuffered selection, display and editing of UV texture.
EditMesh refactor notes (coder)
**** Usage of flags in general
The "->f" flags are reserved for the editmesh.c and editmesh_lib.c core functions. Actually only selection status is there now.
The "->f1" and "->f2" flags are free to use. They're available in vertex/edge/face structs. Since they're free, check carefully when calling other functions that use these flags... for example extrude() or subdivide() use them.
**** Selection flags
EditVert: eve->f & SELECT
EditEdge: eed->f & SELECT
EditFace: efa->f & SELECT
- Selection is only possible when not-hidden!
- Selection flags are always up-to-date, BUT:
if selection mode >= SELECT_EDGE vertex selection flags can be incorrect
if selection mode == SELECT_FACE vertex/edge selection flags can be incorrect
This because of shared vertices or edges.
- use for selecting vertices:
eve->f &= SELECT
- use for selecting edges always:
void EM_select_edge(eed, 1) // 1 = select, 0 = deselect
- use for selecting faces always:
void EM_select_face(efa, 1) // 1 = select, 0 = deselect
- To set the 'f' flags in all of the data:
void EM_set_flag_all(int flag);
void EM_clear_flag_all(int flag);
- the old faceselectedOR() and faceselectedAND() are still there, but only
to be used for evaluating its vertices
**** Code hints for handling selection
If the selectmode is 'face'; vertex or edge selections need to be flushed upward. Same is true for 'edge' selection mode. This means that you'll have to keep track of all selections while coding... selecting the four vertices in a face doesn't automatically select the face anymore.
However, by using the above calls, at least selections flush downward (to vertex level). You then can call:
void EM_selectmode_flush(void);
Which flushes selections back upward, based on the selectmode setting. This function does the following:
- if selectmode 'vertex': select edges/faces based on its selected vertices
- if selectmode 'edge': select faces based its selected edges
This works fine in nice controlled situations.
However, only changing the vertex selections then still doesn't select a face in face mode! If you really can't avoid only working with vertex selections, you can use this call:
void EM_select_flush(void);
Now selection is flushed upward regardless current selectmode. That can be destructive for special cases however, like checkerboard selected faces. So use this only when you know everything else was deselected (or deselect it). Example: adding primitives.
**** Hide flags
EditVert: eve->h
EditEdge: eed->h
EditFace: efa->h
- all hide flags are always up-to-date
- hidden vertices/edges/faces are always deselected. so when you operate on selection only, there's no need to check for hide flag.
**** Unified undo for editmode
New file: editmode_undo.h
A pretty nice function pointer handler style undo. Just code three functions, and your undo will fly! The c file has a good reference.
Also note that the old undo system has been replaced. It currently uses minimal dependencies on Meshes themselves (no abuse of going in/out editmode), and is restricted nicely to editmode functions.
**** Going in/out editmode
As speedup now all vertices/faces/edges are allocated in three big chunks. In vertices/faces/edges now tags are set to denote such data cannot be freed.
ALso the hashtable (lookup) for edges uses no mallocs at all anymore, but is part of the EditEdge itself.
2004-09-23 20:52:51 +00:00
|
|
|
free_editMesh(G.editMesh);
|
2002-10-12 11:37:38 +00:00
|
|
|
waitcursor(1); /* patch yah... */
|
|
|
|
|
|
|
|
G.obedit= 0;
|
|
|
|
}
|
|
|
|
tex_space_mesh(me);
|
|
|
|
|
|
|
|
hasbumped=1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Line state vars */
|
|
|
|
static Object *linehold=NULL;
|
|
|
|
static Mesh *linemhold=NULL;
|
|
|
|
|
|
|
|
static char oldllay[32];
|
|
|
|
static short lwasline=0; /* last was face 3d? */
|
|
|
|
|
|
|
|
static void dxf_close_line(void)
|
|
|
|
{
|
|
|
|
linemhold=NULL;
|
|
|
|
if (linehold==NULL) return;
|
|
|
|
|
|
|
|
G.obedit= linehold;
|
|
|
|
make_editMesh();
|
|
|
|
load_editMesh();
|
EditMesh refactory + undo recode
The changelog is very long... it's on the web too:
http://www.blender3d.org/cms/Mesh_editing_rewrite.425.0.html
EditMesh refactor notes (user)
**** New selection modes
When entering Edit Mode for a Mesh, you now have the choice for three selection modes. These are shown as icons in the 3D header (hotkey is being searched for!).
- Vertex Select
Select vertices as usual, fully compatible with how previous version work
- Edge Select
Vertices are not drawn anymore, and selections happen by default on the edges. It is a true edge select, meaning that you can select three out of four edges in a face, without automatic having the 4th edge selected.
- Face Select
Instead of vertices, now selection 'points' are drawn in the face centers. Selected faces also get a colored outline, like for edges. This also is true face select, for each face individual regardless selection status of its vertices or edges.
While holding SHIFT, and press a selection mode, you can also combine the above choices. Now selection becomes mixed, and will behave as expected.
For example; in Edge+Face select mode, selecting the 4 edges of a face will select the face too.
The selection modes and optional drawing modes (like transparant faces, normals, or solid drawing) all work together. All of Blender's mesh editing tools now react to the correct selection mode as well.
Most noticeable it's in:
**** Extrude
Extruding in Edge or Face Select mode allows much more precise control over what's extruded and what should be excluded. Try for example a checker pattern selection, and extrude it.
New is the fixed translation when faces are extruded. This always follows the (averaged) face normal(s) of the old face(s), enabling much easier working in 3D views . A single 'G' (Grab) or 'R' (Rotate) or 'S' (Scale) will change transform modus as usual.
**** Other things to note
- Hiding edges/faces will also behave different based on Select Mode.
- while editing, normals of faces are updated always now
- Border select (BKEY) has 2 different rules for edges; when one edge is fully inside of the border, it will only select edges that are fully inside. Otherwise it selects each edge intersecting with the border.
- in face mode, adding vertices, edges or a circle is invisible...
- "Add monkey" now works as a normal primitive (rotated and on 3d cursor)
- Mesh undo was fully recoded, hopefully solving issues now with Vertex Keys and Groups
- Going in and out of editmode was fully recoded. Especially on larger models you'll notice substantial speed gain.
**** Todo
Add 'FaceSelect mode' functionality in EditMode, including zbuffered selection, display and editing of UV texture.
EditMesh refactor notes (coder)
**** Usage of flags in general
The "->f" flags are reserved for the editmesh.c and editmesh_lib.c core functions. Actually only selection status is there now.
The "->f1" and "->f2" flags are free to use. They're available in vertex/edge/face structs. Since they're free, check carefully when calling other functions that use these flags... for example extrude() or subdivide() use them.
**** Selection flags
EditVert: eve->f & SELECT
EditEdge: eed->f & SELECT
EditFace: efa->f & SELECT
- Selection is only possible when not-hidden!
- Selection flags are always up-to-date, BUT:
if selection mode >= SELECT_EDGE vertex selection flags can be incorrect
if selection mode == SELECT_FACE vertex/edge selection flags can be incorrect
This because of shared vertices or edges.
- use for selecting vertices:
eve->f &= SELECT
- use for selecting edges always:
void EM_select_edge(eed, 1) // 1 = select, 0 = deselect
- use for selecting faces always:
void EM_select_face(efa, 1) // 1 = select, 0 = deselect
- To set the 'f' flags in all of the data:
void EM_set_flag_all(int flag);
void EM_clear_flag_all(int flag);
- the old faceselectedOR() and faceselectedAND() are still there, but only
to be used for evaluating its vertices
**** Code hints for handling selection
If the selectmode is 'face'; vertex or edge selections need to be flushed upward. Same is true for 'edge' selection mode. This means that you'll have to keep track of all selections while coding... selecting the four vertices in a face doesn't automatically select the face anymore.
However, by using the above calls, at least selections flush downward (to vertex level). You then can call:
void EM_selectmode_flush(void);
Which flushes selections back upward, based on the selectmode setting. This function does the following:
- if selectmode 'vertex': select edges/faces based on its selected vertices
- if selectmode 'edge': select faces based its selected edges
This works fine in nice controlled situations.
However, only changing the vertex selections then still doesn't select a face in face mode! If you really can't avoid only working with vertex selections, you can use this call:
void EM_select_flush(void);
Now selection is flushed upward regardless current selectmode. That can be destructive for special cases however, like checkerboard selected faces. So use this only when you know everything else was deselected (or deselect it). Example: adding primitives.
**** Hide flags
EditVert: eve->h
EditEdge: eed->h
EditFace: efa->h
- all hide flags are always up-to-date
- hidden vertices/edges/faces are always deselected. so when you operate on selection only, there's no need to check for hide flag.
**** Unified undo for editmode
New file: editmode_undo.h
A pretty nice function pointer handler style undo. Just code three functions, and your undo will fly! The c file has a good reference.
Also note that the old undo system has been replaced. It currently uses minimal dependencies on Meshes themselves (no abuse of going in/out editmode), and is restricted nicely to editmode functions.
**** Going in/out editmode
As speedup now all vertices/faces/edges are allocated in three big chunks. In vertices/faces/edges now tags are set to denote such data cannot be freed.
ALso the hashtable (lookup) for edges uses no mallocs at all anymore, but is part of the EditEdge itself.
2004-09-23 20:52:51 +00:00
|
|
|
free_editMesh(G.editMesh);
|
2002-10-12 11:37:38 +00:00
|
|
|
waitcursor(1); /* patch yah... */
|
|
|
|
|
|
|
|
G.obedit= 0;
|
|
|
|
tex_space_mesh(linehold->data);
|
|
|
|
|
|
|
|
linehold=NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void dxf_read_line(int noob) {
|
|
|
|
/* Entity specific vars */
|
|
|
|
float epoint[3]={0.0, 0.0, 0.0};
|
|
|
|
short vspace=0; /* Whether or not coords are relative */
|
|
|
|
|
|
|
|
/* Blender vars */
|
|
|
|
Object *ob;
|
|
|
|
Mesh *me;
|
|
|
|
MVert *mvert, *vtmp;
|
|
|
|
MFace *mface, *ftmp;
|
|
|
|
|
|
|
|
reset_vars;
|
|
|
|
|
|
|
|
read_group(id, val);
|
|
|
|
while(id!=0) {
|
|
|
|
if (id==8) {
|
|
|
|
BLI_strncpy(layname, val, sizeof(layname));
|
|
|
|
} else if (id==10) {
|
|
|
|
cent[0]= (float) atof(val);
|
|
|
|
} else if (id==20) {
|
|
|
|
cent[1]= (float) atof(val);
|
|
|
|
} else if (id==30) {
|
|
|
|
cent[2]= (float) atof(val);
|
|
|
|
} else if (id==11) {
|
|
|
|
epoint[0]= (float) atof(val);
|
|
|
|
} else if (id==21) {
|
|
|
|
epoint[1]= (float) atof(val);
|
|
|
|
} else if (id==31) {
|
|
|
|
epoint[2]= (float) atof(val);
|
|
|
|
} else if (id==60) {
|
|
|
|
/* short invisible= atoi(val); */
|
|
|
|
} else if (id==62) {
|
|
|
|
int colorid= atoi(val);
|
|
|
|
|
|
|
|
CLAMP(colorid, 1, 255);
|
|
|
|
dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]);
|
|
|
|
} else if (id==67) {
|
|
|
|
vspace= atoi(val);
|
|
|
|
}
|
|
|
|
read_group(id, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check to see if we need to make a new object */
|
|
|
|
|
2004-10-15 13:04:21 +00:00
|
|
|
if(!lwasline || strcmp(layname, oldllay)!=0)
|
|
|
|
dxf_close_line();
|
2004-03-14 21:21:09 +00:00
|
|
|
if(linemhold != NULL && linemhold->totvert>MESH_MAX_VERTS)
|
|
|
|
dxf_close_line();
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
if (linemhold==NULL) {
|
2004-10-15 13:04:21 +00:00
|
|
|
dxf_get_mesh(&me, &ob, noob);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
if(ob) VECCOPY(ob->loc, cent);
|
|
|
|
|
|
|
|
dxf_add_mat (ob, me, color, layname);
|
|
|
|
|
|
|
|
linehold= ob;
|
|
|
|
linemhold= me;
|
|
|
|
} else {
|
|
|
|
ob= linehold;
|
|
|
|
me= linemhold;
|
|
|
|
}
|
|
|
|
|
|
|
|
me->totvert+= 2;
|
|
|
|
me->totface++;
|
|
|
|
|
|
|
|
vtmp= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
|
|
|
|
ftmp= MEM_callocN(me->totface*sizeof(MFace), "mface");
|
|
|
|
|
|
|
|
if(me->mvert) {
|
|
|
|
memcpy(vtmp, me->mvert, (me->totvert-2)*sizeof(MVert));
|
|
|
|
MEM_freeN(me->mvert);
|
|
|
|
}
|
|
|
|
me->mvert= vtmp;
|
|
|
|
vtmp=NULL;
|
|
|
|
|
|
|
|
if(me->mface) {
|
|
|
|
memcpy(ftmp, me->mface, (me->totface-1)*sizeof(MFace));
|
|
|
|
MEM_freeN(me->mface);
|
|
|
|
}
|
|
|
|
me->mface= ftmp;
|
|
|
|
ftmp=NULL;
|
|
|
|
|
|
|
|
mvert= &me->mvert[(me->totvert-2)];
|
2004-10-15 13:04:21 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
VecSubf(mvert->co, cent, vcenter);
|
|
|
|
mvert++;
|
|
|
|
if (vspace) { VECCOPY(mvert->co, epoint);
|
|
|
|
} else VecSubf(mvert->co, epoint, vcenter);
|
|
|
|
|
|
|
|
mface= &(((MFace*)me->mface)[me->totface-1]);
|
|
|
|
mface->v1= me->totvert-2;
|
|
|
|
mface->v2= me->totvert-1;
|
|
|
|
|
|
|
|
mface->edcode= 1;
|
|
|
|
mface->mat_nr= 0;
|
|
|
|
|
|
|
|
hasbumped=1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 2D Polyline state vars */
|
|
|
|
static Object *p2dhold=NULL;
|
|
|
|
static Mesh *p2dmhold=NULL;
|
|
|
|
static char oldplay[32];
|
|
|
|
static short lwasp2d=0;
|
|
|
|
|
|
|
|
static void dxf_close_2dpoly(void)
|
|
|
|
{
|
|
|
|
p2dmhold= NULL;
|
|
|
|
if (p2dhold==NULL) return;
|
2004-11-26 19:59:11 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
G.obedit= p2dhold;
|
|
|
|
make_editMesh();
|
|
|
|
load_editMesh();
|
EditMesh refactory + undo recode
The changelog is very long... it's on the web too:
http://www.blender3d.org/cms/Mesh_editing_rewrite.425.0.html
EditMesh refactor notes (user)
**** New selection modes
When entering Edit Mode for a Mesh, you now have the choice for three selection modes. These are shown as icons in the 3D header (hotkey is being searched for!).
- Vertex Select
Select vertices as usual, fully compatible with how previous version work
- Edge Select
Vertices are not drawn anymore, and selections happen by default on the edges. It is a true edge select, meaning that you can select three out of four edges in a face, without automatic having the 4th edge selected.
- Face Select
Instead of vertices, now selection 'points' are drawn in the face centers. Selected faces also get a colored outline, like for edges. This also is true face select, for each face individual regardless selection status of its vertices or edges.
While holding SHIFT, and press a selection mode, you can also combine the above choices. Now selection becomes mixed, and will behave as expected.
For example; in Edge+Face select mode, selecting the 4 edges of a face will select the face too.
The selection modes and optional drawing modes (like transparant faces, normals, or solid drawing) all work together. All of Blender's mesh editing tools now react to the correct selection mode as well.
Most noticeable it's in:
**** Extrude
Extruding in Edge or Face Select mode allows much more precise control over what's extruded and what should be excluded. Try for example a checker pattern selection, and extrude it.
New is the fixed translation when faces are extruded. This always follows the (averaged) face normal(s) of the old face(s), enabling much easier working in 3D views . A single 'G' (Grab) or 'R' (Rotate) or 'S' (Scale) will change transform modus as usual.
**** Other things to note
- Hiding edges/faces will also behave different based on Select Mode.
- while editing, normals of faces are updated always now
- Border select (BKEY) has 2 different rules for edges; when one edge is fully inside of the border, it will only select edges that are fully inside. Otherwise it selects each edge intersecting with the border.
- in face mode, adding vertices, edges or a circle is invisible...
- "Add monkey" now works as a normal primitive (rotated and on 3d cursor)
- Mesh undo was fully recoded, hopefully solving issues now with Vertex Keys and Groups
- Going in and out of editmode was fully recoded. Especially on larger models you'll notice substantial speed gain.
**** Todo
Add 'FaceSelect mode' functionality in EditMode, including zbuffered selection, display and editing of UV texture.
EditMesh refactor notes (coder)
**** Usage of flags in general
The "->f" flags are reserved for the editmesh.c and editmesh_lib.c core functions. Actually only selection status is there now.
The "->f1" and "->f2" flags are free to use. They're available in vertex/edge/face structs. Since they're free, check carefully when calling other functions that use these flags... for example extrude() or subdivide() use them.
**** Selection flags
EditVert: eve->f & SELECT
EditEdge: eed->f & SELECT
EditFace: efa->f & SELECT
- Selection is only possible when not-hidden!
- Selection flags are always up-to-date, BUT:
if selection mode >= SELECT_EDGE vertex selection flags can be incorrect
if selection mode == SELECT_FACE vertex/edge selection flags can be incorrect
This because of shared vertices or edges.
- use for selecting vertices:
eve->f &= SELECT
- use for selecting edges always:
void EM_select_edge(eed, 1) // 1 = select, 0 = deselect
- use for selecting faces always:
void EM_select_face(efa, 1) // 1 = select, 0 = deselect
- To set the 'f' flags in all of the data:
void EM_set_flag_all(int flag);
void EM_clear_flag_all(int flag);
- the old faceselectedOR() and faceselectedAND() are still there, but only
to be used for evaluating its vertices
**** Code hints for handling selection
If the selectmode is 'face'; vertex or edge selections need to be flushed upward. Same is true for 'edge' selection mode. This means that you'll have to keep track of all selections while coding... selecting the four vertices in a face doesn't automatically select the face anymore.
However, by using the above calls, at least selections flush downward (to vertex level). You then can call:
void EM_selectmode_flush(void);
Which flushes selections back upward, based on the selectmode setting. This function does the following:
- if selectmode 'vertex': select edges/faces based on its selected vertices
- if selectmode 'edge': select faces based its selected edges
This works fine in nice controlled situations.
However, only changing the vertex selections then still doesn't select a face in face mode! If you really can't avoid only working with vertex selections, you can use this call:
void EM_select_flush(void);
Now selection is flushed upward regardless current selectmode. That can be destructive for special cases however, like checkerboard selected faces. So use this only when you know everything else was deselected (or deselect it). Example: adding primitives.
**** Hide flags
EditVert: eve->h
EditEdge: eed->h
EditFace: efa->h
- all hide flags are always up-to-date
- hidden vertices/edges/faces are always deselected. so when you operate on selection only, there's no need to check for hide flag.
**** Unified undo for editmode
New file: editmode_undo.h
A pretty nice function pointer handler style undo. Just code three functions, and your undo will fly! The c file has a good reference.
Also note that the old undo system has been replaced. It currently uses minimal dependencies on Meshes themselves (no abuse of going in/out editmode), and is restricted nicely to editmode functions.
**** Going in/out editmode
As speedup now all vertices/faces/edges are allocated in three big chunks. In vertices/faces/edges now tags are set to denote such data cannot be freed.
ALso the hashtable (lookup) for edges uses no mallocs at all anymore, but is part of the EditEdge itself.
2004-09-23 20:52:51 +00:00
|
|
|
free_editMesh(G.editMesh);
|
2002-10-12 11:37:38 +00:00
|
|
|
waitcursor(1); /* patch yah... */
|
|
|
|
|
|
|
|
G.obedit= 0;
|
|
|
|
tex_space_mesh(p2dhold->data);
|
|
|
|
|
|
|
|
p2dhold=NULL;
|
|
|
|
}
|
|
|
|
|
2004-10-15 13:04:21 +00:00
|
|
|
static void dxf_read_ellipse(int noob)
|
|
|
|
{
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The Parameter option of the ELLIPSE command uses the following equation to define an elliptical arc.
|
|
|
|
*
|
|
|
|
* p(u)=c+a*cos(u)+b*sin(u)
|
|
|
|
*
|
|
|
|
* The variables a, b, c are determined when you select the endpoints for the
|
|
|
|
* first axis and the distance for the second axis. a is the negative of 1/2
|
|
|
|
* of the major axis length, b is the negative of 1/2 the minor axis length,
|
|
|
|
* and c is the center point (2-D) of the ellipse.
|
|
|
|
*
|
|
|
|
* Because this is actually a vector equation and the variable c is actually
|
|
|
|
* a point with X and Y values, it really should be written as:
|
|
|
|
*
|
|
|
|
* p(u)=(Cx+a*cos(u))*i+(Cy+b*sin(u))*j
|
|
|
|
*
|
|
|
|
* where
|
|
|
|
*
|
|
|
|
* Cx is the X value of the point c
|
|
|
|
* Cy is the Y value of the point c
|
|
|
|
* a is -(1/2 of the major axis length)
|
|
|
|
* b is -(1/2 of the minor axis length)
|
|
|
|
* i and j represent unit vectors in the X and Y directions
|
|
|
|
*
|
|
|
|
* http://astronomy.swin.edu.au/~pbourke/geomformats/dxf2000/ellipse_command39s_parameter_option_dxf_06.htm
|
|
|
|
* (reproduced with permission)
|
|
|
|
*
|
|
|
|
* NOTE: The start and end angles ('parameters') are in radians, whereas those for the circular arc are
|
|
|
|
* in degrees. The 'sense' of u appears to be determined by the extrusion direction (see more detailed comment
|
|
|
|
* in the code)
|
|
|
|
*
|
|
|
|
* TODO: The code is specific to ellipses in the x-y plane right now.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Entity specific vars */
|
|
|
|
float epoint[3]={0.0, 0.0, 0.0};
|
|
|
|
float center[3]={0.0, 0.0, 0.0};
|
|
|
|
float extrusion[3]={0.0, 0.0, 1.0};
|
|
|
|
float axis_endpoint[3] = {0.0, 0.0, 0.0}; /* major axis endpoint */
|
|
|
|
short vspace=0; /* Whether or not coords are relative */
|
|
|
|
float a, b, x, y, z;
|
|
|
|
float phid = 0.0f, phi = 0.0f, theta = 0.0f;
|
|
|
|
float start_angle = 0.0f;
|
|
|
|
float end_angle = 2*M_PI;
|
|
|
|
float axis_ratio = 1.0f;
|
|
|
|
float temp;
|
|
|
|
int v, tot;
|
|
|
|
int isArc=0;
|
|
|
|
/* Blender vars */
|
|
|
|
Object *ob;
|
|
|
|
Mesh *me;
|
|
|
|
MVert *mvert;
|
|
|
|
MFace *mface;
|
|
|
|
|
|
|
|
reset_vars;
|
|
|
|
read_group(id, val);
|
|
|
|
while(id!=0) {
|
|
|
|
if (id==8) {
|
|
|
|
BLI_strncpy(layname, val, sizeof(layname));
|
|
|
|
} else if (id==10) {
|
|
|
|
center[0]= (float) atof(val);
|
|
|
|
} else if (id==20) {
|
|
|
|
center[1]= (float) atof(val);
|
|
|
|
} else if (id==30) {
|
|
|
|
center[2]= (float) atof(val);
|
|
|
|
} else if (id==11) {
|
|
|
|
axis_endpoint[0]= (float) atof(val);
|
|
|
|
} else if (id==21) {
|
|
|
|
axis_endpoint[1]= (float) atof(val);
|
|
|
|
} else if (id==31) {
|
|
|
|
axis_endpoint[2]= (float) atof(val);
|
|
|
|
} else if (id==40) {
|
|
|
|
axis_ratio = (float) atof(val);
|
|
|
|
} else if (id==41) {
|
|
|
|
printf("dxf: start = %f", atof(val) * 180/M_PI);
|
|
|
|
start_angle = -atof(val) + M_PI_2;
|
|
|
|
} else if (id==42) {
|
|
|
|
printf("dxf: end = %f", atof(val) * 180/M_PI);
|
|
|
|
end_angle = -atof(val) + M_PI_2;
|
|
|
|
} else if (id==62) {
|
|
|
|
int colorid= atoi(val);
|
|
|
|
CLAMP(colorid, 1, 255);
|
|
|
|
dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]);
|
|
|
|
} else if (id==67) {
|
|
|
|
vspace= atoi(val);
|
|
|
|
} else if (id==100) {
|
|
|
|
isArc = 1;
|
|
|
|
} else if (id==210) {
|
|
|
|
extrusion[0] = atof(val);
|
|
|
|
} else if (id==220) {
|
|
|
|
extrusion[1] = atof(val);
|
|
|
|
} else if (id==230) {
|
|
|
|
extrusion[2] = atof(val);
|
|
|
|
}
|
|
|
|
read_group(id, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!lwasline || strcmp(layname, oldllay)!=0) dxf_close_line();
|
|
|
|
if(linemhold != NULL && linemhold->totvert>MESH_MAX_VERTS)
|
|
|
|
dxf_close_line();
|
|
|
|
|
|
|
|
/* The 'extrusion direction' seems akin to a face normal,
|
|
|
|
* insofar as it determines the direction of increasing phi.
|
|
|
|
* This is again x-y plane specific; it should be fixed at
|
|
|
|
* some point. */
|
|
|
|
|
|
|
|
if (extrusion[2] < 0) {
|
|
|
|
temp = start_angle;
|
|
|
|
start_angle = M_PI - end_angle;
|
|
|
|
end_angle = M_PI - temp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(end_angle > start_angle)
|
|
|
|
end_angle -= 2 * M_PI;
|
|
|
|
|
|
|
|
phi = start_angle;
|
|
|
|
|
|
|
|
x = axis_endpoint[0];
|
|
|
|
y = axis_endpoint[1];
|
|
|
|
z = axis_endpoint[2];
|
|
|
|
a = sqrt(x*x + y*y + z*z);
|
|
|
|
b = a * axis_ratio;
|
|
|
|
|
|
|
|
theta = atan2(y, x);
|
|
|
|
|
|
|
|
x = a * sin(phi);
|
|
|
|
y = b * cos(phi);
|
|
|
|
|
|
|
|
#ifndef DEBUG_CENTRE
|
|
|
|
epoint[0] = center[0] + x*cos(theta) - y*sin(theta);
|
|
|
|
epoint[1] = center[1] + x*sin(theta) + y*cos(theta);
|
|
|
|
epoint[2] = center[2];
|
|
|
|
|
|
|
|
|
|
|
|
cent[0]= epoint[0];
|
|
|
|
cent[1]= epoint[1];
|
|
|
|
cent[2]= epoint[2];
|
|
|
|
#else
|
|
|
|
cent[0]= center[0];
|
|
|
|
cent[1]= center[1];
|
|
|
|
cent[2]= center[2];
|
|
|
|
#endif
|
|
|
|
|
|
|
|
dxf_get_mesh(&me, &ob, noob);
|
|
|
|
strcpy(oldllay, layname);
|
|
|
|
if(ob) VECCOPY(ob->loc, cent);
|
|
|
|
dxf_add_mat (ob, me, color, layname);
|
|
|
|
|
|
|
|
tot = 32; /* # of line segments to divide the arc into */
|
|
|
|
|
|
|
|
phid = (end_angle - start_angle)/tot;
|
|
|
|
|
|
|
|
me->totvert += tot+1;
|
|
|
|
me->totface += tot+1;
|
|
|
|
|
|
|
|
me->mvert = (MVert*) MEM_callocN(me->totvert*sizeof(MVert), "mverts");
|
|
|
|
me->mface = (MFace*) MEM_callocN(me->totface*sizeof(MVert), "mface");
|
|
|
|
|
|
|
|
printf("vertex and face buffers allocated\n");
|
|
|
|
|
|
|
|
for(v = 0; v <= tot; v++) {
|
|
|
|
|
|
|
|
x = a * sin(phi);
|
|
|
|
y = b * cos(phi);
|
|
|
|
epoint[0] = center[0] + x*cos(theta) - y*sin(theta);
|
|
|
|
epoint[1] = center[1] + x*sin(theta) + y*cos(theta);
|
|
|
|
epoint[2] = center[2];
|
|
|
|
|
|
|
|
mvert= &me->mvert[v];
|
|
|
|
|
|
|
|
if (vspace) {
|
|
|
|
VECCOPY(mvert->co, epoint);
|
|
|
|
} else {
|
|
|
|
VecSubf(mvert->co, epoint, vcenter);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (v > 0) {
|
|
|
|
mface= &(((MFace*)me->mface)[v-1]);
|
|
|
|
mface->v1 = v-1;
|
|
|
|
mface->v2 = v;
|
|
|
|
mface->edcode = 1;
|
|
|
|
mface->mat_nr = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
hasbumped = 1;
|
|
|
|
|
|
|
|
VECCOPY(cent, epoint);
|
|
|
|
phi+=phid;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void dxf_read_arc(int noob)
|
|
|
|
{
|
|
|
|
/* Entity specific vars */
|
|
|
|
float epoint[3]={0.0, 0.0, 0.0};
|
|
|
|
float center[3]={0.0, 0.0, 0.0};
|
|
|
|
float extrusion[3]={0.0, 0.0, 1.0};
|
|
|
|
short vspace=0; /* Whether or not coords are relative */
|
|
|
|
float dia = 0.0f;
|
|
|
|
float phid = 0.0f, phi = 0.0f;
|
|
|
|
float start_angle = 0.0f;
|
|
|
|
float end_angle = 2*M_PI;
|
|
|
|
float temp;
|
|
|
|
int v, tot = 32;
|
|
|
|
int isArc=0;
|
|
|
|
/* Blender vars */
|
|
|
|
Object *ob;
|
|
|
|
Mesh *me;
|
|
|
|
MVert *mvert;
|
|
|
|
MFace *mface;
|
|
|
|
|
|
|
|
reset_vars;
|
|
|
|
read_group(id, val);
|
|
|
|
while(id!=0) {
|
|
|
|
if (id==8) {
|
|
|
|
BLI_strncpy(layname, val, sizeof(layname));
|
|
|
|
} else if (id==10) {
|
|
|
|
center[0]= (float) atof(val);
|
|
|
|
} else if (id==20) {
|
|
|
|
center[1]= (float) atof(val);
|
|
|
|
} else if (id==30) {
|
|
|
|
center[2]= (float) atof(val);
|
|
|
|
} else if (id==40) {
|
|
|
|
dia = (float) atof(val);
|
|
|
|
} else if (id==62) {
|
|
|
|
int colorid= atoi(val);
|
|
|
|
|
|
|
|
CLAMP(colorid, 1, 255);
|
|
|
|
dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]);
|
|
|
|
} else if (id==67) {
|
|
|
|
vspace= atoi(val);
|
|
|
|
} else if (id==100) {
|
|
|
|
isArc = 1;
|
|
|
|
} else if (id==50) {
|
|
|
|
start_angle = (90 - atoi(val)) * M_PI/180.0;
|
|
|
|
} else if (id==51) {
|
|
|
|
end_angle = (90 - atoi(val)) * M_PI/180.0;
|
|
|
|
} else if (id==210) {
|
|
|
|
extrusion[0] = atof(val);
|
|
|
|
} else if (id==220) {
|
|
|
|
extrusion[1] = atof(val);
|
|
|
|
} else if (id==230) {
|
|
|
|
extrusion[2] = atof(val);
|
|
|
|
}
|
|
|
|
read_group(id, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!lwasline || strcmp(layname, oldllay)!=0) dxf_close_line();
|
|
|
|
if(linemhold != NULL && linemhold->totvert>MESH_MAX_VERTS)
|
|
|
|
dxf_close_line();
|
|
|
|
|
|
|
|
/* Same xy-plane-specific extrusion direction code as in read_ellipse
|
|
|
|
* (read_arc and read_ellipse should ideally be rewritten to share code)
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (extrusion[2] < 0) {
|
|
|
|
temp = start_angle;
|
|
|
|
start_angle = M_PI - end_angle;
|
|
|
|
end_angle = M_PI - temp;
|
|
|
|
}
|
|
|
|
|
|
|
|
phi = start_angle;
|
|
|
|
if(end_angle > start_angle)
|
|
|
|
end_angle -= 2 * M_PI;
|
|
|
|
|
|
|
|
cent[0]= center[0]+dia*sin(phi);
|
|
|
|
cent[1]= center[1]+dia*cos(phi);
|
|
|
|
cent[2]= center[2];
|
|
|
|
|
|
|
|
dxf_get_mesh(&me, &ob, noob);
|
|
|
|
strcpy(oldllay, layname);
|
|
|
|
if(ob) VECCOPY(ob->loc, cent);
|
|
|
|
dxf_add_mat (ob, me, color, layname);
|
|
|
|
|
|
|
|
tot = 32; /* # of line segments to divide the arc into */
|
|
|
|
phid = (end_angle - start_angle)/tot; /* fix so that arcs have the same 'resolution' as circles? */
|
|
|
|
|
|
|
|
me->totvert += tot+1;
|
|
|
|
me->totface += tot+1;
|
|
|
|
|
|
|
|
me->mvert = (MVert*) MEM_callocN(me->totvert*sizeof(MVert), "mverts");
|
|
|
|
me->mface = (MFace*) MEM_callocN(me->totface*sizeof(MVert), "mface");
|
|
|
|
|
|
|
|
for(v = 0; v <= tot; v++) {
|
|
|
|
|
|
|
|
epoint[0]= center[0]+dia*sin(phi);
|
|
|
|
epoint[1]= center[1]+dia*cos(phi);
|
|
|
|
epoint[2]= center[2];
|
|
|
|
|
|
|
|
mvert= &me->mvert[v];
|
|
|
|
|
|
|
|
if (vspace) {
|
|
|
|
VECCOPY(mvert->co, epoint);
|
|
|
|
} else {
|
|
|
|
VecSubf(mvert->co, epoint, vcenter);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (v > 0) {
|
|
|
|
mface= &(((MFace*)me->mface)[v-1]);
|
|
|
|
mface->v1 = v-1;
|
|
|
|
mface->v2 = v;
|
|
|
|
mface->edcode = 1;
|
|
|
|
mface->mat_nr = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
hasbumped=1;
|
|
|
|
|
|
|
|
VECCOPY(cent, epoint);
|
|
|
|
phi+=phid;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
static void dxf_read_polyline(int noob) {
|
|
|
|
/* Entity specific vars */
|
|
|
|
short vspace=0; /* Whether or not coords are relative */
|
|
|
|
int flag=0;
|
|
|
|
int vflags=0;
|
|
|
|
int vids[4];
|
|
|
|
int nverts;
|
|
|
|
|
|
|
|
/* Blender vars */
|
|
|
|
Object *ob;
|
|
|
|
Mesh *me;
|
|
|
|
float vert[3];
|
|
|
|
|
|
|
|
MVert *mvert, *vtmp;
|
|
|
|
MFace *mface, *ftmp;
|
|
|
|
|
|
|
|
reset_vars;
|
|
|
|
|
|
|
|
read_group(id, val);
|
|
|
|
while(id!=0) {
|
|
|
|
if (id==8) {
|
|
|
|
BLI_strncpy(layname, val, sizeof(layname));
|
|
|
|
} else if (id==10) {
|
|
|
|
cent[0]= (float) atof(val);
|
|
|
|
} else if (id==20) {
|
|
|
|
cent[1]= (float) atof(val);
|
|
|
|
} else if (id==30) {
|
|
|
|
cent[2]= (float) atof(val);
|
|
|
|
} else if (id==60) {
|
|
|
|
/* short invisible= atoi(val); */
|
|
|
|
} else if (id==62) {
|
|
|
|
int colorid= atoi(val);
|
|
|
|
|
|
|
|
CLAMP(colorid, 1, 255);
|
|
|
|
dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]);
|
|
|
|
} else if (id==67) {
|
|
|
|
vspace= atoi(val);
|
|
|
|
} else if (id==70) {
|
|
|
|
flag= atoi(val);
|
|
|
|
}
|
|
|
|
read_group(id, val);
|
|
|
|
}
|
|
|
|
|
2004-11-26 19:59:11 +00:00
|
|
|
if (flag & 9) { // 1= closed curve, 8= 3d curve
|
2002-10-12 11:37:38 +00:00
|
|
|
if(!lwasp2d || strcmp(layname, oldplay)!=0) dxf_close_2dpoly();
|
2004-03-14 21:21:09 +00:00
|
|
|
if(p2dmhold != NULL && p2dmhold->totvert>MESH_MAX_VERTS)
|
|
|
|
dxf_close_2dpoly();
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
if (p2dmhold==NULL) {
|
|
|
|
if (noob) {
|
|
|
|
ob= NULL;
|
|
|
|
me= add_mesh(); G.totmesh++;
|
|
|
|
((ID *)me)->us=0;
|
|
|
|
if (strlen(entname)) new_id(&G.main->mesh, (ID *)me, entname);
|
|
|
|
else if (strlen(layname)) new_id(&G.main->mesh, (ID *)me, layname);
|
|
|
|
|
|
|
|
vcenter= zerovec;
|
|
|
|
} else {
|
|
|
|
ob= add_object(OB_MESH);
|
|
|
|
if (strlen(entname)) new_id(&G.main->object, (ID *)ob, entname);
|
|
|
|
else if (strlen(layname)) new_id(&G.main->object, (ID *)ob, layname);
|
|
|
|
|
|
|
|
if (strlen(layname)) ob->lay= dxf_get_layer_num(layname);
|
|
|
|
else ob->lay= G.scene->lay;
|
|
|
|
|
|
|
|
me= ob->data;
|
|
|
|
|
|
|
|
vcenter= ob->loc;
|
|
|
|
}
|
|
|
|
me->totvert=0;
|
|
|
|
me->totface=0;
|
|
|
|
me->mvert=NULL;
|
|
|
|
me->mface=NULL;
|
|
|
|
|
|
|
|
strcpy(oldplay, layname);
|
|
|
|
|
|
|
|
if(ob) VECCOPY(ob->loc, cent);
|
|
|
|
|
|
|
|
dxf_add_mat (ob, me, color, layname);
|
|
|
|
|
|
|
|
p2dhold= ob;
|
|
|
|
p2dmhold= me;
|
2004-11-26 19:59:11 +00:00
|
|
|
}
|
|
|
|
else {
|
2002-10-12 11:37:38 +00:00
|
|
|
ob= p2dhold;
|
|
|
|
me= p2dmhold;
|
|
|
|
}
|
|
|
|
|
|
|
|
nverts=0;
|
|
|
|
while (group_is(0, "VERTEX")) {
|
|
|
|
read_group(id, val);
|
|
|
|
while(id!=0) {
|
|
|
|
if (id==10) {
|
|
|
|
vert[0]= (float) atof(val);
|
|
|
|
} else if (id==20) {
|
|
|
|
vert[1]= (float) atof(val);
|
|
|
|
} else if (id==30) {
|
|
|
|
vert[2]= (float) atof(val);
|
|
|
|
}
|
|
|
|
read_group(id, val);
|
|
|
|
}
|
|
|
|
nverts++;
|
|
|
|
me->totvert++;
|
|
|
|
|
|
|
|
vtmp= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
|
|
|
|
|
|
|
|
if (me->mvert) {
|
|
|
|
memcpy (vtmp, me->mvert, (me->totvert-1)*sizeof(MVert));
|
|
|
|
MEM_freeN(me->mvert);
|
|
|
|
}
|
|
|
|
me->mvert= vtmp;
|
|
|
|
vtmp= NULL;
|
|
|
|
|
|
|
|
mvert= &me->mvert[me->totvert-1];
|
|
|
|
|
|
|
|
if (vspace) { VECCOPY(mvert->co, vert);
|
|
|
|
} else VecSubf(mvert->co, vert, vcenter);
|
|
|
|
}
|
2004-11-26 19:59:11 +00:00
|
|
|
|
|
|
|
/* make edges */
|
|
|
|
if(nverts>1) {
|
|
|
|
int a, oldtotface;
|
|
|
|
|
|
|
|
oldtotface= me->totface;
|
|
|
|
me->totface+= nverts-1;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2004-11-26 19:59:11 +00:00
|
|
|
ftmp= MEM_callocN(me->totface*sizeof(MFace), "mface");
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2004-11-26 19:59:11 +00:00
|
|
|
if(me->mface) {
|
|
|
|
memcpy(ftmp, me->mface, oldtotface*sizeof(MFace));
|
|
|
|
MEM_freeN(me->mface);
|
|
|
|
}
|
|
|
|
me->mface= ftmp;
|
|
|
|
ftmp=NULL;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2004-11-26 19:59:11 +00:00
|
|
|
mface= me->mface;
|
|
|
|
mface+= oldtotface;
|
|
|
|
|
|
|
|
for(a=1; a<nverts; a++, mface++) {
|
|
|
|
mface->v1= (me->totvert-nverts)+a-1;
|
|
|
|
mface->v2= (me->totvert-nverts)+a;
|
|
|
|
|
|
|
|
mface->edcode= 3;
|
|
|
|
mface->mat_nr= 0;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
2004-11-26 19:59:11 +00:00
|
|
|
test_index_mface(mface, 2);
|
|
|
|
}
|
|
|
|
}
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
lwasp2d=1;
|
2004-11-26 19:59:11 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
else if (flag&64) {
|
2002-10-12 11:37:38 +00:00
|
|
|
if (noob) {
|
|
|
|
ob= NULL;
|
|
|
|
me= add_mesh(); G.totmesh++;
|
|
|
|
((ID *)me)->us=0;
|
|
|
|
|
|
|
|
if (strlen(entname)) new_id(&G.main->mesh, (ID *)me, entname);
|
|
|
|
else if (strlen(layname)) new_id(&G.main->mesh, (ID *)me, layname);
|
|
|
|
|
|
|
|
vcenter= zerovec;
|
|
|
|
} else {
|
|
|
|
ob= add_object(OB_MESH);
|
|
|
|
if (strlen(entname)) new_id(&G.main->object, (ID *)ob, entname);
|
|
|
|
else if (strlen(layname)) new_id(&G.main->object, (ID *)ob, layname);
|
|
|
|
|
|
|
|
if (strlen(layname)) ob->lay= dxf_get_layer_num(layname);
|
|
|
|
else ob->lay= G.scene->lay;
|
|
|
|
|
|
|
|
me= ob->data;
|
|
|
|
|
|
|
|
vcenter= ob->loc;
|
|
|
|
}
|
|
|
|
me->totvert=0;
|
|
|
|
me->totface=0;
|
|
|
|
me->mvert=NULL;
|
|
|
|
me->mface=NULL;
|
|
|
|
|
|
|
|
if(ob) VECCOPY(ob->loc, cent);
|
|
|
|
|
|
|
|
dxf_add_mat (ob, me, color, layname);
|
|
|
|
|
|
|
|
while (group_is(0, "VERTEX")) {
|
|
|
|
vflags= 0;
|
|
|
|
vids[0]= vids[1]= vids[2]= vids[3]= 0;
|
|
|
|
|
|
|
|
vflags=0;
|
|
|
|
read_group(id, val);
|
|
|
|
while(id!=0) {
|
|
|
|
if(id==8) {
|
|
|
|
; /* Layer def, skip */
|
|
|
|
} else if (id==10) {
|
|
|
|
vert[0]= (float) atof(val);
|
|
|
|
} else if (id==20) {
|
|
|
|
vert[1]= (float) atof(val);
|
|
|
|
} else if (id==30) {
|
|
|
|
vert[2]= (float) atof(val);
|
|
|
|
} else if (id==70) {
|
|
|
|
vflags= atoi(val);
|
|
|
|
} else if (id==71) {
|
|
|
|
vids[0]= abs(atoi(val));
|
|
|
|
} else if (id==72) {
|
|
|
|
vids[1]= abs(atoi(val));
|
|
|
|
} else if (id==73) {
|
|
|
|
vids[2]= abs(atoi(val));
|
|
|
|
} else if (id==74) {
|
|
|
|
vids[3]= abs(atoi(val));
|
|
|
|
}
|
|
|
|
read_group(id, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vflags & 128 && vflags & 64) {
|
|
|
|
me->totvert++;
|
|
|
|
|
|
|
|
/* If we are nearing the limit scan to the next entry */
|
2004-03-14 21:21:09 +00:00
|
|
|
if(me->totvert > MESH_MAX_VERTS)
|
2003-12-16 01:27:37 +00:00
|
|
|
while(group_isnt(0, "SEQEND")) read_group(id, val);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
vtmp= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
|
|
|
|
|
|
|
|
if(me->mvert) {
|
|
|
|
memcpy(vtmp, me->mvert, (me->totvert-1)*sizeof(MVert));
|
|
|
|
MEM_freeN(me->mvert);
|
|
|
|
}
|
|
|
|
me->mvert= vtmp;
|
|
|
|
vtmp=NULL;
|
|
|
|
|
|
|
|
mvert= &me->mvert[(me->totvert-1)];
|
|
|
|
|
|
|
|
if (vspace) { VECCOPY(mvert->co, vert);
|
|
|
|
} else VecSubf(mvert->co, vert, vcenter);
|
|
|
|
|
|
|
|
} else if (vflags & 128) {
|
|
|
|
if(vids[2]==0) {
|
|
|
|
error("(PL) Error parsing dxf, not enough vertices near line %d", dxf_line);
|
|
|
|
|
|
|
|
error_exit=1;
|
|
|
|
fclose(dxf_fp);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
me->totface++;
|
|
|
|
|
|
|
|
ftmp= MEM_callocN(me->totface*sizeof(MFace), "mfaces");
|
|
|
|
|
|
|
|
if(me->mface) {
|
|
|
|
memcpy(ftmp, me->mface, (me->totface-1)*sizeof(MFace));
|
|
|
|
MEM_freeN(me->mface);
|
|
|
|
}
|
|
|
|
me->mface= ftmp;
|
|
|
|
ftmp=NULL;
|
|
|
|
|
|
|
|
mface= &(((MFace*)me->mface)[me->totface-1]);
|
|
|
|
mface->v1= vids[0]-1;
|
|
|
|
mface->v2= vids[1]-1;
|
|
|
|
mface->v3= vids[2]-1;
|
|
|
|
|
2004-12-22 19:19:39 +00:00
|
|
|
if(vids[3] && vids[3]!=vids[0]) {
|
2002-10-12 11:37:38 +00:00
|
|
|
mface->v4= vids[3]-1;
|
2004-12-22 19:19:39 +00:00
|
|
|
test_index_mface(mface, 4);
|
|
|
|
}
|
|
|
|
else test_index_mface(mface, 3);
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
mface->edcode= 3;
|
|
|
|
mface->mat_nr= 0;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
error("Error parsing dxf, unknown polyline information near %d", dxf_line);
|
|
|
|
|
|
|
|
error_exit=1;
|
|
|
|
fclose(dxf_fp);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!noob) {
|
|
|
|
G.obedit= ob;
|
|
|
|
make_editMesh();
|
|
|
|
load_editMesh();
|
EditMesh refactory + undo recode
The changelog is very long... it's on the web too:
http://www.blender3d.org/cms/Mesh_editing_rewrite.425.0.html
EditMesh refactor notes (user)
**** New selection modes
When entering Edit Mode for a Mesh, you now have the choice for three selection modes. These are shown as icons in the 3D header (hotkey is being searched for!).
- Vertex Select
Select vertices as usual, fully compatible with how previous version work
- Edge Select
Vertices are not drawn anymore, and selections happen by default on the edges. It is a true edge select, meaning that you can select three out of four edges in a face, without automatic having the 4th edge selected.
- Face Select
Instead of vertices, now selection 'points' are drawn in the face centers. Selected faces also get a colored outline, like for edges. This also is true face select, for each face individual regardless selection status of its vertices or edges.
While holding SHIFT, and press a selection mode, you can also combine the above choices. Now selection becomes mixed, and will behave as expected.
For example; in Edge+Face select mode, selecting the 4 edges of a face will select the face too.
The selection modes and optional drawing modes (like transparant faces, normals, or solid drawing) all work together. All of Blender's mesh editing tools now react to the correct selection mode as well.
Most noticeable it's in:
**** Extrude
Extruding in Edge or Face Select mode allows much more precise control over what's extruded and what should be excluded. Try for example a checker pattern selection, and extrude it.
New is the fixed translation when faces are extruded. This always follows the (averaged) face normal(s) of the old face(s), enabling much easier working in 3D views . A single 'G' (Grab) or 'R' (Rotate) or 'S' (Scale) will change transform modus as usual.
**** Other things to note
- Hiding edges/faces will also behave different based on Select Mode.
- while editing, normals of faces are updated always now
- Border select (BKEY) has 2 different rules for edges; when one edge is fully inside of the border, it will only select edges that are fully inside. Otherwise it selects each edge intersecting with the border.
- in face mode, adding vertices, edges or a circle is invisible...
- "Add monkey" now works as a normal primitive (rotated and on 3d cursor)
- Mesh undo was fully recoded, hopefully solving issues now with Vertex Keys and Groups
- Going in and out of editmode was fully recoded. Especially on larger models you'll notice substantial speed gain.
**** Todo
Add 'FaceSelect mode' functionality in EditMode, including zbuffered selection, display and editing of UV texture.
EditMesh refactor notes (coder)
**** Usage of flags in general
The "->f" flags are reserved for the editmesh.c and editmesh_lib.c core functions. Actually only selection status is there now.
The "->f1" and "->f2" flags are free to use. They're available in vertex/edge/face structs. Since they're free, check carefully when calling other functions that use these flags... for example extrude() or subdivide() use them.
**** Selection flags
EditVert: eve->f & SELECT
EditEdge: eed->f & SELECT
EditFace: efa->f & SELECT
- Selection is only possible when not-hidden!
- Selection flags are always up-to-date, BUT:
if selection mode >= SELECT_EDGE vertex selection flags can be incorrect
if selection mode == SELECT_FACE vertex/edge selection flags can be incorrect
This because of shared vertices or edges.
- use for selecting vertices:
eve->f &= SELECT
- use for selecting edges always:
void EM_select_edge(eed, 1) // 1 = select, 0 = deselect
- use for selecting faces always:
void EM_select_face(efa, 1) // 1 = select, 0 = deselect
- To set the 'f' flags in all of the data:
void EM_set_flag_all(int flag);
void EM_clear_flag_all(int flag);
- the old faceselectedOR() and faceselectedAND() are still there, but only
to be used for evaluating its vertices
**** Code hints for handling selection
If the selectmode is 'face'; vertex or edge selections need to be flushed upward. Same is true for 'edge' selection mode. This means that you'll have to keep track of all selections while coding... selecting the four vertices in a face doesn't automatically select the face anymore.
However, by using the above calls, at least selections flush downward (to vertex level). You then can call:
void EM_selectmode_flush(void);
Which flushes selections back upward, based on the selectmode setting. This function does the following:
- if selectmode 'vertex': select edges/faces based on its selected vertices
- if selectmode 'edge': select faces based its selected edges
This works fine in nice controlled situations.
However, only changing the vertex selections then still doesn't select a face in face mode! If you really can't avoid only working with vertex selections, you can use this call:
void EM_select_flush(void);
Now selection is flushed upward regardless current selectmode. That can be destructive for special cases however, like checkerboard selected faces. So use this only when you know everything else was deselected (or deselect it). Example: adding primitives.
**** Hide flags
EditVert: eve->h
EditEdge: eed->h
EditFace: efa->h
- all hide flags are always up-to-date
- hidden vertices/edges/faces are always deselected. so when you operate on selection only, there's no need to check for hide flag.
**** Unified undo for editmode
New file: editmode_undo.h
A pretty nice function pointer handler style undo. Just code three functions, and your undo will fly! The c file has a good reference.
Also note that the old undo system has been replaced. It currently uses minimal dependencies on Meshes themselves (no abuse of going in/out editmode), and is restricted nicely to editmode functions.
**** Going in/out editmode
As speedup now all vertices/faces/edges are allocated in three big chunks. In vertices/faces/edges now tags are set to denote such data cannot be freed.
ALso the hashtable (lookup) for edges uses no mallocs at all anymore, but is part of the EditEdge itself.
2004-09-23 20:52:51 +00:00
|
|
|
free_editMesh(G.editMesh);
|
2002-10-12 11:37:38 +00:00
|
|
|
waitcursor(1); /* patch yah... */
|
|
|
|
G.obedit= 0;
|
|
|
|
}
|
|
|
|
tex_space_mesh(me);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-10-15 13:04:21 +00:00
|
|
|
static void dxf_read_lwpolyline(int noob) {
|
|
|
|
/* Entity specific vars */
|
|
|
|
short vspace=0; /* Whether or not coords are relative */
|
|
|
|
int flag=0;
|
|
|
|
int nverts=0;
|
|
|
|
int v;
|
|
|
|
|
|
|
|
/* Blender vars */
|
|
|
|
Object *ob;
|
|
|
|
Mesh *me;
|
|
|
|
float vert[3];
|
|
|
|
|
|
|
|
MVert *mvert;
|
|
|
|
MFace *mface;
|
|
|
|
|
|
|
|
reset_vars;
|
|
|
|
|
|
|
|
id = -1;
|
|
|
|
|
|
|
|
/* block structure is
|
|
|
|
* {...}
|
|
|
|
* 90 => nverts
|
|
|
|
* 70 => flags
|
|
|
|
* nverts.times { 10 => x, 20 => y }
|
|
|
|
*/
|
|
|
|
while(id!=70) {
|
|
|
|
read_group(id, val);
|
|
|
|
if (id==8) {
|
|
|
|
BLI_strncpy(layname, val, sizeof(layname));
|
|
|
|
} else if (id==38) {
|
|
|
|
vert[2]= (float) atof(val);
|
|
|
|
} else if (id==60) {
|
|
|
|
/* short invisible= atoi(val); */
|
|
|
|
} else if (id==62) {
|
|
|
|
int colorid= atoi(val);
|
|
|
|
|
|
|
|
CLAMP(colorid, 1, 255);
|
|
|
|
dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]);
|
|
|
|
} else if (id==67) {
|
|
|
|
vspace= atoi(val);
|
|
|
|
} else if (id==70) {
|
|
|
|
flag= atoi(val);
|
|
|
|
} else if (id==90) {
|
|
|
|
nverts= atoi(val);
|
|
|
|
}
|
|
|
|
}
|
2004-11-26 19:59:11 +00:00
|
|
|
printf("nverts %d\n", nverts);
|
2004-10-15 13:04:21 +00:00
|
|
|
if (nverts == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
dxf_get_mesh(&me, &ob, noob);
|
|
|
|
strcpy(oldllay, layname);
|
|
|
|
if(ob) VECCOPY(ob->loc, cent);
|
|
|
|
dxf_add_mat (ob, me, color, layname);
|
|
|
|
|
|
|
|
me->totvert += nverts;
|
|
|
|
me->totface += nverts;
|
|
|
|
me->mvert = (MVert*) MEM_callocN(me->totvert*sizeof(MVert), "mverts");
|
|
|
|
me->mface = (MFace*) MEM_callocN(me->totface*sizeof(MVert), "mface");
|
|
|
|
|
|
|
|
for (v = 0; v < nverts; v++) {
|
|
|
|
read_group(id,val);
|
|
|
|
if (id == 10) {
|
|
|
|
vert[0]= (float) atof(val);
|
|
|
|
} else {
|
|
|
|
error("Error parsing dxf, expected (10, <x>) at line %d", dxf_line);
|
|
|
|
}
|
|
|
|
|
|
|
|
read_group(id,val);
|
|
|
|
if (id == 20) {
|
|
|
|
vert[1]= (float) atof(val);
|
|
|
|
} else {
|
|
|
|
error("Error parsing dxf, expected (20, <y>) at line %d", dxf_line);
|
|
|
|
}
|
|
|
|
|
|
|
|
mvert = &me->mvert[v];
|
|
|
|
|
|
|
|
if (vspace) {
|
|
|
|
VECCOPY(mvert->co, vert);
|
|
|
|
} else {
|
|
|
|
VecSubf(mvert->co, vert, vcenter);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (v > 0) {
|
|
|
|
mface= &(((MFace*)me->mface)[v-1]);
|
|
|
|
mface->v1 = v-1;
|
|
|
|
mface->v2 = v;
|
|
|
|
mface->edcode = 1;
|
|
|
|
mface->mat_nr = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* flag & 1 -> closed polyline
|
|
|
|
* TODO: give the polyline actual 2D faces if it is closed */
|
|
|
|
|
|
|
|
if (flag&1) {
|
|
|
|
if(me->mface) {
|
|
|
|
mface= &(((MFace*)me->mface)[nverts - 1]);
|
|
|
|
mface->v1 = nverts-1;
|
|
|
|
mface->v2 = 0;
|
2004-11-26 19:59:11 +00:00
|
|
|
mface->edcode = 1;
|
|
|
|
mface->mat_nr = 0;
|
2004-10-15 13:04:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
/* 3D Face state vars */
|
|
|
|
static Object *f3dhold=NULL;
|
|
|
|
static Mesh *f3dmhold=NULL;
|
|
|
|
static char oldflay[32];
|
|
|
|
static short lwasf3d=0; /* last was face 3d? */
|
|
|
|
|
|
|
|
static void dxf_close_3dface(void)
|
|
|
|
{
|
|
|
|
f3dmhold= NULL;
|
|
|
|
if (f3dhold==NULL) return;
|
|
|
|
|
|
|
|
G.obedit= f3dhold;
|
|
|
|
make_editMesh();
|
|
|
|
load_editMesh();
|
EditMesh refactory + undo recode
The changelog is very long... it's on the web too:
http://www.blender3d.org/cms/Mesh_editing_rewrite.425.0.html
EditMesh refactor notes (user)
**** New selection modes
When entering Edit Mode for a Mesh, you now have the choice for three selection modes. These are shown as icons in the 3D header (hotkey is being searched for!).
- Vertex Select
Select vertices as usual, fully compatible with how previous version work
- Edge Select
Vertices are not drawn anymore, and selections happen by default on the edges. It is a true edge select, meaning that you can select three out of four edges in a face, without automatic having the 4th edge selected.
- Face Select
Instead of vertices, now selection 'points' are drawn in the face centers. Selected faces also get a colored outline, like for edges. This also is true face select, for each face individual regardless selection status of its vertices or edges.
While holding SHIFT, and press a selection mode, you can also combine the above choices. Now selection becomes mixed, and will behave as expected.
For example; in Edge+Face select mode, selecting the 4 edges of a face will select the face too.
The selection modes and optional drawing modes (like transparant faces, normals, or solid drawing) all work together. All of Blender's mesh editing tools now react to the correct selection mode as well.
Most noticeable it's in:
**** Extrude
Extruding in Edge or Face Select mode allows much more precise control over what's extruded and what should be excluded. Try for example a checker pattern selection, and extrude it.
New is the fixed translation when faces are extruded. This always follows the (averaged) face normal(s) of the old face(s), enabling much easier working in 3D views . A single 'G' (Grab) or 'R' (Rotate) or 'S' (Scale) will change transform modus as usual.
**** Other things to note
- Hiding edges/faces will also behave different based on Select Mode.
- while editing, normals of faces are updated always now
- Border select (BKEY) has 2 different rules for edges; when one edge is fully inside of the border, it will only select edges that are fully inside. Otherwise it selects each edge intersecting with the border.
- in face mode, adding vertices, edges or a circle is invisible...
- "Add monkey" now works as a normal primitive (rotated and on 3d cursor)
- Mesh undo was fully recoded, hopefully solving issues now with Vertex Keys and Groups
- Going in and out of editmode was fully recoded. Especially on larger models you'll notice substantial speed gain.
**** Todo
Add 'FaceSelect mode' functionality in EditMode, including zbuffered selection, display and editing of UV texture.
EditMesh refactor notes (coder)
**** Usage of flags in general
The "->f" flags are reserved for the editmesh.c and editmesh_lib.c core functions. Actually only selection status is there now.
The "->f1" and "->f2" flags are free to use. They're available in vertex/edge/face structs. Since they're free, check carefully when calling other functions that use these flags... for example extrude() or subdivide() use them.
**** Selection flags
EditVert: eve->f & SELECT
EditEdge: eed->f & SELECT
EditFace: efa->f & SELECT
- Selection is only possible when not-hidden!
- Selection flags are always up-to-date, BUT:
if selection mode >= SELECT_EDGE vertex selection flags can be incorrect
if selection mode == SELECT_FACE vertex/edge selection flags can be incorrect
This because of shared vertices or edges.
- use for selecting vertices:
eve->f &= SELECT
- use for selecting edges always:
void EM_select_edge(eed, 1) // 1 = select, 0 = deselect
- use for selecting faces always:
void EM_select_face(efa, 1) // 1 = select, 0 = deselect
- To set the 'f' flags in all of the data:
void EM_set_flag_all(int flag);
void EM_clear_flag_all(int flag);
- the old faceselectedOR() and faceselectedAND() are still there, but only
to be used for evaluating its vertices
**** Code hints for handling selection
If the selectmode is 'face'; vertex or edge selections need to be flushed upward. Same is true for 'edge' selection mode. This means that you'll have to keep track of all selections while coding... selecting the four vertices in a face doesn't automatically select the face anymore.
However, by using the above calls, at least selections flush downward (to vertex level). You then can call:
void EM_selectmode_flush(void);
Which flushes selections back upward, based on the selectmode setting. This function does the following:
- if selectmode 'vertex': select edges/faces based on its selected vertices
- if selectmode 'edge': select faces based its selected edges
This works fine in nice controlled situations.
However, only changing the vertex selections then still doesn't select a face in face mode! If you really can't avoid only working with vertex selections, you can use this call:
void EM_select_flush(void);
Now selection is flushed upward regardless current selectmode. That can be destructive for special cases however, like checkerboard selected faces. So use this only when you know everything else was deselected (or deselect it). Example: adding primitives.
**** Hide flags
EditVert: eve->h
EditEdge: eed->h
EditFace: efa->h
- all hide flags are always up-to-date
- hidden vertices/edges/faces are always deselected. so when you operate on selection only, there's no need to check for hide flag.
**** Unified undo for editmode
New file: editmode_undo.h
A pretty nice function pointer handler style undo. Just code three functions, and your undo will fly! The c file has a good reference.
Also note that the old undo system has been replaced. It currently uses minimal dependencies on Meshes themselves (no abuse of going in/out editmode), and is restricted nicely to editmode functions.
**** Going in/out editmode
As speedup now all vertices/faces/edges are allocated in three big chunks. In vertices/faces/edges now tags are set to denote such data cannot be freed.
ALso the hashtable (lookup) for edges uses no mallocs at all anymore, but is part of the EditEdge itself.
2004-09-23 20:52:51 +00:00
|
|
|
free_editMesh(G.editMesh);
|
2002-10-12 11:37:38 +00:00
|
|
|
waitcursor(1); /* patch yah... */
|
|
|
|
G.obedit= 0;
|
|
|
|
tex_space_mesh(f3dhold->data);
|
|
|
|
|
|
|
|
f3dhold=NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void dxf_read_3dface(int noob)
|
|
|
|
{
|
|
|
|
/* Entity specific vars */
|
|
|
|
float vert2[3]={0.0, 0.0, 0.0};
|
|
|
|
float vert3[3]={0.0, 0.0, 0.0};
|
|
|
|
float vert4[3]={0.0, 0.0, 0.0};
|
|
|
|
short vspace=0;
|
|
|
|
|
|
|
|
int nverts=0;
|
|
|
|
|
|
|
|
/* Blender vars */
|
|
|
|
Object *ob;
|
|
|
|
Mesh *me;
|
|
|
|
MVert *mvert, *vtmp;
|
|
|
|
MFace *mface, *ftmp;
|
|
|
|
|
|
|
|
reset_vars;
|
|
|
|
|
|
|
|
read_group(id, val);
|
|
|
|
while(id!=0) {
|
|
|
|
if (id==8) {
|
|
|
|
BLI_strncpy(layname, val, sizeof(layname));
|
|
|
|
|
|
|
|
/* First vert/origin */
|
|
|
|
} else if (id==10) {
|
|
|
|
cent[0]= (float) atof(val);
|
|
|
|
if (nverts<1)nverts++;
|
|
|
|
} else if (id==20) {
|
|
|
|
cent[1]= (float) atof(val);
|
|
|
|
if (nverts<1)nverts++;
|
|
|
|
} else if (id==30) {
|
|
|
|
cent[2]= (float) atof(val);
|
|
|
|
if (nverts<1)nverts++;
|
|
|
|
|
|
|
|
/* Second vert */
|
|
|
|
} else if (id==11) {
|
|
|
|
vert2[0]= (float) atof(val);
|
|
|
|
if (nverts<2)nverts++;
|
|
|
|
} else if (id==21) {
|
|
|
|
vert2[1]= (float) atof(val);
|
|
|
|
if (nverts<2)nverts++;
|
|
|
|
} else if (id==31) {
|
|
|
|
vert2[2]= (float) atof(val);
|
|
|
|
if (nverts<2)nverts++;
|
|
|
|
|
|
|
|
/* Third vert */
|
|
|
|
} else if (id==12) {
|
|
|
|
vert3[0]= (float) atof(val);
|
|
|
|
if (nverts<3)nverts++;
|
|
|
|
} else if (id==22) {
|
|
|
|
vert3[1]= (float) atof(val);
|
|
|
|
if (nverts<3)nverts++;
|
|
|
|
} else if (id==32) {
|
|
|
|
vert3[2]= (float) atof(val);
|
|
|
|
if (nverts<3)nverts++;
|
|
|
|
|
|
|
|
/* Fourth vert */
|
|
|
|
} else if (id==13) {
|
|
|
|
vert4[0]= (float) atof(val);
|
|
|
|
if (nverts<4)nverts++;
|
|
|
|
} else if (id==23) {
|
|
|
|
vert4[1]= (float) atof(val);
|
|
|
|
if (nverts<4)nverts++;
|
|
|
|
} else if (id==33) {
|
|
|
|
vert4[2]= (float) atof(val);
|
|
|
|
if (nverts<4)nverts++;
|
|
|
|
|
|
|
|
/* Other */
|
|
|
|
} else if (id==60) {
|
|
|
|
/* short invisible= atoi(val); */
|
|
|
|
} else if (id==62) {
|
|
|
|
int colorid= atoi(val);
|
|
|
|
|
|
|
|
CLAMP(colorid, 1, 255);
|
|
|
|
dxf_col_to_rgb(colorid, &color[0], &color[1], &color[2]);
|
|
|
|
} else if (id==67) {
|
|
|
|
vspace= atoi(val);
|
|
|
|
}
|
|
|
|
read_group(id, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check to see if we need to make a new object */
|
|
|
|
|
|
|
|
if(!lwasf3d || strcmp(layname, oldflay)!=0) dxf_close_3dface();
|
2004-03-14 21:21:09 +00:00
|
|
|
if(f3dmhold != NULL && f3dmhold->totvert>MESH_MAX_VERTS)
|
|
|
|
dxf_close_3dface();
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
if(nverts<3) {
|
|
|
|
error("(3DF) Error parsing dxf, not enough vertices near line %d", dxf_line);
|
|
|
|
|
|
|
|
error_exit=1;
|
|
|
|
fclose(dxf_fp);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (f3dmhold==NULL) {
|
|
|
|
if (noob) {
|
|
|
|
ob= NULL;
|
|
|
|
me= add_mesh(); G.totmesh++;
|
|
|
|
((ID *)me)->us=0;
|
|
|
|
|
|
|
|
if (strlen(entname)) new_id(&G.main->mesh, (ID *)me, entname);
|
|
|
|
else if (strlen(layname)) new_id(&G.main->mesh, (ID *)me, layname);
|
|
|
|
|
|
|
|
vcenter= zerovec;
|
|
|
|
} else {
|
|
|
|
ob= add_object(OB_MESH);
|
|
|
|
if (strlen(entname)) new_id(&G.main->object, (ID *)ob, entname);
|
|
|
|
else if (strlen(layname)) new_id(&G.main->object, (ID *)ob, layname);
|
|
|
|
|
|
|
|
if (strlen(layname)) ob->lay= dxf_get_layer_num(layname);
|
|
|
|
else ob->lay= G.scene->lay;
|
|
|
|
|
|
|
|
me= ob->data;
|
|
|
|
|
|
|
|
vcenter= ob->loc;
|
|
|
|
}
|
|
|
|
me->totvert=0;
|
|
|
|
me->totface=0;
|
|
|
|
me->mvert=NULL;
|
|
|
|
me->mface=NULL;
|
|
|
|
|
|
|
|
strcpy(oldflay, layname);
|
|
|
|
|
|
|
|
if(ob) VECCOPY(ob->loc, cent);
|
|
|
|
|
|
|
|
dxf_add_mat (ob, me, color, layname);
|
|
|
|
|
|
|
|
f3dhold= ob;
|
|
|
|
f3dmhold= me;
|
|
|
|
} else {
|
|
|
|
ob= f3dhold;
|
|
|
|
me= f3dmhold;
|
|
|
|
}
|
|
|
|
|
|
|
|
me->totvert+= nverts;
|
|
|
|
me->totface++;
|
|
|
|
|
|
|
|
vtmp= MEM_callocN(me->totvert*sizeof(MVert), "mverts");
|
|
|
|
ftmp= MEM_callocN(me->totface*sizeof(MFace), "mface");
|
|
|
|
|
|
|
|
if(me->mvert) {
|
|
|
|
memcpy(vtmp, me->mvert, (me->totvert-nverts)*sizeof(MVert));
|
|
|
|
MEM_freeN(me->mvert);
|
|
|
|
}
|
|
|
|
me->mvert= vtmp;
|
|
|
|
vtmp=NULL;
|
|
|
|
|
|
|
|
if(me->mface) {
|
|
|
|
memcpy(ftmp, me->mface, (me->totface-1)*sizeof(MFace));
|
|
|
|
MEM_freeN(me->mface);
|
|
|
|
}
|
|
|
|
me->mface= ftmp;
|
|
|
|
ftmp=NULL;
|
|
|
|
|
|
|
|
mvert= &me->mvert[(me->totvert-nverts)];
|
|
|
|
VecSubf(mvert->co, cent, vcenter);
|
|
|
|
|
|
|
|
mvert++;
|
|
|
|
if (vspace) { VECCOPY(mvert->co, vert2);
|
|
|
|
} else VecSubf(mvert->co, vert2, vcenter);
|
|
|
|
|
|
|
|
mvert++;
|
|
|
|
if (vspace) { VECCOPY(mvert->co, vert3);
|
|
|
|
} else VecSubf(mvert->co, vert3, vcenter);
|
|
|
|
|
|
|
|
if (nverts==4) {
|
|
|
|
mvert++;
|
|
|
|
if (vspace) { VECCOPY(mvert->co, vert4);
|
|
|
|
} else VecSubf(mvert->co, vert4, vcenter);
|
|
|
|
}
|
|
|
|
|
|
|
|
mface= &(((MFace*)me->mface)[me->totface-1]);
|
|
|
|
mface->v1= (me->totvert-nverts)+0;
|
|
|
|
mface->v2= (me->totvert-nverts)+1;
|
|
|
|
mface->v3= (me->totvert-nverts)+2;
|
|
|
|
|
|
|
|
if (nverts==4)
|
|
|
|
mface->v4= (me->totvert-nverts)+3;
|
|
|
|
|
|
|
|
mface->edcode= 3;
|
|
|
|
mface->mat_nr= 0;
|
|
|
|
|
|
|
|
test_index_mface(mface, nverts);
|
2005-03-04 20:02:52 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
hasbumped=1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void dxf_read(char *filename)
|
|
|
|
{
|
|
|
|
dxf_line=0;
|
|
|
|
|
|
|
|
dxf_fp= fopen(filename, "r");
|
|
|
|
if (dxf_fp==NULL) return;
|
|
|
|
while (1) {
|
|
|
|
read_group(id, val);
|
|
|
|
if (group_is(0, "EOF")) break;
|
|
|
|
|
|
|
|
if (id==999) continue;
|
|
|
|
id_check(0, "SECTION");
|
|
|
|
|
|
|
|
read_group(id, val);
|
|
|
|
if (group_is(2, "HEADER")) {
|
|
|
|
} else if (group_is(2, "TABLES")) {
|
|
|
|
} else if (group_is(2, "OBJECTS")) {
|
|
|
|
} else if (group_is(2, "CLASSES")) {
|
|
|
|
} else if (group_is(2, "BLOCKS")) {
|
|
|
|
while(1) {
|
|
|
|
read_group(id, val);
|
|
|
|
if (group_is(0, "BLOCK")) {
|
|
|
|
while(group_isnt(0, "ENDBLK")) {
|
|
|
|
read_group(id, val);
|
2004-10-15 13:04:21 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if(id==2) {
|
|
|
|
BLI_strncpy(entname, val, sizeof(entname));
|
|
|
|
} else if (id==3) {
|
|
|
|
/* Now the object def should follow */
|
|
|
|
if(strlen(entname)==0) {
|
|
|
|
error("Error parsing dxf, no mesh name near %d", dxf_line);
|
|
|
|
fclose(dxf_fp);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now the object def should follow */
|
|
|
|
while(group_isnt(0, "ENDBLK")) {
|
|
|
|
read_group(id, val);
|
2004-10-15 13:04:21 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
if(group_is(0, "POLYLINE")) {
|
|
|
|
dxf_read_polyline(1);
|
|
|
|
if(error_exit) return;
|
|
|
|
lwasf3d=0;
|
|
|
|
lwasline=0;
|
|
|
|
|
2004-10-15 13:04:21 +00:00
|
|
|
while(group_isnt(0, "SEQEND")) read_group(id, val);
|
|
|
|
|
|
|
|
} else if(group_is(0, "LWPOLYLINE")) {
|
|
|
|
dxf_read_lwpolyline(1);
|
|
|
|
if(error_exit) return;
|
|
|
|
lwasf3d=0;
|
|
|
|
lwasline=0;
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
while(group_isnt(0, "SEQEND")) read_group(id, val);
|
|
|
|
} else if(group_is(0, "ATTRIB")) {
|
|
|
|
while(group_isnt(0, "SEQEND")) read_group(id, val);
|
|
|
|
lwasf3d=0;
|
|
|
|
lwasp2d=0;
|
|
|
|
lwasline=0;
|
|
|
|
} else if(group_is(0, "POINT")) {
|
|
|
|
dxf_read_point(1);
|
|
|
|
if(error_exit) return;
|
|
|
|
lwasf3d=0;
|
|
|
|
lwasp2d=0;
|
|
|
|
lwasline=0;
|
|
|
|
} else if(group_is(0, "LINE")) {
|
|
|
|
dxf_read_line(1);
|
|
|
|
if(error_exit) return;
|
|
|
|
lwasline=1;
|
|
|
|
lwasp2d=0;
|
|
|
|
lwasf3d=0;
|
|
|
|
} else if(group_is(0, "3DFACE")) {
|
|
|
|
dxf_read_3dface(1);
|
|
|
|
if(error_exit) return;
|
|
|
|
lwasf3d=1;
|
|
|
|
lwasp2d=0;
|
|
|
|
lwasline=0;
|
2004-10-15 13:04:21 +00:00
|
|
|
} else if (group_is(0, "CIRCLE")) {
|
|
|
|
dxf_read_arc(1);
|
|
|
|
} else if (group_is(0, "ELLIPSE")) {
|
|
|
|
dxf_read_ellipse(1);
|
2002-10-12 11:37:38 +00:00
|
|
|
} else if (group_is(0, "ENDBLK")) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (group_is(0, "ENDBLK")) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2004-10-15 13:04:21 +00:00
|
|
|
while(id!=0) read_group(id, val);
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
} else if(group_is(0, "ENDSEC")) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (group_is(2, "ENTITIES")) {
|
|
|
|
while(group_isnt(0, "ENDSEC")) {
|
|
|
|
char obname[32]="";
|
|
|
|
char layname[32]="";
|
|
|
|
float cent[3]={0.0, 0.0, 0.0};
|
|
|
|
float obsize[3]={1.0, 1.0, 1.0};
|
|
|
|
float obrot[3]={0.0, 0.0, 0.0};
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if(!hasbumped) read_group(id, val);
|
|
|
|
hasbumped=0;
|
|
|
|
if (group_is(0, "INSERT")) {
|
|
|
|
Base *base;
|
|
|
|
Object *ob;
|
|
|
|
void *obdata;
|
|
|
|
|
|
|
|
read_group(id, val);
|
2004-10-15 13:04:21 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
while(id!=0) {
|
|
|
|
if(id==2) {
|
|
|
|
BLI_strncpy(obname, val, sizeof(obname));
|
|
|
|
} else if (id==8) {
|
|
|
|
BLI_strncpy(layname, val, sizeof(layname));
|
|
|
|
} else if (id==10) {
|
|
|
|
cent[0]= (float) atof(val);
|
|
|
|
} else if (id==20) {
|
|
|
|
cent[1]= (float) atof(val);
|
|
|
|
} else if (id==30) {
|
|
|
|
cent[2]= (float) atof(val);
|
|
|
|
} else if (id==41) {
|
|
|
|
obsize[0]= (float) atof(val);
|
|
|
|
} else if (id==42) {
|
|
|
|
obsize[1]= (float) atof(val);
|
|
|
|
} else if (id==43) {
|
|
|
|
obsize[2]= (float) atof(val);
|
|
|
|
} else if (id==50) {
|
|
|
|
obrot[2]= (float) (atof(val)*M_PI/180.0);
|
|
|
|
} else if (id==60) {
|
|
|
|
/* short invisible= atoi(val); */
|
|
|
|
}
|
|
|
|
|
|
|
|
read_group(id, val);
|
2004-10-15 13:04:21 +00:00
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(strlen(obname)==0) {
|
|
|
|
error("Error parsing dxf, no object name near %d", dxf_line);
|
|
|
|
fclose(dxf_fp);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
obdata= find_id("ME", obname);
|
|
|
|
|
|
|
|
if (obdata) {
|
|
|
|
ob= alloc_libblock(&G.main->object, ID_OB, obname);
|
|
|
|
|
|
|
|
ob->type= OB_MESH;
|
|
|
|
|
|
|
|
ob->dt= OB_SHADED;
|
2004-01-13 14:50:45 +00:00
|
|
|
if(U.flag & USER_MAT_ON_OB) ob->colbits= -1;
|
2002-10-12 11:37:38 +00:00
|
|
|
|
|
|
|
ob->trackflag= OB_POSY;
|
|
|
|
ob->upflag= OB_POSZ;
|
|
|
|
|
|
|
|
ob->ipoflag = OB_OFFS_OB+OB_OFFS_PARENT;
|
|
|
|
|
|
|
|
ob->dupon= 1; ob->dupoff= 0;
|
|
|
|
ob->dupsta= 1; ob->dupend= 100;
|
|
|
|
|
|
|
|
G.totobj++;
|
|
|
|
|
|
|
|
ob->data= obdata;
|
|
|
|
((ID*)ob->data)->us++;
|
|
|
|
|
|
|
|
VECCOPY(ob->loc, cent);
|
|
|
|
VECCOPY(ob->size, obsize);
|
|
|
|
VECCOPY(ob->rot, obrot);
|
|
|
|
|
|
|
|
ob->mat= MEM_callocN(sizeof(void *)*1, "ob->mat");
|
|
|
|
ob->totcol= (unsigned char) ((Mesh*)ob->data)->totcol;
|
|
|
|
ob->actcol= 1;
|
|
|
|
|
|
|
|
for (i=0; i<ob->totcol; i++) ob->mat[i]= ((Mesh*)ob->data)->mat[i];
|
|
|
|
|
|
|
|
if (strlen(layname)) ob->lay= dxf_get_layer_num(layname);
|
|
|
|
else ob->lay= G.scene->lay;
|
|
|
|
|
|
|
|
/* aan de scene hangen */
|
|
|
|
base= MEM_callocN( sizeof(Base), "add_base");
|
|
|
|
BLI_addhead(&G.scene->base, base);
|
|
|
|
|
|
|
|
base->lay= ob->lay;
|
|
|
|
|
|
|
|
base->object= ob;
|
|
|
|
|
|
|
|
G.obedit= ob;
|
|
|
|
make_editMesh();
|
|
|
|
load_editMesh();
|
EditMesh refactory + undo recode
The changelog is very long... it's on the web too:
http://www.blender3d.org/cms/Mesh_editing_rewrite.425.0.html
EditMesh refactor notes (user)
**** New selection modes
When entering Edit Mode for a Mesh, you now have the choice for three selection modes. These are shown as icons in the 3D header (hotkey is being searched for!).
- Vertex Select
Select vertices as usual, fully compatible with how previous version work
- Edge Select
Vertices are not drawn anymore, and selections happen by default on the edges. It is a true edge select, meaning that you can select three out of four edges in a face, without automatic having the 4th edge selected.
- Face Select
Instead of vertices, now selection 'points' are drawn in the face centers. Selected faces also get a colored outline, like for edges. This also is true face select, for each face individual regardless selection status of its vertices or edges.
While holding SHIFT, and press a selection mode, you can also combine the above choices. Now selection becomes mixed, and will behave as expected.
For example; in Edge+Face select mode, selecting the 4 edges of a face will select the face too.
The selection modes and optional drawing modes (like transparant faces, normals, or solid drawing) all work together. All of Blender's mesh editing tools now react to the correct selection mode as well.
Most noticeable it's in:
**** Extrude
Extruding in Edge or Face Select mode allows much more precise control over what's extruded and what should be excluded. Try for example a checker pattern selection, and extrude it.
New is the fixed translation when faces are extruded. This always follows the (averaged) face normal(s) of the old face(s), enabling much easier working in 3D views . A single 'G' (Grab) or 'R' (Rotate) or 'S' (Scale) will change transform modus as usual.
**** Other things to note
- Hiding edges/faces will also behave different based on Select Mode.
- while editing, normals of faces are updated always now
- Border select (BKEY) has 2 different rules for edges; when one edge is fully inside of the border, it will only select edges that are fully inside. Otherwise it selects each edge intersecting with the border.
- in face mode, adding vertices, edges or a circle is invisible...
- "Add monkey" now works as a normal primitive (rotated and on 3d cursor)
- Mesh undo was fully recoded, hopefully solving issues now with Vertex Keys and Groups
- Going in and out of editmode was fully recoded. Especially on larger models you'll notice substantial speed gain.
**** Todo
Add 'FaceSelect mode' functionality in EditMode, including zbuffered selection, display and editing of UV texture.
EditMesh refactor notes (coder)
**** Usage of flags in general
The "->f" flags are reserved for the editmesh.c and editmesh_lib.c core functions. Actually only selection status is there now.
The "->f1" and "->f2" flags are free to use. They're available in vertex/edge/face structs. Since they're free, check carefully when calling other functions that use these flags... for example extrude() or subdivide() use them.
**** Selection flags
EditVert: eve->f & SELECT
EditEdge: eed->f & SELECT
EditFace: efa->f & SELECT
- Selection is only possible when not-hidden!
- Selection flags are always up-to-date, BUT:
if selection mode >= SELECT_EDGE vertex selection flags can be incorrect
if selection mode == SELECT_FACE vertex/edge selection flags can be incorrect
This because of shared vertices or edges.
- use for selecting vertices:
eve->f &= SELECT
- use for selecting edges always:
void EM_select_edge(eed, 1) // 1 = select, 0 = deselect
- use for selecting faces always:
void EM_select_face(efa, 1) // 1 = select, 0 = deselect
- To set the 'f' flags in all of the data:
void EM_set_flag_all(int flag);
void EM_clear_flag_all(int flag);
- the old faceselectedOR() and faceselectedAND() are still there, but only
to be used for evaluating its vertices
**** Code hints for handling selection
If the selectmode is 'face'; vertex or edge selections need to be flushed upward. Same is true for 'edge' selection mode. This means that you'll have to keep track of all selections while coding... selecting the four vertices in a face doesn't automatically select the face anymore.
However, by using the above calls, at least selections flush downward (to vertex level). You then can call:
void EM_selectmode_flush(void);
Which flushes selections back upward, based on the selectmode setting. This function does the following:
- if selectmode 'vertex': select edges/faces based on its selected vertices
- if selectmode 'edge': select faces based its selected edges
This works fine in nice controlled situations.
However, only changing the vertex selections then still doesn't select a face in face mode! If you really can't avoid only working with vertex selections, you can use this call:
void EM_select_flush(void);
Now selection is flushed upward regardless current selectmode. That can be destructive for special cases however, like checkerboard selected faces. So use this only when you know everything else was deselected (or deselect it). Example: adding primitives.
**** Hide flags
EditVert: eve->h
EditEdge: eed->h
EditFace: efa->h
- all hide flags are always up-to-date
- hidden vertices/edges/faces are always deselected. so when you operate on selection only, there's no need to check for hide flag.
**** Unified undo for editmode
New file: editmode_undo.h
A pretty nice function pointer handler style undo. Just code three functions, and your undo will fly! The c file has a good reference.
Also note that the old undo system has been replaced. It currently uses minimal dependencies on Meshes themselves (no abuse of going in/out editmode), and is restricted nicely to editmode functions.
**** Going in/out editmode
As speedup now all vertices/faces/edges are allocated in three big chunks. In vertices/faces/edges now tags are set to denote such data cannot be freed.
ALso the hashtable (lookup) for edges uses no mallocs at all anymore, but is part of the EditEdge itself.
2004-09-23 20:52:51 +00:00
|
|
|
free_editMesh(G.editMesh);
|
2002-10-12 11:37:38 +00:00
|
|
|
waitcursor(1); /* patch yah... */
|
|
|
|
G.obedit= 0;
|
|
|
|
tex_space_mesh(ob->data);
|
|
|
|
}
|
|
|
|
|
|
|
|
hasbumped=1;
|
|
|
|
|
|
|
|
lwasf3d=0;
|
|
|
|
lwasp2d=0;
|
|
|
|
lwasline=0;
|
|
|
|
} else if(group_is(0, "POLYLINE")) {
|
|
|
|
dxf_read_polyline(0);
|
|
|
|
if(error_exit) return;
|
|
|
|
lwasf3d=0;
|
|
|
|
lwasline=0;
|
|
|
|
|
|
|
|
while(group_isnt(0, "SEQEND")) read_group(id, val);
|
2004-10-15 13:04:21 +00:00
|
|
|
|
|
|
|
} else if(group_is(0, "LWPOLYLINE")) {
|
|
|
|
dxf_read_lwpolyline(0);
|
|
|
|
if(error_exit) return;
|
|
|
|
lwasf3d=0;
|
|
|
|
lwasline=0;
|
|
|
|
//while(group_isnt(0, "SEQEND")) read_group(id, val);
|
|
|
|
|
2002-10-12 11:37:38 +00:00
|
|
|
} else if(group_is(0, "ATTRIB")) {
|
|
|
|
while(group_isnt(0, "SEQEND")) read_group(id, val);
|
|
|
|
lwasf3d=0;
|
|
|
|
lwasp2d=0;
|
|
|
|
lwasline=0;
|
|
|
|
} else if(group_is(0, "POINT")) {
|
|
|
|
dxf_read_point(0);
|
|
|
|
if(error_exit) return;
|
|
|
|
lwasf3d=0;
|
|
|
|
lwasp2d=0;
|
|
|
|
lwasline=0;
|
|
|
|
} else if(group_is(0, "LINE")) {
|
|
|
|
dxf_read_line(0);
|
|
|
|
if(error_exit) return;
|
|
|
|
lwasline=1;
|
|
|
|
lwasp2d=0;
|
|
|
|
lwasf3d=0;
|
|
|
|
} else if(group_is(0, "3DFACE")) {
|
|
|
|
dxf_read_3dface(0);
|
|
|
|
if(error_exit) return;
|
|
|
|
lwasline=0;
|
|
|
|
lwasp2d=0;
|
|
|
|
lwasf3d=1;
|
2004-10-15 13:04:21 +00:00
|
|
|
} else if (group_is(0, "CIRCLE") || group_is(0, "ARC")) {
|
|
|
|
dxf_read_arc(0);
|
|
|
|
} else if (group_is(0, "ELLIPSE")) {
|
|
|
|
dxf_read_ellipse(0);
|
2002-10-12 11:37:38 +00:00
|
|
|
} else if(group_is(0, "ENDSEC")) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
while(group_isnt(0, "ENDSEC")) read_group(id, val);
|
|
|
|
}
|
|
|
|
id_check(0, "EOF");
|
|
|
|
|
|
|
|
fclose (dxf_fp);
|
|
|
|
|
|
|
|
/* Close any remaining state held stuff */
|
|
|
|
dxf_close_3dface();
|
|
|
|
dxf_close_2dpoly();
|
|
|
|
dxf_close_line();
|
|
|
|
}
|