diff options
Diffstat (limited to 'source/blender/blenkernel')
84 files changed, 38547 insertions, 0 deletions
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h new file mode 100644 index 00000000000..53fe4a7146c --- /dev/null +++ b/source/blender/blenkernel/BKE_action.h @@ -0,0 +1,238 @@ +/* BKE_action.h May 2001 + * + * Blender kernel action functionality + * + * Reevan McKay + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef BKE_ACTION_H +#define BKE_ACTION_H + +#include "DNA_listBase.h" + +/** + * The following structures are defined in DNA_action_types.h + */ + +struct bAction; +struct bActionChannel; +struct bPose; +struct bPoseChannel; +struct Object; + +/* Kernel prototypes */ +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Allocate a new pose channel on the heap and binary copy the + * contents of the src pose channel. + */ + struct bPoseChannel * +copy_pose_channel ( + const struct bPoseChannel *src +); + +/** + * Removes and deallocates all channels from a pose. + * Does not free the pose itself. + */ + void +clear_pose ( + struct bPose *pose +); + +/* Sets the value of a pose channel */ + struct bPoseChannel * +set_pose_channel ( + struct bPose *pose, + struct bPoseChannel *chan +); + +/** + * Allocate a new pose on the heap, and copy the src pose and it's channels + * into the new pose. *dst is set to the newly allocated structure. + */ + void +copy_pose( + struct bPose **dst, + const struct bPose *src, + int copyconstraints +); + +/** + * Deallocate the action's channels including constraint channels. + * does not free the action structure. + */ + void +free_action( + struct bAction * id +); + + void +make_local_action( + struct bAction *act +); + + void +do_all_actions( + void +); + +/** + * Return a pointer to the pose channel of the given name + * from this pose. + */ + + struct bPoseChannel * +get_pose_channel ( + const struct bPose *pose, + const char *name +); + +/** + * Looks to see if the channel with the given name + * already exists in this pose - if not a new one is + * allocated and initialized. + */ + void +verify_pose_channel ( + struct bPose* pose, + const char* name +); + +/** + * Allocate a new bAction on the heap and copy + * the contents of src into it. If src is NULL NULL is returned. + */ + + struct bAction* +copy_action( + const struct bAction *src +); + +/** + * Some kind of bounding box operation on the action. + */ + + float +calc_action_start ( + const struct bAction *act +); + + float +calc_action_end ( + const struct bAction *act +); + +/** + * Evaluate the pose from the given action. + * If the pose does not exist, a new one is created. + * Some deep calls into blender are made here. + */ + void +get_pose_from_action ( + struct bPose **pose, + struct bAction *act, + float ctime +); + +/** + * I think this duplicates the src into *pose. + * If the pose does not exist, a new one is created. + * If the pose does not contain channels from src + * new channels are created. + */ + void +get_pose_from_pose ( + struct bPose **pose, + const struct bPose *src +); + + void +clear_pose_constraint_status ( + struct Object *ob +); + +/** + * Blends the common subset of channels from dst and src. + * and writes result to dst. + */ + void +blend_poses ( + struct bPose *dst, + const struct bPose *src, + float srcweight, + short mode +); + +/** + * Iterate through the action channels of the action + * and return the channel with the given name. + * Returns NULL if no channel. + */ + + struct bActionChannel * +get_named_actionchannel ( + struct bAction *act, + const char *name +); + +#ifdef __cplusplus +}; +#endif + +enum { + POSE_BLEND = 0, + POSE_ADD +}; + +enum { + POSE_KEY = 0x10000000, + POSE_LOC = 0x00000001, + POSE_ROT = 0x00000002, + POSE_SIZE = 0x00000004, + POSE_UNUSED1 = 0x00000008, + POSE_UNUSED2 = 0x00000010, + POSE_UNUSED3 = 0x00000020, + POSE_UNUSED4 = 0x00000040, + POSE_UNUSED5 = 0x00000080, + POSE_OBMAT = 0x00000100, + POSE_PARMAT = 0x00000200, + PCHAN_DONE = 0x00000400 + +}; +#endif + + diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h new file mode 100644 index 00000000000..93faf2d34bc --- /dev/null +++ b/source/blender/blenkernel/BKE_anim.h @@ -0,0 +1,52 @@ +/** + * blenlib/BKE_anim.h (mar-2001 nzc); + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_ANIM_H +#define BKE_ANIM_H + +struct Path; +struct Object; +struct PartEff; +struct Scene; + +void free_path(struct Path *path); +void calc_curvepath(struct Object *ob); +int interval_test(int min, int max, int p1, int cycl); +int where_on_path(struct Object *ob, float ctime, float *vec, float *dir); +void frames_duplilist(struct Object *ob); +void vertex_duplilist(struct Scene *sce, struct Object *par); +void particle_duplilist(struct Scene *sce, struct Object *par, struct PartEff *paf); +void free_duplilist(void); +void make_duplilist(struct Scene *sce, struct Object *ob); + +#endif diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h new file mode 100644 index 00000000000..4e52d154644 --- /dev/null +++ b/source/blender/blenkernel/BKE_armature.h @@ -0,0 +1,121 @@ +/** + * blenlib/BKE_armature.h (mar-2001 nzc) + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_ARMATURE_H +#define BKE_ARMATURE_H + +struct Bone; +struct Main; +struct bArmature; +struct bPose; +struct Object; +struct MDeformVert; +struct Mesh; +struct PoseChain; +struct ListBase; + +typedef struct PoseChain +{ + struct PoseChain *next, *prev; + struct Bone *root; + struct Bone *target; + struct bPose *pose; + float goal[3]; + float tolerance; + int iterations; + float goalinv[4][4]; + struct IK_Chain_Extern *solver; +} PoseChain; + +/* Core armature functionality */ +#ifdef __cplusplus +extern "C" { +#endif +struct bArmature *add_armature(void); +void free_boneChildren(struct Bone *bone); +void free_bones (struct bArmature *arm); +void unlink_armature(struct bArmature *arm); +void free_armature(struct bArmature *arm); +void make_local_armature(struct bArmature *arm); +struct bArmature *copy_armature(struct bArmature *arm); +void apply_pose_armature (struct bArmature* arm, struct bPose* pose, int doit); +void calc_armature_deform (struct Object *ob, float *co, int index); +int verify_boneptr (struct bArmature *arm, struct Bone *tBone); +void init_armature_deform(struct Object *parent, struct Object *ob); +struct bArmature* get_armature (struct Object* ob); +struct Bone *get_named_bone (struct bArmature *arm, const char *name); +struct Bone *get_indexed_bone (struct bArmature *arm, int index); +void make_displists_by_armature (struct Object *ob); +void calc_bone_deform (struct Bone *bone, float weight, float *vec, float *co, float *contrib); + +void where_is_armature_time (struct Object *ob, float ctime); +void where_is_armature (struct Object *ob); +void where_is_bone1_time (struct Object *ob, struct Bone *bone, float ctime); + +/* Handy bone matrix functions */ +void bone_to_mat4(struct Bone *bone, float mat[][4]); +void bone_to_mat3(struct Bone *bone, float mat[][3]); +void make_boneMatrixvr (float outmatrix[][4],float delta[3], float roll); +void make_boneMatrix (float outmatrix[][4], struct Bone *bone); +void get_bone_root_pos (struct Bone* bone, float vec[3], int posed); +void get_bone_tip_pos (struct Bone* bone, float vec[3], int posed); +float get_bone_length (struct Bone *bone); +void get_objectspace_bone_matrix (struct Bone* bone, float M_accumulatedMatrix[][4], int root, int posed); +void precalc_bone_irestmat (struct Bone *bone); +void precalc_armature_posemats (struct bArmature *arm); +void precalc_bonelist_irestmats (struct ListBase* bonelist); +void apply_bonemat(struct Bone *bone); + +/* void make_armatureParentMatrices (struct bArmature *arm); */ +void precalc_bone_defmat (struct Bone *bone); +void rebuild_bone_parent_matrix (struct Bone *bone); + +/* Animation functions */ +void where_is_bone_time (struct Object *ob, struct Bone *bone, float ctime); +void where_is_bone (struct Object *ob, struct Bone *bone); +struct PoseChain *ik_chain_to_posechain (struct Object *ob, struct Bone *bone); +void solve_posechain (PoseChain *chain); +void free_posechain (PoseChain *chain); + +/* Gameblender hacks */ +void GB_init_armature_deform(struct ListBase *defbase, float premat[][4], float postmat[][4]); +void GB_calc_armature_deform (float *co, struct MDeformVert *dvert); +void GB_build_mats (float parmat[][4], float obmat[][4], float premat[][4], float postmat[][4]); +void GB_validate_defgroups (struct Mesh *mesh, struct ListBase *defbase); + +/*void make_boneParentMatrix (struct Bone* bone, float mat[][4]);*/ + +#ifdef __cplusplus +} +#endif +#endif diff --git a/source/blender/blenkernel/BKE_bad_level_calls.h b/source/blender/blenkernel/BKE_bad_level_calls.h new file mode 100644 index 00000000000..420a915adf6 --- /dev/null +++ b/source/blender/blenkernel/BKE_bad_level_calls.h @@ -0,0 +1,143 @@ +/** + * blenlib/BKE_bad_level_calls.h (mar-2001 nzc) + * + * Stuff that definitely does not belong in the kernel! These will all + * have to be removed in order to restore sanity. + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_BAD_LEVEL_CALLS_H +#define BKE_BAD_LEVEL_CALLS_H + +/* readfile.c */ +struct PluginSeq; +void open_plugin_seq(struct PluginSeq *pis, char *seqname); +struct SpaceButs; +void set_rects_butspace(struct SpaceButs *buts); +struct SpaceImaSel; +void check_imasel_copy(struct SpaceImaSel *simasel); +struct ScrArea; +struct bScreen; +void unlink_screen(struct bScreen *sc); +void freeAllRad(void); +void free_editText(void); +void setscreen(struct bScreen *sc); +void force_draw_all(void); + /* otherwise the WHILE_SEQ doesn't work */ +struct Sequence; +void build_seqar(struct ListBase *seqbase, struct Sequence ***seqar, int *totseq); + +struct ID; +void BPY_do_pyscript (struct ID *id, short int event); + +/* writefile.c */ +struct Oops; +void free_oops(struct Oops *oops); +void error(char *str, ...); + +/* anim.c */ +extern struct ListBase editNurb; + +/* displist.c */ +#include "DNA_world_types.h" /* for render_types */ +#include "render_types.h" +extern struct RE_Render R; +float RE_Spec(float, int); +void waitcursor(int); +void allqueue(unsigned short event, short val); +#define REDRAWVIEW3D 0x4010 +struct Material; +extern struct Material defmaterial; + +/* effect.c */ +void RE_jitterate1(float *jit1, float *jit2, int num, float rad1); +void RE_jitterate2(float *jit1, float *jit2, int num, float rad2); + +/* exotic.c */ +void load_editMesh(void); +void make_editMesh(void); +void free_editMesh(void); +void free_editArmature(void); +void docentre_new(void); +int saveover(char *str); + +/* image.c */ +#include "DNA_image_types.h" +void free_realtime_image(Image *ima); // has to become a callback, opengl stuff +void RE_make_existing_file(char *name); // from render, but these funcs should be moved anyway + +/* ipo.c */ +void copy_view3d_lock(short val); // was a hack, to make scene layer ipo's possible + +/* library.c */ +void allspace(unsigned short event, short val) ; +#define OOPS_TEST 2 + +/* mball.c */ +extern ListBase editelems; + +/* object.c */ +/* void BPY_free_scriptlink(ScriptLink *slink); */ +/* void BPY_copy_scriptlink(ScriptLink *scriptlink); */ +float *give_cursor(void); // become a callback or argument +void exit_posemode(int freedata); + +/* packedFile.c */ +short pupmenu(char *instr); // will be general callback + +/* sca.c */ +#define LEFTMOUSE 0x001 // because of mouse sensor + +/* scene.c */ +#include "DNA_sequence_types.h" +void free_editing(struct Editing *ed); // scenes and sequences problem... + +/* texture.c */ +#define FLO 128 +#define INT 96 +struct EnvMap; +struct Tex; +void RE_free_envmap(struct EnvMap *env); +struct EnvMap *RE_copy_envmap(struct EnvMap *env); +void RE_free_envmapdata(struct EnvMap *env); +int RE_envmaptex(struct Tex *tex, float *texvec, float *dxt, float *dyt); +void RE_calc_R_ref(void); +extern char texstr[15][8]; /* buttons.c */ + +/* memory for O is declared in the render module... */ +#include "BKE_osa_types.h" +extern Osa O; + +/* editsca.c */ +void make_unique_prop_names(char *str); + +#endif + diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h new file mode 100644 index 00000000000..db38a85bfcd --- /dev/null +++ b/source/blender/blenkernel/BKE_blender.h @@ -0,0 +1,64 @@ +/** + * blenlib/BKE_blender.h (mar-2001 nzc) + * + * Blender util stuff? + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_BLENDER_H +#define BKE_BLENDER_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct ListBase; + +#define BLENDER_VERSION 225 + +int BKE_read_file(char *dir, void *type_r); +int BKE_read_file_from_memory(char* filebuf, int filelength, void *type_r); + +void duplicatelist(struct ListBase *list1, struct ListBase *list2); +void free_blender(void); +void initglobals(void); + +void pushdata(void *data, int len); +void popfirst(void *data); +void poplast(void *data); +void free_pushpop(void); +void pushpop_test(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/blender/blenkernel/BKE_bmfont.h b/source/blender/blenkernel/BKE_bmfont.h new file mode 100644 index 00000000000..5fc9045d05e --- /dev/null +++ b/source/blender/blenkernel/BKE_bmfont.h @@ -0,0 +1,64 @@ +/** + * blenlib/BKE_bmfont.h (mar-2001 nzc) + * + * + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_BMFONT_H +#define BKE_BMFONT_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct bmGlyph; +struct ImBuf; +struct bmFont; + +void printfGlyph(struct bmGlyph * glyph); +void calcAlpha(struct ImBuf * ibuf); +void readBitmapFontVersion0(struct ImBuf * ibuf, + unsigned char * rect, + int step); +void detectBitmapFont(struct ImBuf *ibuf); +int locateGlyph(struct bmFont *bmfont, unsigned short unicode); +void matrixGlyph(struct ImBuf * ibuf, unsigned short unicode, + float *centerx, float *centery, + float *sizex, float *sizey, + float *transx, float *transy, + float *movex, float *movey, float *advance); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/blender/blenkernel/BKE_bmfont_types.h b/source/blender/blenkernel/BKE_bmfont_types.h new file mode 100644 index 00000000000..84fa16779dd --- /dev/null +++ b/source/blender/blenkernel/BKE_bmfont_types.h @@ -0,0 +1,61 @@ +/** + * blenlib/BKE_bmfont_types.h (mar-2001 nzc) + * + * + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_BMFONT_TYPES_H +#define BKE_BMFONT_TYPES_H + +#define is_power_of_two(N) ((N ^ (N - 1)) == (2 * N - 1)) +/* +Moved to IMB_imbuf_types.h where it will live close to the ImBuf type. +It is used as a userflag bit mask. +#define IB_BITMAPFONT 1 +*/ +typedef struct bmGlyph { + unsigned short unicode; + short locx, locy; + signed char ofsx, ofsy; + unsigned char sizex, sizey; + unsigned char advance, reserved; +} bmGlyph; + +typedef struct bmFont { + char magic[4]; + short version; + short glyphcount; + short xsize, ysize; + bmGlyph glyphs[1]; +} bmFont; + +#endif diff --git a/source/blender/blenkernel/BKE_booleanops.h b/source/blender/blenkernel/BKE_booleanops.h new file mode 100644 index 00000000000..df1906a2c70 --- /dev/null +++ b/source/blender/blenkernel/BKE_booleanops.h @@ -0,0 +1,143 @@ +/** + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_BOOLEANOPS_H +#define BKE_BOOLEANOPS_H + + +struct Mesh; +struct Object; +struct Base; +struct CSG_FaceIteratorDescriptor; +struct CSG_VertexIteratorDescriptor; +struct CSG_MeshPropertyDescriptor; + +/** + * Perform a boolean operation between 2 mesh objects and + * add the result as a new mesh into blender data structures. + * Assumes you have checked that the 2 objects are infact mesh + * objects. Returns 1 on success and zero when it encountered + * a problem. In the latter case no object is added and you should + * report an appropriate error. + */ +extern + int +NewBooleanMesh( + struct Base * base, + struct Base * base_select, + int op_type +); + + +/** + * Functions exposed for use by BKE_booleanops_mesh + */ + +/** + * Returns pointers to new mesh descriptors for + * the given mesh. Make sure you call FreeMeshDescriptors + * after calling this function. + */ + +extern + void +BuildMeshDescriptors( + struct Object * ob, + struct CSG_FaceIteratorDescriptor * face_it, + struct CSG_VertexIteratorDescriptor * vertex_it +); + +extern + void +FreeMeshDescriptors( + struct CSG_FaceIteratorDescriptor * face_it, + struct CSG_VertexIteratorDescriptor * vertex_it +); + +extern + int +ConvertCSGDescriptorsToMeshObject( + struct Object *ob, + struct CSG_MeshPropertyDescriptor * props, + struct CSG_FaceIteratorDescriptor * face_it, + struct CSG_VertexIteratorDescriptor * vertex_it, + float parinv[][4] +); + +/** + * This little function adds a new mesh object + * to the blender object list. It uses ob to duplicate + * data as this seems to be easier than cerating a new one. + * This new oject contains no faces nor vertices. + */ + +extern + struct Object * +AddNewBlenderMesh( + struct Base *base +); + +extern + int +InterpNoUserData( + void *d1, + void *d2, + void *dnew, + float epsilon +); + +extern + int +InterpFaceVertexData( + void *d1, + void *d2, + void *dnew, + float epsilon +); + +typedef struct { + float uv[2]; + float color[4]; +} FaceVertexData; + +typedef struct { + struct Material *material; + + /* assorted tface flags */ + void *tpage; + char flag, transp; + short mode, tile; +} FaceData; + + + + +#endif diff --git a/source/blender/blenkernel/BKE_booleanops_mesh.h b/source/blender/blenkernel/BKE_booleanops_mesh.h new file mode 100644 index 00000000000..9a92df9e3b1 --- /dev/null +++ b/source/blender/blenkernel/BKE_booleanops_mesh.h @@ -0,0 +1,122 @@ +/** + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_PyBooleanOps_h +#define BKE_PyBooleanOps_h + +#include "CSG_BooleanOps.h" + +/** + * Internal mesh structure. + * Safe to copy by value... hopefully. + */ + +struct Base; +struct Object; +struct CSG_MeshDescriptor; + +typedef void (*CSG_DestroyMeshFunc)(struct CSG_MeshDescriptor *); + +typedef struct CSG_MeshDescriptor { + struct Base *base; // Ptr to base of original blender object - used in creating a new object + CSG_MeshPropertyDescriptor m_descriptor; + CSG_FaceIteratorDescriptor m_face_iterator; + CSG_VertexIteratorDescriptor m_vertex_iterator; + CSG_DestroyMeshFunc m_destroy_func; +} CSG_MeshDescriptor; + + +extern + int +CSG_LoadBlenderMesh( + struct Object * obj, + CSG_MeshDescriptor *output +); + +/** + * Destroy the contents of a mesh descriptor. + * If the internal descriptor refers to a blender + * mesh, no action is performed apart from freeing + * internal memory in the desriptor. + */ + +extern + void +CSG_DestroyMeshDescriptor( + CSG_MeshDescriptor *mesh +); + +/** + * Perform a boolean operation between 2 meshes and return the + * result as a new mesh descriptor. + * op_type is an integer code of the boolean operation type. + * 1 = intersection, + * 2 = union, + * 3 = difference. + */ + +extern + int +CSG_PerformOp( + CSG_MeshDescriptor *mesh1, + CSG_MeshDescriptor *mesh2, + int op_type, + CSG_MeshDescriptor *output +); + + + +/** + * Add a mesh to blender as a new object. + */ + +extern + int +CSG_AddMeshToBlender( + CSG_MeshDescriptor *mesh +); + +/** + * Test functionality. + */ + +extern + int +NewBooleanMeshTest( + struct Base * base, + struct Base * base_select, + int op_type +); + + + + +#endif diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h new file mode 100644 index 00000000000..2cc323c14ff --- /dev/null +++ b/source/blender/blenkernel/BKE_constraint.h @@ -0,0 +1,64 @@ +/** + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef BKE_CONSTRAINT_H +#define BKE_CONSTRAINT_H + +struct bConstraint; +struct Object; +struct ListBase; +struct bConstraintChannel; +struct bAction; +struct bArmature; + +/* Function prototypes */ +void evaluate_constraint (struct bConstraint *constraint, struct Object *ob, short ownertype, void *ownerdata, float targetmat[][4]); +void free_constraints (struct ListBase *conlist); +void copy_constraints (struct ListBase *dst, struct ListBase *src); +void *copy_constraint_channels (ListBase *dst, ListBase *src); +struct bConstraintChannel *clone_constraint_channels (struct ListBase *dst, struct ListBase *src, struct bConstraintChannel *oldact); +void relink_constraints (struct ListBase *list); +void free_constraint_data (struct bConstraint *con); +void clear_object_constraint_status (struct Object *ob); +void do_constraint_channels (struct ListBase *conbase, struct ListBase *chanbase, float ctime); +short get_constraint_target (struct bConstraint *con, short ownertype, void *ownerdata, float mat[][4], float size[3], float time); +struct bConstraintChannel *find_constraint_channel (ListBase *list, const char *name); +void free_constraint_channels (ListBase *chanbase); + +/* Constraint target/owner types */ +#define TARGET_OBJECT 1 // string is "" +#define TARGET_BONE 2 // string is bone-name +#define TARGET_VERT 3 // string is "VE:#" +#define TARGET_FACE 4 // string is "FA:#" +#define TARGET_CV 5 // string is "CV:#" + +#endif diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h new file mode 100644 index 00000000000..7325594394a --- /dev/null +++ b/source/blender/blenkernel/BKE_curve.h @@ -0,0 +1,86 @@ +/** + * blenlib/BKE_curve.h (mar-2001 nzc) + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_CURVE_H +#define BKE_CURVE_H + +struct Curve; +struct ListBase; +struct Object; +struct Nurb; +struct ListBase; +struct BezTriple; +struct BevList; + + +int copyintoExtendedArray(float *old, int oldx, int oldy, float *newp, int newx, int newy); +void unlink_curve( struct Curve *cu); +void free_curve( struct Curve *cu); +struct Curve *add_curve(int type); +struct Curve *copy_curve( struct Curve *cu); +void make_local_curve( struct Curve *cu); +void test_curve_type( struct Object *ob); +void tex_space_curve( struct Curve *cu); +int count_curveverts( struct ListBase *nurb); +void freeNurb( struct Nurb *nu); +void freeNurblist( struct ListBase *lb); +struct Nurb *duplicateNurb( struct Nurb *nu); +void duplicateNurblist( struct ListBase *lb1, struct ListBase *lb2); +void test2DNurb( struct Nurb *nu); +void minmaxNurb( struct Nurb *nu, float *min, float *max); +void extend_spline(float * pnts, int in, int out); +void calcknots(float *knots, short aantal, short order, short type); +void makecyclicknots(float *knots, short pnts, short order); +void makeknots( struct Nurb *nu, short uv, short type); +void basisNurb(float t, short order, short pnts, float *knots, float *basis, int *start, int *end); +void makeNurbfaces( struct Nurb *nu, float *data); +void makeNurbcurve_forw(struct Nurb *nu, float *data); +void makeNurbcurve( struct Nurb *nu, float *data, int dim); +void maakbez(float q0, float q1, float q2, float q3, float *p, int it); +void make_orco_surf( struct Curve *cu); +void makebevelcurve( struct Object *ob, struct ListBase *disp); +short bevelinside(struct BevList *bl1,struct BevList *bl2); +int vergxcobev(const void *a1, const void *a2); +void calc_bevel_sin_cos(float x1, float y1, float x2, float y2, float *sina, float *cosa); +void alfa_bezpart( struct BezTriple *prevbezt, struct BezTriple *bezt, struct Nurb *nu, float *data_a); +void makeBevelList( struct Object *ob); +void calchandleNurb( struct BezTriple *bezt, struct BezTriple *prev, struct BezTriple *next, int mode); +void calchandlesNurb( struct Nurb *nu); +void testhandlesNurb( struct Nurb *nu); +void autocalchandlesNurb( struct Nurb *nu, int flag); +void autocalchandlesNurb_all(int flag); +void sethandlesNurb(short code); +void swapdata(void *adr1, void *adr2, int len); +void switchdirectionNurb( struct Nurb *nu); + +#endif diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h new file mode 100644 index 00000000000..e7494f28fc4 --- /dev/null +++ b/source/blender/blenkernel/BKE_deform.h @@ -0,0 +1,50 @@ +/* BKE_deform.h June 2001 + * + * support for deformation groups + * + * Reevan McKay + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef BKE_DEFORM_H +#define BKE_DEFORM_H + +struct Object; +struct ListBase; +struct bDeformGroup; + +void copy_defgroups (struct ListBase *lb1, struct ListBase *lb2); +struct bDeformGroup* copy_defgroup (struct bDeformGroup *ingroup); +void color_temperature (float input, unsigned char *r, unsigned char *g, unsigned char *b); + +#endif + diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h new file mode 100644 index 00000000000..8942a6712d6 --- /dev/null +++ b/source/blender/blenkernel/BKE_displist.h @@ -0,0 +1,117 @@ +/* display list (or rather multi purpose list) stuff */ +/* + $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + +*/ + +#ifndef BKE_DISPLIST_H +#define BKE_DISPLIST_H + + +#define DL_POLY 0 +#define DL_SEGM 1 +#define DL_SURF 2 +#define DL_TRIA 3 +#define DL_INDEX3 4 +#define DL_INDEX4 5 +#define DL_VERTCOL 6 +#define DL_VERTS 7 +#define DL_NORS 8 +#define DL_MESH 9 + +/* EVIL: #define DL_SURFINDEX(cyclu, cyclv, sizeu, sizev) */ + +/* prototypes */ + +struct Object; +struct Curve; +struct ListBase; +struct Material; +struct Bone; +struct TFace; + +typedef struct DispListMesh DispListMesh; +struct DispListMesh { + int totvert, totface; + struct MVert *mvert; + struct MCol *mcol; + struct MFaceInt *mface; + struct TFace *tface; +}; + +/* + * All the different DispList.type's use the + * data in the displist structure in fairly + * different ways which can be rather confusing, + * the best thing to do would be to make a structure + * for each displaylist type that has the fields + * needed w/ proper names, and then make the actual + * DispList structure a typed union. + * - zr + */ + +/* needs splitting! */ +typedef struct DispList { + struct DispList *next, *prev; + short type, flag; + int parts, nr; + short col, rt; /* rt wordt gebruikt door initrenderNurbs */ + float *verts, *nors; + int *index; + unsigned int *col1, *col2; + struct DispListMesh *mesh; + + /* Begin NASTY_NLA_STUFF */ +// int *offset, *run; /* Used to index into the bone & weight lists */ +// struct Bone *bones; +// float *weights; + /* End NASTY_NLA_STUFF */ +} DispList; + +extern void copy_displist(struct ListBase *lbn, struct ListBase *lb); +extern void free_disp_elem(DispList *dl); +extern void free_displist_by_type(struct ListBase *lb, int type); +extern DispList *find_displist_create(struct ListBase *lb, int type); +extern DispList *find_displist(struct ListBase *lb, int type); +extern void addnormalsDispList(struct Object *ob, struct ListBase *lb); +extern void count_displist(struct ListBase *lb, int *totvert, int *totface); +extern void curve_to_filledpoly(struct Curve *cu, struct ListBase *dispbase); +extern void freedisplist(struct ListBase *lb); +extern void makeDispList(struct Object *ob); +extern void set_displist_onlyzero(int val); +extern void shadeDispList(struct Object *ob); +void freefastshade(void); +void boundbox_displist(struct Object *ob); +void imagestodisplist(void); +void reshadeall_displist(void); +void test_all_displists(void); + +#endif diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h new file mode 100644 index 00000000000..23d504d0607 --- /dev/null +++ b/source/blender/blenkernel/BKE_effect.h @@ -0,0 +1,65 @@ +/** + * blenlib/BKE_effect.h (mar-2001 nzc) + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_EFFECT_H +#define BKE_EFFECT_H + +struct Effect; +struct ListBase; +struct Object; +struct PartEff; +struct MTex; +struct Mesh; +struct WaveEff; +struct Particle; + +struct Effect *add_effect(int type); +void free_effect(struct Effect *eff); +void free_effects(struct ListBase *lb); +struct Effect *copy_effect(struct Effect *eff); +void copy_act_effect(struct Object *ob); +void copy_effects(struct ListBase *lbn, struct ListBase *lb); +void deselectall_eff(struct Object *ob); +void set_buildvars(struct Object *ob, int *start, int *end); +struct Particle *new_particle(struct PartEff *paf); +struct PartEff *give_parteff(struct Object *ob); +void where_is_particle(struct PartEff *paf, struct Particle *pa, float ctime, float *vec); +void particle_tex(struct MTex *mtex, struct PartEff *paf, float *co, float *no); +void make_particle_keys(int depth, int nr, struct PartEff *paf, struct Particle *part, float *force, int deform, struct MTex *mtex); +void init_mv_jit(float *jit, int num); +void give_mesh_mvert(struct Mesh *me, int nr, float *co, short *no); +void build_particle_system(struct Object *ob); +void calc_wave_deform(struct WaveEff *wav, float ctime, float *co); +void object_wave(struct Object *ob); + +#endif diff --git a/source/blender/blenkernel/BKE_endian.h b/source/blender/blenkernel/BKE_endian.h new file mode 100644 index 00000000000..a675ad893c4 --- /dev/null +++ b/source/blender/blenkernel/BKE_endian.h @@ -0,0 +1,46 @@ +/** + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * Are we little or big endian? From Harbison&Steele. + * BKE_ENDIANNESS(a) returns 1 if big endian and returns 0 if little endian + */ +#ifndef BKE_ENDIAN_H +#define BKE_ENDIAN_H + +#define BKE_ENDIANNESS(a) { \ + union { \ + long l; \ + char c[sizeof (long)]; \ + } u; \ + u.l = 1; \ + a = (u.c[sizeof (long) - 1] == 1) ? 1 : 0; \ +} + +#endif diff --git a/source/blender/blenkernel/BKE_exotic.h b/source/blender/blenkernel/BKE_exotic.h new file mode 100644 index 00000000000..7223abb11ab --- /dev/null +++ b/source/blender/blenkernel/BKE_exotic.h @@ -0,0 +1,54 @@ +/** + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * dxf/vrml/videoscape external file io function prototypes + */ + +#ifndef BKE_EXOTIC_H +#define BKE_EXOTIC_H + +struct Mesh; + +void mcol_to_rgba(unsigned int col, float *r, float *g, float *b, float *a); +unsigned int *mcol_to_vcol(struct Mesh *me); // used in py_main.c + +/** + * Reads all 3D fileformats other than Blender fileformat + * @retval 0 The file could not be read. + * @retval 1 The file was read succesfully. + * @attention Used in filesel.c + */ +int BKE_read_exotic(char *name); + +void write_dxf(char *str); +void write_vrml(char *str); +void write_videoscape(char *str); + +#endif diff --git a/source/blender/blenkernel/BKE_font.h b/source/blender/blenkernel/BKE_font.h new file mode 100644 index 00000000000..51968182663 --- /dev/null +++ b/source/blender/blenkernel/BKE_font.h @@ -0,0 +1,50 @@ +/** + * blenlib/BKE_vfont.h (mar-2001 nzc) + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_VFONT_H +#define BKE_VFONT_H + +struct VFont; +struct Object; +struct Curve; +struct objfnt; + +void BKE_font_register_builtin(void *mem, int size); + +void free_vfont(struct VFont *sc); +struct VFont *load_vfont(char *name); + +struct chartrans *text_to_curve(struct Object *ob, int mode); +void font_duplilist(struct Object *par); + +#endif diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h new file mode 100644 index 00000000000..53c71f03606 --- /dev/null +++ b/source/blender/blenkernel/BKE_global.h @@ -0,0 +1,224 @@ +/** + * blenlib/BKE_global.h (mar-2001 nzc) + * + * Global settings, handles, pointers. This is the root for finding + * any data in Blender. This block is not serialized, but built anew + * for every fresh Blender run. + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_GLOBAL_H +#define BKE_GLOBAL_H + +#include "DNA_listBase.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* forwards */ +struct View3D; +struct View2D; +struct SpaceIpo; +struct SpaceButs; +struct SpaceImage; +struct SpaceOops; +struct SpaceText; +struct SpaceSound; +struct SpaceAction; +struct SpaceNla; +struct Main; +struct Scene; +struct bScreen; +struct Object; +struct bSoundListener; +struct BMF_Font; + +typedef struct Global { + + /* active pointers */ + struct View3D *vd; + struct View2D *v2d; + struct SpaceIpo *sipo; + struct SpaceButs *buts; + struct SpaceImage *sima; + struct SpaceOops *soops; + struct SpaceSound *ssound; + struct SpaceAction *saction; /* __NLA */ + struct SpaceNla *snla; + struct Main *main; + struct Scene *scene; /* denk aan file.c */ + struct bScreen *curscreen; + struct Object *obedit; + + /* fonts, allocated global data */ + struct BMF_Font *font, *fonts, *fontss; + + /* strings: lastsaved */ + char ima[160], sce[160], lib[160]; + + /* totalen */ + short totobj, totlamp, totobjsel, totcurve, totmesh, totmat; + int totvert, totface, totvertsel, totfacesel; + + short machine, afbreek, moving, colact, zbuf; + short qual, background, imagewin, animspeed; + /** + * The current version of Blender. + */ + short version; + short simulf, fields, order, rt; + int f; + + /* Editmode lists */ + struct ListBase edve; + struct ListBase eded; + struct ListBase edvl; + + float textcurs[4][2]; + + /* Frank's variables */ + int renderd; + int real_sfra, real_efra; + int save_over; + + /* Reevan's __NLA variables */ + struct Object *obpose; /* Current posable object */ + struct ListBase edbo; /* Armature Editmode bones */ + + /* this variable is written to / read from FileGlobal->fileflags */ + int fileflags; + + /* Janco's playing ground */ + struct bSoundListener* listener; + + /* Test thingy for Nzc */ + int magic; /* toggle use of experimental render pipe */ + int compat; /* toggle compatibility mode for edge rendering */ + int notonlysolid;/* T-> also edge-render transparent faces */ + int useRscale; /* bitflag for using colour scaling */ + int useGscale; /* bitflag for using colour scaling */ + int useBscale; /* bitflag for using colour scaling */ + float cscale[4]; /* sliders for colour scaling */ + int Rhisto; /* flags for making histograms */ + int Ghisto; + int Bhisto; + + /* special versions */ + short special1, special2; + + int flags; + +} Global; + +/* **************** GLOBAL ********************* */ + +/* G.f */ +#define G_DISABLE_OK 1 +#define G_PLAYANIM 2 +#define G_TEST_DUPLI 4 +#define G_SIMULATION 8 +#define G_BACKBUFSEL 16 +#define G_PICKSEL 32 +#define G_DRAWNORMALS 64 +#define G_DRAWFACES 128 +#define G_FACESELECT 256 +#define G_DRAW_EXT 512 +#define G_VERTEXPAINT 1024 +#define G_ALLEDGES 2048 +#define G_DEBUG 4096 +#define G_SCENESCRIPT 8192 +#define G_PROPORTIONAL 16384 +#define G_WEIGHTPAINT 32768 /* __NLA */ +#define G_TEXTUREPAINT 65536 +#define G_NOFROZEN (1 << 17) // frozen modules inactive + +/* G.fileflags */ + +#define G_AUTOPACK_BIT 0 +#define G_FILE_COMPRESS_BIT 1 +#define G_FILE_AUTOPLAY_BIT 2 +#define G_FILE_ENABLE_ALL_FRAMES_BIT 3 +#define G_FILE_SHOW_DEBUG_PROPS_BIT 4 +#define G_FILE_SHOW_FRAMERATE_BIT 5 +#define G_FILE_SHOW_PROFILE_BIT 6 +#define G_FILE_LOCK_BIT 7 +#define G_FILE_SIGN_BIT 8 +#define G_FILE_PUBLISH_BIT 9 + +#define G_AUTOPACK (1 << G_AUTOPACK_BIT) +#define G_FILE_COMPRESS (1 << G_FILE_COMPRESS_BIT) +#define G_FILE_AUTOPLAY (1 << G_FILE_AUTOPLAY_BIT) +#define G_FILE_ENABLE_ALL_FRAMES (1 << G_FILE_ENABLE_ALL_FRAMES_BIT) +#define G_FILE_SHOW_DEBUG_PROPS (1 << G_FILE_SHOW_DEBUG_PROPS_BIT) +#define G_FILE_SHOW_FRAMERATE (1 << G_FILE_SHOW_FRAMERATE_BIT) +#define G_FILE_SHOW_PROFILE (1 << G_FILE_SHOW_PROFILE_BIT) +#define G_FILE_LOCK (1 << G_FILE_LOCK_BIT) +#define G_FILE_SIGN (1 << G_FILE_SIGN_BIT) +#define G_FILE_PUBLISH (1 << G_FILE_PUBLISH_BIT) + +/* G.simulf */ +#define G_LOADFILE 2 +#define G_RESTART 4 +#define G_QUIT 8 +#define G_SETSCENE 16 + +/* G.flags: double? */ +#define G_FLAGS_AUTOPLAY_BIT 2 +#define G_FLAGS_AUTOPLAY (1 << G_FLAGS_AUTOPLAY_BIT) + +/* G.qual */ +#define R_SHIFTKEY 1 +#define L_SHIFTKEY 2 +#define LR_SHIFTKEY 3 +#define R_ALTKEY 4 +#define L_ALTKEY 8 +#define LR_ALTKEY 12 +#define R_CTRLKEY 16 +#define L_CTRLKEY 32 +#define LR_CTRLKEY 48 + +/* G.order: indicates what endianness the platform where the file was + * written had. */ +#define L_ENDIAN 1 +#define B_ENDIAN 0 + +/* G.special1 */ +#define G_HOLO 1 + +/* Memory is allocated where? blender.c */ +extern Global G; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h new file mode 100644 index 00000000000..ef000e2c370 --- /dev/null +++ b/source/blender/blenkernel/BKE_group.h @@ -0,0 +1,58 @@ +/** + * blenlib/BKE_group.h (mar-2001 nzc) + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_GROUP_H +#define BKE_GROUP_H +struct Group; +struct GroupKey; +struct GroupObject; +struct ObjectKey; +struct Object; + +void free_object_key(struct ObjectKey *ok); +void free_group_object(struct GroupObject *go); +void free_group(struct Group *group); +struct Group *add_group(void); +void object_to_obkey(struct Object *ob, struct ObjectKey *ok); +void obkey_to_object(struct ObjectKey *ok, struct Object *ob); +void add_object_key(struct GroupObject *go, struct GroupKey *gk); +void add_to_group(struct Group *group, struct Object *ob); +void rem_from_group(struct Group *group, struct Object *ob); +void add_group_key(struct Group *group); +void set_object_key(struct Object *ob, struct ObjectKey *ok); +void set_group_key(struct Group *group); +struct Group *find_group(struct Object *ob); +void set_group_key_name(struct Group *group, char *name); +void set_group_key_frame(struct Group *group, float frame); + +#endif diff --git a/source/blender/blenkernel/BKE_ika.h b/source/blender/blenkernel/BKE_ika.h new file mode 100644 index 00000000000..053414d9359 --- /dev/null +++ b/source/blender/blenkernel/BKE_ika.h @@ -0,0 +1,59 @@ +/** + * blenlib/BKE_ika.h (mar-2001 nzc) + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_IKA_H +#define BKE_IKA_H + +struct Ika; +struct Limb; +struct Object; + +void unlink_ika(struct Ika *ika); +void free_ika(struct Ika *ika); +struct Ika *add_ika(void); +struct Ika *copy_ika(struct Ika *ika); +void make_local_ika(struct Ika *ika); +int count_limbs(struct Object *ob); +void calc_limb(struct Limb *li); +void calc_ika(struct Ika *ika, struct Limb *li); +void init_defstate_ika(struct Object *ob); +void itterate_limb(struct Ika *ika, struct Limb *li); +void rotate_ika(struct Object *ob, struct Ika *ika); +void rotate_ika_xy(struct Object *ob, struct Ika *ika); +void itterate_ika(struct Object *ob); +void do_all_ikas(void); +void do_all_visible_ikas(void); +void init_skel_deform(struct Object *par, struct Object *ob); +void calc_skel_deform(struct Ika *ika, float *co); + +#endif diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h new file mode 100644 index 00000000000..4783b66706a --- /dev/null +++ b/source/blender/blenkernel/BKE_image.h @@ -0,0 +1,67 @@ +/** + * blenlib/BKE_image.h (mar-2001 nzc) + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_IMAGE_H +#define BKE_IMAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct Image; +struct ImBuf; +struct Tex; +struct anim; + +void free_image(struct Image *me); +void free_image_buffers(struct Image *ima); +struct Image *add_image(char *name); +void free_unused_animimages(void); +void makepicstring(char *string, int frame); +struct anim *openanim(char * name, int flags); +int calcimanr(int cfra, struct Tex *tex); +void do_laseroptics_patch(struct ImBuf *ibuf); +void de_interlace_ng(struct ImBuf *ibuf); +void de_interlace_st(struct ImBuf *ibuf); +void load_image(struct Image * ima, int flags, char *relabase, int framenum); +void ima_ibuf_is_nul(struct Tex *tex); +int imagewrap(struct Tex *tex, float *texvec); +int imagewraposa(struct Tex *tex, float *texvec, float *dxt, float *dyt); +void converttopremul(struct ImBuf *ibuf); +void makemipmap(struct Image *ima); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/blender/blenkernel/BKE_ipo.h b/source/blender/blenkernel/BKE_ipo.h new file mode 100644 index 00000000000..4a68884d53c --- /dev/null +++ b/source/blender/blenkernel/BKE_ipo.h @@ -0,0 +1,101 @@ +/** + * blenlib/BKE_ipo.h (mar-2001 nzc) + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_IPO_H +#define BKE_IPO_H + +typedef struct CfraElem { + struct CfraElem *next, *prev; + float cfra; + int sel; +} CfraElem; + +struct Ipo; +struct IpoCurve; +struct MTex; +struct Material; +struct Object; +struct Sequence; +struct ListBase; +struct BezTriple; +/* struct IPO_Channel; */ + +float frame_to_float(int cfra); +void free_ipo(struct Ipo *ipo); +struct Ipo *add_ipo(char *name, int idcode); +struct Ipo *copy_ipo(struct Ipo *ipo); +void make_local_obipo(struct Ipo *ipo); +void make_local_matipo(struct Ipo *ipo); +void make_local_keyipo(struct Ipo *ipo); +void make_local_ipo(struct Ipo *ipo); +void calchandles_ipocurve(struct IpoCurve *icu); +void testhandles_ipocurve(struct IpoCurve *icu); +void sort_time_ipocurve(struct IpoCurve *icu); +int test_time_ipocurve(struct IpoCurve *icu); +void correct_bezpart(float *v1, float *v2, float *v3, float *v4); +int findzero(float x, float q0, float q1, float q2, float q3, float *o); +void berekeny(float f1, float f2, float f3, float f4, float *o, int b); +void berekenx(float *f, float *o, int b); +float eval_icu(struct IpoCurve *icu, float ipotime); +void calc_icu(struct IpoCurve *icu, float ctime); +float calc_ipo_time(struct Ipo *ipo, float ctime); +void calc_ipo(struct Ipo *ipo, float ctime); +void write_ipo_poin(void *poin, int type, float val); +float read_ipo_poin(void *poin, int type); +void *give_mtex_poin(struct MTex *mtex, int adrcode ); +void *get_ipo_poin(struct ID *id, struct IpoCurve *icu, int *type); +void set_icu_vars(struct IpoCurve *icu); +void execute_ipo(struct ID *id, struct Ipo *ipo); +void do_ipo_nocalc(struct Ipo *ipo); +void do_ipo(struct Ipo *ipo); +void do_mat_ipo(struct Material *ma); +void do_ob_ipo(struct Object *ob); +void do_seq_ipo(struct Sequence *seq); +int has_ipo_code(struct Ipo *ipo, int code); +void do_all_ipos(void); +int calc_ipo_spec(struct Ipo *ipo, int adrcode, float *ctime); +void clear_delta_obipo(struct Ipo *ipo); +void add_to_cfra_elem(struct ListBase *lb, struct BezTriple *bezt); +void make_cfra_list(struct Ipo *ipo, struct ListBase *elems); +/* the sort is an IPO_Channel... */ +int IPO_GetChannels(struct Ipo *ipo, short *channels); +void test_ipo_get(void); + +float IPO_GetFloatValue(struct Ipo *ipo, +/* struct IPO_Channel channel, */ + /* channels are shorts... bit ugly for now*/ + short c, + float ctime); + + +#endif diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h new file mode 100644 index 00000000000..4ad76e3943c --- /dev/null +++ b/source/blender/blenkernel/BKE_key.h @@ -0,0 +1,69 @@ +/** + * blenlib/BKE_key.h (mar-2001 nzc) + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_KEY_H +#define BKE_KEY_H + +struct Key; +struct KeyBlock; +struct ID; +struct ListBase; +struct Curve; +struct Object; +struct Lattice; +struct Mesh; + +void free_key(struct Key *sc); +struct Key *add_key(struct ID *id); +struct Key *copy_key(struct Key *key); +void make_local_key(struct Key *key); +void sort_keys(struct Key *key); +void set_four_ipo(float d, float *data, int type); +void set_afgeleide_four_ipo(float d, float *data, int type); +int setkeys(float fac, struct ListBase *lb, struct KeyBlock *k[], float *t, int cycl); +void flerp(int aantal, float *in, float *f0, float *f1, float *f2, float *f3, float *t); +void cp_key(int start, int end, int tot, char *poin, struct Key *key, struct KeyBlock *k, int mode); +void cp_cu_key(struct Curve *cu, struct KeyBlock *kb, int start, int end); +void rel_flerp(int aantal, float *in, float *ref, float *out, float fac); +void do_rel_key(int start, int end, int tot, char *basispoin, struct Key *key, float ctime, int mode); +void do_key(int start, int end, int tot, char *poin, struct Key *key, struct KeyBlock **k, float *t, int mode); +void do_mesh_key(struct Mesh *me); +void do_cu_key(struct Curve *cu, struct KeyBlock **k, float *t); +void do_rel_cu_key(struct Curve *cu, float ctime); +void do_curve_key(struct Curve *cu); +void do_latt_key(struct Lattice *lt); +void do_all_keys(void); +void do_ob_key(struct Object *ob); +void do_spec_key(struct Key *key); + +#endif diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h new file mode 100644 index 00000000000..747dc27e175 --- /dev/null +++ b/source/blender/blenkernel/BKE_lattice.h @@ -0,0 +1,59 @@ +/** + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * june-2001 ton + */ + +#ifndef BKE_LATTICE_H +#define BKE_LATTICE_H + +struct Lattice; +struct Object; +struct BPoint; + +extern struct Lattice *editLatt; +extern int lt_applyflag; + + +void resizelattice(struct Lattice *lt); +struct Lattice *add_lattice(void); +struct Lattice *copy_lattice(struct Lattice *lt); +void free_lattice(struct Lattice *lt); +void make_local_lattice(struct Lattice *lt); +void calc_lat_fudu(int flag, int res, float *fu, float *du); +void init_latt_deform(struct Object *oblatt, struct Object *ob); +void calc_latt_deform(float *co); +void end_latt_deform(void); +int object_deform(struct Object *ob); +struct BPoint *latt_bp(struct Lattice *lt, int u, int v, int w); +void outside_lattice(struct Lattice *lt); + + +#endif diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h new file mode 100644 index 00000000000..4e8c9a61c19 --- /dev/null +++ b/source/blender/blenkernel/BKE_library.h @@ -0,0 +1,69 @@ +/** + * blenlib/BKE_library.h (mar-2001 nzc) + * + * Library + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_LIBRARY_TYPES_H +#define BKE_LIBRARY_TYPES_H + +struct ListBase; +struct ID; +struct Main; +struct Library; + +void *alloc_libblock(struct ListBase *lb, short type, char *name); +void *copy_libblock(void *rt); + +void id_lib_extern(struct ID *id); +void id_us_plus(struct ID *id); + +int new_id(struct ListBase *lb, struct ID *id, char *name); + +struct ListBase *wich_libbase(struct Main *mainlib, short type); +int set_listbasepointers(struct Main *main, struct ListBase **lb); + +void free_libblock(struct ListBase *lb, void *idv); +void free_libblock_us(struct ListBase *lb, void *idv); +void free_main(struct Main *mainvar); + +void splitIDname(char *name, char *left, int *nr); +void rename_id(struct ID *id, char *name); +void test_idbutton(char *name); +void all_local(void); +struct ID *find_id(char *type, char *name); +void clear_id_newpoins(void); + +void IDnames_to_pupstring(char **str, char *title, char *extraops, struct ListBase *lb,struct ID* link, short *nr); +void IPOnames_to_pupstring(char **str, char *title, char *extraops, struct ListBase *lb, struct ID* link, short *nr, int blocktype); + +#endif diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h new file mode 100644 index 00000000000..2e16db34e00 --- /dev/null +++ b/source/blender/blenkernel/BKE_main.h @@ -0,0 +1,80 @@ +/** + * blenlib/BKE_main.h (mar-2001 nzc) + * + * Main is the root of the 'database' of a Blender context. All data + * is stuffed into lists, and all these lists are knotted to here. A + * Blender file is not much more but a binary dump of these + * lists. This list of lists is not serialized itself. + * + * Oops... this should be a _types.h file. + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_MAIN_H +#define BKE_MAIN_H + +#include "DNA_listBase.h" + +struct Library; + +typedef struct Main { + struct Main *next, *prev; + char name[160]; + short versionfile, rt; + struct Library *curlib; + ListBase scene; + ListBase library; + ListBase object; + ListBase mesh; + ListBase curve; + ListBase mball; + ListBase mat; + ListBase tex; + ListBase image; + ListBase ika; + ListBase wave; + ListBase latt; + ListBase lamp; + ListBase camera; + ListBase ipo; + ListBase key; + ListBase world; + ListBase screen; + ListBase vfont; + ListBase text; + ListBase sound; + ListBase group; + ListBase armature; /* NLA */ + ListBase action; /* NLA */ +} Main; + + +#endif diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h new file mode 100644 index 00000000000..8533505776e --- /dev/null +++ b/source/blender/blenkernel/BKE_material.h @@ -0,0 +1,68 @@ +/** + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * General operations, lookup, etc. for materials. + */ + +#ifndef BKE_MATERIAL_H +#define BKE_MATERIAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct Material; +struct ID; +struct Object; + +void free_material(struct Material *sc); +void test_object_materials(struct ID *id); +void init_material(struct Material *ma); +struct Material *add_material(char *name); +struct Material *copy_material(struct Material *ma); +void make_local_material(struct Material *ma); +struct Material ***give_matarar(struct Object *ob); +short *give_totcolp(struct Object *ob); +struct Material *give_current_material(struct Object *ob, int act); +ID *material_from(struct Object *ob, int act); +void assign_material(struct Object *ob, struct Material *ma, int act); +void new_material_to_objectdata(struct Object *ob); +void init_render_material(struct Material *ma); +void init_render_materials(void); +void end_render_material(struct Material *ma); +void end_render_materials(void); +void automatname(struct Material *ma); +void delete_material_index(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h new file mode 100644 index 00000000000..c04ce03f176 --- /dev/null +++ b/source/blender/blenkernel/BKE_mball.h @@ -0,0 +1,64 @@ +/** + * blenlib/BKE_mball.h (mar-2001 nzc) + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_MBALL_H +#define BKE_MBALL_H + +struct MetaBall; +struct Object; +struct MetaElem; +struct VERTICES; +struct VERTEX; +struct MB_POINT; +struct PROCESS; +struct CUBE; +struct PROCESS; + +void unlink_mball(struct MetaBall *mb); +void free_mball(struct MetaBall *mb); +struct MetaBall *add_mball(void); +struct MetaBall *copy_mball(struct MetaBall *mb); +void make_local_mball(struct MetaBall *mb); +void tex_space_mball( struct Object *ob); +void make_orco_mball( struct Object *ob); +struct Object *find_basis_mball( struct Object *ob); +void metaball_polygonize(struct Object *ob); +void calc_mballco(struct MetaElem *ml, float *vec); +float densfunc(struct MetaElem *ball, float x, float y, float z); +float metaball(float x, float y, float z); +void accum_mballfaces(int i1, int i2, int i3, int i4); +void *new_pgn_element(int size); +int nextcwedge (int edge, int face); +void BKE_freecubetable(void); + +#endif diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h new file mode 100644 index 00000000000..1f551f8afe0 --- /dev/null +++ b/source/blender/blenkernel/BKE_mesh.h @@ -0,0 +1,116 @@ +/** + * blenlib/BKE_mesh.h (mar-2001 nzc) + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_MESH_H +#define BKE_MESH_H + +/* texflag */ +#define AUTOSPACE 1 + +/* me->flag (let op alternatieven in blendpsx.h) */ +#define ME_ISDONE 1 +#define ME_NOPUNOFLIP 2 +#define ME_TWOSIDED 4 +#define ME_UVEFFECT 8 +#define ME_VCOLEFFECT 16 +#define ME_AUTOSMOOTH 32 +#define ME_SMESH 64 +#define ME_SUBSURF 128 + +/* puno (mface) */ +#define ME_FLIPV1 1 +#define ME_FLIPV2 2 +#define ME_FLIPV3 4 +#define ME_FLIPV4 8 +#define ME_PROJXY 16 +#define ME_PROJXZ 32 +#define ME_PROJYZ 64 + +/* edcode (mface) */ +#define ME_V1V2 1 +#define ME_V2V3 2 +#define ME_V3V1 4 +#define ME_V3V4 4 +#define ME_V4V1 8 + +/* flag (mface) */ +#define ME_SMOOTH 1 + +/***/ + +struct DispList; +struct ListBase; +struct MDeformVert; +struct Mesh; +struct MFace; +struct MVert; +struct Object; +struct TFace; +struct VecNor; + +#ifdef __cplusplus +extern "C" { +#endif + +void unlink_mesh(struct Mesh *me); +void free_mesh(struct Mesh *me); +struct Mesh *add_mesh(void); +struct Mesh *copy_mesh(struct Mesh *me); +void make_local_tface(struct Mesh *me); +void make_local_mesh(struct Mesh *me); +void boundbox_mesh(struct Mesh *me, float *loc, float *size); +void tex_space_mesh(struct Mesh *me); +void make_orco_displist_mesh(struct Object *ob, int subdivlvl); +void make_orco_mesh(struct Mesh *me); +void test_index_mface(struct MFace *mface, int nr); +void test_index_face(struct MFace *mface, struct TFace *tface, int nr); +void flipnorm_mesh(struct Mesh *me); +struct Mesh *get_mesh(struct Object *ob); +void set_mesh(struct Object *ob, struct Mesh *me); +void mball_to_mesh(struct ListBase *lb, struct Mesh *me); +void nurbs_to_mesh(struct Object *ob); +void edge_drawflags_mesh(struct Mesh *me); +void mcol_to_tface(struct Mesh *me, int freedata); +void tface_to_mcol(struct Mesh *me); +void free_dverts(struct MDeformVert *dvert, int totvert); +void copy_dverts(struct MDeformVert *dst, struct MDeformVert *src, int totvert); /* __NLA */ +int mesh_uses_displist(struct Mesh *me); +int rendermesh_uses_displist(struct Mesh *me); +float get_mvert_weight (struct Object *ob, int vert, int defgroup); +int update_realtime_texture(struct TFace *tface, double time); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h new file mode 100644 index 00000000000..9f1ad39f7a6 --- /dev/null +++ b/source/blender/blenkernel/BKE_nla.h @@ -0,0 +1,46 @@ +/** + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef BKE_NLA_H +#define BKE_NLA_H + +struct bActionStrip; +struct ListBase; + +void free_actionstrip(struct bActionStrip* strip); +void free_nlastrips (struct ListBase *nlalist); +void copy_nlastrips (struct ListBase *dst, struct ListBase *src); +void copy_actionstrip (struct bActionStrip **dst, struct bActionStrip **src); + +#endif + + diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h new file mode 100644 index 00000000000..b29a051a4db --- /dev/null +++ b/source/blender/blenkernel/BKE_object.h @@ -0,0 +1,99 @@ +/** + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * General operations, lookup, etc. for blender objects. + */ + +#ifndef BKE_OBJECT_H +#define BKE_OBJECT_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct Base; +struct Object; +struct Camera; +struct BoundBox; +struct View3D; + +void clear_workob(void); +void copy_baseflags(void); +void copy_objectflags(void); +void update_base_layer(struct Object *ob); +void free_object(struct Object *ob); +void unlink_object(struct Object *ob); +int exist_object(struct Object *obtest); +void *add_camera(void); +struct Camera *copy_camera(struct Camera *cam); +void make_local_camera(struct Camera *cam); +void *add_lamp(void); +struct Lamp *copy_lamp(struct Lamp *la); +void make_local_lamp(struct Lamp *la); +void free_camera(struct Camera *ca); +void free_lamp(struct Lamp *la); +void *add_wave(void); + +struct Object *add_object(int type); +void base_init_from_view3d(struct Base *base, struct View3D *v3d); + +struct Object *copy_object(struct Object *ob); +void expand_local_object(struct Object *ob); +void make_local_object(struct Object *ob); +void set_mblur_offs(int blur); +void disable_speed_curve(int val); +float bsystem_time(struct Object *ob, struct Object *par, float cfra, float ofs); +void object_to_mat3(struct Object *ob, float mat[][3]); +void object_to_mat4(struct Object *ob, float mat[][4]); +void ob_parcurve(struct Object *ob, struct Object *par, float mat[][4]); +void ob_parlimb(struct Object *ob, struct Object *par, float mat[][4]); +void ob_parbone(struct Object *ob, struct Object *par, float mat[][4]); /* __NLA */ +void give_parvert(struct Object *par, int nr, float *vec); +void ob_parvert3(struct Object *ob, struct Object *par, float mat[][4]); +void set_no_parent_ipo(int val); +void set_dtime(int dtime); +void disable_where_script(short on); +int during_script(void); +void where_is_object_time(struct Object *ob, float ctime); +void where_is_object(struct Object *ob); +void where_is_object_simul(struct Object *ob); +void what_does_parent1(struct Object *par, int partype, int par1, int par2, int par3); +void what_does_parent(struct Object *ob); +struct BoundBox *unit_boundbox(void); +void minmax_object(struct Object *ob, float *min, float *max); +void solve_tracking (struct Object *ob, float targetmat[][4]); +void solve_constraints (struct Object *ob, short obtype, void *obdata, float ctime); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/blender/blenkernel/BKE_osa_types.h b/source/blender/blenkernel/BKE_osa_types.h new file mode 100644 index 00000000000..f6ccf5e7e31 --- /dev/null +++ b/source/blender/blenkernel/BKE_osa_types.h @@ -0,0 +1,53 @@ +/** + * blenlib/BKE_osa_types.h (mar-2001 nzc) + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_OSA_TYPES_H +#define BKE_OSA_TYPES_H + +/* typedef struct Osa */ +typedef struct RE_Osa +{ + float dxco[3], dyco[3]; + float dxlo[3], dylo[3], dxgl[3], dygl[3], dxuv[3], dyuv[3]; + float dxref[3], dyref[3], dxorn[3], dyorn[3]; + float dxno[3], dyno[3], dxview, dyview; + float dxlv[3], dylv[3]; + float dxwin[3], dywin[3]; + float dxsticky[3], dysticky[3]; +} Osa; + +/* extern Osa O; */ +/* This one used to be done in render/extern/include/render.h, because + memory was allocated in that module. (nzc)*/ + +#endif diff --git a/source/blender/blenkernel/BKE_packedFile.h b/source/blender/blenkernel/BKE_packedFile.h new file mode 100644 index 00000000000..16b6c996aab --- /dev/null +++ b/source/blender/blenkernel/BKE_packedFile.h @@ -0,0 +1,61 @@ +/** + * blenlib/BKE_packedFile.h (mar-2001 nzc) + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_PACKEDFILE_H +#define BKE_PACKEDFILE_H + +struct PackedFile; +struct VFont; +struct bSample; +struct bSound; +struct Image; + +struct PackedFile * newPackedFile(char * filename); +struct PackedFile * newPackedFileMemory(void *mem, int memlen); + +int seekPackedFile(struct PackedFile * pf, int offset, int whence); +void rewindPackedFile(struct PackedFile * pf); +int readPackedFile(struct PackedFile * pf, void * data, int size); +int countPackedFiles(void); +void freePackedFile(struct PackedFile * pf); +void packAll(void); +int writePackedFile(char * filename, struct PackedFile *pf); +int checkPackedFile(char * filename, struct PackedFile * pf); +char * unpackFile(char * abs_name, char * local_name, struct PackedFile * pf, int how); +int unpackVFont(struct VFont * vfont, int how); +void create_local_name(char *localname, char *prefix, char *filename); +int unpackSample(struct bSample *sample, int how); +int unpackImage(struct Image * ima, int how); +void unpackAll(int how); + +#endif diff --git a/source/blender/blenkernel/BKE_plugin_types.h b/source/blender/blenkernel/BKE_plugin_types.h new file mode 100644 index 00000000000..3da89561aac --- /dev/null +++ b/source/blender/blenkernel/BKE_plugin_types.h @@ -0,0 +1,70 @@ +/** + * blenlib/BKE_plugin_types.h (mar-2001 nzc) + * + * Renderrecipe and scene decription. The fact that there is a + * hierarchy here is a bit strange, and not desirable. + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_PLUGIN_TYPES_H +#define BKE_PLUGIN_TYPES_H + +struct ImBuf; + +typedef int (*TexDoit)(int, void*, float*, float*, float*); +typedef void (*SeqDoit)(void*, float, float, int, int, + struct ImBuf*, struct ImBuf*, + struct ImBuf*, struct ImBuf*); + +typedef struct VarStruct { + int type; + char name[16]; + float def, min, max; + char tip[80]; +} VarStruct; + +typedef struct _PluginInfo { + char *name; + char *snames; + + int stypes; + int nvars; + VarStruct *varstr; + float *result; + float *cfra; + + void (*init)(void); + void (*callback)(int); + TexDoit tex_doit; + SeqDoit seq_doit; +} PluginInfo; + +#endif diff --git a/source/blender/blenkernel/BKE_property.h b/source/blender/blenkernel/BKE_property.h new file mode 100644 index 00000000000..8dd3f3e085b --- /dev/null +++ b/source/blender/blenkernel/BKE_property.h @@ -0,0 +1,54 @@ +/** + * blenkernel/BKE_property.h (mar-2001 nzc) + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_PROPERTY_H +#define BKE_PROPERTY_H + +struct bProperty; +struct ListBase; +struct Object; + +void free_property(struct bProperty *prop); +void free_properties(struct ListBase *lb); +struct bProperty *copy_property(struct bProperty *prop); +void copy_properties(struct ListBase *lbn, struct ListBase *lbo); +void init_property(struct bProperty *prop); +struct bProperty *new_property(int type); +struct bProperty *get_property(struct Object *ob, char *name); +int compare_property(struct bProperty *prop, char *str); +void set_property(struct bProperty *prop, char *str); +void add_property(struct bProperty *prop, char *str); +void set_property_valstr(struct bProperty *prop, char *str); +void cp_property(struct bProperty *prop1, struct bProperty *prop2); + +#endif diff --git a/source/blender/blenkernel/BKE_sca.h b/source/blender/blenkernel/BKE_sca.h new file mode 100644 index 00000000000..c3ad581852d --- /dev/null +++ b/source/blender/blenkernel/BKE_sca.h @@ -0,0 +1,74 @@ +/** + * blenlib/BKE_sca.h (mar-2001 nzc) + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_SCA_H +#define BKE_SCA_H + +struct Text; +struct bSensor; +struct Object; +struct bController; +struct bActuator; + +void unlink_controller(struct bController *cont); +void unlink_controllers(struct ListBase *lb); +void free_controller(struct bController *cont); +void free_controllers(struct ListBase *lb); + +void unlink_actuator(struct bActuator *act); +void unlink_actuators(struct ListBase *lb); +void free_actuator(struct bActuator *act); +void free_actuators(struct ListBase *lb); + +void free_text_controllers(struct Text *txt); +void free_sensor(struct bSensor *sens); +void free_sensors(struct ListBase *lb); +struct bSensor *copy_sensor(struct bSensor *sens); +void copy_sensors(struct ListBase *lbn, struct ListBase *lbo); +void init_sensor(struct bSensor *sens); +struct bSensor *new_sensor(int type); +struct bController *copy_controller(struct bController *cont); +void copy_controllers(struct ListBase *lbn, struct ListBase *lbo); +void init_controller(struct bController *cont); +struct bController *new_controller(int type); +struct bActuator *copy_actuator(struct bActuator *act); +void copy_actuators(struct ListBase *lbn, struct ListBase *lbo); +void init_actuator(struct bActuator *act); +struct bActuator *new_actuator(int type); +void clear_sca_new_poins_ob(struct Object *ob); +void clear_sca_new_poins(void); +void set_sca_new_poins_ob(struct Object *ob); +void set_sca_new_poins(void); +void sca_remove_ob_poin(struct Object *obt, struct Object *ob); + +#endif diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h new file mode 100644 index 00000000000..ff4b4c6f258 --- /dev/null +++ b/source/blender/blenkernel/BKE_scene.h @@ -0,0 +1,56 @@ +/** + * blenlib/BKE_scene.h (mar-2001 nzc) + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_SCENE_H +#define BKE_SCENE_H + +struct Scene; +struct Object; +struct Base; +struct AviCodecData; + +void free_avicodecdata(struct AviCodecData *acd); +void free_scene(struct Scene *me); +struct Scene *add_scene(char *name); +int object_in_scene(struct Object *ob, struct Scene *sce); +void sort_baselist(struct Scene *sce); +void set_scene_bg(struct Scene *sce); +void set_scene_name(char *name); +int next_object(int val, struct Base **base, struct Object **ob); +struct Object *scene_find_camera(struct Scene *sc); + +struct Base *scene_add_base(struct Scene *sce, struct Object *ob); +void scene_deselect_all(struct Scene *sce); +void scene_select_base(struct Scene *sce, struct Base *selbase); + +#endif diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h new file mode 100644 index 00000000000..b64caa6dfef --- /dev/null +++ b/source/blender/blenkernel/BKE_screen.h @@ -0,0 +1,40 @@ +/** + * blenlib/BKE_screen.h (mar-2001 nzc) + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_SCREEN_H +#define BKE_SCREEN_H + +void free_screen(struct bScreen *sc); + + +#endif diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h new file mode 100644 index 00000000000..3010bc2d87a --- /dev/null +++ b/source/blender/blenkernel/BKE_sound.h @@ -0,0 +1,51 @@ +/** + * sound.h (mar-2001 nzc) + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_SOUND_H +#define BKE_SOUND_H + +struct PackedFile; +struct bSound; +struct bSample; +struct ListBase; + +extern struct ListBase *samples; + +/* void *sound_get_listener(void); implemented in src!also declared there now */ + +void sound_set_packedfile(struct bSample* sample, struct PackedFile* pf); +struct PackedFile* sound_find_packedfile(struct bSound* sound); +void sound_free_sample(struct bSample* sample); +void sound_free_sound(struct bSound* sound); + +#endif diff --git a/source/blender/blenkernel/BKE_subsurf.h b/source/blender/blenkernel/BKE_subsurf.h new file mode 100644 index 00000000000..745ecb0cdd4 --- /dev/null +++ b/source/blender/blenkernel/BKE_subsurf.h @@ -0,0 +1,43 @@ +/* $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_SUBSURF_H +#define BKE_SUBSURF_H + +struct Mesh; +struct Object; +struct Displist; + +void subsurf_to_mesh(struct Object *oldob, struct Mesh *newme); +void subsurf_make_mesh(struct Object *ob, short subdiv); +void subsurf_make_editmesh(struct Object *ob); +struct DispList* subsurf_mesh_to_displist(struct Mesh *me, struct DispList *dl, short subdiv); + +#endif diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h new file mode 100644 index 00000000000..43e3bb76b12 --- /dev/null +++ b/source/blender/blenkernel/BKE_text.h @@ -0,0 +1,128 @@ +/** + * blenlib/BKE_text.h (mar-2001 nzc) + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_TEXT_H +#define BKE_TEXT_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct Text; +struct TextLine; + +void free_text (struct Text *text); +void txt_set_undostate (int u); +int txt_get_undostate (void); +struct Text* add_empty_text (void); +int reopen_text (struct Text *text); +struct Text* add_text (char *file); +struct Text* copy_text (struct Text *ta); + +void txt_free_cut_buffer (void); + +char* txt_to_buf (struct Text *text); +void txt_clean_text (struct Text *text); +void txt_order_cursors (struct Text *text); +int txt_find_string (struct Text *text, char *findstr); +int txt_has_sel (struct Text *text); +int txt_get_span (struct TextLine *from, struct TextLine *to); +void txt_move_up (struct Text *text, short sel); +void txt_move_down (struct Text *text, short sel); +void txt_move_left (struct Text *text, short sel); +void txt_move_right (struct Text *text, short sel); +void txt_move_bof (struct Text *text, short sel); +void txt_move_eof (struct Text *text, short sel); +void txt_move_bol (struct Text *text, short sel); +void txt_move_eol (struct Text *text, short sel); +void txt_move_toline (struct Text *text, unsigned int line, short sel); +void txt_pop_sel (struct Text *text); +void txt_delete_char (struct Text *text); +void txt_copy_sel (struct Text *text); +void txt_sel_all (struct Text *text); +void txt_sel_line (struct Text *text); +void txt_print_cutbuffer (void); +void txt_cut_sel (struct Text *text); +char* txt_sel_to_buf (struct Text *text); +void txt_insert_buf (struct Text *text, char *in_buffer); +void txt_paste (struct Text *text); +void txt_print_undo (struct Text *text); +void txt_undo_add_toop (struct Text *text, int op, unsigned int froml, unsigned short fromc, unsigned int tol, unsigned short toc); +void txt_do_undo (struct Text *text); +void txt_do_redo (struct Text *text); +void txt_split_curline (struct Text *text); +void txt_backspace_char (struct Text *text); +int txt_add_char (struct Text *text, char add); + + +/* Undo opcodes */ + +/* Simple main cursor movement */ +#define UNDO_CLEFT 001 +#define UNDO_CRIGHT 002 +#define UNDO_CUP 003 +#define UNDO_CDOWN 004 + +/* Simple selection cursor movement */ +#define UNDO_SLEFT 005 +#define UNDO_SRIGHT 006 +#define UNDO_SUP 007 +#define UNDO_SDOWN 021 + +/* Complex movement (opcode is followed + * by 4 character line ID + a 2 character + * position ID and opcode (repeat)) */ +#define UNDO_CTO 022 +#define UNDO_STO 023 + +/* Complex editing (opcode is followed + * by 1 character ID and opcode (repeat)) */ +#define UNDO_INSERT 024 +#define UNDO_BS 025 +#define UNDO_DEL 026 + +/* Text block (opcode is followed + * by 4 character length ID + the text + * block itself + the 4 character length + * ID (repeat) and opcode (repeat)) */ +#define UNDO_DBLOCK 027 /* Delete block */ +#define UNDO_IBLOCK 030 /* Insert block */ + +/* Misc */ +#define UNDO_SWAP 031 /* Swap cursors */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h new file mode 100644 index 00000000000..172afcaecd6 --- /dev/null +++ b/source/blender/blenkernel/BKE_texture.h @@ -0,0 +1,85 @@ +/** + * blenlib/BKE_texture.h (mar-2001 nzc) + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_TEXTURE_H +#define BKE_TEXTURE_H + +struct Tex; +struct MTex; +struct PluginTex; +struct LampRen; +struct ColorBand; +struct HaloRen; + +/* in ColorBand struct */ +#define MAXCOLORBAND 16 + + +void free_texture(struct Tex *t); +int test_dlerr(const char *name, const char *symbol); +void open_plugin_tex(struct PluginTex *pit); +struct PluginTex *add_plugin_tex(char *str); +void free_plugin_tex(struct PluginTex *pit); +struct ColorBand *add_colorband(void); +int do_colorband(struct ColorBand *coba); +void default_tex(struct Tex *tex); +struct Tex *add_texture(char *name); +void default_mtex(struct MTex *mtex); +struct MTex *add_mtex(void); +struct Tex *copy_texture(struct Tex *tex); +void make_local_texture(struct Tex *tex); +void autotexname(struct Tex *tex); +void init_render_texture(struct Tex *tex); +void init_render_textures(void); +void end_render_texture(struct Tex *tex); +void end_render_textures(void); +int clouds(struct Tex *tex, float *texvec); +int blend(struct Tex *tex, float *texvec); +int wood(struct Tex *tex, float *texvec); +int marble(struct Tex *tex, float *texvec); +int magic(struct Tex *tex, float *texvec); +int stucci(struct Tex *tex, float *texvec); +int texnoise(struct Tex *tex); +int plugintex(struct Tex *tex, float *texvec, float *dxt, float *dyt); +void tubemap(float x, float y, float z, float *adr1, float *adr2); +void spheremap(float x, float y, float z, float *adr1, float *adr2); +void do_2d_mapping(struct MTex *mtex, float *t, float *dxt, float *dyt); +int multitex(struct Tex *tex, float *texvec, float *dxt, float *dyt); +void do_material_tex(void); +void do_halo_tex(struct HaloRen *har, float xn, float yn, float *colf); +void do_sky_tex(void); +void do_lamp_tex(struct LampRen *la, float *lavec); +void externtex(struct MTex *mtex, float *vec); +void externtexcol(struct MTex *mtex, float *orco, char *col); +void render_realtime_texture(void); +#endif diff --git a/source/blender/blenkernel/BKE_utildefines.h b/source/blender/blenkernel/BKE_utildefines.h new file mode 100644 index 00000000000..65bad0f40b3 --- /dev/null +++ b/source/blender/blenkernel/BKE_utildefines.h @@ -0,0 +1,300 @@ +/* util defines -- might go away ?*/ + +/* + $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** +*/ + +#ifndef BKE_UTILDEFINES_H +#define BKE_UTILDEFINES_H + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#define ELEM(a, b, c) ( (a)==(b) || (a)==(c) ) +#define ELEM3(a, b, c, d) ( ELEM(a, b, c) || (a)==(d) ) +#define ELEM4(a, b, c, d, e) ( ELEM(a, b, c) || ELEM(a, d, e) ) +#define ELEM5(a, b, c, d, e, f) ( ELEM(a, b, c) || ELEM3(a, d, e, f) ) +#define ELEM6(a, b, c, d, e, f, g) ( ELEM(a, b, c) || ELEM4(a, d, e, f, g) ) +#define ELEM7(a, b, c, d, e, f, g, h) ( ELEM3(a, b, c, d) || ELEM4(a, e, f, g, h) ) +#define ELEM8(a, b, c, d, e, f, g, h, i) ( ELEM4(a, b, c, d, e) || ELEM4(a, f, g, h, i) ) + + +/* string compare */ +#define STREQ(str, a) ( strcmp((str), (a))==0 ) +#define STREQ2(str, a, b) ( STREQ(str, a) || STREQ(str, b) ) +#define STREQ3(str, a, b, c) ( STREQ2(str, a, b) || STREQ(str, c) ) + +/* min/max */ +#define MIN2(x,y) ( (x)<(y) ? (x) : (y) ) +#define MIN3(x,y,z) MIN2( MIN2((x),(y)) , (z) ) +#define MIN4(x,y,z,a) MIN2( MIN2((x),(y)) , MIN2((z),(a)) ) + +#define MAX2(x,y) ( (x)>(y) ? (x) : (y) ) +#define MAX3(x,y,z) MAX2( MAX2((x),(y)) , (z) ) +#define MAX4(x,y,z,a) MAX2( MAX2((x),(y)) , MAX2((z),(a)) ) + +#define SWAP(type, a, b) { type sw_ap; sw_ap=(a); (a)=(b); (b)=sw_ap; } + +#define ABS(a) ( (a)<0 ? (-a) : (a) ) + +#define VECCOPY(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2);} +#define QUATCOPY(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2); *(v1+3)= *(v2+3);} + +#define INIT_MINMAX(min, max) (min)[0]= (min)[1]= (min)[2]= 1.0e30; (max)[0]= (max)[1]= (max)[2]= -1.0e30; + +#define DO_MINMAX(vec, min, max) if( (min)[0]>(vec)[0] ) (min)[0]= (vec)[0]; \ + if( (min)[1]>(vec)[1] ) (min)[1]= (vec)[1]; \ + if( (min)[2]>(vec)[2] ) (min)[2]= (vec)[2]; \ + if( (max)[0]<(vec)[0] ) (max)[0]= (vec)[0]; \ + if( (max)[1]<(vec)[1] ) (max)[1]= (vec)[1]; \ + if( (max)[2]<(vec)[2] ) (max)[2]= (vec)[2]; \ + +#define DO_MINMAX2(vec, min, max) if( (min)[0]>(vec)[0] ) (min)[0]= (vec)[0]; \ + if( (min)[1]>(vec)[1] ) (min)[1]= (vec)[1]; \ + if( (max)[0]<(vec)[0] ) (max)[0]= (vec)[0]; \ + if( (max)[1]<(vec)[1] ) (max)[1]= (vec)[1]; + + +/* interferes elsewhere */ +/* deze getallen ook invullen in blender.h SpaceFile: struct dna herkent geen defines */ +#define FILE_MAXDIR 160 +#define FILE_MAXFILE 80 + + +/* some misc stuff.... */ +#define CLAMP(a, b, c) if((a)<(b)) (a)=(b); else if((a)>(c)) (a)=(c) + +#define KNOTSU(nu) ( (nu)->orderu+ (nu)->pntsu+ (nu->orderu-1)*((nu)->flagu & 1) ) +#define KNOTSV(nu) ( (nu)->orderv+ (nu)->pntsv+ (nu->orderv-1)*((nu)->flagv & 1) ) + +/* this weirdo pops up in two places ... */ +#if !defined(WIN32) && !defined(__BeOS) +#define O_BINARY 0 +#endif + +/* INTEGER CODES */ +#if defined(__sgi) || defined (__sparc) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__) + /* Big Endian */ +#define MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) ) +#else + /* Little Endian */ +#define MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) ) +#endif + +#define ID_NEW(a) if( (a) && (a)->id.newid ) (a)= (void *)(a)->id.newid + +#define FORM MAKE_ID('F','O','R','M') +#define DDG1 MAKE_ID('3','D','G','1') +#define DDG2 MAKE_ID('3','D','G','2') +#define DDG3 MAKE_ID('3','D','G','3') +#define DDG4 MAKE_ID('3','D','G','4') + +#define GOUR MAKE_ID('G','O','U','R') + +#define BLEN MAKE_ID('B','L','E','N') +#define DER_ MAKE_ID('D','E','R','_') +#define V100 MAKE_ID('V','1','0','0') + +#define DATA MAKE_ID('D','A','T','A') +#define GLOB MAKE_ID('G','L','O','B') +#define IMAG MAKE_ID('I','M','A','G') + +#define DNA1 MAKE_ID('D','N','A','1') +#define TEST MAKE_ID('T','E','S','T') +#define REND MAKE_ID('R','E','N','D') +#define USER MAKE_ID('U','S','E','R') + +#define ENDB MAKE_ID('E','N','D','B') + +/* This should, of course, become a function */ +#define DL_SURFINDEX(cyclu, cyclv, sizeu, sizev) \ + \ + if( (cyclv)==0 && a==(sizev)-1) break; \ + if(cyclu) { \ + p1= sizeu*a; \ + p2= p1+ sizeu-1; \ + p3= p1+ sizeu; \ + p4= p2+ sizeu; \ + b= 0; \ + } \ + else { \ + p2= sizeu*a; \ + p1= p2+1; \ + p4= p2+ sizeu; \ + p3= p1+ sizeu; \ + b= 1; \ + } \ + if( (cyclv) && a==sizev-1) { \ + p3-= sizeu*sizev; \ + p4-= sizeu*sizev; \ + } + +/* This one rotates the bytes in an int */ +#define SWITCH_INT(a) { \ + char s_i, *p_i; \ + p_i= (char *)&(a); \ + s_i=p_i[0]; p_i[0]=p_i[3]; p_i[3]=s_i; \ + s_i=p_i[1]; p_i[1]=p_i[2]; p_i[2]=s_i; } + +/* More brain damage. Only really used by packedFile.c */ +// return values +#define RET_OK 0 +#define RET_ERROR 1 +/* and these aren't used at all */ +/* #define RET_CANCEL 2 */ +/* #define RET_YES (1 == 1) */ +/* #define RET_NO (1 == 0) */ + +/* sequence related defines */ +#define WHILE_SEQ(base) { \ + int totseq_, seq_; Sequence **seqar; \ + build_seqar( base, &seqar, &totseq_); \ + for(seq_ = 0; seq_ < totseq_; seq_++) { \ + seq= seqar[seq_]; + + +#define END_SEQ } \ + if(seqar) MEM_freeN(seqar); \ + } + + +/* not really sure about these... some kind of event codes ?*/ +/* INFO: 300 */ +/* pas op: ook in filesel.c en editobject.c */ +#define B_INFOSCR 301 +#define B_INFODELSCR 302 +#define B_INFOSCE 304 +#define B_INFODELSCE 305 +#define B_FILEMENU 306 +#define B_PACKFILE 307 + +/* From iff.h, but seemingly detached from anything else... To which + * encoding scheme do they belong? */ +#define AMI (1 << 31) +#define CDI (1 << 30) +#define Anim (1 << 29) +#define TGA (1 << 28) +#define JPG (1 << 27) +#define TIM (1 << 26) + +#define TIM_CLUT (010) +#define TIM_4 (TIM | TIM_CLUT | 0) +#define TIM_8 (TIM | TIM_CLUT | 1) +#define TIM_16 (TIM | 2) +#define TIM_24 (TIM | 3) + +#define RAWTGA (TGA | 1) + +#define JPG_STD (JPG | (0 << 8)) +#define JPG_VID (JPG | (1 << 8)) +#define JPG_JST (JPG | (2 << 8)) +#define JPG_MAX (JPG | (3 << 8)) +#define JPG_MSK (0xffffff00) + +#define AM_ham (0x0800 | AMI) +#define AM_hbrite (0x0080 | AMI) +#define AM_lace (0x0004 | AMI) +#define AM_hires (0x8000 | AMI) +#define AM_hblace (AM_hbrite | AM_lace) +#define AM_hilace (AM_hires | AM_lace) +#define AM_hamlace (AM_ham | AM_lace) + +#define RGB888 1 +#define RGB555 2 +#define DYUV 3 +#define CLUT8 4 +#define CLUT7 5 +#define CLUT4 6 +#define CLUT3 7 +#define RL7 8 +#define RL3 9 +#define MPLTE 10 + +#define DYUV1 0 +#define DYUVE 1 + +#define CD_rgb8 (RGB888 | CDI) +#define CD_rgb5 (RGB555 | CDI) +#define CD_dyuv (DYUV | CDI) +#define CD_clut8 (CLUT8 | CDI) +#define CD_clut7 (CLUT7 | CDI) +#define CD_clut4 (CLUT4 | CDI) +#define CD_clut3 (CLUT3 | CDI) +#define CD_rl7 (RL7 | CDI) +#define CD_rl3 (RL3 | CDI) +#define CD_mplte (MPLTE | CDI) + +#define C233 1 +#define YUVX 2 +#define HAMX 3 +#define TANX 4 + +#define AN_c233 (Anim | C233) +#define AN_yuvx (Anim | YUVX) +#define AN_hamx (Anim | HAMX) +#define AN_tanx (Anim | TANX) + +#define IMAGIC 0732 + +/* This used to reside in render.h. It does some texturing. */ +#define BRICON Tin= (Tin-0.5)*tex->contrast+tex->bright-0.5; \ + if(Tin<0.0) Tin= 0.0; else if(Tin>1.0) Tin= 1.0; + +#define BRICONRGB Tr= tex->rfac*((Tr-0.5)*tex->contrast+tex->bright-0.5); \ + if(Tr<0.0) Tr= 0.0; else if(Tr>1.0) Tr= 1.0; \ + Tg= tex->gfac*((Tg-0.5)*tex->contrast+tex->bright-0.5); \ + if(Tg<0.0) Tg= 0.0; else if(Tg>1.0) Tg= 1.0; \ + Tb= tex->bfac*((Tb-0.5)*tex->contrast+tex->bright-0.5); \ + if(Tb<0.0) Tb= 0.0; else if(Tb>1.0) Tb= 1.0; + +/* mystifying stuff from blendef... */ +#define SELECT 1 +#define ACTIVE 2 +#define NOT_YET 0 + +/* ???? */ +#define BTST(a,b) ( ( (a) & 1<<(b) )!=0 ) +#define BSET(a,b) ( (a) | 1<<(b) ) + +/* needed for material.c*/ +#define REDRAWBUTSMAT 0x4015 + +/* useless game shit */ +#define MA_FH_NOR 2 + + +#endif diff --git a/source/blender/blenkernel/BKE_world.h b/source/blender/blenkernel/BKE_world.h new file mode 100644 index 00000000000..0ea13557e03 --- /dev/null +++ b/source/blender/blenkernel/BKE_world.h @@ -0,0 +1,45 @@ +/** + * blenlib/BKE_world.h (mar-2001 nzc) + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#ifndef BKE_WORLD_H +#define BKE_WORLD_H + +struct World; + +void free_world(struct World *sc); +struct World *add_world(char *name); +struct World *copy_world(struct World *wrld); +void make_local_world(struct World *wrld); +void init_render_world(void); + +#endif diff --git a/source/blender/blenkernel/BKE_writeavi.h b/source/blender/blenkernel/BKE_writeavi.h new file mode 100644 index 00000000000..f63342ea047 --- /dev/null +++ b/source/blender/blenkernel/BKE_writeavi.h @@ -0,0 +1,50 @@ +/** + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef BKE_WRITEAVI_H +#define BKE_WRITEAVI_H + +#ifdef __cplusplus +extern "C" { +#endif + +void start_avi(void); +void end_avi(void); +void append_avi(int frame); +void makeavistring(char *string); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/source/blender/blenkernel/Makefile b/source/blender/blenkernel/Makefile new file mode 100644 index 00000000000..239941ec59b --- /dev/null +++ b/source/blender/blenkernel/Makefile @@ -0,0 +1,37 @@ +# +# $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. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# +# Bounces make to subdirectories. + +SOURCEDIR = source/blender/blenkernel +DIRS = intern bad_level_call_stubs + +include nan_subdirs.mk diff --git a/source/blender/blenkernel/bad_level_call_stubs/Makefile b/source/blender/blenkernel/bad_level_call_stubs/Makefile new file mode 100644 index 00000000000..2d98ea5a1af --- /dev/null +++ b/source/blender/blenkernel/bad_level_call_stubs/Makefile @@ -0,0 +1,55 @@ +# +# $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. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# +# + +LIBNAME = blenkernel_blc +DIR = $(OCGDIR)/blender/blenkernel/$(LIBNAME) + +include nan_compile.mk + +CFLAGS += $(LEVEL_2_C_WARNINGS) +CFLAGS += $(FIX_STUBS_WARNINGS) + +ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd linux openbsd solaris windows")) + CFLAGS += -funsigned-char +endif + +CPPFLAGS += $(OGL_CPPFLAGS) +CPPFLAGS += -I../../makesdna +CPPFLAGS += -I../../include +CPPFLAGS += -I../../blenlib +CPPFLAGS += -I../../render/extern/include +CPPFLAGS += -I$(NAN_IKSOLVER)/include + +# path to our own external headerfiles +CPPFLAGS += -I.. + diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c new file mode 100644 index 00000000000..239e4f16487 --- /dev/null +++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c @@ -0,0 +1,180 @@ +/** + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * BKE_bad_level_calls function stubs + */ + + +#include "BLI_blenlib.h" + +#include "DNA_material_types.h" + +#include "BKE_bad_level_calls.h" + +int winqueue_break= 0; + +/* readfile.c */ + /* struct PluginSeq; */ +void open_plugin_seq(struct PluginSeq *pis, char *seqname){} + /* struct SpaceButs; */ +void set_rects_butspace(struct SpaceButs *buts){} + /* struct SpaceImaSel; */ +void check_imasel_copy(struct SpaceImaSel *simasel){} + /* struct ScrArea; */ +void unlink_screen(struct bScreen *sc){} +void freeAllRad(void){} +void free_editText(void){} +void free_editArmature(void){} + + +void setscreen(struct bScreen *sc){} +void force_draw_all(void){} + /* otherwise the WHILE_SEQ doesn't work */ + /* struct Sequence; */ + +/* MAART: added "seqar = 0; totseq = 0" because the loader will crash without it. */ +void build_seqar(ListBase *seqbase, struct Sequence ***seqar, int *totseq) +{ + *seqar = 0; + *totseq = 0; +} + +void BPY_do_pyscript(ID *id, short int event){} +void BPY_free_compiled_text(struct Text *text) {}; + +/* writefile.c */ + /* struct Oops; */ +void free_oops(struct Oops *oops){} +void exit_posemode(int freedata){} +void error(char *str, ...){} + +/* anim.c */ +ListBase editNurb; + +/* displist.c */ +#include "DNA_world_types.h" /* for render_types */ +#include "render_types.h" +struct RE_Render R; +float RE_Spec(float inp, int hard){} +void waitcursor(int val){} +void allqueue(unsigned short event, short val){} +#define REDRAWVIEW3D 0x4010 +Material defmaterial; + +/* effect.c */ +void RE_jitterate1(float *jit1, float *jit2, int num, float rad1){} +void RE_jitterate2(float *jit1, float *jit2, int num, float rad2){} + +/* exotic.c */ +void load_editMesh(void){} +void make_editMesh(void){} +void free_editMesh(void){} +void docentre_new(void){} +int saveover(char *str){} + +/* image.c */ +#include "DNA_image_types.h" +void free_realtime_image(Image *ima){} // has to become a callback, opengl stuff +void RE_make_existing_file(char *name){} // from render, but these funcs should be moved anyway + +/* ipo.c */ +void copy_view3d_lock(short val){} // was a hack, to make scene layer ipo's possible + +/* library.c */ +void allspace(unsigned short event, short val){} +#define OOPS_TEST 2 + +/* mball.c */ +ListBase editelems; + +/* object.c */ +void BPY_free_scriptlink(ScriptLink *slink){} +void BPY_copy_scriptlink(ScriptLink *scriptlink){} +float *give_cursor(void){} // become a callback or argument + + +/* packedFile.c */ +short pupmenu(char *instr){} // will be general callback + +/* sca.c */ +#define LEFTMOUSE 0x001 // because of mouse sensor + +/* scene.c */ +#include "DNA_sequence_types.h" +void free_editing(struct Editing *ed){} // scenes and sequences problem... +void BPY_do_all_scripts (short int event){} + +/* IKsolver stubs */ +#include "IK_solver.h" +extern int IK_LoadChain(IK_Chain_ExternPtr chain,IK_Segment_ExternPtr segments, int num_segs) +{ + return 0; +} + +extern int IK_SolveChain( + IK_Chain_ExternPtr chain, + float goal[3], + float tolerance, + int max_iterations, + float max_angle_change, + IK_Segment_ExternPtr output + ) +{ + return 0; +} + +extern void IK_FreeChain(IK_Chain_ExternPtr chain) +{ + ; +} + + +extern IK_Chain_ExternPtr IK_CreateChain(void) +{ + return 0; +} + + + +/* texture.c */ +#define FLO 128 +#define INT 96 + /* struct EnvMap; */ + /* struct Tex; */ +void RE_free_envmap(struct EnvMap *env){} +struct EnvMap *RE_copy_envmap(struct EnvMap *env){} +void RE_free_envmapdata(struct EnvMap *env){} +int RE_envmaptex(struct Tex *tex, float *texvec, float *dxt, float *dyt){} +void RE_calc_R_ref(void){} +char texstr[15][8]; /* buttons.c */ +Osa O; + +/* editsca.c */ +void make_unique_prop_names(char *str) {} diff --git a/source/blender/blenkernel/intern/Makefile b/source/blender/blenkernel/intern/Makefile new file mode 100644 index 00000000000..08202dff9cc --- /dev/null +++ b/source/blender/blenkernel/intern/Makefile @@ -0,0 +1,74 @@ +# +# $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. +# +# Contributor(s): none yet. +# +# ***** END GPL/BL DUAL LICENSE BLOCK ***** +# +# + +LIBNAME = blenkernel +DIR = $(OCGDIR)/blender/$(LIBNAME) + +include nan_compile.mk + +ifeq ($(OS),$(findstring $(OS), "beos darwin freebsd openbsd linux solaris windows")) + CFLAGS += -funsigned-char +endif + +CFLAGS += $(LEVEL_1_C_WARNINGS) + +# OpenGL and Python +CPPFLAGS += -I$(OPENGL_HEADERS) +CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) + +CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include +# Reference to the types in makesdna and imbuf +CPPFLAGS += -I../../makesdna +CPPFLAGS += -I../../imbuf +# This mod uses the BLI and BLO module +CPPFLAGS += -I../../blenlib +CPPFLAGS += -I../../blenloader +CPPFLAGS += -I../../bpython/include +# also avi is used +CPPFLAGS += -I../../avi +CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include + +# we still refer to /include a bit... +CPPFLAGS += -I../../include + +# to include the render stuff: +CPPFLAGS += -I../../render/extern/include + +# for sound +#CPPFLAGS += -I../../../kernel/gen_system + +CPPFLAGS += -I$(NAN_IKSOLVER)/include + +# path to our own external headerfiles +CPPFLAGS += -I.. + diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c new file mode 100644 index 00000000000..9f5de3f34fa --- /dev/null +++ b/source/blender/blenkernel/intern/action.c @@ -0,0 +1,873 @@ +/** + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <string.h> +#include <math.h> +#include <stdlib.h> /* for NULL */ + +#include "MEM_guardedalloc.h" +#include "BLI_arithb.h" +#include "BLI_blenlib.h" + +#include "BKE_action.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_utildefines.h" + +#include "DNA_object_types.h" +#include "DNA_ipo_types.h" +#include "DNA_curve_types.h" +#include "DNA_scene_types.h" +#include "DNA_action_types.h" +#include "DNA_nla_types.h" + +#include "BKE_blender.h" +#include "BKE_ipo.h" +#include "BKE_object.h" +#include "BKE_library.h" +#include "BKE_anim.h" +#include "BKE_armature.h" + +#include "nla.h" + +#include "BKE_constraint.h" +#include "DNA_constraint_types.h" + +/* Local function prototypes */ +static + void +do_pose_constraint_channels( + bPose *pose, + bAction *act, + float ctime +); + +static + void +get_constraint_influence_from_pose ( + bPose *dst, + bPose *src +); + +static + void +blend_constraints( + ListBase *dst, + const ListBase *src, + float srcweight, + short mode +); + +static + void +rest_pose ( + bPose *pose, + int clearflag +); + +/* Implementation */ + + bPoseChannel * +get_pose_channel ( + const bPose *pose, + const char *name +){ + bPoseChannel *chan; + + for (chan=pose->chanbase.first; chan; chan=chan->next){ + if (!strcmp (chan->name, name)) + return chan; + } + + return NULL; +} + +static + void +rest_pose ( + bPose *pose, + int clearflag +){ + bPoseChannel *chan; + int i; + + if (!pose) + return; + + for (chan=pose->chanbase.first; chan; chan=chan->next){ + for (i=0; i<3; i++){ + chan->loc[i]=0.0; + chan->quat[i+1]=0.0; + chan->size[i]=1.0; + } + chan->quat[0]=1.0; + if (clearflag) + chan->flag =0; + } +} + +static + void +blend_constraints( + ListBase *dst, + const ListBase *src, + float srcweight, + short mode +){ + bConstraint *dcon; + const bConstraint *scon; + float dstweight; + + switch (mode){ + case POSE_BLEND: + dstweight = 1.0F - srcweight; + break; + case POSE_ADD: + dstweight = 1.0F; + break; + } + + /* Blend constraints */ + for (dcon=dst->first; dcon; dcon=dcon->next){ + for (scon = src->first; scon; scon=scon->next){ + if (!strcmp(scon->name, dcon->name)) + break; + } + + if (scon){ + dcon->enforce = (dcon->enforce*dstweight) + (scon->enforce*srcweight); + if (mode == POSE_BLEND) + dcon->enforce/=2.0; + + if (dcon->enforce>1.0) + dcon->enforce=1.0; + if (dcon->enforce<0.0) + dcon->enforce=0.0; + + } + } +} + + void +blend_poses ( + bPose *dst, + const bPose *src, + float srcweight, + short mode +){ + bPoseChannel *dchan; + const bPoseChannel *schan; + float dquat[4], squat[4], mat[3][3]; + float dstweight; + int i; + + switch (mode){ + case POSE_BLEND: + dstweight = 1.0F - srcweight; + break; + case POSE_ADD: + dstweight = 1.0F; + break; + default : + dstweight = 1.0F; + } + + for (dchan = dst->chanbase.first; dchan; dchan=dchan->next){ + schan = get_pose_channel(src, dchan->name); + if (schan){ + if (schan->flag & (POSE_ROT|POSE_LOC|POSE_SIZE)){ + + /* Convert both quats to matrices and then back again. + * This prevents interpolation problems + * This sucks because it is slow and stupid + */ + + QuatToMat3(dchan->quat, mat); + Mat3ToQuat(mat, dquat); + QuatToMat3(schan->quat, mat); + Mat3ToQuat(mat, squat); + + /* Do the transformation blend */ + for (i=0; i<3; i++){ + if (schan->flag & POSE_LOC) + dchan->loc[i] = (dchan->loc[i]*dstweight) + (schan->loc[i]*srcweight); + if (schan->flag & POSE_SIZE) + dchan->size[i] = 1.0f + ((dchan->size[i]-1.0f)*dstweight) + ((schan->size[i]-1.0f)*srcweight); + if (schan->flag & POSE_ROT) + dchan->quat[i+1] = (dquat[i+1]*dstweight) + (squat[i+1]*srcweight); + } + + /* Do one more iteration for the quaternions only and normalize the quaternion if needed */ + if (schan->flag & POSE_ROT) + dchan->quat[0] = 1.0f + ((dquat[0]-1.0f)*dstweight) + ((squat[0]-1.0f)*srcweight); + if (mode==POSE_BLEND) + NormalQuat (dchan->quat); + dchan->flag |= schan->flag; + } + } + } +} + + void +clear_pose_constraint_status ( + Object *ob +){ + bPoseChannel *chan; + + if (!ob) + return; + if (!ob->pose) + return; + + for (chan = ob->pose->chanbase.first; chan; chan=chan->next){ + chan->flag &= ~PCHAN_DONE; + } +} + + float +calc_action_start ( + const bAction *act +){ + const bActionChannel *chan; + const IpoCurve *icu; + float size=999999999.0f; + int i; + int foundvert=0; + const bConstraintChannel *conchan; + + + if (!act) + return 0; + + for (chan=act->chanbase.first; chan; chan=chan->next){ + for (icu=chan->ipo->curve.first; icu; icu=icu->next) + for (i=0; i<icu->totvert; i++){ + size = MIN2 (size, icu->bezt[i].vec[1][0]); + foundvert=1; + + } + for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){ + for (icu=conchan->ipo->curve.first; icu; icu=icu->next) + for (i=0; i<icu->totvert; i++){ + size = MIN2 (size, icu->bezt[i].vec[1][0]); + foundvert=1; + } + } + } + + if (!foundvert) + return 0; + else + return size; +} + + float +calc_action_end ( + const bAction *act +){ + const bActionChannel *chan; + const bConstraintChannel *conchan; + const IpoCurve *icu; + float size=0; + int i; + + if (!act) + return 0; + + for (chan=act->chanbase.first; chan; chan=chan->next){ + for (icu=chan->ipo->curve.first; icu; icu=icu->next) + for (i=0; i<icu->totvert; i++) + size = MAX2 (size, icu->bezt[i].vec[1][0]); + + for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next){ + for (icu=conchan->ipo->curve.first; icu; icu=icu->next) + for (i=0; i<icu->totvert; i++) + size = MAX2 (size, icu->bezt[i].vec[1][0]); + } + } + return size; +} + + void +verify_pose_channel ( + bPose* pose, + const char* name +) { + bPoseChannel *chan; + + if (!pose){ + return; + } + + /* See if this channel exists */ + for (chan=pose->chanbase.first; chan; chan=chan->next){ + if (!strcmp (name, chan->name)) + return; + } + + /* If not, create it and add it */ + chan = MEM_callocN(sizeof(bPoseChannel), "verifyPoseChannel"); + + strcpy (chan->name, name); + chan->loc[0] = chan->loc[1] = chan->loc[2] = 0.0F; + chan->quat[1] = chan->quat[2] = chan->quat[3] = 0.0F; chan->quat[0] = 1.0F; + chan->size[0] = chan->size[1] = chan->size[2] = 1.0F; + + chan->flag |= POSE_ROT|POSE_SIZE|POSE_LOC; + + BLI_addtail (&pose->chanbase, chan); +} + + void +get_pose_from_pose ( + bPose **pose, + const bPose *src +){ + const bPoseChannel *pchan; + bPoseChannel *newchan; + + if (!src) + return; + if (!pose) + return; + + /* If there is no pose, create one */ + if (!*pose){ + *pose=MEM_callocN (sizeof(bPose), "pose"); + } + + /* Copy the data from the action into the pose */ + for (pchan=src->chanbase.first; pchan; pchan=pchan->next){ + newchan = copy_pose_channel(pchan); + verify_pose_channel(*pose, pchan->name); + set_pose_channel(*pose, newchan); + } +} + +static void get_constraint_influence_from_pose (bPose *dst, bPose *src) +{ + bConstraint *dcon, *scon; + + if (!src || !dst) + return; + + for (dcon = dst->chanbase.first; dcon; dcon=dcon->next){ + for (scon=src->chanbase.first; scon; scon=scon->next){ + if (!strcmp(scon->name, dcon->name)) + break; + } + if (scon){ + dcon->enforce = scon->enforce; + } + } +} + +/* If the pose does not exist, a new one is created */ + + void +get_pose_from_action ( + bPose **pose, + bAction *act, + float ctime +) { + bActionChannel *achan; + bPoseChannel *pchan; + Ipo *ipo; + IpoCurve *curve; + + + if (!act) + return; + if (!pose) + return; + + /* If there is no pose, create one */ + if (!*pose){ + *pose=MEM_callocN (sizeof(bPose), "pose"); + } + + /* Copy the data from the action into the pose */ + for (achan=act->chanbase.first; achan; achan=achan->next){ + act->achan= achan; + + ipo = achan->ipo; + if (ipo){ + pchan=MEM_callocN (sizeof(bPoseChannel), "gpfa_poseChannel"); + strcpy (pchan->name, achan->name); + + act->pchan=pchan; + /* Evaluates and sets the internal ipo value */ + calc_ipo(ipo, ctime); + + /* Set the pchan flags */ + for (curve = achan->ipo->curve.first; curve; curve=curve->next){ + /* Skip empty curves */ + if (!curve->totvert) + continue; + + switch (curve->adrcode){ + case AC_QUAT_X: + case AC_QUAT_Y: + case AC_QUAT_Z: + case AC_QUAT_W: + pchan->flag |= POSE_ROT; + break; + case AC_LOC_X: + case AC_LOC_Y: + case AC_LOC_Z: + pchan->flag |= POSE_LOC; + break; + case AC_SIZE_X: + case AC_SIZE_Y: + case AC_SIZE_Z: + pchan->flag |= POSE_SIZE; + break; + } + } + + execute_ipo((ID*)act, achan->ipo); + + set_pose_channel(*pose, pchan); + } + } +} + + void +do_all_actions( +){ + Base *base; + bPose *apose=NULL; + bPose *tpose=NULL; + Object *ob; + bActionStrip *strip; + int doit; + float striptime, frametime, length, actlength; + float blendfac, stripframe; + + int set; + + /* NEW: current scene ob ipo's */ + base= G.scene->base.first; + set= 0; + + while(base) { + + ob = base->object; + + /* Retrieve data from the NLA */ + if(ob->type==OB_ARMATURE){ + + doit=0; + + /* Clear pose */ + if (apose){ + clear_pose(apose); + MEM_freeN(apose); + } + /* Clear pose */ + if (tpose){ + clear_pose(tpose); + MEM_freeN(tpose); + } + + copy_pose(&apose, ob->pose, 1); + copy_pose(&tpose, ob->pose, 1); + rest_pose(apose, 1); + + if (base->object->nlastrips.first){ + rest_pose(base->object->pose, 0); + } + + for (strip=base->object->nlastrips.first; strip; strip=strip->next){ + doit = 0; + if (strip->act){ + + /* Determine if the current frame is within the strip's range */ + length = strip->end-strip->start; + actlength = strip->actend-strip->actstart; + striptime = (G.scene->r.cfra-(strip->start)) / length; + stripframe = (G.scene->r.cfra-(strip->start)) ; + + + if (striptime>=0.0){ + + rest_pose(tpose, 1); + + /* Handle path */ + if (strip->flag & ACTSTRIP_USESTRIDE){ + if (ob->parent && ob->parent->type==OB_CURVE){ + Curve *cu = ob->parent->data; + float ctime, pdist; + + if (cu->flag & CU_PATH){ + /* Ensure we have a valid path */ + if(cu->path==0 || cu->path->data==0) calc_curvepath(ob->parent); + + /* Find the position on the path */ + ctime= bsystem_time(ob, ob->parent, (float)G.scene->r.cfra, 0.0); + + if(calc_ipo_spec(cu->ipo, CU_SPEED, &ctime)==0) { + ctime /= cu->pathlen; + CLAMP(ctime, 0.0, 1.0); + } + pdist = ctime*cu->path->totdist; + + if (strip->stridelen) + striptime = pdist / strip->stridelen; + else + striptime = 0; + + striptime = (float)fmod (striptime, 1.0); + + frametime = (striptime * actlength) + strip->actstart; + get_pose_from_action (&tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0)); +#ifdef __NLA_BLENDCON + do_pose_constraint_channels(tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0)); +#endif + doit=1; + } + } + } + + /* Handle repeat */ + + else if (striptime < 1.0){ + /* Mod to repeat */ + striptime*=strip->repeat; + striptime = (float)fmod (striptime, 1.0); + + frametime = (striptime * actlength) + strip->actstart; + get_pose_from_action (&tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0)); +#ifdef __NLA_BLENDCON + do_pose_constraint_channels(tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0)); +#endif + doit=1; + } + /* Handle extend */ + else{ + if (strip->flag & ACTSTRIP_HOLDLASTFRAME){ + striptime = 1.0; + frametime = (striptime * actlength) + strip->actstart; + get_pose_from_action (&tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0)); +#ifdef __NLA_BLENDCON + do_pose_constraint_channels(tpose, strip->act, bsystem_time(ob, 0, frametime, 0.0)); +#endif + doit=1; + } + } + + /* Handle blendin & blendout */ + if (doit){ + /* Handle blendin */ + + if (strip->blendin>0.0 && stripframe<=strip->blendin && G.scene->r.cfra>=strip->start){ + blendfac = stripframe/strip->blendin; + } + else if (strip->blendout>0.0 && stripframe>=(length-strip->blendout) && G.scene->r.cfra<=strip->end){ + blendfac = (length-stripframe)/(strip->blendout); + } + else + blendfac = 1; + + /* Blend this pose with the accumulated pose */ + blend_poses (apose, tpose, blendfac, strip->mode); +#ifdef __NLA_BLENDCON + blend_constraints(&apose->chanbase, &tpose->chanbase, blendfac, strip->mode); +#endif + } + } + if (apose){ + get_pose_from_pose(&ob->pose, apose); +#ifdef __NLA_BLENDCON + get_constraint_influence_from_pose(ob->pose, apose); +#endif + } + } + + } + + /* Do local action (always overrides the nla actions) */ + /* At the moment, only constraint ipos on the local action have any effect */ + if(base->object->action) { + get_pose_from_action (&ob->pose, ob->action, bsystem_time(ob, 0, (float) G.scene->r.cfra, 0.0)); + do_pose_constraint_channels(ob->pose, ob->action, bsystem_time(ob, 0, (float) G.scene->r.cfra, 0.0)); + doit = 1; + } + + if (doit) + apply_pose_armature(get_armature(ob), ob->pose, 1); + + } + base= base->next; + if(base==0 && set==0 && G.scene->set) { + set= 1; + base= G.scene->set->base.first; + } + + } + + if (apose){ + clear_pose(apose); + MEM_freeN(apose); + apose = NULL; + } + if (tpose){ + clear_pose(tpose); + MEM_freeN(tpose); + apose = NULL; + } + +} + +static void do_pose_constraint_channels(bPose *pose, bAction *act, float ctime) +{ + bPoseChannel *pchan; + bActionChannel *achan; + + if (!pose || !act) + return; + + for (pchan=pose->chanbase.first; pchan; pchan=pchan->next){ + achan=get_named_actionchannel(act, pchan->name); + if (achan) + do_constraint_channels(&pchan->constraints, &achan->constraintChannels, ctime); + } +} + + bActionChannel * +get_named_actionchannel ( + bAction *act, + const char *name +){ + bActionChannel *chan; + + if (!act) + return NULL; + + for (chan = act->chanbase.first; chan; chan=chan->next){ + if (!strcmp (chan->name, name)) + return chan; + } + + return NULL; +} + + void +clear_pose ( + bPose *pose +) { + bPoseChannel *chan; + + if (pose->chanbase.first){ + for (chan = pose->chanbase.first; chan; chan=chan->next){ + free_constraints(&chan->constraints); + } + BLI_freelistN (&pose->chanbase); + } +} + + void +make_local_action( + bAction *act +){ + Object *ob; + bAction *actn; + int local=0, lib=0; + + if(act->id.lib==0) return; + if(act->id.us==1) { + act->id.lib= 0; + act->id.flag= LIB_LOCAL; + new_id(0, (ID *)act, 0); + return; + } + + ob= G.main->object.first; + while(ob) { + if(ob->action==act) { + if(ob->id.lib) lib= 1; + else local= 1; + } + ob= ob->id.next; + } + + if(local && lib==0) { + act->id.lib= 0; + act->id.flag= LIB_LOCAL; + new_id(0, (ID *)act, 0); + } + else if(local && lib) { + actn= copy_action(act); + actn->id.us= 0; + + ob= G.main->object.first; + while(ob) { + if(ob->action==act) { + + if(ob->id.lib==0) { + ob->action = actn; + ob->activecon = NULL; + actn->id.us++; + act->id.us--; + } + } + ob= ob->id.next; + } + } +} + + + void +free_action( + bAction *act +){ + bActionChannel *chan; + + /* Free channels */ + for (chan=act->chanbase.first; chan; chan=chan->next){ + if (chan->ipo) + chan->ipo->id.us--; + free_constraint_channels(&chan->constraintChannels); + } + + if (act->chanbase.first) + BLI_freelistN (&act->chanbase); +} + + bAction* +copy_action ( + const bAction *src +){ + bAction *dst = NULL; + bActionChannel *dchan, *schan; + + if(!src) return NULL; + + dst= copy_libblock(src); + duplicatelist(&(dst->chanbase), &(src->chanbase)); + + for (dchan=dst->chanbase.first, schan=src->chanbase.first; dchan; dchan=dchan->next, schan=schan->next){ + dchan->ipo = copy_ipo(dchan->ipo); + copy_constraint_channels(&dchan->constraintChannels, &schan->constraintChannels); + } + dst->id.flag |= LIB_FAKEUSER; + dst->id.us++; + return dst; +} + + bPoseChannel * +copy_pose_channel ( + const bPoseChannel* src +){ + bPoseChannel *dst; + + if (!src) + return NULL; + + dst = MEM_callocN (sizeof(bPoseChannel), "copyPoseChannel"); + memcpy (dst, src, sizeof(bPoseChannel)); + dst->prev=dst->next=NULL; + + return dst; +} + + void +copy_pose( + bPose **dst, + const bPose *src, + int copycon +){ + bPose *outPose; + const bPose * inPose; + bPoseChannel *newChan; + const bPoseChannel *curChan; + + inPose = src; + + if (!inPose){ + *dst=NULL; + return; + } + + outPose=MEM_callocN(sizeof(bPose), "pose"); + + for (curChan=inPose->chanbase.first; curChan; curChan=curChan->next){ + newChan=MEM_callocN(sizeof(bPoseChannel), "copyposePoseChannel"); + + strcpy (newChan->name, curChan->name); + newChan->flag=curChan->flag; + + memcpy (newChan->loc, curChan->loc, sizeof (curChan->loc)); + memcpy (newChan->size, curChan->size, sizeof (curChan->size)); + memcpy (newChan->quat, curChan->quat, sizeof (curChan->quat)); + Mat4CpyMat4 (newChan->obmat, curChan->obmat); + + BLI_addtail (&outPose->chanbase, newChan); + if (copycon){ + copy_constraints(&newChan->constraints, &curChan->constraints); + } + } + + *dst=outPose; +} + +bPoseChannel *set_pose_channel (bPose *pose, bPoseChannel *chan){ + /* chan is no longer valid for the calling function. + and should not be used by that function after calling + this one + */ + bPoseChannel *curChan; + + /* Determine if an equivalent channel exists already */ + for (curChan=pose->chanbase.first; curChan; curChan=curChan->next){ + if (!strcmp (curChan->name, chan->name)){ + if (chan->flag & POSE_ROT) + memcpy (curChan->quat, chan->quat, sizeof(chan->quat)); + if (chan->flag & POSE_SIZE) + memcpy (curChan->size, chan->size, sizeof(chan->size)); + if (chan->flag & POSE_LOC) + memcpy (curChan->loc, chan->loc, sizeof(chan->loc)); + if (chan->flag & PCHAN_DONE) + Mat4CpyMat4 (curChan->obmat, chan->obmat); + + curChan->flag |= chan->flag; + MEM_freeN (chan); + return curChan; + } + } + + MEM_freeN (chan); + return NULL; + /* If an equivalent channel doesn't exist, then don't bother setting it. */ +} + + diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c new file mode 100644 index 00000000000..0fa358b30a0 --- /dev/null +++ b/source/blender/blenkernel/intern/anim.c @@ -0,0 +1,512 @@ +/** + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <math.h> +#include <string.h> + +#include "MEM_guardedalloc.h" +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "DNA_listBase.h" + +#include "DNA_object_types.h" +#include "DNA_curve_types.h" +#include "DNA_key_types.h" +#include "DNA_view3d_types.h" +#include "DNA_effect_types.h" +#include "DNA_mesh_types.h" +#include "DNA_scene_types.h" + +#include "BKE_global.h" +#include "BKE_utildefines.h" +#include "BKE_anim.h" +#include "BKE_ipo.h" +#include "BKE_object.h" +#include "BKE_displist.h" +#include "BKE_key.h" +#include "BKE_font.h" +#include "BKE_effect.h" + +#include "BKE_bad_level_calls.h" + +ListBase duplilist= {0, 0}; + +void free_path(Path *path) +{ + if(path->data) MEM_freeN(path->data); + MEM_freeN(path); +} + + +void calc_curvepath(Object *ob) +{ + BevList *bl; + BevPoint *bevp, *bevpn, *bevpfirst, *bevplast; + Curve *cu; + Nurb *nu; + Path *path; + float *fp, *dist, *maxdist, x, y, z; + float fac, d=0, fac1, fac2; + int a, tot, cycl=0; + float *ft; + + /* in een pad zitten allemaal punten met gelijke afstand: path->len = aantal pt */ + /* NU MET BEVELCURVE!!! */ + + if(ob==0 || ob->type != OB_CURVE) return; + cu= ob->data; + if(ob==G.obedit) nu= editNurb.first; + else nu= cu->nurb.first; + + if(cu->path) free_path(cu->path); + cu->path= 0; + + if((cu->flag & CU_PATH)==0) return; + + bl= cu->bev.first; + if(bl==0) { + makeDispList(ob); + bl= cu->bev.first; + } + if(bl==0) return; + + cu->path=path= MEM_callocN(sizeof(Path), "path"); + + /* als POLY: laatste punt != eerste punt */ + cycl= (bl->poly!= -1); + + if(cycl) tot= bl->nr; + else tot= bl->nr-1; + + path->len= tot+1; + /* exception: vector handle paths and polygon paths should be subdivided at least a factor 6 (or more?) */ + if(path->len<6*nu->pntsu) path->len= 6*nu->pntsu; + + dist= (float *)MEM_mallocN((tot+1)*4, "berekenpaddist"); + + /* alle lengtes in *dist */ + bevp= bevpfirst= (BevPoint *)(bl+1); + fp= dist; + *fp= 0; + for(a=0; a<tot; a++) { + fp++; + if(cycl && a==tot-1) { + x= bevpfirst->x - bevp->x; + y= bevpfirst->y - bevp->y; + z= bevpfirst->z - bevp->z; + } + else { + x= (bevp+1)->x - bevp->x; + y= (bevp+1)->y - bevp->y; + z= (bevp+1)->z - bevp->z; + } + *fp= *(fp-1)+ (float)sqrt(x*x+y*y+z*z); + + bevp++; + } + + path->totdist= *fp; + + /* de padpunten in path->data */ + /* nu ook met TILT */ + ft= path->data = (float *)MEM_callocN(16*path->len, "pathdata"); + + bevp= bevpfirst; + bevpn= bevp+1; + bevplast= bevpfirst + (bl->nr-1); + fp= dist+1; + maxdist= dist+tot; + fac= 1.0f/((float)path->len-1.0f); + + for(a=0; a<path->len; a++) { + + d= ((float)a)*fac*path->totdist; + + /* we zoeken plek 'd' in het array */ + while((d>= *fp) && fp<maxdist) { + fp++; + if(bevp<bevplast) bevp++; + bevpn= bevp+1; + if(bevpn>bevplast) { + if(cycl) bevpn= bevpfirst; + else bevpn= bevplast; + } + } + + fac1= *(fp)- *(fp-1); + fac2= *(fp)-d; + fac1= fac2/fac1; + fac2= 1.0f-fac1; + + ft[0]= fac1*bevp->x+ fac2*(bevpn)->x; + ft[1]= fac1*bevp->y+ fac2*(bevpn)->y; + ft[2]= fac1*bevp->z+ fac2*(bevpn)->z; + ft[3]= fac1*bevp->alfa+ fac2*(bevpn)->alfa; + + ft+= 4; + + } + + MEM_freeN(dist); +} + +int interval_test(int min, int max, int p1, int cycl) +{ + + if(cycl) { + if( p1 < min) + p1= ((p1 -min) % (max-min+1)) + max+1; + else if(p1 > max) + p1= ((p1 -min) % (max-min+1)) + min; + } + else { + if(p1 < min) p1= min; + else if(p1 > max) p1= max; + } + return p1; +} + +int where_on_path(Object *ob, float ctime, float *vec, float *dir) /* geeft OK terug */ +{ + Curve *cu; + Nurb *nu; + BevList *bl; + Path *path; + float *fp, *p0, *p1, *p2, *p3, fac; + float data[4]; + int cycl=0, s0, s1, s2, s3; + + + if(ob==0 || ob->type != OB_CURVE) return 0; + cu= ob->data; + if(cu->path==0 || cu->path->data==0) calc_curvepath(ob); + path= cu->path; + fp= path->data; + + /* cyclic testen */ + bl= cu->bev.first; + if(bl && bl->poly> -1) cycl= 1; + + /* ctime is van 0.0-1.0 */ + ctime *= (path->len-1); + + s1= (int)floor(ctime); + fac= (float)(s1+1)-ctime; + + /* path->len is gecorrigeerd voor cyclic, zie boven, is beetje warrig! */ + s0= interval_test(0, path->len-1-cycl, s1-1, cycl); + s1= interval_test(0, path->len-1-cycl, s1, cycl); + s2= interval_test(0, path->len-1-cycl, s1+1, cycl); + s3= interval_test(0, path->len-1-cycl, s1+2, cycl); + + p0= fp + 4*s0; + p1= fp + 4*s1; + p2= fp + 4*s2; + p3= fp + 4*s3; + + if(cu->flag & CU_FOLLOW) { + + set_afgeleide_four_ipo(1.0f-fac, data, KEY_BSPLINE); + + dir[0]= data[0]*p0[0] + data[1]*p1[0] + data[2]*p2[0] + data[3]*p3[0] ; + dir[1]= data[0]*p0[1] + data[1]*p1[1] + data[2]*p2[1] + data[3]*p3[1] ; + dir[2]= data[0]*p0[2] + data[1]*p1[2] + data[2]*p2[2] + data[3]*p3[2] ; + + /* compatible maken met vectoquat */ + dir[0]= -dir[0]; + dir[1]= -dir[1]; + dir[2]= -dir[2]; + } + + nu= cu->nurb.first; + + /* zeker van zijn dat de eerste en laatste frame door de punten gaat */ + if((nu->type & 7)==CU_POLY) set_four_ipo(1.0f-fac, data, KEY_LINEAR); + else if((nu->type & 7)==CU_BEZIER) set_four_ipo(1.0f-fac, data, KEY_LINEAR); + else if(s0==s1 || p2==p3) set_four_ipo(1.0f-fac, data, KEY_CARDINAL); + else set_four_ipo(1.0f-fac, data, KEY_BSPLINE); + + vec[0]= data[0]*p0[0] + data[1]*p1[0] + data[2]*p2[0] + data[3]*p3[0] ; + vec[1]= data[0]*p0[1] + data[1]*p1[1] + data[2]*p2[1] + data[3]*p3[1] ; + vec[2]= data[0]*p0[2] + data[1]*p1[2] + data[2]*p2[2] + data[3]*p3[2] ; + + vec[3]= data[0]*p0[3] + data[1]*p1[3] + data[2]*p2[3] + data[3]*p3[3] ; + + return 1; +} + +void frames_duplilist(Object *ob) +{ + extern int enable_cu_speed; /* object.c */ + Object *newob; + int cfrao, ok; + + cfrao= G.scene->r.cfra; + if(ob->parent==0 && ob->track==0 && ob->ipo==0) return; + + if(ob->transflag & OB_DUPLINOSPEED) enable_cu_speed= 0; + + /* dit om zeker van te zijn dat er iets gezbufferd wordt: in drawobject.c: dt==wire en boundboxclip */ + if(G.background==0 && ob->type==OB_MESH) { + Mesh *me= ob->data; + DispList *dl; + if(me->disp.first==0) addnormalsDispList(ob, &me->disp); + if(ob->dt==OB_SHADED) { + dl= ob->disp.first; + if(dl==0 || dl->col1==0) shadeDispList(ob); + } + } + + for(G.scene->r.cfra= ob->dupsta; G.scene->r.cfra<=ob->dupend; G.scene->r.cfra++) { + + ok= 1; + if(ob->dupoff) { + ok= G.scene->r.cfra - ob->dupsta; + ok= ok % (ob->dupon+ob->dupoff); + if(ok < ob->dupon) ok= 1; + else ok= 0; + } + if(ok) { + newob= MEM_mallocN(sizeof(Object), "newobobj dupli"); + memcpy(newob, ob, sizeof(Object)); + + /* alleen de basis-ball behoeft een displist */ + if(newob->type==OB_MBALL) newob->disp.first= newob->disp.last= 0; + + BLI_addtail(&duplilist, newob); + do_ob_ipo(newob); + where_is_object(newob); + + newob->flag |= OB_FROMDUPLI; + newob->id.newid= (ID *)ob; /* duplicator bewaren */ + } + } + + G.scene->r.cfra= cfrao; + enable_cu_speed= 1; + do_ob_ipo(ob); +} + + +void vertex_duplilist(Scene *sce, Object *par) +{ + Object *ob, *newob; + Base *base; + MVert *mvert; + Mesh *me; + float vec[3], pvec[3], pmat[4][4], mat[3][3], tmat[4][4]; + float *q2; + int lay, totvert, a; + + Mat4CpyMat4(pmat, par->obmat); + + Mat4One(tmat); + + lay= G.scene->lay; + + base= sce->base.first; + while(base) { + + if(base->object->type>0 && (lay & base->lay) && G.obedit!=base->object) { + ob= base->object->parent; + while(ob) { + if(ob==par) { + + ob= base->object; + /* mballs have a different dupli handling */ + if(ob->type!=OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */ + + me= par->data; + mvert= me->mvert; + mvert+= (me->totvert-1); + VECCOPY(pvec, mvert->co); + Mat4MulVecfl(pmat, pvec); + + mvert= me->mvert; + totvert= me->totvert; + + for(a=0; a<totvert; a++, mvert++) { + + /* bereken de extra offset (tov. nulpunt parent) die de kinderen krijgen */ + VECCOPY(vec, mvert->co); + Mat4MulVecfl(pmat, vec); + VecSubf(vec, vec, pmat[3]); + VecAddf(vec, vec, ob->obmat[3]); + + newob= MEM_mallocN(sizeof(Object), "newobj dupli"); + memcpy(newob, ob, sizeof(Object)); + newob->flag |= OB_FROMDUPLI; + newob->id.newid= (ID *)par; /* duplicator bewaren */ + + /* alleen de basis-ball behoeft een displist */ + if(newob->type==OB_MBALL) newob->disp.first= newob->disp.last= 0; + + VECCOPY(newob->obmat[3], vec); + + if(par->transflag & OB_DUPLIROT) { + VECCOPY(vec, mvert->no); + vec[0]= -vec[0]; vec[1]= -vec[1]; vec[2]= -vec[2]; + + q2= vectoquat(vec, ob->trackflag, ob->upflag); + + QuatToMat3(q2, mat); + Mat4CpyMat4(tmat, newob->obmat); + Mat4MulMat43(newob->obmat, tmat, mat); + } + + newob->parent= 0; + newob->track= 0; + /* newob->borig= base; */ + + BLI_addtail(&duplilist, newob); + + VECCOPY(pvec, vec); + + } + break; + } + ob= ob->parent; + } + } + base= base->next; + } +} + + +void particle_duplilist(Scene *sce, Object *par, PartEff *paf) +{ + Object *ob, *newob; + Base *base; + Particle *pa; + float ctime, vec1[3]; + float vec[3], tmat[4][4], mat[3][3]; + float *q2; + int lay, a; + + pa= paf->keys; + if(pa==0) { + build_particle_system(par); + pa= paf->keys; + if(pa==0) return; + } + + ctime= bsystem_time(par, 0, (float)G.scene->r.cfra, 0.0); + + lay= G.scene->lay; + + base= sce->base.first; + while(base) { + + if(base->object->type>0 && (base->lay & lay) && G.obedit!=base->object) { + ob= base->object->parent; + while(ob) { + if(ob==par) { + + ob= base->object; + + pa= paf->keys; + for(a=0; a<paf->totpart; a++, pa+=paf->totkey) { + + if(ctime > pa->time) { + if(ctime < pa->time+pa->lifetime) { + + newob= MEM_mallocN(sizeof(Object), "newobj dupli"); + memcpy(newob, ob, sizeof(Object)); + newob->flag |= OB_FROMDUPLI; + newob->id.newid= (ID *)par; /* duplicator bewaren */ + + /* alleen de basis-ball behoeft een displist */ + if(newob->type==OB_MBALL) newob->disp.first= newob->disp.last= 0; + + where_is_particle(paf, pa, ctime, vec); + if(paf->stype==PAF_VECT) { + where_is_particle(paf, pa, ctime+1.0f, vec1); + + VecSubf(vec1, vec1, vec); + q2= vectoquat(vec1, ob->trackflag, ob->upflag); + + QuatToMat3(q2, mat); + Mat4CpyMat4(tmat, newob->obmat); + Mat4MulMat43(newob->obmat, tmat, mat); + } + + VECCOPY(newob->obmat[3], vec); + + newob->parent= 0; + newob->track= 0; + + BLI_addtail(&duplilist, newob); + + } + } + } + break; + } + ob= ob->parent; + } + } + base= base->next; + } +} + + +void free_duplilist() +{ + Object *ob; + + while( ob= duplilist.first) { + BLI_remlink(&duplilist, ob); + MEM_freeN(ob); + } + +} + +void make_duplilist(Scene *sce, Object *ob) +{ + PartEff *paf; + + if(ob->transflag & OB_DUPLI) { + if(ob->transflag & OB_DUPLIVERTS) { + if(ob->type==OB_MESH) { + if(ob->transflag & OB_DUPLIVERTS) { + if( paf=give_parteff(ob) ) particle_duplilist(sce, ob, paf); + else vertex_duplilist(sce, ob); + } + } + else if(ob->type==OB_FONT) { + font_duplilist(ob); + } + } + else if(ob->transflag & OB_DUPLIFRAMES) frames_duplilist(ob); + } +} + diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c new file mode 100644 index 00000000000..86ce2faa07c --- /dev/null +++ b/source/blender/blenkernel/intern/armature.c @@ -0,0 +1,1451 @@ +/** + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <stdlib.h> +#include <math.h> +#include <string.h> +#include <stdio.h> +#include "MEM_guardedalloc.h" + +#include "nla.h" + +#include "BLI_arithb.h" +#include "BLI_blenlib.h" + +#include "DNA_mesh_types.h" +#include "DNA_armature_types.h" +#include "DNA_action_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_view3d_types.h" +#include "DNA_constraint_types.h" + +#include "BKE_displist.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_library.h" +#include "BKE_blender.h" +#include "BKE_armature.h" +#include "BKE_action.h" +#include "BKE_constraint.h" +#include "BKE_object.h" +#include "BKE_object.h" +#include "BKE_deform.h" +#include "BKE_utildefines.h" + +#include "BIF_editdeform.h" + +#include "IK_solver.h" + +/* Function prototypes */ + +static void apply_pose_bonechildren (Bone* bone, bPose* pose, int doit); +static float dist_to_bone (float vec[3], float b1[3], float b2[3]); +static Bone *get_named_bone_bonechildren (Bone *bone, const char *name); +static Bone *get_indexed_bone_bonechildren (Bone *bone, int *index); +/*void make_bone_parent_matrix (Bone* bone);*/ +static void copy_bonechildren (Bone* newBone, Bone* oldBone); +static void calc_armature_deform_bonechildren (Bone *bone, float *vec, float *co, float *contrib, float obmat[][4]); +static int verify_boneptr_children (Bone *cBone, Bone *tBone); +static void where_is_bonelist_time (Object *ob, ListBase *base, float ctime); +static Bone *get_last_ik_bone (Bone *bone); +static void precalc_bonelist_posemats(ListBase *bonelist, float parlen); + +/* Globals */ +static float g_premat[4][4]; +static float g_postmat[4][4]; +static MDeformVert *g_dverts; +static ListBase *g_defbase; +static bArmature *g_defarm; + +/* Functions */ + +float get_bone_length (Bone *bone) +{ + float result[3]; + + VecSubf (result, bone->tail, bone->head); + return (float)sqrt(result[0]*result[0] + result[1]*result[1] + result[2]*result[2]); + +} + +void apply_bonemat(Bone *bone) +{ + float mat[3][3], imat[3][3], tmat[3][3]; + + if(!bone) + return; + + Mat3CpyMat4(mat, bone->obmat); + + VECCOPY(bone->loc, bone->obmat[3]); + + Mat3ToQuat(mat, bone->quat); + QuatToMat3(bone->quat, tmat); + + Mat3Inv(imat, tmat); + + Mat3MulMat3(tmat, imat, mat); + + bone->size[0]= tmat[0][0]; + bone->size[1]= tmat[1][1]; + bone->size[2]= tmat[2][2]; + +} + +void GB_build_mats (float parmat[][4], float obmat[][4], float premat[][4], float postmat[][4]) +{ + float obinv[4][4]; +#if 0 + Mat4Invert(obinv, obmat); + Mat4CpyMat4(premat, obmat); + Mat4MulMat4(postmat, parmat, obinv); + + Mat4Invert (postmat, premat); +#else + Mat4Invert(obinv, obmat); + Mat4CpyMat4(premat, obmat); + Mat4MulMat4(postmat, parmat, obinv); + + Mat4Invert (premat, postmat); +#endif +} + +void GB_init_armature_deform(ListBase *defbase, float premat[][4], float postmat[][4]) +{ + g_defbase = defbase; + Mat4CpyMat4 (g_premat, premat); + Mat4CpyMat4 (g_postmat, postmat); + +} + +void GB_validate_defgroups (Mesh *mesh, ListBase *defbase) +{ + /* Should only be called when the mesh or armature changes */ + int j, i; + MDeformVert *dvert; + + for (j=0; j<mesh->totvert; j++){ + dvert = mesh->dvert+j; + for (i=0; i<dvert->totweight; i++) + dvert->dw[i].data = ((bDeformGroup*)BLI_findlink (defbase, dvert->dw[i].def_nr))->data; + } +} + +void GB_calc_armature_deform (float *co, MDeformVert *dvert) +{ + float vec[3]={0, 0, 0}; + float contrib = 0; + int i; + Bone *bone; + + Mat4MulVecfl(g_premat, co); + + for (i=0; i<dvert->totweight; i++){ + bone = dvert->dw[i].data; + if (bone) calc_bone_deform (bone, dvert->dw[i].weight, vec, co, &contrib); + } + + if (contrib){ + vec[0]/=contrib; + vec[1]/=contrib; + vec[2]/=contrib; + } + + VecAddf (co, vec, co); + Mat4MulVecfl(g_postmat, co); +} + +static Bone *get_last_ik_bone (Bone *bone) +{ + Bone *curBone; + + for (curBone = bone->childbase.first; curBone; curBone=curBone->next){ + if (curBone->flag & BONE_IK_TOPARENT){ + return get_last_ik_bone (curBone); + } + } + + return bone; +} + +#if 0 +static Bone *get_first_ik_bone (Bone *bone) +{ + Bone *curBone; + + for (curBone = bone; curBone; curBone=curBone->parent){ + if (!bone->parent) + return curBone; + if (!bone->flag & BONE_IK_TOPARENT) + return curBone; + } + + return bone; +/* for (curBone = bone->childbase.first; curBone; curBone=curBone->next){ + if (curBone->flag & BONE_IK_TOPARENT){ + return get_last_ik_bone (curBone); + } + } +*/ + return bone; + +} +#endif + +void where_is_bone(Object *ob, Bone *bone) +{ + where_is_bone_time (ob, bone, G.scene->r.cfra); +} + +void where_is_bone_time (Object *ob, Bone *bone, float ctime) +{ + where_is_bone1_time (ob, get_last_ik_bone(bone), ctime); +} + +void rebuild_bone_parent_matrix (Bone *bone) +{ + if (!bone) + return; + + if (bone->parent) + rebuild_bone_parent_matrix(bone->parent); + + /* Get the parent inverse */ + if (bone->parent) + Mat4MulMat4(bone->parmat, bone->parent->obmat, bone->parent->parmat); + else + Mat4One (bone->parmat); + +} +void where_is_bone1_time (Object *ob, Bone *bone, float ctime) +/* Assumes the pose has already been retrieved from the action */ +/* Also assumes where_is_object has been called for owner */ +{ + bPose *pose; + bPoseChannel *chan; + bArmature *arm; + float imat[4][4]; + float totmat[4][4]; + Object conOb; + + pose = ob->pose; + if (!pose) + return; + + arm = get_armature(ob); + + /* Ensure there is achannel for this bone*/ + verify_pose_channel (pose, bone->name); + + /* Search the pose for a channel with the same name, and copy the + transformations from the channel into the bone */ + for (chan=pose->chanbase.first; chan; chan=chan->next){ + if (!strcmp (chan->name, bone->name)){ + +#if 1 /* If 1 attempt to use pose caching features */ + /* Bail out if we've been recalced recently */ + if (chan->flag & PCHAN_DONE){ + Mat4CpyMat4 (bone->obmat, chan->obmat); + if (bone->parent){ + if ((bone->flag & BONE_IK_TOPARENT)) + where_is_bone1_time (ob, bone->parent, ctime); + else + where_is_bone_time (ob, bone->parent, ctime); + } + return; + } + else + chan->flag |= PCHAN_DONE; +#endif + break; + } + } + +#if 1 + /* Ensure parents have been evaluated */ + if (bone->parent){ + if ((bone->flag & BONE_IK_TOPARENT)) + where_is_bone1_time (ob, bone->parent, ctime); + else + where_is_bone_time (ob, bone->parent, ctime); + } + + /* Build the parent matrix : Depreciated */ +// if (bone->parent) +// Mat4MulMat4(bone->parmat, bone->parent->obmat, bone->parent->parmat); +// else +// Mat4One (bone->parmat); +#endif + + if (arm){ + if ((arm->flag & ARM_RESTPOS) || ((G.obedit && (ob->data == G.obedit->data)))){ + Mat4One (bone->obmat); + Mat4One (chan->obmat); + return; + } + } + + if (bone->flag & BONE_IK_TOPARENT){ + bone->loc[0]=bone->loc[1]=bone->loc[2]=0.0F; + } + bone_to_mat4(bone, bone->obmat); + + /* Do constraints */ + // clear_workob(); + + memset(&conOb, 0, sizeof(Object)); + conOb.size[0]= conOb.size[1]= conOb.size[2]= 1.0; + + /* Collect the constraints from the pose */ + conOb.constraints.first = chan->constraints.first; + conOb.constraints.last = chan->constraints.last; + + /* Totmat takes bone's obmat to worldspace */ + + { + float parmat[4][4]; + float temp[4][4]; + + Mat4CpyMat4 (temp, bone->obmat); + Mat4One (bone->obmat); + get_objectspace_bone_matrix(bone, parmat, 1, 1); + Mat4CpyMat4 (bone->obmat, temp); + Mat4MulMat4 (totmat, parmat, ob->obmat); + } + + /* Build a workob to pass the bone to the constraint solver */ + conOb.data = ob->data; + conOb.type = ob->type; + conOb.parent = ob; + conOb.trackflag = ob->trackflag; + conOb.upflag = ob->upflag; + + VECCOPY(conOb.size, bone->size); + + Mat4MulMat4 (conOb.obmat, bone->obmat, totmat); + + /* Solve */ + solve_constraints (&conOb, TARGET_BONE, (void*)bone, ctime); + + { + float parmat[4][4]; + float temp[4][4]; + + Mat4CpyMat4 (temp, bone->obmat); + Mat4One (bone->obmat); + get_objectspace_bone_matrix(bone, parmat, 1, 1); + Mat4CpyMat4 (bone->obmat, temp); + Mat4MulMat4 (totmat, parmat, ob->obmat); + } + + VECCOPY(bone->size, conOb.size); + + /* Take out of worldspace */ + Mat4Invert (imat, totmat); + Mat4MulMat4 (bone->obmat, conOb.obmat, imat); + Mat4CpyMat4 (chan->obmat, bone->obmat); + +} + + +bArmature *get_armature(Object *ob) +{ + if(ob==NULL) return NULL; + if(ob->type==OB_ARMATURE) return ob->data; + else return NULL; +} + +void init_armature_deform(Object *parent, Object *ob) +{ + bArmature *arm; + bDeformGroup *dg; + Bone *curBone; + MDeformVert *dvert; + int totverts; + float obinv[4][4]; + int i, j; + + arm = get_armature(parent); + if (!arm) + return; + + if (ob) + where_is_object (ob); + +#if 1 + apply_pose_armature (arm, parent->pose, 1); /* Hopefully doit parameter can be set to 0 in future */ + where_is_armature (parent); +#else + apply_pose_armature (arm, parent->pose, 0); +#endif + + g_defbase = &ob->defbase; + g_defarm = arm; + + Mat4Invert(obinv, ob->obmat); + Mat4CpyMat4(g_premat, ob->obmat); + Mat4MulMat4(g_postmat, parent->obmat, obinv); + + Mat4Invert (g_premat, g_postmat); + + /* Store the deformation verts */ + if (ob->type==OB_MESH){ + g_dverts = ((Mesh*)ob->data)->dvert; + totverts = ((Mesh*)ob->data)->totvert; + } + else{ + g_dverts=NULL; + totverts=0; + } + + /* Precalc bone defmats */ + precalc_armature_posemats (arm); + + for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){ + precalc_bone_defmat(curBone); + } + + /* Validate bone data in bDeformGroups */ + + for (dg=g_defbase->first; dg; dg=dg->next) + dg->data = (void*)get_named_bone(arm, dg->name); + + if (g_dverts){ + for (j=0; j<totverts; j++){ + dvert = g_dverts+j; + for (i=0; i<dvert->totweight; i++){ + bDeformGroup *fg; + fg = BLI_findlink (g_defbase, dvert->dw[i].def_nr); + + if (fg) + dvert->dw[i].data = fg->data; + else + dvert->dw[i].data = NULL; + } + } + } +} + +void get_bone_root_pos (Bone* bone, float vec[3], int posed) +{ + Bone *curBone; + float mat[4][4]; + + get_objectspace_bone_matrix(bone, mat, 1, posed); + VECCOPY (vec, mat[3]); + return; + + rebuild_bone_parent_matrix(bone); + if (posed){ + + get_objectspace_bone_matrix(bone, mat, 1, posed); + VECCOPY (vec, mat[3]); + } + else { + vec[0]=vec[1]=vec[2]=0.0F; + for (curBone=bone; curBone; curBone=curBone->parent){ + if (curBone==bone) + VecAddf (vec, vec, curBone->head); + else + VecAddf (vec, vec, curBone->tail); + } + } +} + +void get_bone_tip_pos (Bone* bone, float vec[3], int posed) +{ + Bone *curBone; + float mat[4][4], tmat[4][4], rmat[4][4], bmat[4][4], fmat[4][4]; + + get_objectspace_bone_matrix(bone, mat, 0, posed); + VECCOPY (vec, mat[3]); + return; + + rebuild_bone_parent_matrix(bone); + if (posed){ + + Mat4One (mat); + + for (curBone = bone; curBone; curBone=curBone->parent){ + Mat4One (bmat); + /* [BMAT] This bone's offset */ + VECCOPY (bmat[3], curBone->head); + if (curBone==bone){ + Mat4One (tmat); + VecSubf (tmat[3], curBone->tail, curBone->head); + Mat4MulMat4 (bmat, tmat, curBone->obmat); + VecAddf (bmat[3], bmat[3], curBone->head); + } + else + VecAddf (bmat[3], bmat[3], curBone->obmat[3]); // Test + + /* [RMAT] Parent's bone length = parent rotmat * bone length */ + if (curBone->parent){ + Mat4One (tmat); + VecSubf (tmat[3], curBone->parent->tail, curBone->parent->head); + Mat4MulMat4 (rmat, tmat, curBone->parent->obmat); + VecSubf (rmat[3], rmat[3], curBone->parent->obmat[3]); + } + else + Mat4One (rmat); + + Mat4MulSerie (fmat, rmat, bmat, mat, 0, 0, 0, 0, 0); + Mat4CpyMat4 (mat, fmat); + } + + VECCOPY (vec, mat[3]); + } + else{ + vec[0]=vec[1]=vec[2]=0.0F; + for (curBone=bone; curBone; curBone=curBone->parent){ + VecAddf (vec, vec, curBone->tail); + } + } +} + +int verify_boneptr (bArmature *arm, Bone *bone) +{ + /* Ensures that a given bone exists in an armature */ + Bone *curBone; + + if (!arm) + return 0; + + for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){ + if (verify_boneptr_children (curBone, bone)) + return 1; + } + + return 0; +} + +static int verify_boneptr_children (Bone *cBone, Bone *tBone) +{ + Bone *curBone; + + if (cBone == tBone) + return 1; + + for (curBone=cBone->childbase.first; curBone; curBone=curBone->next){ + if (verify_boneptr_children (curBone, tBone)) + return 1; + } + return 0; +} + + +static float dist_to_bone (float vec[3], float b1[3], float b2[3]) +{ +/* float dist=0; */ + float bdelta[3]; + float pdelta[3]; + float hsqr, a, l; + + VecSubf (bdelta, b2, b1); + l = Normalise (bdelta); + + VecSubf (pdelta, vec, b1); + + a = bdelta[0]*pdelta[0] + bdelta[1]*pdelta[1] + bdelta[2]*pdelta[2]; + hsqr = ((pdelta[0]*pdelta[0]) + (pdelta[1]*pdelta[1]) + (pdelta[2]*pdelta[2])); + + if (a < 0.0F){ + //return 100000; + /* If we're past the end of the bone, do some weird field attenuation thing */ + return ((b1[0]-vec[0])*(b1[0]-vec[0]) +(b1[1]-vec[1])*(b1[1]-vec[1]) +(b1[2]-vec[2])*(b1[2]-vec[2])) ; + } + else if (a > l){ + //return 100000; + /* If we're past the end of the bone, do some weird field attenuation thing */ + return ((b2[0]-vec[0])*(b2[0]-vec[0]) +(b2[1]-vec[1])*(b2[1]-vec[1]) +(b2[2]-vec[2])*(b2[2]-vec[2])) ; + } + else { + return (hsqr - (a*a)); + } + + +} + +static void calc_armature_deform_bonechildren (Bone *bone, float *vec, float *co, float *contrib, float obmat[][4]) +{ + Bone *curBone; + float root[3]; + float tip[3]; + float dist, fac, ifac; + float cop[3]; + float bdsqr; + + + get_bone_root_pos (bone, root, 0); + get_bone_tip_pos (bone, tip, 0); + + bdsqr = bone->dist*bone->dist; + VECCOPY (cop, co); + + dist = dist_to_bone(cop, root, tip); + + if ((dist) <= bdsqr){ + fac = (dist)/bdsqr; + ifac = 1.0F-fac; + + ifac*=bone->weight; + + if (!vec) + (*contrib) +=ifac; + else{ + ifac*=(1.0F/(*contrib)); + + VECCOPY (cop, co); + + Mat4MulVecfl(bone->defmat, cop); + + VecSubf (cop, cop, co); // Make this a delta from the base position + cop[0]*=ifac; cop[1]*=ifac; cop[2]*=ifac; + VecAddf (vec, vec, cop); + + } + } + +// calc_bone_deform (bone, bone->weight, vec, co, contrib, obmat); + for (curBone = bone->childbase.first; curBone; curBone=curBone->next) + calc_armature_deform_bonechildren (curBone, vec, co, contrib, obmat); +} + +void precalc_bone_irestmat (Bone *bone) +{ + float restmat[4][4]; + + get_objectspace_bone_matrix(bone, restmat, 1, 0); + Mat4Invert (bone->irestmat, restmat); +} + +static void precalc_bonelist_posemats(ListBase *bonelist, float parlen) +{ + Bone *curBone; + float length; + float T_parlen[4][4]; + float T_root[4][4]; + float M_obmat[4][4]; + float R_bmat[4][4]; + float M_accumulatedMatrix[4][4]; + float delta[3]; + + for (curBone = bonelist->first; curBone; curBone=curBone->next){ + + /* Get the length translation (length along y axis) */ + length = get_bone_length(curBone); + + /* Get the bone's root offset (in the parent's coordinate system) */ + Mat4One (T_root); + VECCOPY (T_root[3], curBone->head); + + /* Compose the restmat */ + VecSubf(delta, curBone->tail, curBone->head); + make_boneMatrixvr(R_bmat, delta, curBone->roll); + + /* Retrieve the obmat (user transformation) */ + Mat4CpyMat4 (M_obmat, curBone->obmat); + + /* Compose the accumulated matrix (i.e. parent matrix * parent translation ) */ + if (curBone->parent){ + Mat4One (T_parlen); + T_parlen[3][1] = parlen; + Mat4MulMat4 (M_accumulatedMatrix, T_parlen, curBone->parent->posemat); + } + else + Mat4One (M_accumulatedMatrix); + + /* Compose the matrix for this bone */ + Mat4MulSerie (curBone->posemat, M_accumulatedMatrix, T_root, R_bmat, M_obmat, NULL, NULL, NULL, NULL); + + precalc_bonelist_posemats(&curBone->childbase, length); + } +} + +void precalc_armature_posemats (bArmature *arm) +{ + precalc_bonelist_posemats(&arm->bonebase, 0.0); +} + +void precalc_bone_defmat (Bone *bone) +{ + Bone *curBone; +#if 0 + float restmat[4][4]; + float posemat[4][4]; + float imat[4][4]; + + /* Store restmat and restmat inverse - Calculate once when leaving editmode */ + /* Store all bones' posemats - Do when applied */ + + /* EXPENSIVE! Don't do this! */ + get_objectspace_bone_matrix(bone, restmat, 1, 0); + get_objectspace_bone_matrix(bone, posemat, 1, 1); + Mat4Invert (imat, restmat); + Mat4MulMat4 (bone->defmat, imat, posemat); + /* /EXPENSIVE */ +#else + Mat4MulMat4 (bone->defmat, bone->irestmat, bone->posemat); +#endif + for (curBone = bone->childbase.first; curBone; curBone=curBone->next){ + precalc_bone_defmat(curBone); + } +} + +void calc_bone_deform (Bone *bone, float weight, float *vec, float *co, float *contrib) +{ + float cop[3]; + + if (!weight) + return; + + VECCOPY (cop, co); + + Mat4MulVecfl(bone->defmat, cop); + + vec[0]+=(cop[0]-co[0])*weight; + vec[1]+=(cop[1]-co[1])*weight; + vec[2]+=(cop[2]-co[2])*weight; + + (*contrib)+=weight; +} + +void calc_armature_deform (Object *ob, float *co, int index) +{ + bArmature *arm; + Bone *bone; + Bone *curBone; + float vec[3]; + float contrib=0; + int i; + MDeformVert *dvert = g_dverts+index; + + arm=g_defarm; + vec[0]=vec[1]=vec[2]=0; + + /* Apply the object's matrix */ + Mat4MulVecfl(g_premat, co); + + if (g_dverts){ + for (i=0; i<dvert->totweight; i++){ + bone = dvert->dw[i].data; + if (bone) calc_bone_deform (bone, dvert->dw[i].weight, vec, co, &contrib); + } + + if (contrib){ + vec[0]/=contrib; + vec[1]/=contrib; + vec[2]/=contrib; + } + VecAddf (co, vec, co); + Mat4MulVecfl(g_postmat, co); + return; + } + + + // Count the number of interested bones + for (curBone = arm->bonebase.first; curBone; curBone=curBone->next) + calc_armature_deform_bonechildren (curBone, NULL, co, &contrib, ob->obmat); + + // Do the deformation + for (curBone = arm->bonebase.first; curBone; curBone=curBone->next) + calc_armature_deform_bonechildren (curBone, vec, co, &contrib, ob->obmat); + + VecAddf (co, vec, co); + Mat4MulVecfl(g_postmat, co); +} + +void apply_pose_armature (bArmature* arm, bPose* pose, int doit) +{ + Bone *curBone; + for (curBone = arm->bonebase.first; curBone; curBone=curBone->next){ + apply_pose_bonechildren (curBone, pose, doit); + } +} + +void where_is_armature (Object *ob) +{ + where_is_object (ob); + where_is_armature_time(ob, (float)G.scene->r.cfra); +} + +void where_is_armature_time (Object *ob, float ctime) +{ + bArmature *arm; + + arm = get_armature(ob); + if (!arm) + return; + + where_is_bonelist_time (ob, &arm->bonebase, ctime); + +} + +static void where_is_bonelist_time (Object *ob, ListBase *base, float ctime) +{ + Bone *curBone; + + for (curBone=base->first; curBone; curBone=curBone->next){ + if (!curBone->childbase.first) + where_is_bone1_time (ob, curBone, ctime); + + where_is_bonelist_time(ob, &curBone->childbase, ctime); + } +} +static void apply_pose_bonechildren (Bone* bone, bPose* pose, int doit) +{ + Bone *curBone; + bPoseChannel *chan; + + if (!pose){ + + bone->dsize[0]=bone->dsize[1]=bone->dsize[2]=1.0F; + bone->size[0]=bone->size[1]=bone->size[2]=1.0F; + + bone->dquat[0]=bone->dquat[1]=bone->dquat[2]=bone->dquat[3]=0; + bone->quat[0]=bone->quat[1]=bone->quat[2]=bone->quat[3]=0.0F; + + bone->dloc[0]=bone->dloc[1]=bone->dloc[2]=0.0F; + bone->loc[0]=bone->loc[1]=bone->loc[2]=0.0F; + } + + // Ensure there is achannel for this bone + verify_pose_channel (pose, bone->name); + + // Search the pose for a channel with the same name + if (pose){ + for (chan=pose->chanbase.first; chan; chan=chan->next){ + if (!strcmp (chan->name, bone->name)){ + if (chan->flag & POSE_LOC) + memcpy (bone->loc, chan->loc, sizeof (bone->loc)); + if (chan->flag & POSE_SIZE) + memcpy (bone->size, chan->size, sizeof (bone->size)); + if (chan->flag & POSE_ROT) + memcpy (bone->quat, chan->quat, sizeof (bone->quat)); + + if (doit){ + bone_to_mat4(bone, bone->obmat); + } + else{ + Mat4CpyMat4 (bone->obmat, chan->obmat); + } + + + break; + } + } + } + + for (curBone = bone->childbase.first; curBone; curBone=curBone->next){ + apply_pose_bonechildren (curBone, pose, doit); + } +} + +void make_boneMatrixvr (float outmatrix[][4],float delta[3], float roll) +/* Calculates the rest matrix of a bone based + On its vector and a roll around that vector */ +{ + float nor[3],axis[3],target[3]={0,1,0}; + float theta; + float rMatrix[3][3], bMatrix[3][3], fMatrix[3][3]; + + VECCOPY (nor,delta); + Normalise (nor); + + /* Find Axis & Amount for bone matrix*/ + Crossf (axis,target,nor); + Normalise (axis); + theta=(float) acos (Inpf (target,nor)); + + /* Make Bone matrix*/ + VecRotToMat3(axis, theta, bMatrix); + + /* Make Roll matrix*/ + VecRotToMat3(nor, roll, rMatrix); + + /* Combine and output result*/ + Mat3MulMat3 (fMatrix,rMatrix,bMatrix); + Mat4CpyMat3 (outmatrix,fMatrix); +} + +void make_boneMatrix (float outmatrix[][4], Bone *bone) +/* Calculates the rest matrix of a bone based + On its vector and a roll around that vector */ +{ + float delta[3]; + float parmat[4][4], imat[4][4], obmat[4][4]; + + if (bone->parent){ + VecSubf (delta, bone->parent->tail, bone->parent->head); + make_boneMatrixvr(parmat, delta, bone->parent->roll); + } + else{ + Mat4One (parmat); + } + + Mat4Invert (imat, parmat); + + VecSubf (delta, bone->tail, bone->head); + make_boneMatrixvr(obmat, delta, bone->roll); + + Mat4MulMat4(outmatrix, obmat, imat); + +} + + +bArmature *add_armature() +{ + bArmature *arm; + + arm= alloc_libblock (&G.main->armature, ID_AR, "Armature"); + + if(arm) { + + + } + return arm; +} + + +void free_boneChildren(Bone *bone) +{ + Bone *child; + + if (bone) { + + child=bone->childbase.first; + if (child){ + while (child){ + free_boneChildren (child); + child=child->next; + } + BLI_freelistN (&bone->childbase); + } + } +} + +void free_bones (bArmature *arm) +{ + Bone *bone; + /* Free children (if any) */ + bone= arm->bonebase.first; + if (bone) { + while (bone){ + free_boneChildren (bone); + bone=bone->next; + } + } + + + BLI_freelistN(&arm->bonebase); +} + +void free_armature(bArmature *arm) +{ + if (arm) { +/* unlink_armature(arm);*/ + free_bones(arm); + } +} + +void make_local_armature(bArmature *arm) +{ + int local=0, lib=0; + Object *ob; + bArmature *newArm; + + if (arm->id.lib==0) + return; + if (arm->id.us==1) { + arm->id.lib= 0; + arm->id.flag= LIB_LOCAL; + new_id(0, (ID*)arm, 0); + return; + } + + if(local && lib==0) { + arm->id.lib= 0; + arm->id.flag= LIB_LOCAL; + new_id(0, (ID *)arm, 0); + } + else if(local && lib) { + newArm= copy_armature(arm); + newArm->id.us= 0; + + ob= G.main->object.first; + while(ob) { + if(ob->data==arm) { + + if(ob->id.lib==0) { + ob->data= newArm; + newArm->id.us++; + arm->id.us--; + } + } + ob= ob->id.next; + } + } +} + +static void copy_bonechildren (Bone* newBone, Bone* oldBone) +{ + Bone *curBone, *newChildBone; + + /* Copy this bone's list*/ + duplicatelist (&newBone->childbase, &oldBone->childbase); + + /* For each child in the list, update it's children*/ + newChildBone=newBone->childbase.first; + for (curBone=oldBone->childbase.first;curBone;curBone=curBone->next){ + newChildBone->parent=newBone; + copy_bonechildren(newChildBone,curBone); + newChildBone=newChildBone->next; + } +} + +bArmature *copy_armature(bArmature *arm) +{ + bArmature *newArm; + Bone *oldBone, *newBone; + + newArm= copy_libblock (arm); + duplicatelist(&newArm->bonebase, &arm->bonebase); + + /* Duplicate the childrens' lists*/ + newBone=newArm->bonebase.first; + for (oldBone=arm->bonebase.first;oldBone;oldBone=oldBone->next){ + newBone->parent=NULL; + copy_bonechildren (newBone, oldBone); + newBone=newBone->next; + }; + + return newArm; +} + + +void bone_to_mat3(Bone *bone, float mat[][3]) /* no parent */ +{ + float smat[3][3]; + float rmat[3][3]; +/* float q1[4], vec[3];*/ + + /* size */ +/* if(bone->ipo) { + vec[0]= bone->size[0]+bone->dsize[0]; + vec[1]= bone->size[1]+bone->dsize[1]; + vec[2]= bone->size[2]+bone->dsize[2]; + SizeToMat3(vec, smat); + } + else +*/ { + SizeToMat3(bone->size, smat); + } + + /* rot */ + /*if(bone->flag & BONE_QUATROT) { + if(bone->ipo) { + QuatMul(q1, bone->quat, bone->dquat); + QuatToMat3(q1, rmat); + } + else + */ { + NormalQuat(bone->quat); + QuatToMat3(bone->quat, rmat); + } +/* } +*/ + Mat3MulMat3(mat, rmat, smat); +} + +void bone_to_mat4(Bone *bone, float mat[][4]) +{ + float tmat[3][3]; + + bone_to_mat3(bone, tmat); + + Mat4CpyMat3(mat, tmat); + + VECCOPY(mat[3], bone->loc); +// VecAddf(mat[3], mat[3], bone->loc); +/* if(bone->ipo) { + mat[3][0]+= bone->dloc[0]; + mat[3][1]+= bone->dloc[1]; + mat[3][2]+= bone->dloc[2]; + } +*/ +} + +Bone *get_indexed_bone (bArmature *arm, int index) +/* + Walk the list until the index is reached +*/ +{ + Bone *bone=NULL, *curBone; + int ref=index; + + if (!arm) + return NULL; + + for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){ + bone = get_indexed_bone_bonechildren (curBone, &ref); + if (bone) + return bone; + } + + return bone; +} + +Bone *get_named_bone (bArmature *arm, const char *name) +/* + Walk the list until the bone is found +*/ +{ + Bone *bone=NULL, *curBone; + + if (!arm) return NULL; + + for (curBone=arm->bonebase.first; curBone; curBone=curBone->next){ + bone = get_named_bone_bonechildren (curBone, name); + if (bone) + return bone; + } + + return bone; +} + +static Bone *get_indexed_bone_bonechildren (Bone *bone, int *index) +{ + Bone *curBone, *rbone; + + if (!*index) + return bone; + + (*index)--; + + for (curBone=bone->childbase.first; curBone; curBone=curBone->next){ + rbone=get_indexed_bone_bonechildren (curBone, index); + if (rbone) + return rbone; + } + + return NULL; +} + +static Bone *get_named_bone_bonechildren (Bone *bone, const char *name) +{ + Bone *curBone, *rbone; + + if (!strcmp (bone->name, name)) + return bone; + + for (curBone=bone->childbase.first; curBone; curBone=curBone->next){ + rbone=get_named_bone_bonechildren (curBone, name); + if (rbone) + return rbone; + } + + return NULL; +} + +void make_displists_by_armature (Object *ob) +{ + Base *base; + + if (ob){ + for (base= G.scene->base.first; base; base= base->next){ + if ((ob==base->object->parent) && (base->lay & G.scene->lay)) + if (base->object->partype==PARSKEL ) + makeDispList(base->object); + } + } +} + +void get_objectspace_bone_matrix (struct Bone* bone, float M_accumulatedMatrix[][4], int root, int posed) +/* Gets matrix that transforms the bone to object space */ +/* This function is also used to compute the orientation of the bone for display */ +{ + Bone *curBone; + + Bone *bonelist[256]; + int bonecount=0, i; + + Mat4One (M_accumulatedMatrix); + + /* Build a list of bones from tip to root */ + for (curBone=bone; curBone; curBone=curBone->parent){ + bonelist[bonecount] = curBone; + bonecount++; + } + + /* Count through the inverted list (i.e. iterate from root to tip)*/ + for (i=0; i<bonecount; i++){ + float T_root[4][4]; + float T_len[4][4]; + float R_bmat[4][4]; + float M_obmat[4][4]; + float M_boneMatrix[4][4]; + float delta[3]; + + curBone = bonelist[bonecount-i-1]; + + /* Get the length translation (length along y axis) */ + Mat4One (T_len); + T_len[3][1] = get_bone_length(curBone); + + if ((curBone == bone) && (root)) + Mat4One (T_len); + + /* Get the bone's root offset (in the parent's coordinate system) */ + Mat4One (T_root); + VECCOPY (T_root[3], curBone->head); + + /* Compose the restmat */ + VecSubf(delta, curBone->tail, curBone->head); + make_boneMatrixvr(R_bmat, delta, curBone->roll); + + + /* Retrieve the obmat (user transformation) */ + if (posed) + Mat4CpyMat4 (M_obmat, curBone->obmat); + else + Mat4One (M_obmat); + + /* Compose the matrix for this bone */ +#if 0 + Mat4MulSerie (M_boneMatrix, M_accumulatedMatrix, T_root, M_obmat, R_bmat, T_len, NULL, NULL, NULL); +#else + Mat4MulSerie (M_boneMatrix, M_accumulatedMatrix, T_root, R_bmat, M_obmat, T_len, NULL, NULL, NULL); +#endif + Mat4CpyMat4 (M_accumulatedMatrix, M_boneMatrix); + } + + +} + +void solve_posechain (PoseChain *chain) +{ + float goal[3]; + int i; + Bone *curBone; + float M_obmat[4][4]; + float M_basischange[4][4]; + bPoseChannel *chan; + + if (!chain->solver) return; + + /** + * Transform the goal from worldspace + * to the coordinate system of the root + * of the chain. The matrix for this + * was computed when the chain was built + * in ik_chain_to_posechain + */ + + VECCOPY (goal, chain->goal); + Mat4MulVecfl (chain->goalinv, goal); + + /* Solve the chain */ + + IK_SolveChain(chain->solver, + goal, + chain->tolerance, + chain->iterations, + 0.1f, + chain->solver->segments); + + /* Copy the results back into the bones */ + for (i = chain->solver->num_segments-1, curBone=chain->target->parent; i>=0; i--, curBone=curBone->parent){ + + /* Retrieve the delta rotation from the solver */ + Mat4One(M_basischange); + Mat4CpyMat3(M_basischange, chain->solver->segments[i].basis_change); + + + /** + * Multiply the bone's usertransform by the + * basis change to get the new usertransform + */ + + Mat4CpyMat4 (M_obmat, curBone->obmat); + Mat4MulMat4 (curBone->obmat, M_basischange, M_obmat); + + /* Store the solve results on the childrens' channels */ + for (chan = chain->pose->chanbase.first; chan; chan=chan->next){ + if (!strcmp (chan->name, curBone->name)){ + Mat4CpyMat4 (chan->obmat, curBone->obmat); + break; + } + } + + } +} + +void free_posechain (PoseChain *chain) +{ + if (chain->solver) { + MEM_freeN (chain->solver->segments); + chain->solver->segments = NULL; + IK_FreeChain(chain->solver); + } + MEM_freeN (chain); +} + +PoseChain *ik_chain_to_posechain (Object *ob, Bone *bone) +{ + IK_Segment_Extern *segs; + PoseChain *chain = NULL; + Bone *curBone, *rootBone; + int segcount, curseg, icurseg; + float imat[4][4]; + Bone *bonelist[256]; + float rootmat[4][4]; + float bonespace[4][4]; + + /** + * Some interesting variables in this function: + * + * Bone->obmat Bone's user transformation; + * It is initialized in where_is_bone1_time + * + * rootmat Bone's coordinate system, computed by + * get_objectspace_bone_matrix. Takes all + * parents transformations into account. + */ + + + + /* Ensure that all of the bone parent matrices are correct */ + + /* Find the chain's root & count the segments needed */ + segcount = 0; + for (curBone = bone; curBone; curBone=curBone->parent){ + rootBone = curBone; + if (curBone!=bone){ + bonelist[segcount]=curBone; + segcount++; + } + if (!curBone->parent) + break; + else if (!(curBone->flag & BONE_IK_TOPARENT)) + break; + } + + if (!segcount) + return NULL; + + + /** + * Initialize a record to store information about the original bones + * This will be the return value for this function. + */ + + chain = MEM_callocN(sizeof(PoseChain), "posechain"); + chain->solver = IK_CreateChain(); + chain->target = bone; + chain->root = rootBone; + chain->pose = ob->pose; + + /* Allocate some IK segments */ + segs = MEM_callocN (sizeof(IK_Segment_Extern)*segcount, "iksegments"); + + + /** + * Remove the offset from the first bone in the chain and take the target to chainspace + */ + + + get_objectspace_bone_matrix(rootBone, bonespace, 1, 1); + Mat4One (rootmat); + VECCOPY (rootmat[3], bonespace[3]); + + /* Take the target to bonespace */ + Mat4MulMat4 (imat, rootmat, ob->obmat); + Mat4Invert (chain->goalinv, imat); + + + /** + * Build matrices from the root to the tip + * We count backwards through the bone list (which is sorted tip to root) + * and forwards through the ik_segment list + */ + + for (curseg = segcount-1; curseg>=0; curseg--){ + float M_basismat[4][4]; + float R_parmat[4][4]; + float iR_parmat[4][4]; + float R_bonemat[4][4]; + + /* Retrieve the corresponding bone for this segment */ + icurseg=segcount-curseg-1; + curBone = bonelist[curseg]; + + /* Get the basis matrix */ + Mat4One (R_parmat); + get_objectspace_bone_matrix(curBone, R_bonemat, 1, 1); + R_bonemat[3][0]=R_bonemat[3][1]=R_bonemat[3][2]=0.0F; + + if (curBone->parent && (curBone->flag & BONE_IK_TOPARENT)){ + get_objectspace_bone_matrix(curBone->parent, R_parmat, 1, 1); + R_parmat[3][0]=R_parmat[3][1]=R_parmat[3][2]=0.0F; + } + + Mat4Invert(iR_parmat, R_parmat); + Mat4MulMat4(M_basismat, R_bonemat, iR_parmat); + + /* Copy the matrix into the basis and transpose */ + Mat3CpyMat4(segs[icurseg].basis, M_basismat); + Mat3Transp(segs[icurseg].basis); + + /* Fill out the IK segment */ + segs[icurseg].length = get_bone_length(curBone); + + }; + + IK_LoadChain(chain->solver, segs, segcount); + return chain; +} + + + +void precalc_bonelist_irestmats (ListBase* bonelist) +{ + Bone *curbone; + + if (!bonelist) + return; + + for (curbone = bonelist->first; curbone; curbone=curbone->next){ + precalc_bone_irestmat(curbone); + precalc_bonelist_irestmats(&curbone->childbase); + } +} diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c new file mode 100644 index 00000000000..23927fd793c --- /dev/null +++ b/source/blender/blenkernel/intern/blender.c @@ -0,0 +1,343 @@ + +/* blender.c jan 94 MIXED MODEL + * + * algemene hulp funkties en data + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifndef WIN32 + #include <unistd.h> // for read close + #include <sys/param.h> // for MAXPATHLEN +#else + #include <io.h> // for open close read +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <fcntl.h> // for open + +#include "MEM_guardedalloc.h" +#include "DNA_listBase.h" +#include "DNA_sdna_types.h" +#include "DNA_userdef_types.h" +#include "DNA_object_types.h" +#include "DNA_curve_types.h" + +#include "BLI_blenlib.h" +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" + +#ifdef WIN32 +#include "BLI_winstuff.h" +#endif + +#include "DNA_screen_types.h" + +#include "BKE_library.h" +#include "BKE_blender.h" +#include "BKE_displist.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_object.h" +#include "BKE_scene.h" +#include "BKE_effect.h" +#include "BKE_curve.h" +#include "BKE_font.h" + +#include "BKE_bad_level_calls.h" /* for BPY_do_pyscript */ + +#include "BLO_readfile.h" /* for BLO_read_file */ + +#include "BKE_bad_level_calls.h" // for freeAllRad editNurb free_editMesh free_editText free_editArmature +#include "BKE_utildefines.h" // O_BINARY FALSE + +#include "nla.h" + +Global G; +UserDef U; + +char versionstr[48]= ""; + +/* ************************************************ */ +/* pushpop faciliteit: om tijdelijk data te bewaren */ + +ListBase ppmain={0, 0}; + +typedef struct PushPop { + struct PushPop *next, *prev; + void *data; + int len; +} PushPop; + +void pushdata(void *data, int len) +{ + PushPop *pp; + + pp= MEM_mallocN(sizeof(PushPop), "pushpop"); + BLI_addtail(&ppmain, pp); + pp->data= MEM_mallocN(len, "pushpop"); + pp->len= len; + memcpy(pp->data, data, len); +} + +void popfirst(void *data) +{ + PushPop *pp; + + pp= ppmain.first; + if(pp) { + memcpy(data, pp->data, pp->len); + BLI_remlink(&ppmain, pp); + MEM_freeN(pp->data); + MEM_freeN(pp); + } + else printf("error in popfirst\n"); +} + +void poplast(void *data) +{ + PushPop *pp; + + pp= ppmain.last; + if(pp) { + memcpy(data, pp->data, pp->len); + BLI_remlink(&ppmain, pp); + MEM_freeN(pp->data); + MEM_freeN(pp); + } + else printf("error in poplast\n"); +} + +void free_pushpop() +{ + PushPop *pp; + + pp= ppmain.first; + while(pp) { + BLI_remlink(&ppmain, pp); + MEM_freeN(pp->data); + MEM_freeN(pp); + } +} + +void pushpop_test() +{ + if(ppmain.first) printf("pushpop not empty\n"); + free_pushpop(); +} + + + +/* ********** vrijgeven ********** */ + +void free_blender(void) +{ + free_main(G.main); + G.main= NULL; + + IMB_freeImBufdata(); /* imbuf lib */ +} + +void duplicatelist(ListBase *list1, ListBase *list2) /* kopie van 2 naar 1 */ +{ + struct Link *link1, *link2; + + list1->first= list1->last= 0; + + link2= list2->first; + while(link2) { + + link1= MEM_dupallocN(link2); + BLI_addtail(list1, link1); + + link2= link2->next; + } +} + +void initglobals(void) +{ + memset(&G, 0, sizeof(Global)); + + U.savetime= 1; + + G.animspeed= 4; + + G.main= MEM_callocN(sizeof(Main), "initglobals"); + + strcpy(G.ima, "//"); + + G.version= BLENDER_VERSION; + + G.order= 1; + G.order= (((char*)&G.order)[0])?L_ENDIAN:B_ENDIAN; + + sprintf(versionstr, "www.blender.nl %d", G.version); + + clear_workob(); /* object.c */ +} + +/***/ + +static void clear_global(void) { + extern short winqueue_break; /* screen.c */ + + freeAllRad(); + free_main(G.main); /* free all lib data */ + freefastshade(); /* anders oude lampgegevens */ + + + /* hangende vars voorkomen */ + R.backbuf= 0; + + /* force all queues to be left */ + winqueue_break= 1; + + if (G.obedit) { + freeNurblist(&editNurb); + free_editMesh(); + free_editText(); + free_editArmature(); + } + + G.curscreen= NULL; + G.scene= NULL; + G.main= NULL; + + G.obedit= NULL; + G.obpose= NULL; + G.saction= NULL; + G.buts= NULL; + G.v2d= NULL; + G.vd= NULL; + G.soops= NULL; + G.sima= NULL; + G.sipo= NULL; + + G.f &= ~(G_WEIGHTPAINT + G_VERTEXPAINT + G_FACESELECT); +} + +static void setup_app_data(BlendFileData *bfd, char *filename) { + Object *ob; + + clear_global(); + + G.save_over = 1; + + G.main= bfd->main; + if (bfd->user) { + U= *bfd->user; + MEM_freeN(bfd->user); + } + + R.winpos= bfd->winpos; + R.displaymode= bfd->displaymode; + G.curscreen= bfd->curscreen; + G.fileflags= bfd->fileflags; + + G.scene= G.curscreen->scene; + + /* weinig DispListen, wel text_to_curve */ + // this should be removed!!! But first a better displist system (ton) + for (ob= G.main->object.first; ob; ob= ob->id.next) { + if(ob->type==OB_FONT) { + Curve *cu= ob->data; + if(cu->nurb.first==0) text_to_curve(ob, 0); + } + else if(ob->type==OB_MESH) { + makeDispList(ob); + if(ob->effect.first) object_wave(ob); + } + } + + if (!G.background) { + setscreen(G.curscreen); + } + /* baseflags */ + set_scene_bg(G.scene); + + if (G.f & G_SCENESCRIPT) { + BPY_do_pyscript(&G.scene->id, SCRIPT_ONLOAD); + } + + strcpy(G.sce, filename); + strcpy(G.main->name, filename); /* is gegarandeerd current file */ + + MEM_freeN(bfd); +} + +int BKE_read_file(char *dir, void *type_r) { + BlendReadError bre; + BlendFileData *bfd; + + if (!G.background) + waitcursor(1); + + bfd= BLO_read_from_file(dir, &bre); + if (bfd) { + if (type_r) + *((BlenFileType*)type_r)= bfd->type; + + setup_app_data(bfd, dir); + } else { + error("Loading %s failed: %s", dir, BLO_bre_as_string(bre)); + } + + if (!G.background) + waitcursor(0); + + return (bfd?1:0); +} + +int BKE_read_file_from_memory(char* filebuf, int filelength, void *type_r) +{ + BlendReadError bre; + BlendFileData *bfd; + + if (!G.background) + waitcursor(1); + + bfd= BLO_read_from_memory(filebuf, filelength, &bre); + if (bfd) { + if (type_r) + *((BlenFileType*)type_r)= bfd->type; + + setup_app_data(bfd, "<memory>"); + } else { + error("Loading failed: %s", BLO_bre_as_string(bre)); + } + + if (!G.background) + waitcursor(0); + + return (bfd?1:0); +} diff --git a/source/blender/blenkernel/intern/bmfont.c b/source/blender/blenkernel/intern/bmfont.c new file mode 100644 index 00000000000..c5c4221a076 --- /dev/null +++ b/source/blender/blenkernel/intern/bmfont.c @@ -0,0 +1,293 @@ +/** + * bmfont.c + * + * 04-10-2000 frank + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * + */ + +/** + * Two external functions: + * + * void detectBitmapFont(ImBuf *ibuf) + * detects if an image buffer contains a bitmap font. It makes the + * specific bitmap data which is stored in the bitmap invisible to blender. + * + * void matrixGlyph(ImBuf * ibuf, unsigned short unicode, *float x 7) + * returns all the information about the character (unicode) in the floats + * + * Room for improvement: + * add kerning data in the bitmap + * all calculations in matrixGlyph() are static and could be done during + * initialization + */ + +#include <stdio.h> + +#include "MEM_guardedalloc.h" +#include "BLI_blenlib.h" +#include "BKE_global.h" +#include "IMB_imbuf_types.h" + +#include "BKE_bmfont.h" +#include "BKE_bmfont_types.h" + +void printfGlyph(bmGlyph * glyph) +{ + printf("unicode: %d '%c'\n", glyph->unicode, glyph->unicode); + printf(" locx: %4d locy: %4d\n", glyph->locx, glyph->locy); + printf(" sizex: %3d sizey: %3d\n", glyph->sizex, glyph->sizey); + printf(" ofsx: %3d ofsy: %3d\n", glyph->ofsx, glyph->ofsy); + printf(" advan: %3d reser: %3d\n", glyph->advance, glyph->reserved); +} + +#define MAX2(x,y) ( (x)>(y) ? (x) : (y) ) +#define MAX3(x,y,z) MAX2( MAX2((x),(y)) , (z) ) + +void calcAlpha(ImBuf * ibuf) +{ + int i; + char * rect; + + if (ibuf) { + rect = (char *) ibuf->rect; + for (i = ibuf->x * ibuf->y ; i > 0 ; i--) { + rect[3] = MAX3(rect[0], rect[1], rect[2]); + rect += 4; + } + } +} + +void readBitmapFontVersion0(ImBuf * ibuf, unsigned char * rect, int step) +{ + int glyphcount, bytes, i, index, linelength, ysize; + unsigned char * buffer; + bmFont * bmfont; + + linelength = ibuf->x * step; + + glyphcount = (rect[6 * step] << 8) | rect[7 * step]; + bytes = ((glyphcount - 1) * sizeof(bmGlyph)) + sizeof(bmFont); + + ysize = (bytes + (ibuf->x - 1)) / ibuf->x; + + if (ysize < ibuf->y) { + // we're first going to copy all data into a liniar buffer. + // step can be 4 or 1 bytes, and the data is not sequential because + // the bitmap was flipped vertically. + + buffer = MEM_mallocN(bytes, "readBitmapFontVersion0:buffer"); + + index = 0; + for (i = 0; i < bytes; i++) { + buffer[i] = rect[index]; + index += step; + if (index >= linelength) { + // we've read one line, no skip to the line *before* that + rect -= linelength; + index -= linelength; + } + } + + // we're now going to endian convert the data + + bmfont = MEM_mallocN(bytes, "readBitmapFontVersion0:bmfont"); + index = 0; + + // first read the header + bmfont->magic[0] = buffer[index++]; + bmfont->magic[1] = buffer[index++]; + bmfont->magic[2] = buffer[index++]; + bmfont->magic[3] = buffer[index++]; + bmfont->version = (buffer[index] << 8) | buffer[index + 1]; index += 2; + bmfont->glyphcount = (buffer[index] << 8) | buffer[index + 1]; index += 2; + bmfont->xsize = (buffer[index] << 8) | buffer[index + 1]; index += 2; + bmfont->ysize = (buffer[index] << 8) | buffer[index + 1]; index += 2; + + for (i = 0; i < bmfont->glyphcount; i++) { + bmfont->glyphs[i].unicode = (buffer[index] << 8) | buffer[index + 1]; index += 2; + bmfont->glyphs[i].locx = (buffer[index] << 8) | buffer[index + 1]; index += 2; + bmfont->glyphs[i].locy = (buffer[index] << 8) | buffer[index + 1]; index += 2; + bmfont->glyphs[i].ofsx = buffer[index++]; + bmfont->glyphs[i].ofsy = buffer[index++]; + bmfont->glyphs[i].sizex = buffer[index++]; + bmfont->glyphs[i].sizey = buffer[index++]; + bmfont->glyphs[i].advance = buffer[index++]; + bmfont->glyphs[i].reserved = buffer[index++]; + if (G.f & G_DEBUG) { + printfGlyph(&bmfont->glyphs[i]); + } + } + + MEM_freeN(buffer); + + if (G.f & G_DEBUG) { + printf("Oldy = %d Newy = %d\n", ibuf->y, ibuf->y - ysize); + printf("glyphcount = %d\n", glyphcount); + printf("bytes = %d\n", bytes); + } + + // we've read the data from the image. Now we're going + // to crop the image vertically so only the bitmap data + // remains visible + + ibuf->y -= ysize; + ibuf->userdata = bmfont; + ibuf->userflags |= IB_BITMAPFONT; + + if (ibuf->depth < 32) { + // we're going to fake alpha here: + calcAlpha(ibuf); + } + } else { + printf("readBitmapFontVersion0: corrupted bitmapfont\n"); + } +} + +void detectBitmapFont(ImBuf *ibuf) +{ + unsigned char * rect; + unsigned short version; + long i; + + if (ibuf != NULL) { + // bitmap must have an x size that is a power of two + if (is_power_of_two(ibuf->x)) { + rect = (unsigned char *) (ibuf->rect + (ibuf->x * (ibuf->y - 1))); + // printf ("starts with: %s %c %c %c %c\n", rect, rect[0], rect[1], rect[2], rect[3]); + if (rect[0] == 'B' && rect[1] == 'F' && rect[2] == 'N' && rect[3] == 'T') { + // printf("found 8bit font !\n"); + // round y size down + // do the 8 bit font stuff. (not yet) + } else { + // we try all 4 possible combinations + for (i = 0; i < 4; i++) { + if (rect[0] == 'B' && rect[4] == 'F' && rect[8] == 'N' && rect[12] == 'T') { + // printf("found 24bit font !\n"); + // We're going to parse the file: + + version = (rect[16] << 8) | rect[20]; + + if (version == 0) { + readBitmapFontVersion0(ibuf, rect, 4); + } else { + printf("detectBitmapFont :Unsupported version %d\n", version); + } + + // on succes ibuf->userdata points to the bitmapfont + if (ibuf->userdata) { + break; + } + } + rect++; + } + } + } + } +} + +int locateGlyph(bmFont *bmfont, unsigned short unicode) +{ + int min, max, current = 0; + + if (bmfont) { + min = 0; + max = bmfont->glyphcount; + while (1) { + // look halfway for glyph + current = (min + max) >> 1; + + if (bmfont->glyphs[current].unicode == unicode) { + break; + } else if (bmfont->glyphs[current].unicode < unicode) { + // have to move up + min = current; + } else { + // have to move down + max = current; + } + + if (max - min <= 1) { + // unable to locate glyph + current = 0; + break; + } + } + } + + return(current); +} + +void matrixGlyph(ImBuf * ibuf, unsigned short unicode, + float *centerx, float *centery, + float *sizex, float *sizey, + float *transx, float *transy, + float *movex, float *movey, + float *advance) +{ + int index; + bmFont *bmfont; + + *centerx = *centery = 0.0; + *sizex = *sizey = 1.0; + *transx = *transy = 0.0; + *movex = *movey = 0.0; + *advance = 1.0; + + if (ibuf) { + bmfont = ibuf->userdata; + if (bmfont && (ibuf->userflags & IB_BITMAPFONT)) { + index = locateGlyph(bmfont, unicode); + if (index) { + + *sizex = (bmfont->glyphs[index].sizex) / (float) (bmfont->glyphs[0].sizex); + *sizey = (bmfont->glyphs[index].sizey) / (float) (bmfont->glyphs[0].sizey); + + *transx = bmfont->glyphs[index].locx / (float) ibuf->x; + *transy = (ibuf->y - bmfont->glyphs[index].locy) / (float) ibuf->y; + + *centerx = bmfont->glyphs[0].locx / (float) ibuf->x; + *centery = (ibuf->y - bmfont->glyphs[0].locy) / (float) ibuf->y; + + // 2.0 units is the default size of an object + + *movey = 1.0f - *sizey + 2.0f * (bmfont->glyphs[index].ofsy - bmfont->glyphs[0].ofsy) / (float) bmfont->glyphs[0].sizey; + *movex = *sizex - 1.0f + 2.0f * (bmfont->glyphs[index].ofsx - bmfont->glyphs[0].ofsx) / (float) bmfont->glyphs[0].sizex; + + *advance = 2.0f * bmfont->glyphs[index].advance / (float) bmfont->glyphs[0].advance; + + // printfGlyph(&bmfont->glyphs[index]); + // printf("%c %d %0.5f %0.5f %0.5f %0.5f %0.5f \n", unicode, index, *sizex, *sizey, *transx, *transy, *advance); + } + } + } +} diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c new file mode 100644 index 00000000000..9c1a4607dca --- /dev/null +++ b/source/blender/blenkernel/intern/constraint.c @@ -0,0 +1,732 @@ +/** + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <stdio.h> +#include <string.h> + +#include "MEM_guardedalloc.h" +#include "nla.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" + +#include "DNA_armature_types.h" +#include "DNA_constraint_types.h" +#include "DNA_object_types.h" +#include "DNA_action_types.h" +#include "DNA_curve_types.h" + +#include "BKE_utildefines.h" +#include "BKE_action.h" +#include "BKE_armature.h" +#include "BKE_blender.h" +#include "BKE_constraint.h" +#include "BKE_object.h" +#include "BKE_ipo.h" +#include "BKE_global.h" +#include "BKE_library.h" + +#include "blendef.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif +/* Local function prototypes */ +static void constraint_target_to_mat4 (Object *ob, const char *substring, float mat[][4], float size[3], float ctime); + +/* Functions */ + +bConstraintChannel *find_constraint_channel (ListBase *list, const char *name){ + bConstraintChannel *chan; + + for (chan = list->first; chan; chan=chan->next){ + if (!strcmp(name, chan->name)){ + return chan; + } + } + return NULL; +} + +void do_constraint_channels (ListBase *conbase, ListBase *chanbase, float ctime) +{ + bConstraint *con; + bConstraintChannel *chan; + IpoCurve *icu; + + for (con=conbase->first; con; con=con->next){ + chan = find_constraint_channel(chanbase, con->name); + if (chan && chan->ipo){ + calc_ipo(chan->ipo, ctime); + for (icu=chan->ipo->curve.first; icu; icu=icu->next){ + switch (icu->adrcode){ + case CO_ENFORCE: + con->enforce = icu->curval; + if (con->enforce<0) con->enforce=0; + else if (con->enforce>1) con->enforce=1; + break; + } + } + } + } +} + +void Mat4BlendMat4(float out[][4], float dst[][4], float src[][4], float srcweight) +{ + float squat[4], dquat[4], fquat[4]; + float ssize[3], dsize[3], fsize[4]; + float sloc[3], dloc[3], floc[3]; + float mat3[3][3], dstweight; + float qmat[3][3], smat[3][3]; + int i; + + + dstweight = 1.0F-srcweight; + + Mat3CpyMat4(mat3, dst); + Mat3ToQuat(mat3, dquat); + Mat3ToSize(mat3, dsize); + VECCOPY (dloc, dst[3]); + + Mat3CpyMat4(mat3, src); + Mat3ToQuat(mat3, squat); + Mat3ToSize(mat3, ssize); + VECCOPY (sloc, src[3]); + + /* Do the actual blend */ + for (i=0; i<3; i++){ + floc[i] = (dloc[i]*dstweight) + (sloc[i]*srcweight); + fsize[i] = 1.0f + ((dsize[i]-1.0f)*dstweight) + ((ssize[i]-1.0f)*srcweight); + fquat[i+1] = (dquat[i+1]*dstweight) + (squat[i+1]*srcweight); + } + + /* Do one more iteration for the quaternions only and normalize the quaternion if needed */ + fquat[0] = 1.0f + ((dquat[0]-1.0f)*dstweight) + ((squat[0]-1.0f)*srcweight); + NormalQuat (fquat); + + QuatToMat3(fquat, qmat); + SizeToMat3(fsize, smat); + + Mat3MulMat3(mat3, qmat, smat); + Mat4CpyMat3(out, mat3); + VECCOPY (out[3], floc); +} + +static void constraint_target_to_mat4 (Object *ob, const char *substring, float mat[][4], float size[3], float ctime) +{ + + /* Update the location of the target object */ + where_is_object_time (ob, ctime); + + /* Case OBJECT */ + if (!strlen(substring)){ + Mat4CpyMat4 (mat, ob->obmat); + VECCOPY (size, ob->size); + return; + } + + /* Case BONE */ + else { + bArmature *arm; + Bone *bone; + float bmat[4][4]; + float bsize[3]={1, 1, 1}; + + arm = get_armature(ob); + + /** + * Locate the bone (if there is one) + * Ensures that the bone's transformation is fully constrained + * (Cyclical relationships are disallowed elsewhere) + */ + bone = get_named_bone(arm, substring); + if (bone){ + where_is_bone_time(ob, bone, ctime); + get_objectspace_bone_matrix(bone, bmat, 1, 1); + VECCOPY(bsize, bone->size); + } + else + Mat4One (bmat); + + /** + * Multiply the objectspace bonematrix by the skeletons's global + * transform to obtain the worldspace transformation of the target + */ + VECCOPY(size, bsize); + Mat4MulMat4 (mat, bmat, ob->obmat); + + return; + } +} + +void clear_object_constraint_status (Object *ob) +{ + bConstraint *con; + + if (!ob) return; + + /* Clear the object's constraints */ + for (con = ob->constraints.first; con; con=con->next){ + con->flag &= ~CONSTRAINT_DONE; + } + + /* Clear the object's subdata constraints */ + switch (ob->type){ + case OB_ARMATURE: + { + clear_pose_constraint_status (ob); + } + break; + default: + break; + } +} + +short get_constraint_target (bConstraint *con, short ownertype, void* ownerdata, float mat[][4], float size[3], float ctime) +{ + short valid=0; + + switch (con->type){ + case CONSTRAINT_TYPE_NULL: + { + Mat4One(mat); + } + break; + case CONSTRAINT_TYPE_ACTION: + { + if (ownertype == TARGET_BONE){ + bActionConstraint *data = (bActionConstraint*)con->data; + bPose *pose=NULL; + bPoseChannel *pchan=NULL; + float tempmat[4][4], imat[4][4], ans[4][4], restmat[4][4], irestmat[4][4]; + float tempmat3[3][3]; + float eul[3], size[3]; + float s,t; + Bone *curBone; + Bone tbone; + int i; + + curBone = (Bone*)ownerdata; + + if (data->tar){ + constraint_target_to_mat4(data->tar, data->subtarget, tempmat, size, ctime); + valid=1; + } + else + Mat4One (tempmat); + + /* If this is a bone, undo parent transforms */ + if (strlen(data->subtarget)){ + Bone* bone; + + Mat4Invert(imat, data->tar->obmat); + bone = get_named_bone(get_armature(data->tar), data->subtarget); + if (bone){ + get_objectspace_bone_matrix(bone, restmat, 1, 0); + Mat4Invert(irestmat, restmat); + } + } + else{ + Mat4One(imat); + Mat4One(irestmat); + } + + Mat4MulSerie(ans, imat, tempmat, irestmat, NULL, NULL, NULL, NULL, NULL); + + Mat3CpyMat4(tempmat3, ans); + Mat3ToEul(tempmat3, eul); + + eul[0]*=(float)(180.0/M_PI); + eul[1]*=(float)(180.0/M_PI); + eul[2]*=(float)(180.0/M_PI); + + /* Target is the animation */ + s = (eul[data->type]-data->min)/(data->max-data->min); + if (s<0) + s=0; + if (s>1) + s=1; + + t = ( s * (data->end-data->start)) + data->start; + + /* Get the appropriate information from the action */ + pose = MEM_callocN(sizeof(bPose), "pose"); + + verify_pose_channel(pose, curBone->name); + get_pose_from_action (&pose, data->act, t); + + /* Find the appropriate channel */ + pchan = get_pose_channel(pose, curBone->name); + if (pchan){ + memset(&tbone, 0x00, sizeof(Bone)); + + VECCOPY (tbone.loc, pchan->loc); + VECCOPY (tbone.size, pchan->size); + for (i=0; i<4; i++) + tbone.quat[i]=pchan->quat[i]; + + bone_to_mat4(&tbone, mat); + + } + else{ + Mat4One(mat); + } + /* Clean up */ + clear_pose(pose); + MEM_freeN(pose); + } + + } + break; + case CONSTRAINT_TYPE_LOCLIKE: + { + bLocateLikeConstraint *data = (bLocateLikeConstraint*)con->data; + + if (data->tar){ + constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime); + valid=1; + } + else + Mat4One (mat); + } + break; + case CONSTRAINT_TYPE_ROTLIKE: + { + bRotateLikeConstraint *data; + data = (bRotateLikeConstraint*)con->data; + + if (data->tar){ + constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime); + valid=1; + } + else + Mat4One (mat); + } + break; + case CONSTRAINT_TYPE_TRACKTO: + { + bTrackToConstraint *data; + data = (bTrackToConstraint*)con->data; + + if (data->tar){ + constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime); + valid=1; + } + else + Mat4One (mat); + } + break; + case CONSTRAINT_TYPE_KINEMATIC: + { + bTrackToConstraint *data; + data = (bTrackToConstraint*)con->data; + + if (data->tar){ + constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime); + valid=1; + } + else + Mat4One (mat); + } + break; + default: + Mat4One(mat); + break; + } + + return valid; +} + +void relink_constraints (struct ListBase *list) +{ + bConstraint *con; + + for (con = list->first; con; con=con->next){ + switch (con->type){ + case CONSTRAINT_TYPE_KINEMATIC: + { + bKinematicConstraint *data; + data = con->data; + + ID_NEW(data->tar); + } + break; + case CONSTRAINT_TYPE_NULL: + { + } + break; + case CONSTRAINT_TYPE_TRACKTO: + { + bTrackToConstraint *data; + data = con->data; + + ID_NEW(data->tar); + } + break; + case CONSTRAINT_TYPE_ACTION: + { + bActionConstraint *data; + data = con->data; + + ID_NEW(data->tar); + } + break; + case CONSTRAINT_TYPE_LOCLIKE: + { + bLocateLikeConstraint *data; + data = con->data; + + ID_NEW(data->tar); + } + break; + case CONSTRAINT_TYPE_ROTLIKE: + { + bRotateLikeConstraint *data; + data = con->data; + + ID_NEW(data->tar); + } + break; + } + } +} + +void *copy_constraint_channels (ListBase *dst, ListBase *src) +{ + bConstraintChannel *dchan, *schan; + bConstraintChannel *newact=NULL; + + dst->first=dst->last=NULL; + duplicatelist(dst, src); + + for (dchan=dst->first, schan=src->first; dchan; dchan=dchan->next, schan=schan->next){ + dchan->ipo = copy_ipo(schan->ipo); + } + + return newact; +} + +bConstraintChannel *clone_constraint_channels (ListBase *dst, ListBase *src, bConstraintChannel *oldact) +{ + bConstraintChannel *dchan, *schan; + bConstraintChannel *newact=NULL; + + dst->first=dst->last=NULL; + duplicatelist(dst, src); + + for (dchan=dst->first, schan=src->first; dchan; dchan=dchan->next, schan=schan->next){ + id_us_plus((ID *)dchan->ipo); + if (schan==oldact) + newact=dchan; + } + + return newact; +} + +void copy_constraints (ListBase *dst, ListBase *src) +{ + bConstraint *con; + + dst->first=dst->last=NULL; + + duplicatelist (dst, src); + + /* Update specific data */ + if (!dst->first) + return; + + for (con = dst->first; con; con=con->next){ + switch (con->type){ + case CONSTRAINT_TYPE_ACTION: + { + bActionConstraint *data; + + con->data = MEM_dupallocN (con->data); + data = (bActionConstraint*) con->data; + } + break; + case CONSTRAINT_TYPE_LOCLIKE: + { + bLocateLikeConstraint *data; + + con->data = MEM_dupallocN (con->data); + data = (bLocateLikeConstraint*) con->data; + } + break; + case CONSTRAINT_TYPE_ROTLIKE: + { + bRotateLikeConstraint *data; + + con->data = MEM_dupallocN (con->data); + data = (bRotateLikeConstraint*) con->data; + } + break; + case CONSTRAINT_TYPE_NULL: + { + con->data = NULL; + } + break; + case CONSTRAINT_TYPE_TRACKTO: + { + bTrackToConstraint *data; + + con->data = MEM_dupallocN (con->data); + data = (bTrackToConstraint*) con->data; + } + break; + case CONSTRAINT_TYPE_KINEMATIC: + { + bKinematicConstraint *data; + + con->data = MEM_dupallocN (con->data); + data = (bKinematicConstraint*) con->data; + } + break; + default: + con->data = MEM_dupallocN (con->data); + break; + } + } +} + +void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype, void *ownerdata, float targetmat[][4]) +/* ob is likely to be a workob */ +{ + float M_oldmat[4][4]; + float M_identity[4][4]; + float enforce = 1.0; + + if (!constraint || !ob) + return; + + Mat4One (M_identity); + + /* We've already been calculated */ + if (constraint->flag & CONSTRAINT_DONE){ + return; + } + + switch (constraint->type){ + case CONSTRAINT_TYPE_ACTION: + { + float temp[4][4]; + bActionConstraint *data; + + data = constraint->data; + Mat4CpyMat4 (temp, ob->obmat); + + Mat4MulMat4(ob->obmat, targetmat, temp); + } + break; + case CONSTRAINT_TYPE_LOCLIKE: + { + bLocateLikeConstraint *data; + + data = constraint->data; + + if (data->flag & LOCLIKE_X) + ob->obmat[3][0] = targetmat[3][0]; + if (data->flag & LOCLIKE_Y) + ob->obmat[3][1] = targetmat[3][1]; + if (data->flag & LOCLIKE_Z) + ob->obmat[3][2] = targetmat[3][2]; + } + break; + case CONSTRAINT_TYPE_ROTLIKE: + { + float tmat[4][4]; + float size[3]; + + Mat4ToSize(ob->obmat, size); + + Mat4CpyMat4 (tmat, targetmat); + Mat4Ortho(tmat); + + ob->obmat[0][0] = tmat[0][0]*size[0]; + ob->obmat[0][1] = tmat[0][1]*size[1]; + ob->obmat[0][2] = tmat[0][2]*size[2]; + + ob->obmat[1][0] = tmat[1][0]*size[0]; + ob->obmat[1][1] = tmat[1][1]*size[1]; + ob->obmat[1][2] = tmat[1][2]*size[2]; + + ob->obmat[2][0] = tmat[2][0]*size[0]; + ob->obmat[2][1] = tmat[2][1]*size[1]; + ob->obmat[2][2] = tmat[2][2]*size[2]; + } + break; + case CONSTRAINT_TYPE_NULL: + { + } + break; + case CONSTRAINT_TYPE_TRACKTO: + { + bTrackToConstraint *data; + float size[3]; + + data=(bTrackToConstraint*)constraint->data; + + if (data->tar){ + + Mat4ToSize (ob->obmat, size); + + Mat4CpyMat4 (M_oldmat, ob->obmat); + + // Clear the object's rotation + ob->obmat[0][0]=ob->size[0]; + ob->obmat[0][1]=0; + ob->obmat[0][2]=0; + ob->obmat[1][0]=0; + ob->obmat[1][1]=ob->size[1]; + ob->obmat[1][2]=0; + ob->obmat[2][0]=0; + ob->obmat[2][1]=0; + ob->obmat[2][2]=ob->size[2]; + + solve_tracking(ob, targetmat); + } + } + break; + case CONSTRAINT_TYPE_KINEMATIC: + { + bKinematicConstraint *data; + float imat[4][4]; + float temp[4][4]; + float totmat[4][4]; + + data=(bKinematicConstraint*)constraint->data; + + if (data->tar && ownertype==TARGET_BONE && ownerdata){ + Bone *curBone = (Bone*)ownerdata; + PoseChain *chain; + Object *armob; + + /* Retrieve the owner armature object from the workob */ + armob = ob->parent; + + /* Make an IK chain */ + chain = ik_chain_to_posechain(armob, curBone); + if (!chain) + return; + chain->iterations = data->iterations; + chain->tolerance = data->tolerance; + + + { + float parmat[4][4]; + + /* Take the obmat to objectspace */ + Mat4CpyMat4 (temp, curBone->obmat); + Mat4One (curBone->obmat); + get_objectspace_bone_matrix(curBone, parmat, 1, 1); + Mat4CpyMat4 (curBone->obmat, temp); + Mat4MulMat4 (totmat, parmat, ob->parent->obmat); + + Mat4Invert (imat, totmat); + + Mat4CpyMat4 (temp, ob->obmat); + Mat4MulMat4 (ob->obmat, temp, imat); + } + + + /* Solve it */ + if (chain->solver){ + VECCOPY (chain->goal, targetmat[3]); + solve_posechain(chain); + } + + free_posechain(chain); + + { + float parmat[4][4]; + + /* Take the obmat to worldspace */ + Mat4CpyMat4 (temp, curBone->obmat); + Mat4One (curBone->obmat); + get_objectspace_bone_matrix(curBone, parmat, 1, 1); + Mat4CpyMat4 (curBone->obmat, temp); + Mat4MulMat4 (totmat, parmat, ob->parent->obmat); + + Mat4CpyMat4 (temp, ob->obmat); + Mat4MulMat4 (ob->obmat, temp, totmat); + + } + } + } + break; + case CONSTRAINT_TYPE_FOLLOWPATH: + break; + default: + printf ("Error: Unknown constraint type\n"); + break; + } + +} + +void free_constraint_data (bConstraint *con) +{ + if (con->data){ + switch (con->type){ + default: + break; + }; + + MEM_freeN (con->data); + } +} + +void free_constraints (ListBase *conlist) +{ + bConstraint *con; + + /* Do any specific freeing */ + for (con=conlist->first; con; con=con->next) + { + free_constraint_data (con); + }; + + /* Free the whole list */ + BLI_freelistN(conlist); +} + +void free_constraint_channels (ListBase *chanbase) +{ + bConstraintChannel *chan; + + for (chan=chanbase->first; chan; chan=chan->next) + { + if (chan->ipo){ + chan->ipo->id.us--; + } + } + + BLI_freelistN(chanbase); +}
\ No newline at end of file diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c new file mode 100644 index 00000000000..1f0c838e816 --- /dev/null +++ b/source/blender/blenkernel/intern/curve.c @@ -0,0 +1,2344 @@ + +/* curve.c MIXED MODEL + * + * maart 95 + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#define STRUBI hack + +#include <math.h> // floor +#include <string.h> +#include <stdlib.h> + +#ifdef WIN32 +#include "BLI_winstuff.h" +#endif +#include "MEM_guardedalloc.h" +#include "BLI_blenlib.h" +#include "BLI_arithb.h" + +#include "DNA_object_types.h" +#include "DNA_curve_types.h" +#include "DNA_material_types.h" +#include "DNA_mesh_types.h" + +/* for dereferencing pointers */ +#include "DNA_ID.h" +#include "DNA_vfont_types.h" +#include "DNA_key_types.h" +#include "DNA_ipo_types.h" + +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_utildefines.h" // VECCOPY +#include "BKE_object.h" +#include "BKE_mesh.h" +#include "BKE_curve.h" +#include "BKE_displist.h" +#include "BKE_ipo.h" +#include "BKE_anim.h" +#include "BKE_library.h" +#include "BKE_key.h" + + +/* globals */ + +extern ListBase editNurb; /* editcurve.c */ + +/* local */ +int cu_isectLL(float *v1, float *v2, float *v3, float *v4, + short cox, short coy, + float *labda, float *mu, float *vec); + + +#ifdef STRUBI +/* hotfix; copies x*y array into extended (x+dx)*(y+dy) array +old[] and new[] can be the same ! */ +int copyintoExtendedArray(float *old, int oldx, int oldy, float *new, int newx, int newy) +{ + int x, y; + float *oldp, *newp; + if (newx < oldx || newy < oldy) return 0; + + + for (y = newy - 1; y >= oldy; y--) { + for (x = newx - 1; x >= 0; x--) { + newp = new + 3 * (y * newx + x); + newp[0] = 0.0; newp[1] = 0.0; newp[2] = 0.0; + } + } + + for (; y >= 0; y--) { + + for (x = newx - 1; x >= oldx; x--) { + newp = new + 3 * (y * newx + x); + newp[0] = 0.0; newp[1] = 0.0; newp[2] = 0.0; + } + for (; x >= 0; x--) { + oldp = old + 3 * (y * oldx + x); + newp = new + 3 * (y * newx + x); + VECCOPY(newp, oldp); + } + } + return 1; +} +#endif + +void unlink_curve(Curve *cu) +{ + int a; + + for(a=0; a<cu->totcol; a++) { + if(cu->mat[a]) cu->mat[a]->id.us--; + cu->mat[a]= 0; + } + if(cu->vfont) cu->vfont->id.us--; + cu->vfont= 0; + if(cu->key) cu->key->id.us--; + cu->key= 0; + if(cu->ipo) cu->ipo->id.us--; + cu->ipo= 0; +} + + +/* niet curve zelf vrijgeven */ +void free_curve(Curve *cu) +{ + + freeNurblist(&cu->nurb); + BLI_freelistN(&cu->bev); + freedisplist(&cu->disp); + + unlink_curve(cu); + + if(cu->mat) MEM_freeN(cu->mat); + if(cu->str) MEM_freeN(cu->str); + if(cu->bb) MEM_freeN(cu->bb); + if(cu->path) free_path(cu->path); +} + +Curve *add_curve(int type) +{ + Curve *cu; + char *str; + + if(type==OB_CURVE) str= "Curve"; + else if(type==OB_SURF) str= "Surf"; + else str= "Text"; + + cu= alloc_libblock(&G.main->curve, ID_CU, str); + + cu->size[0]= cu->size[1]= cu->size[2]= 1.0; + cu->flag= CU_FRONT+CU_BACK; + cu->pathlen= 100; + cu->resolu= cu->resolv= 6; + cu->width= 1.0; + cu->spacing= cu->linedist= 1.0; + cu->fsize= 1.0; + cu->texflag= AUTOSPACE; + + cu->bb= unit_boundbox(); + + return cu; +} + +Curve *copy_curve(Curve *cu) +{ + Curve *cun; + int a; + + cun= copy_libblock(cu); + cun->nurb.first= cun->nurb.last= 0; + duplicateNurblist( &(cun->nurb), &(cu->nurb)); + + cun->mat= MEM_dupallocN(cu->mat); + for(a=0; a<cun->totcol; a++) { + id_us_plus((ID *)cun->mat[a]); + } + + cun->str= MEM_dupallocN(cu->str); + cun->bb= MEM_dupallocN(cu->bb); + + cun->key= copy_key(cu->key); + if(cun->key) cun->key->from= (ID *)cun; + + cun->disp.first= cun->disp.last= 0; + cun->bev.first= cun->bev.last= 0; + cun->path= 0; + + /* ook single user ipo */ + if(cun->ipo) cun->ipo= copy_ipo(cun->ipo); + + id_us_plus((ID *)cun->vfont); + + return cun; +} + +void make_local_curve(Curve *cu) +{ + Object *ob = 0; + Curve *cun; + int local=0, lib=0; + + /* - zijn er alleen lib users: niet doen + * - zijn er alleen locale users: flag zetten + * - mixed: copy + */ + + if(cu->id.lib==0) return; + + if(cu->vfont) cu->vfont->id.lib= 0; + + if(cu->id.us==1) { + cu->id.lib= 0; + cu->id.flag= LIB_LOCAL; + new_id(0, (ID *)cu, 0); + return; + } + + ob= G.main->object.first; + while(ob) { + if(ob->data==cu) { + if(ob->id.lib) lib= 1; + else local= 1; + } + ob= ob->id.next; + } + + if(local && lib==0) { + cu->id.lib= 0; + cu->id.flag= LIB_LOCAL; + new_id(0, (ID *)cu, 0); + } + else if(local && lib) { + cun= copy_curve(cu); + cun->id.us= 0; + + ob= G.main->object.first; + while(ob) { + if(ob->data==cu) { + + if(ob->id.lib==0) { + ob->data= cun; + cun->id.us++; + cu->id.us--; + } + } + ob= ob->id.next; + } + } +} + + +void test_curve_type(Object *ob) +{ + Nurb *nu; + Curve *cu; + + cu= ob->data; + if(cu->vfont) { + ob->type= OB_FONT; + return; + } + else { + nu= cu->nurb.first; + while(nu) { + if(nu->pntsv>1) { + ob->type= OB_SURF; + return; + } + nu= nu->next; + } + } + ob->type= OB_CURVE; +} + +void tex_space_curve(Curve *cu) +{ + DispList *dl; + BoundBox *bb; + float *data, min[3], max[3], loc[3], size[3]; + int tot, doit= 0; + + if(cu->bb==0) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox"); + bb= cu->bb; + + INIT_MINMAX(min, max); + + dl= cu->disp.first; + while(dl) { + + if(dl->type==DL_INDEX3 || dl->type==DL_INDEX3) tot= dl->nr; + else tot= dl->nr*dl->parts; + + if(tot) doit= 1; + data= dl->verts; + while(tot--) { + DO_MINMAX(data, min, max); + data+= 3; + } + dl= dl->next; + } + + if(doit) { + loc[0]= (min[0]+max[0])/2.0f; + loc[1]= (min[1]+max[1])/2.0f; + loc[2]= (min[2]+max[2])/2.0f; + + size[0]= (max[0]-min[0])/2.0f; + size[1]= (max[1]-min[1])/2.0f; + size[2]= (max[2]-min[2])/2.0f; + } + else { + loc[0]= loc[1]= loc[2]= 0.0f; + size[0]= size[1]= size[2]= 1.0f; + } + + bb->vec[0][0]=bb->vec[1][0]=bb->vec[2][0]=bb->vec[3][0]= loc[0]-size[0]; + bb->vec[4][0]=bb->vec[5][0]=bb->vec[6][0]=bb->vec[7][0]= loc[0]+size[0]; + + bb->vec[0][1]=bb->vec[1][1]=bb->vec[4][1]=bb->vec[5][1]= loc[1]-size[1]; + bb->vec[2][1]=bb->vec[3][1]=bb->vec[6][1]=bb->vec[7][1]= loc[1]+size[1]; + + bb->vec[0][2]=bb->vec[3][2]=bb->vec[4][2]=bb->vec[7][2]= loc[2]-size[2]; + bb->vec[1][2]=bb->vec[2][2]=bb->vec[5][2]=bb->vec[6][2]= loc[2]+size[2]; + + if(cu->texflag & AUTOSPACE) { + VECCOPY(cu->loc, loc); + VECCOPY(cu->size, size); + cu->rot[0]= cu->rot[1]= cu->rot[2]= 0.0; + + if(cu->size[0]==0.0) cu->size[0]= 1.0; + else if(cu->size[0]>0.0 && cu->size[0]<0.00001) cu->size[0]= 0.00001; + else if(cu->size[0]<0.0 && cu->size[0]> -0.00001) cu->size[0]= -0.00001; + + if(cu->size[1]==0.0) cu->size[1]= 1.0; + else if(cu->size[1]>0.0 && cu->size[1]<0.00001) cu->size[1]= 0.00001; + else if(cu->size[1]<0.0 && cu->size[1]> -0.00001) cu->size[1]= -0.00001; + + if(cu->size[2]==0.0) cu->size[2]= 1.0; + else if(cu->size[2]>0.0 && cu->size[2]<0.00001) cu->size[2]= 0.00001; + else if(cu->size[2]<0.0 && cu->size[2]> -0.00001) cu->size[2]= -0.00001; + + } +} + + +int count_curveverts(ListBase *nurb) +{ + Nurb *nu; + int tot=0; + + nu= nurb->first; + while(nu) { + if(nu->bezt) tot+= 3*nu->pntsu; + else if(nu->bp) tot+= nu->pntsu*nu->pntsv; + + nu= nu->next; + } + return tot; +} + + + +/* **************** NURBS ROUTINES ******************** */ + +void freeNurb(Nurb *nu) +{ + + if(nu==0) return; + + if(nu->bezt) MEM_freeN(nu->bezt); + nu->bezt= 0; + if(nu->bp) MEM_freeN(nu->bp); + nu->bp= 0; + if(nu->knotsu) MEM_freeN(nu->knotsu); + nu->knotsu= 0; + if(nu->knotsv) MEM_freeN(nu->knotsv); + nu->knotsv= 0; + /* if(nu->trim.first) freeNurblist(&(nu->trim)); */ + + MEM_freeN(nu); + +} + + +void freeNurblist(ListBase *lb) +{ + Nurb *nu, *next; + + if(lb==0) return; + + nu= lb->first; + while(nu) { + next= nu->next; + freeNurb(nu); + nu= next; + } + lb->first= lb->last= 0; +} + +Nurb *duplicateNurb(Nurb *nu) +{ + Nurb *newnu; + int len; + + newnu= (Nurb*)MEM_mallocN(sizeof(Nurb),"duplicateNurb"); + if(newnu==0) return 0; + memcpy(newnu, nu, sizeof(Nurb)); + + if(nu->bezt) { + newnu->bezt= + (BezTriple*)MEM_mallocN((nu->pntsu)* sizeof(BezTriple),"duplicateNurb2"); + memcpy(newnu->bezt, nu->bezt, nu->pntsu*sizeof(BezTriple)); + } + else { + len= nu->pntsu*nu->pntsv; + newnu->bp= + (BPoint*)MEM_mallocN((len)* sizeof(BPoint),"duplicateNurb3"); + memcpy(newnu->bp, nu->bp, len*sizeof(BPoint)); + + newnu->knotsu=newnu->knotsv= 0; + + if(nu->knotsu) { + len= KNOTSU(nu); + if(len) { + newnu->knotsu= MEM_mallocN(len*sizeof(float), "duplicateNurb4"); + memcpy(newnu->knotsu, nu->knotsu, sizeof(float)*len); + } + } + if(nu->pntsv>1 && nu->knotsv) { + len= KNOTSV(nu); + if(len) { + newnu->knotsv= MEM_mallocN(len*sizeof(float), "duplicateNurb5"); + memcpy(newnu->knotsv, nu->knotsv, sizeof(float)*len); + } + } + } + return newnu; +} + +void duplicateNurblist(ListBase *lb1, ListBase *lb2) +{ + Nurb *nu, *nun; + + freeNurblist(lb1); + + nu= lb2->first; + while(nu) { + nun= duplicateNurb(nu); + BLI_addtail(lb1, nun); + + nu= nu->next; + } +} + +void test2DNurb(Nurb *nu) +{ + BezTriple *bezt; + BPoint *bp; + int a; + + if( nu->type== CU_BEZIER+CU_2D ) { + a= nu->pntsu; + bezt= nu->bezt; + while(a--) { + bezt->vec[0][2]= 0.0; + bezt->vec[1][2]= 0.0; + bezt->vec[2][2]= 0.0; + bezt++; + } + } + else if(nu->type & CU_2D) { + a= nu->pntsu*nu->pntsv; + bp= nu->bp; + while(a--) { + bp->vec[2]= 0.0; + bp++; + } + } +} + +void minmaxNurb(Nurb *nu, float *min, float *max) +{ + BezTriple *bezt; + BPoint *bp; + int a; + + if( (nu->type & 7)==CU_BEZIER ) { + a= nu->pntsu; + bezt= nu->bezt; + while(a--) { + DO_MINMAX(bezt->vec[0], min, max); + DO_MINMAX(bezt->vec[1], min, max); + DO_MINMAX(bezt->vec[2], min, max); + bezt++; + } + } + else { + a= nu->pntsu*nu->pntsv; + bp= nu->bp; + while(a--) { + DO_MINMAX(bp->vec, min, max); + bp++; + } + } + +} + +/* ~~~~~~~~~~~~~~~~~~~~Non Uniform Rational B Spline berekeningen ~~~~~~~~~~~ */ + + +/* voor de goede orde: eigenlijk horen hier doubles gebruikt te worden */ + +void extend_spline(float * pnts, int in, int out) +{ + float *_pnts; + double * add; + int i, j, k; + + _pnts = pnts; + add = (double*)MEM_mallocN((in)* sizeof(double), "extend_spline"); + + for (k = 3; k > 0; k--){ + pnts = _pnts; + + /* punten kopieren naar add */ + for (i = 0; i < in; i++){ + add[i] = *pnts; + pnts += 3; + } + + /* inverse forward differencen */ + for (i = 0; i < in - 1; i++){ + for (j = in - 1; j > i; j--){ + add[j] -= add[j - 1]; + } + } + + pnts = _pnts; + for (i = out; i > 0; i--){ + *pnts = (float)(add[0]); + pnts += 3; + for (j = 0; j < in - 1; j++){ + add[j] += add[j+1]; + } + } + + _pnts++; + } + + MEM_freeN(add); +} + + +void calcknots(float *knots, short aantal, short order, short type) +/* knots: aantal pnts NIET gecorrigeerd voor cyclic */ +/* aantal, order, type; 0: uniform, 1: endpoints, 2: bezier */ +{ + float k; + int a; + + if(type==0) { + for(a=0;a<aantal+order;a++) { + knots[a]= (float)a; + } + } + else if(type==1) { + k= 0.0; + for(a=1;a<=aantal+order;a++) { + knots[a-1]= k; + if(a>=order && a<=aantal) k+= 1.0; + } + } + else if(type==2) { + if(order==4) { + k= 0.34; + for(a=0;a<aantal+order;a++) { + knots[a]= (float)floor(k); + k+= (1.0/3.0); + } + } + else if(order==3) { + k= 0.6; + for(a=0;a<aantal+order;a++) { + if(a>=order && a<=aantal) k+= (0.5); + knots[a]= (float)floor(k); + } + } + } +} + +void makecyclicknots(float *knots, short pnts, short order) +/* pnts, order: aantal pnts NIET gecorrigeerd voor cyclic */ +{ + int a, b; + + if(knots==0) return; + + /* eerst lange rijen (order -1) dezelfde knots aan uiteinde verwijderen */ + if(order>2) { + b= pnts+order-1; + for(a=1; a<order-1; a++) { + if(knots[b]!= knots[b-a]) break; + } + if(a==order-1) knots[pnts+order-2]+= 1.0; + } + + b= order; + for(a=pnts+order-1; a<pnts+order+order-1; a++) { + knots[a]= knots[a-1]+ (knots[b]-knots[b-1]); + b--; + } +} + + +void makeknots(Nurb *nu, short uv, short type) /* 0: uniform, 1: endpoints, 2: bezier */ +{ + if( (nu->type & 7)==CU_NURBS ) { + if(uv & 1) { + if(nu->knotsu) MEM_freeN(nu->knotsu); + if(nu->pntsu>1) { + nu->knotsu= MEM_callocN(4+sizeof(float)*KNOTSU(nu), "makeknots"); + calcknots(nu->knotsu, nu->pntsu, nu->orderu, type); + if(nu->flagu & 1) makecyclicknots(nu->knotsu, nu->pntsu, nu->orderu); + } + else nu->knotsu= 0; + } + if(uv & 2) { + if(nu->knotsv) MEM_freeN(nu->knotsv); + if(nu->pntsv>1) { + nu->knotsv= MEM_callocN(4+sizeof(float)*KNOTSV(nu), "makeknots"); + calcknots(nu->knotsv, nu->pntsv, nu->orderv, type); + if(nu->flagv & 1) makecyclicknots(nu->knotsv, nu->pntsv, nu->orderv); + } + else nu->knotsv= 0; + } + } +} + +void basisNurb(float t, short order, short pnts, float *knots, float *basis, int *start, int *end) +{ + float d, e; + int i, i1 = 0, i2 = 0 ,j, orderpluspnts; + + orderpluspnts= order+pnts; + + /* this is for float inaccuracy */ + if(t < knots[0]) t= knots[0]; + else if(t > knots[orderpluspnts-1]) t= knots[orderpluspnts-1]; + + /* dit stuk is order '1' */ + for(i=0;i<orderpluspnts-1;i++) { + if(knots[i]!=knots[i+1] && t>= knots[i] && t<=knots[i+1]) { + basis[i]= 1.0; + i1= i-order+1; + if(i1<0) i1= 0; + i2= i; + i++; + while(i<orderpluspnts-1) { + basis[i]= 0.0; + i++; + } + break; + } + else basis[i]= 0.0; + } + basis[i]= 0.0; + + /* printf("u %f\n", t); for(k=0;k<orderpluspnts;k++) printf(" %2.2f",basis[k]); printf("\n"); */ + + /* dit is order 2,3,... */ + for(j=2; j<=order; j++) { + + if(i2+j>= orderpluspnts) i2= orderpluspnts-j-1; + + for(i= i1; i<=i2; i++) { + if(basis[i]!=0.0) + d= ((t-knots[i])*basis[i]) / (knots[i+j-1]-knots[i]); + else + d= 0.0; + + if(basis[i+1]!=0.0) + e= ((knots[i+j]-t)*basis[i+1]) / (knots[i+j]-knots[i+1]); + else + e= 0.0; + + basis[i]= d+e; + } + } + + *start= 1000; + *end= 0; + + for(i=i1; i<=i2; i++) { + if(basis[i]>0.0) { + *end= i; + if(*start==1000) *start= i; + } + } +} + + +void makeNurbfaces(Nurb *nu, float *data) +/* data moet 3*4*resolu*resolv lang zijn en op nul staan */ +{ + BPoint *bp; + float *basisu, *basis, *basisv, *sum, *fp, *in; + float u, v, ustart, uend, ustep, vstart, vend, vstep, sumdiv; + int i, j, iofs, jofs, cycl, len, resolu, resolv; + int istart, iend, jsta, jen, *jstart, *jend, ratcomp; + + if(nu->knotsu==0 || nu->knotsv==0) return; + if(nu->orderu>nu->pntsu) return; + if(nu->orderv>nu->pntsv) return; + if(data==0) return; + + /* alloceren en vars goedzetten */ + len= nu->pntsu*nu->pntsv; + if(len==0) return; + sum= (float *)MEM_callocN(sizeof(float)*len, "makeNurbfaces1"); + + resolu= nu->resolu; + resolv= nu->resolv; + len= resolu*resolv; + if(len==0) { + MEM_freeN(sum); + return; + } + + bp= nu->bp; + i= nu->pntsu*nu->pntsv; + ratcomp=0; + while(i--) { + if(bp->vec[3]!=1.0) { + ratcomp= 1; + break; + } + bp++; + } + + fp= nu->knotsu; + ustart= fp[nu->orderu-1]; + if(nu->flagu & 1) uend= fp[nu->pntsu+nu->orderu-1]; + else uend= fp[nu->pntsu]; + ustep= (uend-ustart)/(resolu-1+(nu->flagu & 1)); + basisu= (float *)MEM_mallocN(sizeof(float)*KNOTSU(nu), "makeNurbfaces3"); + + fp= nu->knotsv; + vstart= fp[nu->orderv-1]; + + if(nu->flagv & 1) vend= fp[nu->pntsv+nu->orderv-1]; + else vend= fp[nu->pntsv]; + vstep= (vend-vstart)/(resolv-1+(nu->flagv & 1)); + len= KNOTSV(nu); + basisv= (float *)MEM_mallocN(sizeof(float)*len*resolv, "makeNurbfaces3"); + jstart= (int *)MEM_mallocN(sizeof(float)*resolv, "makeNurbfaces4"); + jend= (int *)MEM_mallocN(sizeof(float)*resolv, "makeNurbfaces5"); + + /* voorberekenen basisv en jstart,jend */ + if(nu->flagv & 1) cycl= nu->orderv-1; + else cycl= 0; + v= vstart; + basis= basisv; + while(resolv--) { + basisNurb(v, nu->orderv, (short)(nu->pntsv+cycl), nu->knotsv, basis, jstart+resolv, jend+resolv); + basis+= KNOTSV(nu); + v+= vstep; + } + + if(nu->flagu & 1) cycl= nu->orderu-1; + else cycl= 0; + in= data; + u= ustart; + while(resolu--) { + + basisNurb(u, nu->orderu, (short)(nu->pntsu+cycl), nu->knotsu, basisu, &istart, &iend); + + basis= basisv; + resolv= nu->resolv; + while(resolv--) { + + jsta= jstart[resolv]; + jen= jend[resolv]; + + /* bereken sum */ + sumdiv= 0.0; + fp= sum; + + for(j= jsta; j<=jen; j++) { + + if(j>=nu->pntsv) jofs= (j - nu->pntsv); + else jofs= j; + bp= nu->bp+ nu->pntsu*jofs+istart-1; + + for(i= istart; i<=iend; i++, fp++) { + + if(i>= nu->pntsu) { + iofs= i- nu->pntsu; + bp= nu->bp+ nu->pntsu*jofs+iofs; + } + else bp++; + + if(ratcomp) { + *fp= basisu[i]*basis[j]*bp->vec[3]; + sumdiv+= *fp; + } + else *fp= basisu[i]*basis[j]; + } + } + + if(ratcomp) { + fp= sum; + for(j= jsta; j<=jen; j++) { + for(i= istart; i<=iend; i++, fp++) { + *fp/= sumdiv; + } + } + } + + /* een! (1.0) echt punt nu */ + fp= sum; + for(j= jsta; j<=jen; j++) { + + if(j>=nu->pntsv) jofs= (j - nu->pntsv); + else jofs= j; + bp= nu->bp+ nu->pntsu*jofs+istart-1; + + for(i= istart; i<=iend; i++, fp++) { + + if(i>= nu->pntsu) { + iofs= i- nu->pntsu; + bp= nu->bp+ nu->pntsu*jofs+iofs; + } + else bp++; + + if(*fp!=0.0) { + in[0]+= (*fp) * bp->vec[0]; + in[1]+= (*fp) * bp->vec[1]; + in[2]+= (*fp) * bp->vec[2]; + } + } + } + + in+=3; + basis+= KNOTSV(nu); + } + u+= ustep; + } + + /* vrijgeven */ + MEM_freeN(sum); + MEM_freeN(basisu); + MEM_freeN(basisv); + MEM_freeN(jstart); + MEM_freeN(jend); +} + + +void makeNurbcurve_forw(Nurb *nu, float *data) +/* *data: moet 3*4*pntsu*resolu lang zijn en op nul staan */ +{ + BPoint *bp; + float *basisu, *sum, *fp, *in; + float u, ustart, uend, ustep, sumdiv; + int i, j, k, len, resolu, istart, iend; + int wanted, org; + + if(nu->knotsu==0) return; + if(data==0) return; + + /* alloceren en vars goedzetten */ + len= nu->pntsu; + if(len==0) return; + sum= (float *)MEM_callocN(sizeof(float)*len, "makeNurbcurve1"); + + resolu= nu->resolu*nu->pntsu; + if(resolu==0) { + MEM_freeN(sum); + return; + } + + fp= nu->knotsu; + ustart= fp[nu->orderu-1]; + uend= fp[nu->pntsu]; + ustep= (uend-ustart)/(resolu-1); + basisu= (float *)MEM_mallocN(sizeof(float)*(nu->orderu+nu->pntsu), "makeNurbcurve3"); + + in= data; + u= ustart; + for (k = nu->orderu - 1; k < nu->pntsu; k++){ + + wanted = (int)((nu->knotsu[k+1] - nu->knotsu[k]) / ustep); + org = 4; /* gelijk aan order */ + if (org > wanted) org = wanted; + + for (j = org; j > 0; j--){ + + basisNurb(u, nu->orderu, nu->pntsu, nu->knotsu, basisu, &istart, &iend); + /* bereken sum */ + sumdiv= 0.0; + fp= sum; + for(i= istart; i<=iend; i++, fp++) { + /* hier nog rationele component doen */ + *fp= basisu[i]; + sumdiv+= *fp; + } + if(sumdiv!=0.0) if(sumdiv<0.999 || sumdiv>1.001) { + /* is dit normaliseren ook nodig? */ + fp= sum; + for(i= istart; i<=iend; i++, fp++) { + *fp/= sumdiv; + } + } + + /* een! (1.0) echt punt nu */ + fp= sum; + bp= nu->bp+ istart; + for(i= istart; i<=iend; i++, bp++, fp++) { + + if(*fp!=0.0) { + in[0]+= (*fp) * bp->vec[0]; + in[1]+= (*fp) * bp->vec[1]; + in[2]+= (*fp) * bp->vec[2]; + } + } + + in+=3; + + u+= ustep; + } + + if (wanted > org){ + extend_spline(in - 3 * org, org, wanted); + in += 3 * (wanted - org); + u += ustep * (wanted - org); + } + } + + /* vrijgeven */ + MEM_freeN(sum); + MEM_freeN(basisu); +} + + +void makeNurbcurve(Nurb *nu, float *data, int dim) +/* data moet dim*4*pntsu*resolu lang zijn en op nul staan */ +{ + BPoint *bp; + float u, ustart, uend, ustep, sumdiv; + float *basisu, *sum, *fp, *in; + int i, len, resolu, istart, iend, cycl; + + if(nu->knotsu==0) return; + if(nu->orderu>nu->pntsu) return; + if(data==0) return; + + /* alloceren en vars goedzetten */ + len= nu->pntsu; + if(len==0) return; + sum= (float *)MEM_callocN(sizeof(float)*len, "makeNurbcurve1"); + + resolu= nu->resolu*nu->pntsu; + if(resolu==0) { + MEM_freeN(sum); + return; + } + + fp= nu->knotsu; + ustart= fp[nu->orderu-1]; + if(nu->flagu & 1) uend= fp[nu->pntsu+nu->orderu-1]; + else uend= fp[nu->pntsu]; + ustep= (uend-ustart)/(resolu-1+(nu->flagu & 1)); + basisu= (float *)MEM_mallocN(sizeof(float)*KNOTSU(nu), "makeNurbcurve3"); + + if(nu->flagu & 1) cycl= nu->orderu-1; + else cycl= 0; + + in= data; + u= ustart; + while(resolu--) { + + basisNurb(u, nu->orderu, (short)(nu->pntsu+cycl), nu->knotsu, basisu, &istart, &iend); + /* bereken sum */ + sumdiv= 0.0; + fp= sum; + bp= nu->bp+ istart-1; + for(i= istart; i<=iend; i++, fp++) { + + if(i>=nu->pntsu) bp= nu->bp+(i - nu->pntsu); + else bp++; + + *fp= basisu[i]*bp->vec[3]; + sumdiv+= *fp; + } + if(sumdiv!=0.0) if(sumdiv<0.999 || sumdiv>1.001) { + /* is dit normaliseren ook nodig? */ + fp= sum; + for(i= istart; i<=iend; i++, fp++) { + *fp/= sumdiv; + } + } + + /* een! (1.0) echt punt nu */ + fp= sum; + bp= nu->bp+ istart-1; + for(i= istart; i<=iend; i++, fp++) { + + if(i>=nu->pntsu) bp= nu->bp+(i - nu->pntsu); + else bp++; + + if(*fp!=0.0) { + + in[0]+= (*fp) * bp->vec[0]; + in[1]+= (*fp) * bp->vec[1]; + if(dim>=3) { + in[2]+= (*fp) * bp->vec[2]; + if(dim==4) in[3]+= (*fp) * bp->alfa; + } + } + } + + in+= dim; + + u+= ustep; + } + + /* vrijgeven */ + MEM_freeN(sum); + MEM_freeN(basisu); +} + +void maakbez(float q0, float q1, float q2, float q3, float *p, int it) +{ + float rt0,rt1,rt2,rt3,f; + int a; + + f= (float)it; + rt0= q0; + rt1= 3.0f*(q1-q0)/f; + f*= f; + rt2= 3.0f*(q0-2.0f*q1+q2)/f; + f*= it; + rt3= (q3-q0+3.0f*(q1-q2))/f; + + q0= rt0; + q1= rt1+rt2+rt3; + q2= 2*rt2+6*rt3; + q3= 6*rt3; + + for(a=0; a<=it; a++) { + *p= q0; + p+= 3; + q0+= q1; + q1+= q2; + q2+= q3; + } +} + +/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +void make_orco_surf(Curve *cu) +{ + Nurb *nu; + int a, b, tot=0; + int sizeu, sizev;// ### + float *data; + + + /* eerst voorspellen hoelang datablok moet worden */ + nu= cu->nurb.first; + while(nu) { +#ifdef STRUBI +/* this is a bad hack: as we want to avoid the seam in a cyclic nurbs +texture wrapping, reserve extra orco data space to save these extra needed +vertex based UV coordinates for the meridian vertices. +Vertices on the 0/2pi boundary are not duplicated inside the displist but later in +the renderface/vert construction. + +See also blenderWorldManipulation.c: init_render_surf() + +*/ + + sizeu = nu->resolu; sizev = nu->resolv; + if (nu->flagu & CU_CYCLIC) sizeu++; + if (nu->flagv & CU_CYCLIC) sizev++; + if(nu->pntsv>1) tot+= sizeu * sizev; +#else + if(nu->pntsv>1) tot+= nu->resolu*nu->resolv; +#endif + nu= nu->next; + } + /* makeNurbfaces wil nullen */ + data= cu->orco= MEM_callocN(3*sizeof(float)*tot, "make_orco"); + + nu= cu->nurb.first; + while(nu) { + if(nu->pntsv>1) { + sizeu = nu->resolu; + sizev = nu->resolv; +#ifdef STRUBI + if (nu->flagu & CU_CYCLIC) sizeu++; + if (nu->flagv & CU_CYCLIC) sizev++; +#endif + + if(cu->flag & CU_UV_ORCO) { + for(b=0; b< sizeu; b++) { + for(a=0; a< sizev; a++) { + + if(sizev <2) data[0]= 0.0f; + else data[0]= -1.0f + 2.0f*((float)a)/(sizev - 1); + + if(sizeu <2) data[1]= 0.0f; + else data[1]= -1.0f + 2.0f*((float)b)/(sizeu - 1); + + data[2]= 0.0; + + data+= 3; + } + } + } + else { + makeNurbfaces(nu, data); +#ifdef STRUBI + for(b=0; b< nu->resolu; b++) { + for(a=0; a< nu->resolv; a++) { + data = cu->orco + 3 * (b * nu->resolv + a); + data[0]= (data[0]-cu->loc[0])/cu->size[0]; + data[1]= (data[1]-cu->loc[1])/cu->size[1]; + data[2]= (data[2]-cu->loc[2])/cu->size[2]; + } + } + copyintoExtendedArray(cu->orco, nu->resolv, nu->resolu, cu->orco, sizev, sizeu); + /* copy U/V-cyclic orco's */ + if (nu->flagv & CU_CYCLIC) { + b = sizeu - 1; + for(a=0; a< sizev; a++) { + data = cu->orco + 3 * (b * sizev + a); + VECCOPY(data, cu->orco + 3*a); + } + } + if (nu->flagu & CU_CYCLIC) { + a = sizev - 1; + for(b=0; b< sizeu; b++) { + data = cu->orco + 3 * (b * sizev + a); + VECCOPY(data, cu->orco + 3 * b*sizev); + } + } + +#else + tot= sizeu * sizev; + while(tot--) { + data[0]= (data[0]-cu->loc[0])/cu->size[0]; + data[1]= (data[1]-cu->loc[1])/cu->size[1]; + data[2]= (data[2]-cu->loc[2])/cu->size[2]; + + data+= 3; + } +#endif + } + } + nu= nu->next; + } + /* loadkeypostype(22, base, base); */ + +} + + + +/* ***************** BEVEL ****************** */ + +void makebevelcurve(Object *ob, ListBase *disp) +{ + DispList *dl, *dlnew; + Curve *bevcu, *cu; + float *fp, facx, facy, hoek, dhoek; + int nr, a; + + cu= ob->data; + + if(cu->bevobj && cu->bevobj!=ob) { + if(cu->bevobj->type==OB_CURVE) { + bevcu= cu->bevobj->data; + if(bevcu->ext1==0.0 && bevcu->ext2==0.0) { + facx= cu->bevobj->size[0]; + facy= cu->bevobj->size[1]; + + dl= bevcu->disp.first; + if(dl==0) { + makeDispList(cu->bevobj); + dl= bevcu->disp.first; + } + while(dl) { + if ELEM(dl->type, DL_POLY, DL_SEGM) { + dlnew= MEM_mallocN(sizeof(DispList), "makebevelcurve1"); + *dlnew= *dl; + dlnew->verts= MEM_mallocN(3*sizeof(float)*dl->parts*dl->nr, "makebevelcurve1"); + memcpy(dlnew->verts, dl->verts, 3*sizeof(float)*dl->parts*dl->nr); + + BLI_addtail(disp, dlnew); + fp= dlnew->verts; + nr= dlnew->parts*dlnew->nr; + while(nr--) { + fp[2]= fp[1]*facy; + fp[1]= -fp[0]*facx; + fp[0]= 0.0; + fp+= 3; + } + } + dl= dl->next; + } + } + } + } + else if(cu->ext2==0.0) { + dl= MEM_callocN(sizeof(DispList), "makebevelcurve2"); + dl->verts= MEM_mallocN(2*3*sizeof(float), "makebevelcurve2"); + BLI_addtail(disp, dl); + dl->type= DL_SEGM; + dl->parts= 1; + dl->nr= 2; + fp= dl->verts; + fp[0]= fp[1]= 0.0; + fp[2]= -cu->ext1; + fp[3]= fp[4]= 0.0; + fp[5]= cu->ext1; + } + else { + nr= 4+2*cu->bevresol; + + dl= MEM_callocN(sizeof(DispList), "makebevelcurve3"); + dl->verts= MEM_mallocN(nr*3*sizeof(float), "makebevelcurve3"); + BLI_addtail(disp, dl); + dl->type= DL_SEGM; + dl->parts= 1; + dl->nr= nr; + + /* eerst cirkel maken */ + fp= dl->verts; + hoek= -0.5*M_PI; + dhoek= (float)(M_PI/(nr-2)); + for(a=0; a<nr; a++) { + fp[0]= 0.0; + fp[1]= (float)(cos(hoek)*(cu->ext2)); + fp[2]= (float)(sin(hoek)*(cu->ext2)); + hoek+= dhoek; + fp+= 3; + if(cu->ext1!=0.0 && a==((nr/2)-1) ) { + VECCOPY(fp, fp-3); + fp+=3; + a++; + } + } + if(cu->ext1==0.0) dl->nr--; + else { + fp= dl->verts; + for(a=0; a<nr; a++) { + if(a<=(nr/2-1)) fp[2]-= (cu->ext1); + else fp[2]+= (cu->ext1); + fp+= 3; + } + } + } + +} + +int cu_isectLL(float *v1, float *v2, float *v3, float *v4, short cox, short coy, float *labda, float *mu, float *vec) +{ + /* return: + -1: colliniar + 0: no intersection of segments + 1: exact intersection of segments + 2: cross-intersection of segments + */ + float deler; + + deler= (v1[cox]-v2[cox])*(v3[coy]-v4[coy])-(v3[cox]-v4[cox])*(v1[coy]-v2[coy]); + if(deler==0.0) return -1; + + *labda= (v1[coy]-v3[coy])*(v3[cox]-v4[cox])-(v1[cox]-v3[cox])*(v3[coy]-v4[coy]); + *labda= -(*labda/deler); + + deler= v3[coy]-v4[coy]; + if(deler==0) { + deler=v3[cox]-v4[cox]; + *mu= -(*labda*(v2[cox]-v1[cox])+v1[cox]-v3[cox])/deler; + } else { + *mu= -(*labda*(v2[coy]-v1[coy])+v1[coy]-v3[coy])/deler; + } + vec[cox]= *labda*(v2[cox]-v1[cox])+v1[cox]; + vec[coy]= *labda*(v2[coy]-v1[coy])+v1[coy]; + + if(*labda>=0.0 && *labda<=1.0 && *mu>=0.0 && *mu<=1.0) { + if(*labda==0.0 || *labda==1.0 || *mu==0.0 || *mu==1.0) return 1; + return 2; + } + return 0; +} + + +short bevelinside(BevList *bl1,BevList *bl2) +{ + /* is bl2 INSIDE bl1 ? met links-rechts methode en "labda's" */ + /* geeft als correct gat 1 terug */ + BevPoint *bevp, *prevbevp; + float min,max,vec[3],hvec1[3],hvec2[3],lab,mu; + int nr, links=0,rechts=0,mode; + + /* neem eerste vertex van het mogelijke gat */ + + bevp= (BevPoint *)(bl2+1); + hvec1[0]= bevp->x; + hvec1[1]= bevp->y; + hvec1[2]= 0.0; + VECCOPY(hvec2,hvec1); + hvec2[0]+=1000; + + /* test deze met alle edges van mogelijk omringende poly */ + /* tel aantal overgangen links en rechts */ + + bevp= (BevPoint *)(bl1+1); + nr= bl1->nr; + prevbevp= bevp+(nr-1); + + while(nr--) { + min= prevbevp->y; + max= bevp->y; + if(max<min) { + min= max; + max= prevbevp->y; + } + if(min!=max) { + if(min<=hvec1[1] && max>=hvec1[1]) { + /* er is een overgang, snijpunt berekenen */ + mode= cu_isectLL(&(prevbevp->x),&(bevp->x),hvec1,hvec2,0,1,&lab,&mu,vec); + /* als lab==0.0 of lab==1.0 dan snijdt de edge exact de overgang + * alleen toestaan voor lab= 1.0 (of andersom, maakt niet uit) + */ + if(mode>=0 && lab!=0.0) { + if(vec[0]<hvec1[0]) links++; + else rechts++; + } + } + } + prevbevp= bevp; + bevp++; + } + + if( (links & 1) && (rechts & 1) ) return 1; + return 0; +} + + +struct bevelsort { + float left; + BevList *bl; + int dir; +}; + +int vergxcobev(const void *a1, const void *a2) +{ + const struct bevelsort *x1=a1,*x2=a2; + + if( x1->left > x2->left ) return 1; + else if( x1->left < x2->left) return -1; + return 0; +} + +/* deze kan niet zomaar door atan2 vervangen worden, maar waarom? */ + +void calc_bevel_sin_cos(float x1, float y1, float x2, float y2, float *sina, float *cosa) +{ + float t01, t02, x3, y3; + + t01= (float)sqrt(x1*x1+y1*y1); + t02= (float)sqrt(x2*x2+y2*y2); + if(t01==0.0) t01= 1.0; + if(t02==0.0) t02= 1.0; + + x1/=t01; + y1/=t01; + x2/=t02; + y2/=t02; + + t02= x1*x2+y1*y2; + if(fabs(t02)>=1.0) t02= .5*M_PI; + else t02= (saacos(t02))/2.0f; + + t02= (float)sin(t02); + if(t02==0.0) t02= 1.0; + + x3= x1-x2; + y3= y1-y2; + if(x3==0 && y3==0) { + /* printf("x3 en y3 nul \n"); */ + x3= y1; + y3= -x1; + } else { + t01= (float)sqrt(x3*x3+y3*y3); + x3/=t01; + y3/=t01; + } + + *sina= -y3/t02; + *cosa= x3/t02; + +} + +void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float *data_a) +{ + BezTriple *pprev, *next, *last; + float fac, dfac, t[4]; + int a; + + last= nu->bezt+(nu->pntsu-1); + + /* een punt terug */ + if(prevbezt==nu->bezt) { + if(nu->flagu & 1) pprev= last; + else pprev= prevbezt; + } + else pprev= prevbezt-1; + + /* een punt verder */ + if(bezt==last) { + if(nu->flagu & 1) next= nu->bezt; + else next= bezt; + } + else next= bezt+1; + + fac= 0.0; + dfac= 1.0f/(float)nu->resolu; + + for(a=0; a<nu->resolu; a++, fac+= dfac) { + + set_four_ipo(fac, t, KEY_BSPLINE); + + data_a[a]= t[0]*pprev->alfa + t[1]*prevbezt->alfa + t[2]*bezt->alfa + t[3]*next->alfa; + } +} + +void makeBevelList(Object *ob) +{ + /* - alle curves omzetten in poly's, met aangegeven resol en vlaggen voor dubbele punten + - eventueel intelligent punten verwijderen (geval Nurb) + - scheiden in verschillende blokken met Boundbox + - Autogat detectie */ + Curve *cu; + Nurb *nu; + BezTriple *bezt, *prevbezt; + BPoint *bp; + BevList *bl, *blnew, *blnext; + BevPoint *bevp, *bevp2, *bevp1 = NULL, *bevp0; + float *data, *data_a, *v1, *v2, min, inp, x1, x2, y1, y2, vec[3]; + struct bevelsort *sortdata, *sd, *sd1; + int a, b, len, nr, poly; + + /* deze fie moet object hebben in verband met tflag en upflag */ + cu= ob->data; + + /* STAP 1: POLY'S MAKEN */ + + BLI_freelistN(&(cu->bev)); + if(ob==G.obedit) nu= editNurb.first; + else nu= cu->nurb.first; + + while(nu) { + if(nu->pntsu>1) { + + if((nu->type & 7)==CU_POLY) { + + len= nu->pntsu; + bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList"); + BLI_addtail(&(cu->bev), bl); + + if(nu->flagu & 1) bl->poly= 0; + else bl->poly= -1; + bl->nr= len; + bl->flag= 0; + bevp= (BevPoint *)(bl+1); + bp= nu->bp; + + while(len--) { + bevp->x= bp->vec[0]; + bevp->y= bp->vec[1]; + bevp->z= bp->vec[2]; + bevp->alfa= bp->alfa; + bevp->f1= 1; + bevp++; + bp++; + } + } + else if((nu->type & 7)==CU_BEZIER) { + + len= nu->resolu*(nu->pntsu+ (nu->flagu & 1) -1)+1; /* voor laatste punt niet cyclic */ + bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList"); + BLI_addtail(&(cu->bev), bl); + + if(nu->flagu & 1) bl->poly= 0; + else bl->poly= -1; + bevp= (BevPoint *)(bl+1); + + a= nu->pntsu-1; + bezt= nu->bezt; + if(nu->flagu & 1) { + a++; + prevbezt= nu->bezt+(nu->pntsu-1); + } + else { + prevbezt= bezt; + bezt++; + } + + data= MEM_mallocN(3*sizeof(float)*(nu->resolu+1), "makeBevelList2"); + data_a= MEM_callocN(sizeof(float)*(nu->resolu+1), "data_a"); + + while(a--) { + if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) { + + bevp->x= prevbezt->vec[1][0]; + bevp->y= prevbezt->vec[1][1]; + bevp->z= prevbezt->vec[1][2]; + bevp->alfa= prevbezt->alfa; + bevp->f1= 1; + bevp->f2= 0; + bevp++; + bl->nr++; + bl->flag= 1; + } + else { + v1= prevbezt->vec[1]; + v2= bezt->vec[0]; + + /* altijd alle drie doen: anders blijft data hangen */ + maakbez(v1[0], v1[3], v2[0], v2[3], data, nu->resolu); + maakbez(v1[1], v1[4], v2[1], v2[4], data+1, nu->resolu); + maakbez(v1[2], v1[5], v2[2], v2[5], data+2, nu->resolu); + + if((nu->type & CU_2D)==0) { + if(cu->flag & CU_3D) { + alfa_bezpart(prevbezt, bezt, nu, data_a); + } + } + + + /* met handlecodes dubbele punten aangeven */ + if(prevbezt->h1==prevbezt->h2) { + if(prevbezt->h1==0 || prevbezt->h1==HD_VECT) bevp->f1= 1; + } + else { + if(prevbezt->h1==0 || prevbezt->h1==HD_VECT) bevp->f1= 1; + else if(prevbezt->h2==0 || prevbezt->h2==HD_VECT) bevp->f1= 1; + } + + v1= data; + v2= data_a; + nr= nu->resolu; + + while(nr--) { + bevp->x= v1[0]; + bevp->y= v1[1]; + bevp->z= v1[2]; + bevp->alfa= v2[0]; + bevp++; + v1+=3; + v2++; + } + bl->nr+= nu->resolu; + + } + prevbezt= bezt; + bezt++; + } + + MEM_freeN(data); + MEM_freeN(data_a); + + if((nu->flagu & 1)==0) { /* niet cyclic: endpoint */ + bevp->x= prevbezt->vec[1][0]; + bevp->y= prevbezt->vec[1][1]; + bevp->z= prevbezt->vec[1][2]; + bl->nr++; + } + + } + else if((nu->type & 7)==CU_NURBS) { + if(nu->pntsv==1) { + len= nu->resolu*nu->pntsu; + bl= MEM_mallocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList3"); + BLI_addtail(&(cu->bev), bl); + bl->nr= len; + bl->flag= 0; + if(nu->flagu & 1) bl->poly= 0; + else bl->poly= -1; + bevp= (BevPoint *)(bl+1); + + data= MEM_callocN(4*sizeof(float)*len, "makeBevelList4"); /* moet op nul staan */ + makeNurbcurve(nu, data, 4); + + v1= data; + while(len--) { + bevp->x= v1[0]; + bevp->y= v1[1]; + bevp->z= v1[2]; + bevp->alfa= v1[3]; + + bevp->f1= bevp->f2= 0; + bevp++; + v1+=4; + } + MEM_freeN(data); + } + } + } + nu= nu->next; + } + + /* STAP 2: DUBBELE PUNTEN EN AUTOMATISCHE RESOLUTIE, DATABLOKKEN VERKLEINEN */ + bl= cu->bev.first; + while(bl) { + nr= bl->nr; + bevp1= (BevPoint *)(bl+1); + bevp0= bevp1+(nr-1); + nr--; + while(nr--) { + if( fabs(bevp0->x-bevp1->x)<0.00001 ) { + if( fabs(bevp0->y-bevp1->y)<0.00001 ) { + if( fabs(bevp0->z-bevp1->z)<0.00001 ) { + bevp0->f2= 1; + bl->flag++; + } + } + } + bevp0= bevp1; + bevp1++; + } + bl= bl->next; + } + bl= cu->bev.first; + while(bl) { + blnext= bl->next; + if(bl->flag) { + nr= bl->nr- bl->flag+1; /* +1 want vectorbezier zet ook flag */ + blnew= MEM_mallocN(sizeof(BevList)+nr*sizeof(BevPoint), "makeBevelList"); + memcpy(blnew, bl, sizeof(BevList)); + blnew->nr= 0; + BLI_remlink(&(cu->bev), bl); + BLI_insertlinkbefore(&(cu->bev),blnext,blnew); /* zodat bevlijst met nurblijst gelijk loopt */ + bevp0= (BevPoint *)(bl+1); + bevp1= (BevPoint *)(blnew+1); + nr= bl->nr; + while(nr--) { + if(bevp0->f2==0) { + memcpy(bevp1, bevp0, sizeof(BevPoint)); + bevp1++; + blnew->nr++; + } + bevp0++; + } + MEM_freeN(bl); + blnew->flag= 0; + } + bl= blnext; + } + + /* STAP 3: POLY'S TELLEN EN AUTOGAT */ + bl= cu->bev.first; + poly= 0; + while(bl) { + if(bl->poly>=0) { + poly++; + bl->poly= poly; + bl->gat= 0; + } + bl= bl->next; + } + + + /* meest linkse punten vinden, tevens richting testen */ + if(poly>0) { + sd= sortdata= MEM_mallocN(sizeof(struct bevelsort)*poly, "makeBevelList5"); + bl= cu->bev.first; + while(bl) { + if(bl->poly>0) { + + min= 300000.0; + bevp= (BevPoint *)(bl+1); + nr= bl->nr; + while(nr--) { + if(min>bevp->x) { + min= bevp->x; + bevp1= bevp; + } + bevp++; + } + sd->bl= bl; + sd->left= min; + + bevp= (BevPoint *)(bl+1); + if(bevp1== bevp) bevp0= bevp+ (bl->nr-1); + else bevp0= bevp1-1; + bevp= bevp+ (bl->nr-1); + if(bevp1== bevp) bevp2= (BevPoint *)(bl+1); + else bevp2= bevp1+1; + + inp= (bevp1->x- bevp0->x)*(bevp0->y- bevp2->y) + +(bevp0->y- bevp1->y)*(bevp0->x- bevp2->x); + + if(inp>0.0) sd->dir= 1; + else sd->dir= 0; + + sd++; + } + + bl= bl->next; + } + qsort(sortdata,poly,sizeof(struct bevelsort), vergxcobev); + + sd= sortdata+1; + for(a=1; a<poly; a++, sd++) { + bl= sd->bl; /* is bl een gat? */ + sd1= sortdata+ (a-1); + for(b=a-1; b>=0; b--, sd1--) { /* alle polys links ervan */ + if(bevelinside(sd1->bl, bl)) { + bl->gat= 1- sd1->bl->gat; + break; + } + } + } + + /* draairichting */ + if((cu->flag & CU_3D)==0) { + sd= sortdata; + for(a=0; a<poly; a++, sd++) { + if(sd->bl->gat==sd->dir) { + bl= sd->bl; + bevp1= (BevPoint *)(bl+1); + bevp2= bevp1+ (bl->nr-1); + nr= bl->nr/2; + while(nr--) { + SWAP(BevPoint, *bevp1, *bevp2); + bevp1++; + bevp2--; + } + } + } + } + MEM_freeN(sortdata); + } + + /* STAP 4: COSINUSSEN */ + bl= cu->bev.first; + while(bl) { + + if(bl->nr==2) { /* 2 pnt, apart afhandelen: KAN DAT NIET AFGESCHAFT? */ + bevp2= (BevPoint *)(bl+1); + bevp1= bevp2+1; + + x1= bevp1->x- bevp2->x; + y1= bevp1->y- bevp2->y; + + calc_bevel_sin_cos(x1, y1, -x1, -y1, &(bevp1->sina), &(bevp1->cosa)); + bevp2->sina= bevp1->sina; + bevp2->cosa= bevp1->cosa; + + if(cu->flag & CU_3D) { /* 3D */ + float *quat, q[4]; + + vec[0]= bevp1->x - bevp2->x; + vec[1]= bevp1->y - bevp2->y; + vec[2]= bevp1->z - bevp2->z; + + quat= vectoquat(vec, 5, 1); + + Normalise(vec); + q[0]= (float)cos(0.5*bevp1->alfa); + x1= (float)sin(0.5*bevp1->alfa); + q[1]= x1*vec[0]; + q[2]= x1*vec[1]; + q[3]= x1*vec[2]; + QuatMul(quat, q, quat); + + QuatToMat3(quat, bevp1->mat); + Mat3CpyMat3(bevp2->mat, bevp1->mat); + } + + } + else if(bl->nr>2) { + bevp2= (BevPoint *)(bl+1); + bevp1= bevp2+(bl->nr-1); + bevp0= bevp1-1; + + + nr= bl->nr; + + while(nr--) { + + if(cu->flag & CU_3D) { /* 3D */ + float *quat, q[4]; + + vec[0]= bevp2->x - bevp0->x; + vec[1]= bevp2->y - bevp0->y; + vec[2]= bevp2->z - bevp0->z; + + Normalise(vec); + + quat= vectoquat(vec, 5, 1); + + q[0]= (float)cos(0.5*bevp1->alfa); + x1= (float)sin(0.5*bevp1->alfa); + q[1]= x1*vec[0]; + q[2]= x1*vec[1]; + q[3]= x1*vec[2]; + QuatMul(quat, q, quat); + + QuatToMat3(quat, bevp1->mat); + } + + x1= bevp1->x- bevp0->x; + x2= bevp1->x- bevp2->x; + y1= bevp1->y- bevp0->y; + y2= bevp1->y- bevp2->y; + + calc_bevel_sin_cos(x1, y1, x2, y2, &(bevp1->sina), &(bevp1->cosa)); + + + bevp0= bevp1; + bevp1= bevp2; + bevp2++; + } + /* niet cyclic gevallen corrigeren */ + if(bl->poly== -1) { + if(bl->nr>2) { + bevp= (BevPoint *)(bl+1); + bevp1= bevp+1; + bevp->sina= bevp1->sina; + bevp->cosa= bevp1->cosa; + Mat3CpyMat3(bevp->mat, bevp1->mat); + bevp= (BevPoint *)(bl+1); + bevp+= (bl->nr-1); + bevp1= bevp-1; + bevp->sina= bevp1->sina; + bevp->cosa= bevp1->cosa; + Mat3CpyMat3(bevp->mat, bevp1->mat); + } + } + } + bl= bl->next; + } +} + +/* ****************** HANDLES ************** */ + +/* + * handlecodes: + * 1: niets, 1:auto, 2:vector, 3:aligned + */ + + +void calchandleNurb(BezTriple *bezt,BezTriple *prev, BezTriple *next, int mode) +{ + float *p1,*p2,*p3,pt[3]; + float dx1,dy1,dz1,dx,dy,dz,vx,vy,vz,len,len1,len2; + + if(bezt->h1==0 && bezt->h2==0) return; + + p2= bezt->vec[1]; + + if(prev==0) { + p3= next->vec[1]; + pt[0]= 2*p2[0]- p3[0]; + pt[1]= 2*p2[1]- p3[1]; + pt[2]= 2*p2[2]- p3[2]; + p1= pt; + } + else p1= prev->vec[1]; + + if(next==0) { + pt[0]= 2*p2[0]- p1[0]; + pt[1]= 2*p2[1]- p1[1]; + pt[2]= 2*p2[2]- p1[2]; + p3= pt; + } + else p3= next->vec[1]; + + if(mode && bezt->h1==HD_AUTO && prev) { + dx= p2[0] - (p1[0]+p1[3])/2.0f; + dy= p2[1] - (p1[1]+p1[4])/2.0f; + dz= p2[2] - (p1[2]+p1[5])/2.0f; + } + else { + dx= p2[0]- p1[0]; + dy= p2[1]- p1[1]; + dz= p2[2]- p1[2]; + } + len1= (float)sqrt(dx*dx+dy*dy+dz*dz); + + if(mode && bezt->h2==HD_AUTO && next) { + dx1= (p3[0]+p3[-3])/2.0f - p2[0]; + dy1= (p3[1]+p3[-2])/2.0f - p2[1]; + dz1= (p3[2]+p3[-1])/2.0f - p2[2]; + } + else { + dx1= p3[0]- p2[0]; + dy1= p3[1]- p2[1]; + dz1= p3[2]- p2[2]; + } + len2= (float)sqrt(dx1*dx1+dy1*dy1+dz1*dz1); + + if(len1==0.0f) len1=1.0f; + if(len2==0.0f) len2=1.0f; + + + if(bezt->h1==HD_AUTO || bezt->h2==HD_AUTO) { /* auto */ + vx= dx1/len2 + dx/len1; + vy= dy1/len2 + dy/len1; + vz= dz1/len2 + dz/len1; + len= 2.71f*(float)sqrt(vx*vx + vy*vy + vz*vz); + if(len!=0.0f) { + + if(len1>5.0f*len2) len1= 5.0f*len2; + if(len2>5.0f*len1) len2= 5.0f*len1; + + if(bezt->h1==HD_AUTO) { + len1/=len; + *(p2-3)= *p2-vx*len1; + *(p2-2)= *(p2+1)-vy*len1; + *(p2-1)= *(p2+2)-vz*len1; + } + if(bezt->h2==HD_AUTO) { + len2/=len; + *(p2+3)= *p2+vx*len2; + *(p2+4)= *(p2+1)+vy*len2; + *(p2+5)= *(p2+2)+vz*len2; + } + } + } + + if(bezt->h1==HD_VECT) { /* vector */ + dx/=3.0; + dy/=3.0; + dz/=3.0; + *(p2-3)= *p2-dx; + *(p2-2)= *(p2+1)-dy; + *(p2-1)= *(p2+2)-dz; + } + if(bezt->h2==HD_VECT) { + dx1/=3.0; + dy1/=3.0; + dz1/=3.0; + *(p2+3)= *p2+dx1; + *(p2+4)= *(p2+1)+dy1; + *(p2+5)= *(p2+2)+dz1; + } + + len2= VecLenf(p2, p2+3); + len1= VecLenf(p2, p2-3); + if(len1==0.0) len1=1.0; + if(len2==0.0) len2=1.0; + if(bezt->f1 & 1) { /* volgorde van berekenen */ + if(bezt->h2==HD_ALIGN) { /* aligned */ + len= len2/len1; + p2[3]= p2[0]+len*(p2[0]-p2[-3]); + p2[4]= p2[1]+len*(p2[1]-p2[-2]); + p2[5]= p2[2]+len*(p2[2]-p2[-1]); + } + if(bezt->h1==HD_ALIGN) { + len= len1/len2; + p2[-3]= p2[0]+len*(p2[0]-p2[3]); + p2[-2]= p2[1]+len*(p2[1]-p2[4]); + p2[-1]= p2[2]+len*(p2[2]-p2[5]); + } + } + else { + if(bezt->h1==HD_ALIGN) { + len= len1/len2; + p2[-3]= p2[0]+len*(p2[0]-p2[3]); + p2[-2]= p2[1]+len*(p2[1]-p2[4]); + p2[-1]= p2[2]+len*(p2[2]-p2[5]); + } + if(bezt->h2==HD_ALIGN) { /* aligned */ + len= len2/len1; + p2[3]= p2[0]+len*(p2[0]-p2[-3]); + p2[4]= p2[1]+len*(p2[1]-p2[-2]); + p2[5]= p2[2]+len*(p2[2]-p2[-1]); + } + } +} + +void calchandlesNurb(Nurb *nu) /* wel eerst (zonodig) de handlevlaggen zetten */ +{ + BezTriple *bezt, *prev, *next; + short a; + + if((nu->type & 7)!=1) return; + if(nu->pntsu<2) return; + + a= nu->pntsu; + bezt= nu->bezt; + if(nu->flagu & 1) prev= bezt+(a-1); + else prev= 0; + next= bezt+1; + + while(a--) { + calchandleNurb(bezt, prev, next, 0); + prev= bezt; + if(a==1) { + if(nu->flagu & 1) next= nu->bezt; + else next= 0; + } + else next++; + + bezt++; + } +} + + +void testhandlesNurb(Nurb *nu) +{ + /* Te gebruiken als er iets an de handles is veranderd. + * Loopt alle BezTriples af met de volgende regels: + * FASE 1: types veranderen? + * Autocalchandles: worden ligned als NOT(000 || 111) + * Vectorhandles worden 'niets' als (selected en andere niet) + * FASE 2: handles herbereken + */ + BezTriple *bezt; + short flag, a; + + if((nu->type & 7)!=CU_BEZIER) return; + + bezt= nu->bezt; + a= nu->pntsu; + while(a--) { + flag= 0; + if(bezt->f1 & 1) flag++; + if(bezt->f2 & 1) flag += 2; + if(bezt->f3 & 1) flag += 4; + + if( !(flag==0 || flag==7) ) { + if(bezt->h1==HD_AUTO) { /* auto */ + bezt->h1= HD_ALIGN; + } + if(bezt->h2==HD_AUTO) { /* auto */ + bezt->h2= HD_ALIGN; + } + + if(bezt->h1==HD_VECT) { /* vector */ + if(flag < 4) bezt->h1= 0; + } + if(bezt->h2==HD_VECT) { /* vector */ + if( flag > 3) bezt->h2= 0; + } + } + bezt++; + } + + calchandlesNurb(nu); +} + +void autocalchandlesNurb(Nurb *nu, int flag) +{ + /* Kijkt naar de coordinaten van de handles en berekent de soort */ + + BezTriple *bezt2, *bezt1, *bezt0; + int i, align, leftsmall, rightsmall; + + if(nu==0 || nu->bezt==0) return; + + bezt2 = nu->bezt; + bezt1 = bezt2 + (nu->pntsu-1); + bezt0 = bezt1 - 1; + i = nu->pntsu; + + while(i--) { + + align= leftsmall= rightsmall= 0; + + /* linker handle: */ + if(flag==0 || (bezt1->f1 & flag) ) { + bezt1->h1= 0; + /* afstand te klein: vectorhandle */ + if( VecLenf( bezt1->vec[1], bezt0->vec[1] ) < 0.0001) { + bezt1->h1= HD_VECT; + leftsmall= 1; + } + else { + /* aligned handle? */ + if(DistVL2Dfl(bezt1->vec[1], bezt1->vec[0], bezt1->vec[2]) < 0.0001) { + align= 1; + bezt1->h1= HD_ALIGN; + } + /* of toch vector handle? */ + if(DistVL2Dfl(bezt1->vec[0], bezt1->vec[1], bezt0->vec[1]) < 0.0001) + bezt1->h1= HD_VECT; + + } + } + /* rechter handle: */ + if(flag==0 || (bezt1->f3 & flag) ) { + bezt1->h2= 0; + /* afstand te klein: vectorhandle */ + if( VecLenf( bezt1->vec[1], bezt2->vec[1] ) < 0.0001) { + bezt1->h2= HD_VECT; + rightsmall= 1; + } + else { + /* aligned handle? */ + if(align) bezt1->h2= HD_ALIGN; + + /* of toch vector handle? */ + if(DistVL2Dfl(bezt1->vec[2], bezt1->vec[1], bezt2->vec[1]) < 0.0001) + bezt1->h2= HD_VECT; + + } + } + if(leftsmall && bezt1->h2==HD_ALIGN) bezt1->h2= 0; + if(rightsmall && bezt1->h1==HD_ALIGN) bezt1->h1= 0; + + /* onzalige combinatie: */ + if(bezt1->h1==HD_ALIGN && bezt1->h2==HD_VECT) bezt1->h1= 0; + if(bezt1->h2==HD_ALIGN && bezt1->h1==HD_VECT) bezt1->h2= 0; + + bezt0= bezt1; + bezt1= bezt2; + bezt2++; + } + + calchandlesNurb(nu); +} + +void autocalchandlesNurb_all(int flag) +{ + Nurb *nu; + + nu= editNurb.first; + while(nu) { + autocalchandlesNurb(nu, flag); + nu= nu->next; + } +} + +void sethandlesNurb(short code) +{ + /* code==1: set autohandle */ + /* code==2: set vectorhandle */ + /* als code==3 (HD_ALIGN) toggelt het, vectorhandles worden HD_FREE */ + Nurb *nu; + BezTriple *bezt; + short a, ok=0; + + if(code==1 || code==2) { + nu= editNurb.first; + while(nu) { + if( (nu->type & 7)==1) { + bezt= nu->bezt; + a= nu->pntsu; + while(a--) { + if(bezt->f1 || bezt->f3) { + if(bezt->f1) bezt->h1= code; + if(bezt->f3) bezt->h2= code; + if(bezt->h1!=bezt->h2) { + if ELEM(bezt->h1, HD_ALIGN, HD_AUTO) bezt->h1= HD_FREE; + if ELEM(bezt->h2, HD_ALIGN, HD_AUTO) bezt->h2= HD_FREE; + } + } + bezt++; + } + calchandlesNurb(nu); + } + nu= nu->next; + } + } + else { + /* is er 1 handle NIET vrij: alles vrijmaken, else ALIGNED maken */ + + nu= editNurb.first; + while(nu) { + if( (nu->type & 7)==1) { + bezt= nu->bezt; + a= nu->pntsu; + while(a--) { + if(bezt->f1 && bezt->h1) ok= 1; + if(bezt->f3 && bezt->h2) ok= 1; + if(ok) break; + bezt++; + } + } + nu= nu->next; + } + if(ok) ok= HD_FREE; + else ok= HD_ALIGN; + + nu= editNurb.first; + while(nu) { + if( (nu->type & 7)==1) { + bezt= nu->bezt; + a= nu->pntsu; + while(a--) { + if(bezt->f1) bezt->h1= ok; + if(bezt->f3 ) bezt->h2= ok; + + bezt++; + } + calchandlesNurb(nu); + } + nu= nu->next; + } + } +} + +void swapdata(void *adr1, void *adr2, int len) +{ + + if(len<=0) return; + + if(len<65) { + char adr[64]; + + memcpy(adr, adr1, len); + memcpy(adr1, adr2, len); + memcpy(adr2, adr, len); + } + else { + char *adr; + + adr= (char *)malloc(len); + memcpy(adr, adr1, len); + memcpy(adr1, adr2, len); + memcpy(adr2, adr, len); + free(adr); + } +} + +void switchdirectionNurb(Nurb *nu) +{ + BezTriple *bezt1, *bezt2; + BPoint *bp1, *bp2; + float *fp1, *fp2, *tempf; + int a, b; + + if(nu->pntsu==1 && nu->pntsv==1) return; + + if((nu->type & 7)==CU_BEZIER) { + a= nu->pntsu; + bezt1= nu->bezt; + bezt2= bezt1+(a-1); + if(a & 1) a+= 1; /* bij oneven ook van middelste inhoud swappen */ + a/= 2; + while(a>0) { + if(bezt1!=bezt2) SWAP(BezTriple, *bezt1, *bezt2); + + swapdata(bezt1->vec[0], bezt1->vec[2], 12); + if(bezt1!=bezt2) swapdata(bezt2->vec[0], bezt2->vec[2], 12); + + SWAP(char, bezt1->h1, bezt1->h2); + SWAP(short, bezt1->f1, bezt1->f3); + + if(bezt1!=bezt2) { + SWAP(char, bezt2->h1, bezt2->h2); + SWAP(short, bezt2->f1, bezt2->f3); + bezt1->alfa= -bezt1->alfa; + bezt2->alfa= -bezt2->alfa; + } + a--; + bezt1++; + bezt2--; + } + } + else if(nu->pntsv==1) { + a= nu->pntsu; + bp1= nu->bp; + bp2= bp1+(a-1); + a/= 2; + while(bp1!=bp2 && a>0) { + SWAP(BPoint, *bp1, *bp2); + a--; + bp1->alfa= -bp1->alfa; + bp2->alfa= -bp2->alfa; + bp1++; + bp2--; + } + if((nu->type & 7)==CU_NURBS) { + /* de knots omkeren */ + a= KNOTSU(nu); + fp1= nu->knotsu; + fp2= fp1+(a-1); + a/= 2; + while(fp1!=fp2 && a>0) { + SWAP(float, *fp1, *fp2); + a--; + fp1++; + fp2--; + } + /* en weer in stijgende lijn maken */ + a= KNOTSU(nu); + fp1= nu->knotsu; + fp2=tempf= MEM_mallocN(sizeof(float)*a, "switchdirect"); + while(a--) { + fp2[0]= fabs(fp1[1]-fp1[0]); + fp1++; + fp2++; + } + + a= KNOTSU(nu)-1; + fp1= nu->knotsu; + fp2= tempf; + fp1[0]= 0.0; + fp1++; + while(a--) { + fp1[0]= fp1[-1]+fp2[0]; + fp1++; + fp2++; + } + MEM_freeN(tempf); + } + } + else { + + for(b=0; b<nu->pntsv; b++) { + + bp1= nu->bp+b*nu->pntsu; + a= nu->pntsu; + bp2= bp1+(a-1); + a/= 2; + + while(bp1!=bp2 && a>0) { + SWAP(BPoint, *bp1, *bp2); + a--; + bp1++; + bp2--; + } + } + } +} diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c new file mode 100644 index 00000000000..76983001bb6 --- /dev/null +++ b/source/blender/blenkernel/intern/deform.c @@ -0,0 +1,120 @@ +/* deform.c June 2001 + * + * support for deformation groups + * + * Reevan McKay + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" + +#include "DNA_object_types.h" + +#include "BKE_deform.h" + + +void color_temperature (float input, unsigned char *r, unsigned char *g, unsigned char *b) +{ + + /* blue to red */ + + float fr = (float)(*r); + float fg = (float)(*g); + float fb = (float)(*b); + + if (input < 0.0F) + input = 0.0F; + + if (input > 1.0F) + input = 1.0F; + + if (input<=0.25f){ + fr=0.0f; + fg=255.0f * (input*4.0f); + fb=255.0f; + } + else if (input<=0.50f){ + fr=0.0f; + fg=255.0f; + fb=255.0f * (1.0f-((input-0.25f)*4.0f)); + } + else if (input<=0.75){ + fr=255.0f * ((input-0.50f)*4.0f); + fg=255.0f; + fb=0.0f; + } + else if (input<=1.0){ + fr=255.0f; + fg=255.0f * (1.0f-((input-0.75f)*4.0f)); + fb=0.0f; + } + + (*r) = (unsigned char)(fr * ((input/2.0f)+0.5f)); + (*g) = (unsigned char)(fg * ((input/2.0f)+0.5f)); + (*b) = (unsigned char)(fb * ((input/2.0f)+0.5f)); + + +}; + +void copy_defgroups(ListBase *outbase, ListBase *inbase) +{ + bDeformGroup *defgroup, *defgroupn; + + outbase->first= outbase->last= 0; + + for (defgroup = inbase->first; defgroup; defgroup=defgroup->next){ + defgroupn= copy_defgroup(defgroup); + BLI_addtail(outbase, defgroupn); + } +} + +bDeformGroup* copy_defgroup (bDeformGroup *ingroup) +{ + bDeformGroup *outgroup; + + if (!ingroup) + return NULL; + + outgroup=MEM_callocN(sizeof(bDeformGroup), "deformGroup"); + + /* For now, just copy everything over. */ + memcpy (outgroup, ingroup, sizeof(bDeformGroup)); + + outgroup->next=outgroup->prev=NULL; + + return outgroup; +} + diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c new file mode 100644 index 00000000000..b9f9d59c5e3 --- /dev/null +++ b/source/blender/blenkernel/intern/displist.c @@ -0,0 +1,2085 @@ + +/* displist.c GRAPHICS + * + * + * maart 95 + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#include <math.h> +#include <stdio.h> +#include <string.h> + +#ifdef WIN32 +#include "BLI_winstuff.h" +#endif +#include "MEM_guardedalloc.h" + +#include "nla.h" /* For __NLA: Please do not remove yet */ + +#include "IMB_imbuf_types.h" + +#include "DNA_texture_types.h" +#include "DNA_meta_types.h" +#include "DNA_curve_types.h" +#include "DNA_listBase.h" +#include "DNA_lamp_types.h" +#include "DNA_object_types.h" +#include "DNA_mesh_types.h" +#include "DNA_scene_types.h" +#include "DNA_image_types.h" +#include "DNA_material_types.h" +#include "DNA_view3d_types.h" +#include "DNA_lattice_types.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_editVert.h" + +#include "BKE_bad_level_calls.h" +#include "BKE_utildefines.h" +#include "BKE_global.h" +#include "BKE_displist.h" +#include "BKE_object.h" +#include "BKE_world.h" +#include "BKE_mesh.h" +#include "BKE_effect.h" +#include "BKE_mball.h" +#include "BKE_material.h" +#include "BKE_curve.h" +#include "BKE_anim.h" +#include "BKE_screen.h" +#include "BKE_texture.h" +#include "BKE_library.h" +#include "BKE_font.h" +#include "BKE_lattice.h" +#include "BKE_scene.h" +#include "BKE_subsurf.h" + +/***/ + +typedef struct _FastLamp FastLamp; +struct _FastLamp { + FastLamp *next; + + short type, mode, lay, rt; + float co[3]; + float vec[3]; + float dist, distkw, att1, att2, spotsi, spotbl, r, g, b; +}; + +/***/ + +static FastLamp *fastlamplist= NULL; +static float fviewmat[4][4]; + +static void displistmesh_free(DispListMesh *dlm) { + // also check on mvert and mface, can be NULL after decimator (ton) + if( dlm->mvert) MEM_freeN(dlm->mvert); + if (dlm->mface) MEM_freeN(dlm->mface); + if (dlm->mcol) MEM_freeN(dlm->mcol); + if (dlm->tface) MEM_freeN(dlm->tface); + MEM_freeN(dlm); +} + +static DispListMesh *displistmesh_copy(DispListMesh *odlm) { + DispListMesh *ndlm= MEM_dupallocN(odlm); + ndlm->mvert= MEM_dupallocN(odlm->mvert); + ndlm->mface= MEM_dupallocN(odlm->mface); + if (odlm->mcol) ndlm->mcol= MEM_dupallocN(odlm->mcol); + if (odlm->tface) ndlm->tface= MEM_dupallocN(odlm->tface); + + return ndlm; +} + +void free_disp_elem(DispList *dl) +{ + if(dl) { + if(dl->verts) MEM_freeN(dl->verts); + if(dl->nors) MEM_freeN(dl->nors); + if(dl->index) MEM_freeN(dl->index); + if(dl->col1) MEM_freeN(dl->col1); + if(dl->col2) MEM_freeN(dl->col2); + if(dl->mesh) displistmesh_free(dl->mesh); + MEM_freeN(dl); + } +} + +void freedisplist(ListBase *lb) +{ + DispList *dl; + + dl= lb->first; + while(dl) { + BLI_remlink(lb, dl); + free_disp_elem(dl); + dl= lb->first; + } +} + +void free_displist_by_type(ListBase *lb, int type) +{ + DispList *dl; + + for (dl= lb->first; dl; ) { + DispList *next= dl->next; + + if (dl->type==type) { + BLI_remlink(lb, dl); + free_disp_elem(dl); + } + + dl= next; + } +} + +DispList *find_displist_create(ListBase *lb, int type) +{ + DispList *dl; + + dl= lb->first; + while(dl) { + if(dl->type==type) return dl; + dl= dl->next; + } + + dl= MEM_callocN(sizeof(DispList), "find_disp"); + dl->type= type; + BLI_addtail(lb, dl); + + return dl; +} + +DispList *find_displist(ListBase *lb, int type) +{ + DispList *dl; + + dl= lb->first; + while(dl) { + if(dl->type==type) return dl; + dl= dl->next; + } + + return 0; +} + +void copy_displist(ListBase *lbn, ListBase *lb) +{ + DispList *dln, *dl; + + lbn->first= lbn->last= 0; + + dl= lb->first; + while(dl) { + + dln= MEM_dupallocN(dl); + BLI_addtail(lbn, dln); + dln->verts= MEM_dupallocN(dl->verts); + dln->nors= MEM_dupallocN(dl->nors); + dln->index= MEM_dupallocN(dl->index); + dln->col1= MEM_dupallocN(dl->col1); + dln->col2= MEM_dupallocN(dl->col2); + if (dl->mesh) + dln->mesh= displistmesh_copy(dl->mesh); + + dl= dl->next; + } +} + +static void initfastshade(void) +{ + Base *base; + Object *ob; + Lamp *la; + FastLamp *fl; + float mat[4][4]; + + R.vlr= 0; + + init_render_world(); + + if(fastlamplist) return; + if(G.scene->camera==0) G.scene->camera= scene_find_camera(G.scene); + if(G.scene->camera==0) return; + + /* uit roteerscene gejat */ + where_is_object(G.scene->camera); + Mat4CpyMat4(R.viewinv, G.scene->camera->obmat); + Mat4Ortho(R.viewinv); + Mat4Invert(fviewmat, R.viewinv); + + + /* initrendertexture(); */ + + base= G.scene->base.first; + while(base) { + ob= base->object; + if( ob->type==OB_LAMP && (base->lay & G.scene->lay)) { + + Mat4MulMat4(mat, ob->obmat, fviewmat); + + la= ob->data; + fl= MEM_mallocN(sizeof(FastLamp), "initfastshade2"); + + fl->next= fastlamplist; + fastlamplist= fl; + + fl->type= la->type; + fl->mode= la->mode; + fl->lay= base->lay; + + fl->vec[0]= mat[2][0]; + fl->vec[1]= mat[2][1]; + fl->vec[2]= mat[2][2]; + Normalise(fl->vec); + + fl->co[0]= mat[3][0]; + fl->co[1]= mat[3][1]; + fl->co[2]= mat[3][2]; + + fl->dist= la->dist; + fl->distkw= fl->dist*fl->dist; + fl->att1= la->att1; + fl->att2= la->att2; + + fl->spotsi= (float)cos( M_PI*la->spotsize/360.0 ); + fl->spotbl= (1.0f-fl->spotsi)*la->spotblend; + + fl->r= la->energy*la->r; + fl->g= la->energy*la->g; + fl->b= la->energy*la->b; + } + + if(base->next==0 && G.scene->set && base==G.scene->base.last) base= G.scene->set->base.first; + else base= base->next; + } +} + + +void freefastshade() +{ + while (fastlamplist) { + FastLamp *fl= fastlamplist; + fastlamplist= fl->next; + + MEM_freeN(fl); + } +} + + +static void fastshade(float *co, float *nor, float *orco, Material *ma, char *col1, char *col2, char *vertcol) +{ + FastLamp *fl; + float i, t, inp, soft, inpr, inpg, inpb, isr=0, isg=0, isb=0, lv[3], lampdist, ld; + float inpr1, inpg1, inpb1, isr1=0, isg1=0, isb1=0; + int a, back; + + if(ma==0) return; + R.mat= ma; + R.matren= ma->ren; + ma= R.matren; + + if(ma->mode & MA_VERTEXCOLP) { + if(vertcol) { + ma->r= vertcol[3]/255.0; + ma->g= vertcol[2]/255.0; + ma->b= vertcol[1]/255.0; + } + } + + if(ma->texco) { + VECCOPY(R.lo, orco); + VECCOPY(R.vn, nor); + + if(ma->texco & TEXCO_GLOB) { + VECCOPY(R.gl, R.lo); + } + if(ma->texco & TEXCO_WINDOW) { + VECCOPY(R.winco, R.lo); + } + if(ma->texco & TEXCO_STICKY) { + VECCOPY(R.sticky, R.lo); + } + if(ma->texco & TEXCO_UV) { + VECCOPY(R.uv, R.lo); + } + if(ma->texco & TEXCO_OBJECT) { + VECCOPY(R.co, R.lo); + } + if(ma->texco & TEXCO_NORM) { + VECCOPY(R.orn, R.vn); + } + if(ma->texco & TEXCO_REFL) { + + inp= 2.0*(R.vn[2]); + R.ref[0]= (inp*R.vn[0]); + R.ref[1]= (inp*R.vn[1]); + R.ref[2]= (-1.0+inp*R.vn[2]); + } + + if(ma->mode & MA_VERTEXCOLP) { + R.mat->r= ma->r; + R.mat->g= ma->g; + R.mat->b= ma->b; + } + do_material_tex(); + } + + if(ma->mode & MA_SHLESS) { + if(vertcol && (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP))== MA_VERTEXCOL ) { + col1[3]= vertcol[3]*ma->r; + col1[2]= vertcol[2]*ma->g; + col1[1]= vertcol[1]*ma->b; + } + else { + col1[3]= (255.0*ma->r); + col1[2]= (255.0*ma->g); + col1[1]= (255.0*ma->b); + } + if(col2) { + col2[3]= col1[3]; + col2[2]= col1[2]; + col2[1]= col1[1]; + } + return; + } + + if( vertcol && (ma->mode & (MA_VERTEXCOL+MA_VERTEXCOLP))== MA_VERTEXCOL ) { + inpr= inpr1= ma->emit+vertcol[3]/255.0; + inpg= inpg1= ma->emit+vertcol[2]/255.0; + inpb= inpb1= ma->emit+vertcol[1]/255.0; + } + else { + inpr= inpg= inpb= inpr1= inpg1= inpb1= ma->emit; + } + + /* col[0]= (255.0*ma->r); */ + /* col[1]= (255.0*ma->g); */ + /* col[2]= (255.0*ma->b); */ + + for (fl= fastlamplist; fl; fl= fl->next) { + /* if(fl->mode & LA_LAYER) if((fl->lay & ma->lay)==0) continue; */ + + if(fl->type==LA_SUN || fl->type==LA_HEMI) { + VECCOPY(lv, fl->vec); + lampdist= 1.0; + } + else { + lv[0]= fl->co[0] - co[0]; + lv[1]= fl->co[1] - co[1]; + lv[2]= fl->co[2] - co[2]; + ld= sqrt(lv[0]*lv[0]+lv[1]*lv[1]+lv[2]*lv[2]); + lv[0]/=ld; + lv[1]/=ld; + lv[2]/=ld; + + if(fl->mode & LA_QUAD) { + t= 1.0; + if(fl->att1>0.0) + t= fl->dist/(fl->dist+fl->att1*ld); + if(fl->att2>0.0) + t*= fl->distkw/(fl->distkw+fl->att2*ld*ld); + + lampdist= t; + } + else { + lampdist= (fl->dist/(fl->dist+ld)); + } + + if(fl->mode & LA_SPHERE) { + t= fl->dist - ld; + if(t<0.0) continue; + + t/= fl->dist; + lampdist*= (t); + } + } + + if(fl->type==LA_SPOT) { + inp= lv[0]*fl->vec[0]+lv[1]*fl->vec[1]+lv[2]*fl->vec[2]; + if(inp<fl->spotsi) continue; + else { + t= inp-fl->spotsi; + i= 1.0; + soft= 1.0; + if(t<fl->spotbl && fl->spotbl!=0.0) { + /* zachte gebied */ + i= t/fl->spotbl; + t= i*i; + soft= (3.0*t-2.0*t*i); + inp*= soft; + } + + lampdist*=inp; + } + } + + inp= nor[0]*lv[0]+ nor[1]*lv[1]+ nor[2]*lv[2]; + + back= 0; + if(inp<0.0) { + back= 1; + inp= -inp; + } + inp*= lampdist*ma->ref; + + if(back==0) { + inpr+= inp*fl->r; + inpg+= inp*fl->g; + inpb+= inp*fl->b; + } else if(col2) { + inpr1+= inp*fl->r; + inpg1+= inp*fl->g; + inpb1+= inp*fl->b; + } + if(ma->spec) { + + lv[2]+= 1.0; + Normalise(lv); + t= nor[0]*lv[0]+nor[1]*lv[1]+nor[2]*lv[2]; + if(t>0) { + t= ma->spec*lampdist*RE_Spec(t, ma->har); + if(back==0) { + isr+= t*(fl->r * ma->specr); + isg+= t*(fl->g * ma->specg); + isb+= t*(fl->b * ma->specb); + } + else if(col2) { + isr1+= t*(fl->r * ma->specr); + isg1+= t*(fl->g * ma->specg); + isb1+= t*(fl->b * ma->specb); + } + } + } + + } + + a= 256*(inpr*ma->r + ma->ambr +isr); + if(a>255) col1[3]= 255; + else col1[3]= a; + a= 256*(inpg*ma->g + ma->ambg +isg); + if(a>255) col1[2]= 255; + else col1[2]= a; + a= 256*(inpb*ma->b + ma->ambb +isb); + if(a>255) col1[1]= 255; + else col1[1]= a; + + if(col2) { + a= 256*(inpr1*ma->r + ma->ambr +isr1); + if(a>255) col2[3]= 255; + else col2[3]= a; + a= 256*(inpr1*ma->g + ma->ambg +isg1); + if(a>255) col2[2]= 255; + else col2[2]= a; + a= 256*(inpr1*ma->b + ma->ambb +isb1); + if(a>255) col2[1]= 255; + else col2[1]= a; + } + +} + +void addnormalsDispList(Object *ob, ListBase *lb) +{ + DispList *dl = NULL; + Mesh *me; + MVert *ve1, *ve2, *ve3, *ve4; + MFace *mface; + float *vdata, *ndata, nor[3]; + float *v1, *v2, *v3, *v4; + float *n1, *n2, *n3, *n4; + int a, b, p1, p2, p3, p4; + + + if(ob->type==OB_MESH) { + + me= get_mesh(ob); + + if (mesh_uses_displist(me)) { + DispList *dl= find_displist(&me->disp, DL_MESH); + + if (dl && !dl->nors) { + DispListMesh *dlm= dl->mesh; + int i; + + dl->nors= MEM_mallocN(sizeof(*dl->nors)*3*dlm->totface, "meshnormals"); + + for (i=0; i<dlm->totface; i++) { + MFaceInt *mf= &dlm->mface[i]; + float *no= &dl->nors[i*3]; + + if (mf->v3) { + if (mf->v4) + CalcNormFloat4(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, dlm->mvert[mf->v4].co, no); + else + CalcNormFloat(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, no); + } + } + } + } else { + if(me->totface==0) return; + + if(me->disp.first==0) { + dl= MEM_callocN(sizeof(DispList), "meshdisp"); + dl->type= DL_NORS; + dl->parts= 1; + dl->nr= me->totface; + BLI_addtail(&me->disp, dl); + } + + if(dl->nors==0) { + dl->nors= MEM_mallocN(sizeof(float)*3*me->totface, "meshnormals"); + n1= dl->nors; + mface= me->mface; + a= me->totface; + while(a--) { + if(mface->v3) { + ve1= me->mvert+mface->v1; + ve2= me->mvert+mface->v2; + ve3= me->mvert+mface->v3; + ve4= me->mvert+mface->v4; + + if(mface->v4) CalcNormFloat4(ve1->co, ve2->co, ve3->co, ve4->co, n1); + else CalcNormFloat(ve1->co, ve2->co, ve3->co, n1); + } + n1+= 3; + mface++; + } + } + } + + return; + } + + dl= lb->first; + + while(dl) { + if(dl->type==DL_INDEX3) { + if(dl->nors==0) { + dl->nors= MEM_callocN(sizeof(float)*3, "dlnors"); + if(dl->verts[2]<0.0) dl->nors[2]= -1.0; + else dl->nors[2]= 1.0; + } + } + else if(dl->type==DL_SURF) { + if(dl->nors==0) { + dl->nors= MEM_callocN(sizeof(float)*3*dl->nr*dl->parts, "dlnors"); + + vdata= dl->verts; + ndata= dl->nors; + + for(a=0; a<dl->parts; a++) { + + DL_SURFINDEX(dl->flag & 1, dl->flag & 2, dl->nr, dl->parts); + + v1= vdata+ 3*p1; + n1= ndata+ 3*p1; + v2= vdata+ 3*p2; + n2= ndata+ 3*p2; + v3= vdata+ 3*p3; + n3= ndata+ 3*p3; + v4= vdata+ 3*p4; + n4= ndata+ 3*p4; + + for(; b<dl->nr; b++) { + + CalcNormFloat4(v1, v3, v4, v2, nor); + + VecAddf(n1, n1, nor); + VecAddf(n2, n2, nor); + VecAddf(n3, n3, nor); + VecAddf(n4, n4, nor); + + v2= v1; v1+= 3; + v4= v3; v3+= 3; + n2= n1; n1+= 3; + n4= n3; n3+= 3; + } + } + a= dl->parts*dl->nr; + v1= ndata; + while(a--) { + Normalise(v1); + v1+= 3; + } + } + } + dl= dl->next; + } +} + + +void shadeDispList(Object *ob) +{ + MFace *mface; + MVert *mvert; + DispList *dl, *dlob, *dldeform; + Material *ma = NULL; + Mesh *me; + Curve *cu; +/* extern Material defmaterial; *//* initrender.c, already in bad lev calls*/ + float *orco, imat[3][3], tmat[4][4], mat[4][4], vec[3], xn, yn, zn; + float *fp, *nor, n1[3]; + unsigned int *col1, *col2, *vertcol; + int a, lastmat= -1, need_orco = 0; + + if(ob->flag & OB_FROMDUPLI) return; + initfastshade(); + + Mat4MulMat4(mat, ob->obmat, fviewmat); + + Mat4Invert(tmat, mat); + Mat3CpyMat4(imat, tmat); + + /* we halen de dl_verts eruit, deform info */ + dldeform= find_displist(&ob->disp, DL_VERTS); + if(dldeform) BLI_remlink(&ob->disp, dldeform); + + /* Metaballs hebben de standaard displist aan het Object zitten */ + if(ob->type!=OB_MBALL) freedisplist(&ob->disp); + + if((R.flag & R_RENDERING)==0) { + need_orco= 0; + for(a=0; a<ob->totcol; a++) { + ma= give_current_material(ob, a+1); + if(ma) { + init_render_material(ma); + if(ma->ren->texco & TEXCO_ORCO) need_orco= 1; + } + } + } + if(ob->type==OB_MESH) { + + me= ob->data; + + if (mesh_uses_displist(me)) { + if (need_orco) { + make_orco_displist_mesh(ob, me->subdiv); + orco= me->orco; + } + + dl= me->disp.first; + while(dl) { + if(dl->type==DL_MESH) { + DispListMesh *dlm= dl->mesh; + int i; + + dlob= MEM_callocN(sizeof(DispList), "displistshade"); + BLI_addtail(&ob->disp, dlob); + dlob->type= DL_VERTCOL; + + dlob->col1= MEM_mallocN(sizeof(*dlob->col1)*dlm->totface*4, "col1"); + if (me->flag & ME_TWOSIDED) + dlob->col2= MEM_mallocN(sizeof(*dlob->col2)*dlm->totface*4, "col1"); + + for (i=0; i<dlm->totface; i++) { + MFaceInt *mf= &dlm->mface[i]; + + if (mf->v3) { + int j, vidx[4], nverts= mf->v4?4:3; + unsigned int *col1base= &dlob->col1[i*4]; + unsigned int *col2base= dlob->col2?&dlob->col2[i*4]:NULL; + MCol *mcolbase= dlm->mcol?&dlm->mcol[i*4]:NULL; + float nor[3]; + + ma= give_current_material(ob, mf->mat_nr+1); + if(ma==0) ma= &defmaterial; + + vidx[0]= mf->v1; + vidx[1]= mf->v2; + vidx[2]= mf->v3; + vidx[3]= mf->v4; + + if (mf->v4) + CalcNormFloat4(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, dlm->mvert[mf->v4].co, nor); + else + CalcNormFloat(dlm->mvert[mf->v1].co, dlm->mvert[mf->v2].co, dlm->mvert[mf->v3].co, nor); + + n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2]; + n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2]; + n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2]; + Normalise(n1); + + for (j=0; j<nverts; j++) { + MVert *mv= &dlm->mvert[vidx[j]]; + unsigned int *col1= &col1base[j]; + unsigned int *col2= col2base?&col2base[j]:NULL; + MCol *mcol= mcolbase?&mcolbase[j]:NULL; + + VECCOPY(vec, mv->co); + Mat4MulVecfl(mat, vec); + + if (need_orco && orco) + fastshade(vec, n1, &orco[vidx[j]*3], ma, (char *)col1, (char*)col2, (char*) mcol); + else + fastshade(vec, n1, mv->co, ma, (char *)col1, (char*)col2, (char*) mcol); + } + } + } + } + dl= dl->next; + } + + if (need_orco && orco) { + MEM_freeN(me->orco); + me->orco= NULL; + } + } + else if(me->totvert>0) { + + if(me->orco==0 && need_orco) { + make_orco_mesh(me); + } + orco= me->orco; + /* ms= me->msticky; */ + + dl= me->disp.first; + if(dl==0 || dl->nors==0) addnormalsDispList(ob, &me->disp); + dl= me->disp.first; + if(dl==0 || dl->nors==0) return; + nor= dl->nors; + + dl= MEM_callocN(sizeof(DispList), "displistshade"); + BLI_addtail(&ob->disp, dl); + dl->type= DL_VERTCOL; + col1= dl->col1= MEM_mallocN(4*sizeof(int)*me->totface, "col1"); + col2= 0; + if(me->tface) tface_to_mcol(me); + vertcol= (unsigned int *)me->mcol; + + if( me->flag & ME_TWOSIDED) { + col2= dl->col2= MEM_mallocN(4*sizeof(int)*me->totface, "col2"); + } + + /* even geen puno's */ + mvert= me->mvert; + a= me->totvert; + while(FALSE || a--) { + + VECCOPY(vec, mvert->co); + Mat4MulVecfl(mat, vec); + + xn= mvert->no[0]; + yn= mvert->no[1]; + zn= mvert->no[2]; + + /* transpose ! */ + n1[0]= imat[0][0]*xn+imat[0][1]*yn+imat[0][2]*zn; + n1[1]= imat[1][0]*xn+imat[1][1]*yn+imat[1][2]*zn; + n1[2]= imat[2][0]*xn+imat[2][1]*yn+imat[2][2]*zn; + Normalise(n1); + + mvert++; + } + + mface= me->mface; + a= me->totface; + while(a--) { + + if(mface->v3) { + + /* transpose ! */ + n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2]; + n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2]; + n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2]; + Normalise(n1); + + if(lastmat!=mface->mat_nr) { + ma= give_current_material(ob, mface->mat_nr+1); + if(ma==0) ma= &defmaterial; + lastmat= mface->mat_nr; + } + + mvert= me->mvert+mface->v1; + VECCOPY(vec, mvert->co); + Mat4MulVecfl(mat, vec); + + if(orco) fastshade(vec, n1, orco+3*mface->v1, ma, (char *)col1, (char *)col2, (char *)vertcol); + else fastshade(vec, n1, mvert->co, ma, (char *)col1, (char *)col2, (char *)vertcol); + col1++; + if(vertcol) vertcol++; + if(col2) col2++; + + mvert= me->mvert+mface->v2; + VECCOPY(vec, mvert->co); + Mat4MulVecfl(mat, vec); + + if(orco) fastshade(vec, n1, orco+3*mface->v2, ma, (char *)col1, (char *)col2, (char *)vertcol); + else fastshade(vec, n1, mvert->co, ma, (char *)col1, (char *)col2, (char *)vertcol); + col1++; + if(vertcol) vertcol++; + if(col2) col2++; + + mvert= me->mvert+mface->v3; + VECCOPY(vec, mvert->co); + Mat4MulVecfl(mat, vec); + + if(orco) fastshade(vec, n1, orco+3*mface->v3, ma, (char *)col1, (char *)col2, (char *)vertcol); + else fastshade(vec, n1, mvert->co, ma, (char *)col1, (char *)col2, (char *)vertcol); + col1++; + if(vertcol) vertcol++; + if(col2) col2++; + + if(mface->v4) { + mvert= me->mvert+mface->v4; + VECCOPY(vec, mvert->co); + Mat4MulVecfl(mat, vec); + + if(orco) fastshade(vec, n1, orco+3*mface->v4, ma, (char *)col1, (char *)col2, (char *)vertcol); + else fastshade(vec, n1, mvert->co, ma, (char *)col1, (char *)col2, (char *)vertcol); + } + col1++; + if(vertcol) vertcol++; + if(col2) col2++; + + } + else { + col1+=4; + if(vertcol) vertcol+=4; + if(col2) col2+=4; + } + + nor+= 3; + mface++; + } + + if(me->orco) { + MEM_freeN(me->orco); + me->orco= 0; + } + if(me->tface) { + MEM_freeN(me->mcol); + me->mcol= 0; + } + } + } + else if ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT) { + + /* nu hebben we wel de normalen nodig */ + cu= ob->data; + dl= cu->disp.first; + + while(dl) { + dlob= MEM_callocN(sizeof(DispList), "displistshade"); + BLI_addtail(&ob->disp, dlob); + dlob->type= DL_VERTCOL; + dlob->parts= dl->parts; + dlob->nr= dl->nr; + + if(dl->type==DL_INDEX3) { + col1= dlob->col1= MEM_mallocN(sizeof(int)*dl->nr, "col1"); + } + else { + col1= dlob->col1= MEM_mallocN(sizeof(int)*dl->parts*dl->nr, "col1"); + } + + + ma= give_current_material(ob, dl->col+1); + if(ma==0) ma= &defmaterial; + + if(dl->type==DL_INDEX3) { + if(dl->nors) { + /* er is maar 1 normaal */ + n1[0]= imat[0][0]*dl->nors[0]+imat[0][1]*dl->nors[1]+imat[0][2]*dl->nors[2]; + n1[1]= imat[1][0]*dl->nors[0]+imat[1][1]*dl->nors[1]+imat[1][2]*dl->nors[2]; + n1[2]= imat[2][0]*dl->nors[0]+imat[2][1]*dl->nors[1]+imat[2][2]*dl->nors[2]; + Normalise(n1); + + fp= dl->verts; + + a= dl->nr; + while(a--) { + VECCOPY(vec, fp); + Mat4MulVecfl(mat, vec); + + fastshade(vec, n1, fp, ma, (char *)col1, 0, 0); + + fp+= 3; col1++; + } + } + } + else if(dl->type==DL_SURF) { + if(dl->nors) { + a= dl->nr*dl->parts; + fp= dl->verts; + nor= dl->nors; + + while(a--) { + VECCOPY(vec, fp); + Mat4MulVecfl(mat, vec); + + n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2]; + n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2]; + n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2]; + Normalise(n1); + + fastshade(vec, n1, fp, ma, (char *)col1, 0, 0); + + fp+= 3; nor+= 3; col1++; + } + } + } + dl= dl->next; + } + } + else if(ob->type==OB_MBALL) { + /* normalen zijn er al */ + dl= ob->disp.first; + + while(dl) { + + if(dl->type==DL_INDEX4) { + if(dl->nors) { + + if(dl->col1) MEM_freeN(dl->col1); + col1= dl->col1= MEM_mallocN(sizeof(int)*dl->nr, "col1"); + + ma= give_current_material(ob, dl->col+1); + if(ma==0) ma= &defmaterial; + + fp= dl->verts; + nor= dl->nors; + + a= dl->nr; + while(a--) { + VECCOPY(vec, fp); + Mat4MulVecfl(mat, vec); + + /* transpose ! */ + n1[0]= imat[0][0]*nor[0]+imat[0][1]*nor[1]+imat[0][2]*nor[2]; + n1[1]= imat[1][0]*nor[0]+imat[1][1]*nor[1]+imat[1][2]*nor[2]; + n1[2]= imat[2][0]*nor[0]+imat[2][1]*nor[1]+imat[2][2]*nor[2]; + Normalise(n1); + + fastshade(vec, n1, fp, ma, (char *)col1, 0, 0); + + fp+= 3; col1++; nor+= 3; + } + } + } + dl= dl->next; + } + } + + if((R.flag & R_RENDERING)==0) { + for(a=0; a<ob->totcol; a++) { + ma= give_current_material(ob, a+1); + if(ma) end_render_material(ma); + } + } + + /* deze was er tijdelijk uitgehaald */ + if(dldeform) BLI_addtail(&ob->disp, dldeform); +} + +void reshadeall_displist(void) +{ + DispList *dldeform; + Base *base; + Object *ob; + + freefastshade(); + + base= G.scene->base.first; + while(base) { + if(base->lay & G.scene->lay) { + + ob= base->object; + + /* we halen de dl_verts eruit, deform info */ + dldeform= find_displist(&ob->disp, DL_VERTS); + if(dldeform) BLI_remlink(&ob->disp, dldeform); + + /* Metaballs hebben de standaard displist aan het Object zitten */ + if(ob->type==OB_MBALL) shadeDispList(ob); + else freedisplist(&ob->disp); + + if(dldeform) BLI_addtail(&ob->disp, dldeform); + } + base= base->next; + } +} + +void count_displist(ListBase *lb, int *totvert, int *totface) +{ + DispList *dl; + + dl= lb->first; + while(dl) { + + switch(dl->type) { + case DL_SURF: + *totvert+= dl->nr*dl->parts; + *totface+= (dl->nr-1)*(dl->parts-1); + break; + case DL_INDEX3: + case DL_INDEX4: + *totvert+= dl->nr; + *totface+= dl->parts; + break; + case DL_POLY: + case DL_SEGM: + *totvert+= dl->nr*dl->parts; + } + + dl= dl->next; + } +} + +static void curve_to_displist(ListBase *nubase, ListBase *dispbase) +{ + Nurb *nu; + DispList *dl; + BezTriple *bezt, *prevbezt; + BPoint *bp; + float *data, *v1, *v2; + int a, len; + + nu= nubase->first; + + while(nu) { + if(nu->hide==0) { + if((nu->type & 7)==CU_BEZIER) { + + /* tellen */ + len= 0; + a= nu->pntsu-1; + if(nu->flagu & 1) a++; + + prevbezt= nu->bezt; + bezt= prevbezt+1; + while(a--) { + if(a==0 && (nu->flagu & 1)) bezt= nu->bezt; + + if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) len++; + else len+= nu->resolu; + + if(a==0 && (nu->flagu & 1)==0) len++; + + prevbezt= bezt; + bezt++; + } + + dl= MEM_callocN(sizeof(DispList), "makeDispListbez"); + /* len+1 i.v.m. maakbez */ + dl->verts= MEM_callocN( (len+1)*3*sizeof(float), "dlverts"); + BLI_addtail(dispbase, dl); + dl->parts= 1; + dl->nr= len; + dl->col= nu->mat_nr; + + data= dl->verts; + + if(nu->flagu & 1) { + dl->type= DL_POLY; + a= nu->pntsu; + } + else { + dl->type= DL_SEGM; + a= nu->pntsu-1; + } + + prevbezt= nu->bezt; + bezt= prevbezt+1; + + while(a--) { + if(a==0 && dl->type== DL_POLY) bezt= nu->bezt; + + if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) { + VECCOPY(data, prevbezt->vec[1]); + data+= 3; + } + else { + v1= prevbezt->vec[1]; + v2= bezt->vec[0]; + maakbez(v1[0], v1[3], v2[0], v2[3], data, nu->resolu); + maakbez(v1[1], v1[4], v2[1], v2[4], data+1, nu->resolu); + if((nu->type & 8)==0) + maakbez(v1[2], v1[5], v2[2], v2[5], data+2, nu->resolu); + data+= 3*nu->resolu; + } + + if(a==0 && dl->type==DL_SEGM) { + VECCOPY(data, bezt->vec[1]); + } + + prevbezt= bezt; + bezt++; + } + } + else if((nu->type & 7)==CU_NURBS) { + len= nu->pntsu*nu->resolu; + dl= MEM_callocN(sizeof(DispList), "makeDispListsurf"); + dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts"); + BLI_addtail(dispbase, dl); + dl->parts= 1; + dl->nr= len; + dl->col= nu->mat_nr; + + data= dl->verts; + if(nu->flagu & 1) dl->type= DL_POLY; + else dl->type= DL_SEGM; + makeNurbcurve(nu, data, 3); + } + else if((nu->type & 7)==CU_POLY) { + len= nu->pntsu; + dl= MEM_callocN(sizeof(DispList), "makeDispListpoly"); + dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts"); + BLI_addtail(dispbase, dl); + dl->parts= 1; + dl->nr= len; + dl->col= nu->mat_nr; + + data= dl->verts; + if(nu->flagu & 1) dl->type= DL_POLY; + else dl->type= DL_SEGM; + + a= len; + bp= nu->bp; + while(a--) { + VECCOPY(data, bp->vec); + bp++; + data+= 3; + } + } + } + nu= nu->next; + } +} + + +static void filldisplist(ListBase *dispbase, ListBase *to) +{ + EditVert *eve, *v1, *vlast; + EditVlak *evl; + DispList *dlnew=0, *dl; + float *f1; + int colnr=0, cont=1, tot, a, *index; + long totvert; + + if(dispbase==0) return; + if(dispbase->first==0) return; + + /* tijd= clock(); */ + /* bit-wise and comes after == .... so this doesn't work... */ +/* if(G.f & G_PLAYANIM == 0) waitcursor(1); */ + if( !(G.f & G_PLAYANIM) ) waitcursor(1); + + while(cont) { + cont= 0; + totvert=0; + + dl= dispbase->first; + while(dl) { + + if(dl->type==DL_POLY) { + if(colnr<dl->col) cont= 1; + else if(colnr==dl->col) { + + colnr= dl->col; + + /* editverts en edges maken */ + f1= dl->verts; + a= dl->nr; + eve= v1= 0; + + while(a--) { + vlast= eve; + + eve= BLI_addfillvert(f1); + totvert++; + + if(vlast==0) v1= eve; + else { + BLI_addfilledge(vlast, eve); + } + f1+=3; + } + + if(eve!=0 && v1!=0) { + BLI_addfilledge(eve, v1); + } + } + } + dl= dl->next; + } + + /* to make edgefill work + G.obedit can be 0 on file load */ + if (G.obedit) { + BLI_setScanFillObjectRef(G.obedit); + BLI_setScanFillColourRef(&G.obedit->actcol); + } + + if(totvert && BLI_edgefill(0)!=0) { + + /* vlakken tellen */ + tot= 0; + evl= fillvlakbase.first; + while(evl) { + tot++; + evl= evl->next; + } + + if(tot) { + dlnew= MEM_callocN(sizeof(DispList), "filldisplist"); + dlnew->type= DL_INDEX3; + dlnew->col= colnr; + dlnew->nr= totvert; + dlnew->parts= tot; + + dlnew->index= MEM_mallocN(tot*3*sizeof(int), "dlindex"); + dlnew->verts= MEM_mallocN(totvert*3*sizeof(float), "dlverts"); + + /* vertdata */ + f1= dlnew->verts; + totvert= 0; + eve= fillvertbase.first; + while(eve) { + VECCOPY(f1, eve->co); + f1+= 3; + + /* indexnummer */ + eve->vn= (EditVert *)totvert; + totvert++; + + eve= eve->next; + } + + /* indexdata */ + evl= fillvlakbase.first; + index= dlnew->index; + while(evl) { + index[0]= (long)evl->v1->vn; + index[1]= (long)evl->v2->vn; + index[2]= (long)evl->v3->vn; + + index+= 3; + evl= evl->next; + } + } + + BLI_addhead(to, dlnew); + + } + BLI_end_edgefill(); + + colnr++; + } + + /* poly's niet vrijgeven. nodig voor wireframe display */ + + /* same as above ... */ +/* if(G.f & G_PLAYANIM == 0) waitcursor(0); */ + if( !(G.f & G_PLAYANIM) ) waitcursor(0); + /* printf("time: %d\n",(clock()-tijd)/1000); */ + +} + +static void bevels_to_filledpoly(Curve *cu, ListBase *dispbase) +{ + ListBase front, back; + DispList *dl, *dlnew; + float *fp, *fp1; + int a, dpoly; + + front.first= front.last= back.first= back.last= 0; + + if(cu->flag & CU_3D) return; + if( (cu->flag & (CU_FRONT+CU_BACK))==0 ) return; + + dl= dispbase->first; + while(dl) { + if(dl->type==DL_SURF) { + if(dl->flag==2) { + if(cu->flag & CU_BACK) { + dlnew= MEM_callocN(sizeof(DispList), "filldisp"); + BLI_addtail(&front, dlnew); + dlnew->verts= fp1= MEM_mallocN(sizeof(float)*3*dl->parts, "filldisp1"); + dlnew->nr= dl->parts; + dlnew->parts= 1; + dlnew->type= DL_POLY; + dlnew->col= dl->col; + + fp= dl->verts; + dpoly= 3*dl->nr; + + a= dl->parts; + while(a--) { + VECCOPY(fp1, fp); + fp1+= 3; + fp+= dpoly; + } + } + if(cu->flag & CU_FRONT) { + dlnew= MEM_callocN(sizeof(DispList), "filldisp"); + BLI_addtail(&back, dlnew); + dlnew->verts= fp1= MEM_mallocN(sizeof(float)*3*dl->parts, "filldisp1"); + dlnew->nr= dl->parts; + dlnew->parts= 1; + dlnew->type= DL_POLY; + dlnew->col= dl->col; + + fp= dl->verts+3*(dl->nr-1); + dpoly= 3*dl->nr; + + a= dl->parts; + while(a--) { + VECCOPY(fp1, fp); + fp1+= 3; + fp+= dpoly; + } + } + } + } + dl= dl->next; + } + + filldisplist(&front, dispbase); + filldisplist(&back, dispbase); + + freedisplist(&front); + freedisplist(&back); + + filldisplist(dispbase, dispbase); + +} + +void curve_to_filledpoly(Curve *cu, ListBase *dispbase) +{ + DispList *dl; + Nurb *nu; + + dl= dispbase->first; + + if(cu->flag & CU_3D) return; + + nu= cu->nurb.first; + while(nu) { + if(nu->flagu & CU_CYCLIC) break; + nu= nu->next; + } + if(nu==0) return; + + if(dl->type==DL_SURF) bevels_to_filledpoly(cu, dispbase); + else { + if(cu->flag & CU_FRONT) filldisplist(dispbase, dispbase); + } +} + + +static int dl_onlyzero= 0; + +void set_displist_onlyzero(int val) +{ + dl_onlyzero= val; +} + +void makeDispList(Object *ob) +{ + Mesh *me; + Nurb *nu; + Curve *cu; + BPoint *bp; + ListBase dlbev, *dispbase; + DispList *dl, *dlb; + BevList *bl; + BevPoint *bevp; + float *data, *fp1, widfac, vec[3]; + int len, a, b, draw=0; + + if(ob==0) return; + if(ob->flag & OB_FROMDUPLI) return; + freedisplist(&(ob->disp)); + + if(ob->type==OB_MESH) { + me= ob->data; + + freedisplist(&(me->disp)); + + tex_space_mesh(ob->data); + + object_deform(ob); + + if(ob->effect.first) object_wave(ob); + + if ((me->flag & ME_SUBSURF) && me->subdiv>0) { + if (ob==G.obedit) + subsurf_make_editmesh(ob); + else + subsurf_make_mesh(ob, me->subdiv); + } + } + else if(ob->type==OB_MBALL) { + ob= find_basis_mball(ob); + + metaball_polygonize(ob); + tex_space_mball(ob); + } + else if(ob->type==OB_SURF) { + + draw= ob->dt; + cu= ob->data; + dispbase= &(cu->disp); + if(dl_onlyzero && dispbase->first) return; + freedisplist(dispbase); + + if(ob==G.obedit) nu= editNurb.first; + else nu= cu->nurb.first; + + while(nu) { + if(nu->hide==0) { + if(nu->pntsv==1) { + if(draw==0) len= nu->pntsu; + else len= nu->pntsu*nu->resolu; + + dl= MEM_callocN(sizeof(DispList), "makeDispListsurf"); + dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts"); + + BLI_addtail(dispbase, dl); + dl->parts= 1; + dl->nr= len; + dl->col= nu->mat_nr; + + data= dl->verts; + if(nu->flagu & 1) dl->type= DL_POLY; + else dl->type= DL_SEGM; + + if(draw==0) { + bp= nu->bp; + while(len--) { + VECCOPY(data, bp->vec); + bp++; + data+= 3; + } + } + else makeNurbcurve(nu, data, 3); + } + else { + if(draw==0 && ob==G.obedit) ; + else { + if(draw==0) len= nu->pntsu*nu->pntsv; + else len= nu->resolu*nu->resolv; + + dl= MEM_callocN(sizeof(DispList), "makeDispListsurf"); + dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts"); + BLI_addtail(dispbase, dl); + + if(draw==0) { + dl->parts= nu->pntsv; + dl->nr= nu->pntsu; + if(nu->flagu & 1) dl->flag|= 1; + if(nu->flagv & 1) dl->flag|= 2; + } + else { + dl->parts= nu->resolu; /* andersom want makeNurbfaces gaat zo */ + dl->nr= nu->resolv; + if(nu->flagv & 1) dl->flag|= 1; /* ook andersom ! */ + if(nu->flagu & 1) dl->flag|= 2; + } + dl->col= nu->mat_nr; + + data= dl->verts; + dl->type= DL_SURF; + + if(draw==0) { + bp= nu->bp; + while(len--) { + VECCOPY(data, bp->vec); + bp++; + data+= 3; + } + } + else makeNurbfaces(nu, data); + } + } + } + nu= nu->next; + } + + tex_space_curve(cu); + + if(ob!=G.obedit) object_deform(ob); + } + else if ELEM(ob->type, OB_CURVE, OB_FONT) { + + draw= ob->dt; + cu= ob->data; + dispbase= &(cu->disp); + if(dl_onlyzero && dispbase->first) return; + freedisplist(dispbase); + + if(cu->path) free_path(cu->path); + cu->path= 0; + + BLI_freelistN(&(cu->bev)); + + if(ob==G.obedit) { + if(ob->type==OB_CURVE) curve_to_displist(&editNurb, dispbase); + else curve_to_displist(&cu->nurb, dispbase); + if(cu->flag & CU_PATH) makeBevelList(ob); + } + else if(cu->ext1==0.0 && cu->ext2==0.0 && cu->bevobj==0 && cu->width==1.0) { + curve_to_displist(&cu->nurb, dispbase); + if(cu->flag & CU_PATH) makeBevelList(ob); + } + else { + + makeBevelList(ob); + + dlbev.first= dlbev.last= 0; + if(cu->ext1!=0.0 || cu->ext2!=0.0 || cu->bevobj) { + if(ob->dt!=0) makebevelcurve(ob, &dlbev); + } + + /* met bevellist werken */ + widfac= cu->width-1.0; + bl= cu->bev.first; + nu= cu->nurb.first; + while(bl) { + if(dlbev.first==0) { + dl= MEM_callocN(sizeof(DispList), "makeDispListbev"); + dl->verts= MEM_callocN(3*sizeof(float)*bl->nr, "dlverts"); + BLI_addtail(dispbase, dl); + if(bl->poly!= -1) dl->type= DL_POLY; + else dl->type= DL_SEGM; + dl->parts= 1; + dl->nr= bl->nr; + dl->col= nu->mat_nr; + + a= dl->nr; + bevp= (BevPoint *)(bl+1); + data= dl->verts; + while(a--) { + data[0]= bevp->x+widfac*bevp->sina; + data[1]= bevp->y+widfac*bevp->cosa; + data[2]= bevp->z; + bevp++; + data+=3; + } + } + else { + /* voor iedere stuk van de bevel een aparte dispblok maken */ + dlb= dlbev.first; + while(dlb) { + dl= MEM_callocN(sizeof(DispList), "makeDispListbev1"); + dl->verts= MEM_callocN(3*sizeof(float)*dlb->nr*bl->nr, "dlverts"); + BLI_addtail(dispbase, dl); + /* dl->type= dlb->type; */ + + dl->type= DL_SURF; + dl->flag= 0; + if(dlb->type==DL_POLY) dl->flag++; + if(bl->poly>=0) dl->flag+=2; + + dl->parts= bl->nr; + dl->nr= dlb->nr; + dl->col= nu->mat_nr; + + data= dl->verts; + bevp= (BevPoint *)(bl+1); + a= bl->nr; + while(a--) { /* voor ieder punt van poly een bevelstuk maken */ + + /* roteer bevelstuk en schrijf in data */ + fp1= dlb->verts; + b= dlb->nr; + + while(b--) { + if(cu->flag & CU_3D) { + + vec[0]= fp1[1]+widfac; + vec[1]= fp1[2]; + vec[2]= 0.0; + + Mat3MulVecfl(bevp->mat, vec); + + data[0]= bevp->x+ vec[0]; + data[1]= bevp->y+ vec[1]; + data[2]= bevp->z+ vec[2]; + } + else { + data[0]= bevp->x+ (fp1[1]+widfac)*bevp->sina; + data[1]= bevp->y+ (fp1[1]+widfac)*bevp->cosa; + data[2]= bevp->z+ fp1[2]; + } + + data+=3; + fp1+=3; + } + + bevp++; + } + + dlb= dlb->next; + } + } + + bl= bl->next; + nu= nu->next; + } + + if(cu->ext1!=0.0 || cu->ext2!=0.0 || cu->bevobj) { + freedisplist(&dlbev); + } + } + + if(ob!=G.obedit) object_deform(ob); + + tex_space_curve(cu); + + } +} + + +/*******************************/ +/***** OUTLINE *****/ +/*******************************/ + +typedef struct Sample{ + short x, y; +} Sample; + +typedef struct Segment{ + /* coordinaten */ + struct Segment * next, * prev; + float co[2]; +} Segment; + + + +static int dflt_in_out(struct ImBuf * ibuf, int x, int y) +{ + unsigned char * rect; + + if (ibuf == 0) return (0); + if (x < 0 || y < 0 || x >= ibuf->x || y >= ibuf->y || ibuf->rect == 0) return (-1); + + rect = (unsigned char *) (ibuf->rect + (y * ibuf->x) + x); + if (rect[0] > 0x81) return (1); + return(0); +} + + +static Sample * outline(struct ImBuf * ibuf, + int (*in_or_out)(struct ImBuf *, int, int)) +{ + static int dirs[8][2] = { + {-1, 0}, {-1, 1}, {0, 1}, {1, 1}, + {1, 0}, {1, -1}, {0, -1}, {-1, -1} + }; + + int dir, x, y, in, i; + int count, sampcount; + int startx = 0, starty = 0; + Sample * samp, * oldsamp; + + /* wat erin gaat: + * 1 - plaatje waarvan outline berekent moet worden, + * 2 - pointer naar functie die bepaalt welke pixel in of uit is + */ + + if (ibuf == 0) return (0); + if (ibuf->rect == 0) return (0); + + if (in_or_out == 0) in_or_out = dflt_in_out; + in = in_or_out(ibuf, 0, 0); + + /* zoek naar eerste overgang en ga van daar uit 'zoeken' */ + for (y = 0; y < ibuf->y; y++) { + for (x = 0; x < ibuf->x; x++) { + if (in_or_out(ibuf, x, y) != in) { + /* eerste 'andere' punt gevonden !! */ + + if (x != startx) dir = 0; + else dir = 6; + + startx = x; starty = y; + count = 1; + sampcount = 2000; + samp = MEM_mallocN(sampcount * sizeof(Sample), "wire_samples"); + + do{ + samp[count].x = x; samp[count].y = y; + count++; + + if (count >= sampcount) { + oldsamp = samp; + samp = MEM_mallocN(2 * sampcount * sizeof(Sample), "wire_samples"); + memcpy(samp, oldsamp, sampcount * sizeof(Sample)); + sampcount *= 2; + MEM_freeN(oldsamp); + } + + i = 0; + while(in_or_out(ibuf, x + dirs[dir][0], y + dirs[dir][1]) == in) { + dir = (dir + 1) & 0x7; + if (i++ == 9) break; + } + + if (i >= 8) { + /* dit moet een losse punt geweest zijn */ + break; + } + + x += dirs[dir][0]; + y += dirs[dir][1]; + dir = (dir - 3) & 0x7; + } while(x != startx || y != starty); + + if (i >= 8) { + /* losse punten patch */ + MEM_freeN(samp); + } else { + count = count - 1; + samp[0].x = count >> 16; + samp[0].y = count; + return(samp); + } + } + } + } + /* printf("geen overgang \n"); */ + return(0); +} + + + +/*******************************/ +/***** WIREFRAME *****/ +/*******************************/ + + +static float DistToLine2D(short *v1, short *v2, short *v3) /* met formule van Hesse :GEEN LIJNSTUK! */ +{ + float a[2],deler; + + a[0] = v2[1]-v3[1]; + a[1] = v3[0]-v2[0]; + deler = sqrt(a[0]*a[0]+a[1]*a[1]); + if(deler == 0.0) return 0; + + return fabs((v1[0]-v2[0])*a[0]+(v1[1]-v2[1])*a[1])/deler; + +} + +static float ComputeMaxShpError(Sample *samp, int first, int last, int *splitPoint) + /* samp: Array of digitized points */ + /* first, last: Indices defining region */ + /* splitpoint: Point of maximum error */ +{ + int i; + float maxDist; /* Maximum error */ + float dist; /* Current error */ + + *splitPoint = (last - first + 1) / 2; + maxDist = 0.0; + + for (i = first + 1; i < last; i++) { + dist = DistToLine2D((short *)(samp+i), (short *)(samp+first), (short *)(samp+last)); + + if (dist >= maxDist) { + maxDist = dist; + *splitPoint = i; + } + } + + return (maxDist); +} + + +static void FitPoly(Sample *samp, int first, int last, float shperr, ListBase *seglist) + /* Samp: Array of digitized points */ + /* first,last: Indices of first and last pts in region */ + /* spherr: User-defined error squared */ +{ + Segment * seg; /* Control points segment*/ + float maxError; /* Maximum fitting error */ + int splitPoint; /* Point to split point set at */ + int nPts; /* Number of points in subset */ + + nPts = last - first + 1; + + /* Use heuristic if region only has two points in it */ + + seg = MEM_mallocN(sizeof(Segment), "wure_segment"); + + seg->co[0] = samp[first].x; + seg->co[1] = samp[first].y; + + if (nPts == 2) { + BLI_addtail(seglist, seg); + return; + } + + maxError = ComputeMaxShpError(samp, first, last, &splitPoint); + if (maxError < shperr) { + BLI_addtail(seglist, seg); + return; + } + + /* Fitting failed -- split at max error point and fit recursively */ + + FitPoly(samp, first, splitPoint, shperr, seglist); + FitPoly(samp, splitPoint, last, shperr, seglist); + + MEM_freeN(seg); +} + + +static void ibuf2wire(ListBase * wireframe, struct ImBuf * ibuf) +{ + int count; + Sample * samp; + + /* eerst een lijst met samples maken */ + + samp = outline(ibuf, 0); + if (samp == 0) return; + + count = (samp[0].x << 16) + samp[0].y; + if (count) FitPoly(samp, 1, count, 1.0, wireframe); /* was 3.0. Frank */ + + MEM_freeN(samp); +} + + + +void imagestodisplist(void) +{ + Base *base; + Object *ob; + Material *ma; + Tex *tex; + Mesh *me; + ListBase _wireframe, *wireframe; + DispList *dl; + Segment *seg; + float *data, xfac, yfac, xsi, ysi, vec[3]; + int tot; + + _wireframe.first= 0; + _wireframe.last= 0; + wireframe = &_wireframe; + + init_render_textures(); + + base= G.scene->base.first; + while(base) { + if(( (base->flag & SELECT) && (base->lay & G.scene->lay) ) ) { + if( base->object->type==OB_MESH) { + ob= base->object; + me= ob->data; + + ma= give_current_material(ob, 1); + + if(ma && ma->mtex[0] && ma->mtex[0]->tex) { + tex= ma->mtex[0]->tex; + + /* dit zorgt voor correct laden van nieuwe imbufs */ + externtex(ma->mtex[0], vec); + + if(tex->type==TEX_IMAGE && tex->ima && tex->ima->ibuf) { + + ob->dtx |= OB_DRAWIMAGE; + + ibuf2wire(wireframe, tex->ima->ibuf); + + tot= 0; + seg = wireframe->first; + while (seg) { + tot++; + seg = seg->next; + } + + if(tot) { + freedisplist(&(ob->disp)); + + dl= MEM_callocN(sizeof(DispList), "makeDispListimage"); + dl->verts= MEM_callocN(3*sizeof(float)*tot, "dlverts"); + + BLI_addtail(&(ob->disp), dl); + dl->type= DL_POLY; + dl->parts= 1; + dl->nr= tot; + + xsi= 0.5*(tex->ima->ibuf->x); + ysi= 0.5*(tex->ima->ibuf->y); + xfac= me->size[0]/xsi; + yfac= me->size[1]/ysi; + + data= dl->verts; + seg = wireframe->first; + while (seg) { + data[0]= xfac*(seg->co[0]-xsi); + data[1]= yfac*(seg->co[1]-ysi); + data+= 3; + seg = seg->next; + } + BLI_freelistN(wireframe); + } + } + } + } + } + base= base->next; + } + + end_render_textures(); + + allqueue(REDRAWVIEW3D, 0); +} + +/* on frame change */ + +void test_all_displists(void) +{ + Base *base; + Object *ob; + unsigned int lay; + + /* background */ + lay= G.scene->lay; + + base= G.scene->base.first; + while(base) { + if(base->lay & lay) { + ob= base->object; + + + if(ob->type==OB_MBALL && ob->ipo) { + // find metaball object holding the displist + // WARNING: if more metaballs have IPO's the displist + // is recalculated to often... + + if(ob->disp.first == NULL) { + ob= find_basis_mball(ob); + } + + makeDispList(ob); + } + else if(ob->parent) { + + if (ob->parent->type == OB_LATTICE) + makeDispList(ob); + else if ((ob->parent->type == OB_IKA) && (ob->partype == PARSKEL)) + makeDispList(ob); +#ifdef __NLA + else if ((ob->parent->type==OB_ARMATURE) && (ob->partype == PARSKEL)) + makeDispList(ob); + +#endif + } + + if ELEM(ob->type, OB_CURVE, OB_SURF) { + if(ob!=G.obedit) { + if( ((Curve *)(ob->data))->key ) makeDispList(ob); + } + } + else if(ob->type==OB_FONT) { + Curve *cu= ob->data; + if(cu->textoncurve) { + if( ((Curve *)cu->textoncurve->data)->key ) { + text_to_curve(ob, 0); + makeDispList(ob); + } + } + } + else if(ob->type==OB_MESH) { + if(ob->effect.first) object_wave(ob); + if(ob!=G.obedit) { + if( ((Mesh *)(ob->data))->key ) makeDispList(ob); + } + } + + } + if(base->next==0 && G.scene->set && base==G.scene->base.last) base= G.scene->set->base.first; + else base= base->next; + } +} + + +void boundbox_displist(Object *ob) +{ + BoundBox *bb=0; + float min[3], max[3]; + DispList *dl; + float *vert; + int a, tot=0; + + INIT_MINMAX(min, max); + + if(ob->type==OB_MESH) { + Mesh *me= ob->data; + + dl= find_displist(&ob->disp, DL_VERTS); + if(!dl) return; + + if(me->bb==0) me->bb= MEM_callocN(sizeof(BoundBox), "boundbox"); + bb= me->bb; + + vert= dl->verts; + for(a=0; a<dl->nr; a++, vert+=3) { + DO_MINMAX(vert, min, max); + } + } + else if(ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { + Curve *cu= ob->data; + + if(cu->bb==0) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox"); + bb= cu->bb; + + dl= cu->disp.first; + + while (dl) { + if(dl->type==DL_INDEX3 || dl->type==DL_INDEX3) tot= dl->nr; + else tot= dl->nr*dl->parts; + + vert= dl->verts; + for(a=0; a<tot; a++, vert+=3) { + DO_MINMAX(vert, min, max); + } + + dl= dl->next; + } + } + + if(bb) { + bb->vec[0][0]=bb->vec[1][0]=bb->vec[2][0]=bb->vec[3][0]= min[0]; + bb->vec[4][0]=bb->vec[5][0]=bb->vec[6][0]=bb->vec[7][0]= max[0]; + + bb->vec[0][1]=bb->vec[1][1]=bb->vec[4][1]=bb->vec[5][1]= min[1]; + bb->vec[2][1]=bb->vec[3][1]=bb->vec[6][1]=bb->vec[7][1]= max[1]; + + bb->vec[0][2]=bb->vec[3][2]=bb->vec[4][2]=bb->vec[7][2]= min[2]; + bb->vec[1][2]=bb->vec[2][2]=bb->vec[5][2]=bb->vec[6][2]= max[2]; + } +} + diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c new file mode 100644 index 00000000000..c39ad72ecdf --- /dev/null +++ b/source/blender/blenkernel/intern/effect.c @@ -0,0 +1,854 @@ +/* effect.c MIX MODEL + * + * dec 95 + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <math.h> +#include <stdlib.h> + +#include "MEM_guardedalloc.h" +#include "DNA_listBase.h" +#include "DNA_effect_types.h" +#include "DNA_object_types.h" +#include "DNA_mesh_types.h" +#include "DNA_material_types.h" +#include "DNA_curve_types.h" +#include "DNA_key_types.h" +#include "DNA_texture_types.h" +#include "DNA_scene_types.h" +#include "DNA_lattice_types.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_rand.h" + +#include "BKE_utildefines.h" +#include "BKE_bad_level_calls.h" +#include "BKE_global.h" +#include "BKE_material.h" +#include "BKE_effect.h" +#include "BKE_key.h" +#include "BKE_ipo.h" +#include "BKE_screen.h" +#include "BKE_texture.h" +#include "BKE_blender.h" +#include "BKE_object.h" +#include "BKE_displist.h" +#include "BKE_lattice.h" + + +Effect *add_effect(int type) +{ + Effect *eff=0; + BuildEff *bld; + PartEff *paf; + WaveEff *wav; + int a; + + switch(type) { + case EFF_BUILD: + bld= MEM_callocN(sizeof(BuildEff), "neweff"); + eff= (Effect *)bld; + + bld->sfra= 1.0; + bld->len= 100.0; + break; + + case EFF_PARTICLE: + paf= MEM_callocN(sizeof(PartEff), "neweff"); + eff= (Effect *)paf; + + paf->sta= 1.0; + paf->end= 100.0; + paf->lifetime= 50.0; + for(a=0; a<PAF_MAXMULT; a++) { + paf->life[a]= 50.0; + paf->child[a]= 4; + paf->mat[a]= 1; + } + + paf->totpart= 1000; + paf->totkey= 8; + paf->staticstep= 5; + paf->defvec[2]= 1.0f; + paf->nabla= 0.05f; + + break; + + case EFF_WAVE: + wav= MEM_callocN(sizeof(WaveEff), "neweff"); + eff= (Effect *)wav; + + wav->flag |= (WAV_X+WAV_Y+WAV_CYCL); + + wav->height= 0.5f; + wav->width= 1.5f; + wav->speed= 0.5f; + wav->narrow= 1.5f; + wav->lifetime= 0.0f; + wav->damp= 10.0f; + + break; + } + + eff->type= eff->buttype= type; + eff->flag |= SELECT; + + return eff; +} + +void free_effect(Effect *eff) +{ + PartEff *paf; + + if(eff->type==EFF_PARTICLE) { + paf= (PartEff *)eff; + if(paf->keys) MEM_freeN(paf->keys); + } + MEM_freeN(eff); +} + + +void free_effects(ListBase *lb) +{ + Effect *eff; + + eff= lb->first; + while(eff) { + BLI_remlink(lb, eff); + free_effect(eff); + eff= lb->first; + } +} + +Effect *copy_effect(Effect *eff) +{ + Effect *effn; + + effn= MEM_dupallocN(eff); + if(effn->type==EFF_PARTICLE) ((PartEff *)effn)->keys= 0; + + return effn; +} + +void copy_act_effect(Object *ob) +{ + /* return de aktieve eff gekopieerd */ + Effect *effn, *eff; + + eff= ob->effect.first; + while(eff) { + if(eff->flag & SELECT) { + + effn= copy_effect(eff); + BLI_addtail(&ob->effect, effn); + + eff->flag &= ~SELECT; + return; + + } + eff= eff->next; + } + + /* als tie hier komt: new effect */ + eff= add_effect(EFF_BUILD); + BLI_addtail(&ob->effect, eff); + +} + +void copy_effects(ListBase *lbn, ListBase *lb) +{ + Effect *eff, *effn; + + lbn->first= lbn->last= 0; + + eff= lb->first; + while(eff) { + effn= copy_effect(eff); + BLI_addtail(lbn, effn); + + eff= eff->next; + } + +} + +void deselectall_eff(Object *ob) +{ + Effect *eff= ob->effect.first; + + while(eff) { + eff->flag &= ~SELECT; + eff= eff->next; + } +} + +void set_buildvars(Object *ob, int *start, int *end) +{ + BuildEff *bld; + float ctime; + + bld= ob->effect.first; + while(bld) { + if(bld->type==EFF_BUILD) { + ctime= bsystem_time(ob, 0, (float)G.scene->r.cfra, bld->sfra-1.0f); + if(ctime < 0.0) { + *end= *start; + } + else if(ctime < bld->len) { + *end= *start+ (int)((*end - *start)*ctime/bld->len); + } + + return; + } + bld= bld->next; + } +} + +/* ***************** PARTICLES ***************** */ + +Particle *new_particle(PartEff *paf) +{ + static Particle *pa; + static int cur; + + /* afspraak: als paf->keys==0: alloc */ + if(paf->keys==0) { + pa= paf->keys= MEM_callocN( paf->totkey*paf->totpart*sizeof(Particle), "particlekeys" ); + cur= 0; + } + else { + if(cur && cur<paf->totpart) pa+=paf->totkey; + cur++; + } + return pa; +} + +PartEff *give_parteff(Object *ob) +{ + PartEff *paf; + + paf= ob->effect.first; + while(paf) { + if(paf->type==EFF_PARTICLE) return paf; + paf= paf->next; + } + return 0; +} + +void where_is_particle(PartEff *paf, Particle *pa, float ctime, float *vec) +{ + Particle *p[4]; + float dt, t[4]; + int a; + + if(paf->totkey==1) { + VECCOPY(vec, pa->co); + return; + } + + /* eerst op zoek naar de eerste particlekey */ + a= (int)((paf->totkey-1)*(ctime-pa->time)/pa->lifetime); + if(a>=paf->totkey) a= paf->totkey-1; + + pa+= a; + + if(a>0) p[0]= pa-1; else p[0]= pa; + p[1]= pa; + + if(a+1<paf->totkey) p[2]= pa+1; else p[2]= pa; + if(a+2<paf->totkey) p[3]= pa+2; else p[3]= p[2]; + + if(p[1]==p[2]) dt= 0.0; + else dt= (ctime-p[1]->time)/(p[2]->time - p[1]->time); + + if(paf->flag & PAF_BSPLINE) set_four_ipo(dt, t, KEY_BSPLINE); + else set_four_ipo(dt, t, KEY_CARDINAL); + + vec[0]= t[0]*p[0]->co[0] + t[1]*p[1]->co[0] + t[2]*p[2]->co[0] + t[3]*p[3]->co[0]; + vec[1]= t[0]*p[0]->co[1] + t[1]*p[1]->co[1] + t[2]*p[2]->co[1] + t[3]*p[3]->co[1]; + vec[2]= t[0]*p[0]->co[2] + t[1]*p[1]->co[2] + t[2]*p[2]->co[2] + t[3]*p[3]->co[2]; + +} + + +void particle_tex(MTex *mtex, PartEff *paf, float *co, float *no) +{ + extern float Tin, Tr, Tg, Tb; + float old; + + externtex(mtex, co); + + if(paf->texmap==PAF_TEXINT) { + Tin*= paf->texfac; + no[0]+= Tin*paf->defvec[0]; + no[1]+= Tin*paf->defvec[1]; + no[2]+= Tin*paf->defvec[2]; + } + else if(paf->texmap==PAF_TEXRGB) { + no[0]+= (Tr-0.5f)*paf->texfac; + no[1]+= (Tg-0.5f)*paf->texfac; + no[2]+= (Tb-0.5f)*paf->texfac; + } + else { /* PAF_TEXGRAD */ + + old= Tin; + co[0]+= paf->nabla; + externtex(mtex, co); + no[0]+= (old-Tin)*paf->texfac; + + co[0]-= paf->nabla; + co[1]+= paf->nabla; + externtex(mtex, co); + no[1]+= (old-Tin)*paf->texfac; + + co[1]-= paf->nabla; + co[2]+= paf->nabla; + externtex(mtex, co); + no[2]+= (old-Tin)*paf->texfac; + + } +} + +void make_particle_keys(int depth, int nr, PartEff *paf, Particle *part, float *force, int deform, MTex *mtex) +{ + Particle *pa, *opa = NULL; + float damp, deltalife; + int b, rt1, rt2; + + damp= 1.0f-paf->damp; + pa= part; + + /* startsnelheid: random */ + if(paf->randfac!=0.0) { + pa->no[0]+= (float)(paf->randfac*( BLI_drand() -0.5)); + pa->no[1]+= (float)(paf->randfac*( BLI_drand() -0.5)); + pa->no[2]+= (float)(paf->randfac*( BLI_drand() -0.5)); + } + + /* startsnelheid: texture */ + if(mtex && paf->texfac!=0.0) { + particle_tex(mtex, paf, pa->co, pa->no); + } + + /* keys */ + if(paf->totkey>1) { + + deltalife= pa->lifetime/(paf->totkey-1); + opa= pa; + pa++; + + b= paf->totkey-1; + while(b--) { + /* nieuwe tijd */ + pa->time= opa->time+deltalife; + + /* nieuwe plek */ + pa->co[0]= opa->co[0] + deltalife*opa->no[0]; + pa->co[1]= opa->co[1] + deltalife*opa->no[1]; + pa->co[2]= opa->co[2] + deltalife*opa->no[2]; + + /* nieuwe snelheid */ + pa->no[0]= opa->no[0] + deltalife*force[0]; + pa->no[1]= opa->no[1] + deltalife*force[1]; + pa->no[2]= opa->no[2] + deltalife*force[2]; + + /* snelheid: texture */ + if(mtex && paf->texfac!=0.0) { + particle_tex(mtex, paf, pa->co, pa->no); + } + if(damp!=1.0) { + pa->no[0]*= damp; + pa->no[1]*= damp; + pa->no[2]*= damp; + } + + opa= pa; + pa++; + /* opa wordt onderin ook gebruikt */ + } + } + + if(deform) { + /* alle keys deformen */ + pa= part; + b= paf->totkey; + while(b--) { + calc_latt_deform(pa->co); + pa++; + } + } + + /* de grote vermenigvuldiging */ + if(depth<PAF_MAXMULT && paf->mult[depth]!=0.0) { + + /* uit gemiddeld 'mult' deel van de particles ontstaan 'child' nieuwe */ + damp = (float)nr; + rt1= (int)(damp*paf->mult[depth]); + rt2= (int)((damp+1.0)*paf->mult[depth]); + if(rt1!=rt2) { + + for(b=0; b<paf->child[depth]; b++) { + pa= new_particle(paf); + *pa= *opa; + pa->lifetime= paf->life[depth]; + if(paf->randlife!=0.0) { + pa->lifetime*= 1.0f+ (float)(paf->randlife*( BLI_drand() - 0.5)); + } + pa->mat_nr= paf->mat[depth]; + + make_particle_keys(depth+1, b, paf, pa, force, deform, mtex); + } + } + } +} + +void init_mv_jit(float *jit, int num) +{ + float *jit2, x, rad1, rad2, rad3; + int i; + + if(num==0) return; + + rad1= (float)(1.0/sqrt((float)num)); + rad2= (float)(1.0/((float)num)); + rad3= (float)sqrt((float)num)/((float)num); + + BLI_srand(31415926 + num); + x= 0; + for(i=0; i<2*num; i+=2) { + + jit[i]= x+ (float)(rad1*(0.5-BLI_drand())); + jit[i+1]= ((float)i/2)/num +(float)(rad1*(0.5-BLI_drand())); + + jit[i]-= (float)floor(jit[i]); + jit[i+1]-= (float)floor(jit[i+1]); + + x+= rad3; + x -= (float)floor(x); + } + + jit2= MEM_mallocN(12 + 2*sizeof(float)*num, "initjit"); + + for (i=0 ; i<4 ; i++) { + RE_jitterate1(jit, jit2, num, rad1); + RE_jitterate1(jit, jit2, num, rad1); + RE_jitterate2(jit, jit2, num, rad2); + } + MEM_freeN(jit2); +} + + +void give_mesh_mvert(Mesh *me, int nr, float *co, short *no) +{ + static float *jit=0; + static int jitlevel=1; + MVert *mvert; + MFace *mface; + float u, v, *v1, *v2, *v3, *v4; + int curface, curjit; + short *n1, *n2, *n3, *n4; + + /* signal */ + if(me==0) { + if(jit) MEM_freeN(jit); + jit= 0; + return; + } + + if(me->totface==0 || nr<me->totvert) { + mvert= me->mvert + (nr % me->totvert); + VECCOPY(co, mvert->co); + VECCOPY(no, mvert->no); + } + else { + + nr-= me->totvert; + + if(jit==0) { + jitlevel= nr/me->totface; + if(jitlevel==0) jitlevel= 1; + if(jitlevel>100) jitlevel= 100; + + jit= MEM_callocN(2+ jitlevel*2*sizeof(float), "jit"); + init_mv_jit(jit, jitlevel); + + } + + curjit= nr/me->totface; + curjit= curjit % jitlevel; + + curface= nr % me->totface; + + mface= me->mface; + mface+= curface; + + v1= (me->mvert+(mface->v1))->co; + v2= (me->mvert+(mface->v2))->co; + n1= (me->mvert+(mface->v1))->no; + n2= (me->mvert+(mface->v2))->no; + if(mface->v3==0) { + v3= (me->mvert+(mface->v2))->co; + v4= (me->mvert+(mface->v1))->co; + n3= (me->mvert+(mface->v2))->no; + n4= (me->mvert+(mface->v1))->no; + } + else if(mface->v4==0) { + v3= (me->mvert+(mface->v3))->co; + v4= (me->mvert+(mface->v1))->co; + n3= (me->mvert+(mface->v3))->no; + n4= (me->mvert+(mface->v1))->no; + } + else { + v3= (me->mvert+(mface->v3))->co; + v4= (me->mvert+(mface->v4))->co; + n3= (me->mvert+(mface->v3))->no; + n4= (me->mvert+(mface->v4))->no; + } + + u= jit[2*curjit]; + v= jit[2*curjit+1]; + + co[0]= (float)((1.0-u)*(1.0-v)*v1[0] + (1.0-u)*(v)*v2[0] + (u)*(v)*v3[0] + (u)*(1.0-v)*v4[0]); + co[1]= (float)((1.0-u)*(1.0-v)*v1[1] + (1.0-u)*(v)*v2[1] + (u)*(v)*v3[1] + (u)*(1.0-v)*v4[1]); + co[2]= (float)((1.0-u)*(1.0-v)*v1[2] + (1.0-u)*(v)*v2[2] + (u)*(v)*v3[2] + (u)*(1.0-v)*v4[2]); + + no[0]= (short)((1.0-u)*(1.0-v)*n1[0] + (1.0-u)*(v)*n2[0] + (u)*(v)*n3[0] + (u)*(1.0-v)*n4[0]); + no[1]= (short)((1.0-u)*(1.0-v)*n1[1] + (1.0-u)*(v)*n2[1] + (u)*(v)*n3[1] + (u)*(1.0-v)*n4[1]); + no[2]= (short)((1.0-u)*(1.0-v)*n1[2] + (1.0-u)*(v)*n2[2] + (u)*(v)*n3[2] + (u)*(1.0-v)*n4[2]); + + } +} + + +void build_particle_system(Object *ob) +{ + Object *par; + PartEff *paf; + Particle *pa; + Mesh *me; + MVert *mvert; + MTex *mtexmove=0; + Material *ma; + float framelenont, ftime, dtime, force[3], imat[3][3], vec[3]; + float fac, prevobmat[4][4], sfraont, co[3]; + int deform=0, a, cur, cfraont, cfralast, totpart; + short no[3]; + + if(ob->type!=OB_MESH) return; + me= ob->data; + if(me->totvert==0) return; + + ma= give_current_material(ob, 1); + if(ma) { + mtexmove= ma->mtex[7]; + } + + paf= give_parteff(ob); + if(paf==0) return; + + waitcursor(1); + + disable_speed_curve(1); + + /* alle particles genereren */ + if(paf->keys) MEM_freeN(paf->keys); + paf->keys= 0; + new_particle(paf); + + cfraont= G.scene->r.cfra; + cfralast= -1000; + framelenont= G.scene->r.framelen; + G.scene->r.framelen= 1.0; + sfraont= ob->sf; + ob->sf= 0.0; + + /* mult generaties? */ + totpart= paf->totpart; + for(a=0; a<PAF_MAXMULT; a++) { + if(paf->mult[a]!=0.0) { + /* interessante formule! opdezewijze is na 'x' generaties het totale aantal paf->totpart */ + totpart= (int)(totpart / (1.0+paf->mult[a]*paf->child[a])); + } + else break; + } + + ftime= paf->sta; + dtime= (paf->end - paf->sta)/totpart; + + /* hele hiera onthouden */ + par= ob; + while(par) { + pushdata(par, sizeof(Object)); + par= par->parent; + } + + /* alles op eerste frame zetten */ + G.scene->r.cfra= cfralast= (int)floor(ftime); + par= ob; + while(par) { + /* do_ob_ipo(par); */ + do_ob_key(par); + par= par->parent; + } + do_mat_ipo(ma); + + if((paf->flag & PAF_STATIC)==0) { + where_is_object(ob); + Mat4CpyMat4(prevobmat, ob->obmat); + Mat4Invert(ob->imat, ob->obmat); + Mat3CpyMat4(imat, ob->imat); + } + else { + Mat4One(prevobmat); + Mat3One(imat); + } + + BLI_srand(paf->seed); + + /* gaat anders veuls te hard */ + force[0]= paf->force[0]*0.05f; + force[1]= paf->force[1]*0.05f; + force[2]= paf->force[2]*0.05f; + + deform= (ob->parent && ob->parent->type==OB_LATTICE); + if(deform) init_latt_deform(ob->parent, 0); + + /* init */ + give_mesh_mvert(me, totpart, co, no); + + for(a=0; a<totpart; a++, ftime+=dtime) { + + pa= new_particle(paf); + pa->time= ftime; + + /* ob op juiste tijd zetten */ + + if((paf->flag & PAF_STATIC)==0) { + + cur= (int)floor(ftime) + 1 ; /* + 1 heeft een reden: (obmat/prevobmat) anders beginnen b.v. komeetstaartjes te laat */ + if(cfralast != cur) { + G.scene->r.cfra= cfralast= cur; + + /* later bijgevoegd: blur? */ + bsystem_time(ob, ob->parent, (float)G.scene->r.cfra, 0.0); + + par= ob; + while(par) { + /* do_ob_ipo(par); */ + par->ctime= -1234567.0; + do_ob_key(par); + par= par->parent; + } + do_mat_ipo(ma); + Mat4CpyMat4(prevobmat, ob->obmat); + where_is_object(ob); + Mat4Invert(ob->imat, ob->obmat); + Mat3CpyMat4(imat, ob->imat); + } + } + /* coordinaat ophalen */ + if(paf->flag & PAF_FACE) give_mesh_mvert(me, a, co, no); + else { + mvert= me->mvert + (a % me->totvert); + VECCOPY(co, mvert->co); + VECCOPY(no, mvert->no); + } + + VECCOPY(pa->co, co); + + if(paf->flag & PAF_STATIC); + else { + Mat4MulVecfl(ob->obmat, pa->co); + + VECCOPY(vec, co); + Mat4MulVecfl(prevobmat, vec); + + /* eerst even startsnelheid: object */ + VecSubf(pa->no, pa->co, vec); + VecMulf(pa->no, paf->obfac); + + /* nu juiste interframe co berekenen */ + fac= (ftime- (float)floor(ftime)); + pa->co[0]= fac*pa->co[0] + (1.0f-fac)*vec[0]; + pa->co[1]= fac*pa->co[1] + (1.0f-fac)*vec[1]; + pa->co[2]= fac*pa->co[2] + (1.0f-fac)*vec[2]; + } + + /* startsnelheid: normaal */ + if(paf->normfac!=0.0) { + /* sp= mvert->no; */ + /* transpose ! */ + vec[0]= imat[0][0]*no[0] + imat[0][1]*no[1] + imat[0][2]*no[2]; + vec[1]= imat[1][0]*no[0] + imat[1][1]*no[1] + imat[1][2]*no[2]; + vec[2]= imat[2][0]*no[0] + imat[2][1]*no[1] + imat[2][2]*no[2]; + + Normalise(vec); + VecMulf(vec, paf->normfac); + VecAddf(pa->no, pa->no, vec); + } + pa->lifetime= paf->lifetime; + if(paf->randlife!=0.0) { + pa->lifetime*= 1.0f+ (float)(paf->randlife*( BLI_drand() - 0.5)); + } + pa->mat_nr= 1; + + make_particle_keys(0, a, paf, pa, force, deform, mtexmove); + } + + if(deform) end_latt_deform(); + + /* restore */ + G.scene->r.cfra= cfraont; + G.scene->r.framelen= framelenont; + give_mesh_mvert(0, 0, 0, 0); + + + /* hele hiera terug */ + par= ob; + while(par) { + popfirst(par); + /* geen ob->ipo doen: insertkey behouden */ + do_ob_key(par); + par= par->parent; + } + + /* restore: NA popfirst */ + ob->sf= sfraont; + + disable_speed_curve(0); + + waitcursor(0); + +} + +/* ************* WAVE **************** */ + +void calc_wave_deform(WaveEff *wav, float ctime, float *co) +{ + /* co is in lokale coords */ + float lifefac, x, y, amplit; + + /* mag eigenlijk niet voorkomen */ + if((wav->flag & (WAV_X+WAV_Y))==0) return; + + lifefac= wav->height; + + if( wav->lifetime!=0.0) { + x= ctime - wav->timeoffs; + if(x>wav->lifetime) { + + lifefac= x-wav->lifetime; + + if(lifefac > wav->damp) lifefac= 0.0; + else lifefac= (float)(wav->height*(1.0 - sqrt(lifefac/wav->damp))); + } + } + if(lifefac==0.0) return; + + x= co[0]-wav->startx; + y= co[1]-wav->starty; + + if(wav->flag & WAV_X) { + if(wav->flag & WAV_Y) amplit= (float)sqrt( (x*x + y*y)); + else amplit= x; + } + else amplit= y; + + /* zo maaktie mooie cirkels */ + amplit-= (ctime-wav->timeoffs)*wav->speed; + + if(wav->flag & WAV_CYCL) { + amplit = (float)fmod(amplit-wav->width, 2.0*wav->width) + wav->width; + } + + /* GAUSSIAN */ + + if(amplit> -wav->width && amplit<wav->width) { + + amplit = amplit*wav->narrow; + amplit= (float)(1.0/exp(amplit*amplit) - wav->minfac); + + co[2]+= lifefac*amplit; + } +} + +void object_wave(Object *ob) +{ + WaveEff *wav; + DispList *dl; + Mesh *me; + MVert *mvert; + float *fp, ctime; + int a, first; + + /* is er een mave */ + wav= ob->effect.first; + while(wav) { + if(wav->type==EFF_WAVE) break; + wav= wav->next; + } + if(wav==0) return; + + if(ob->type==OB_MESH) { + + ctime= bsystem_time(ob, 0, (float)G.scene->r.cfra, 0.0); + first= 1; + + me= ob->data; + dl= find_displist_create(&ob->disp, DL_VERTS); + + if(dl->verts) MEM_freeN(dl->verts); + dl->nr= me->totvert; + dl->verts= MEM_mallocN(3*4*me->totvert, "wave"); + + wav= ob->effect.first; + while(wav) { + if(wav->type==EFF_WAVE) { + + /* voorberekenen */ + wav->minfac= (float)(1.0/exp(wav->width*wav->narrow*wav->width*wav->narrow)); + if(wav->damp==0) wav->damp= 10.0f; + + mvert= me->mvert; + fp= dl->verts; + + for(a=0; a<me->totvert; a++, mvert++, fp+=3) { + if(first) VECCOPY(fp, mvert->co); + calc_wave_deform(wav, ctime, fp); + } + first= 0; + } + wav= wav->next; + } + } +} diff --git a/source/blender/blenkernel/intern/exotic.c b/source/blender/blenkernel/intern/exotic.c new file mode 100644 index 00000000000..104b1b24efe --- /dev/null +++ b/source/blender/blenkernel/intern/exotic.c @@ -0,0 +1,4081 @@ +/* exotic.c mei 95 MIXED MODEL + * + * $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. + * + * Contributor(s): none yet. + * + * ***** 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> +#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" +#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" + +#include "BPY_extern.h" + +/***/ + +static int is_dxf(char *str); +static void dxf_read(char *filename); + +/***/ + +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; + short end; + 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; + } + + if(verts>65000) { + 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; + } + + /* de vlakken en kleuren tellen */ + 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++; + } + } + + if(totedge+tottria+totquad>65000) { + printf(" var1: %d, var2: %d, var3: %d \n", totedge, tottria, totquad); + error("too many faces"); + MEM_freeN(vertdata); + fclose(fp); + return; + } + + /* nieuw object */ + 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"); + + /* kleuren */ + 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; + } + + /* materialen */ + 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(); + free_editMesh(); + 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; + short end; + 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; + } + + if(verts>65000) { + 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++; + } + + /* de vlakken tellen */ + 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; + + } + + if(totedge+tottria+totquad>65000) { + printf(" var1: %d, var2: %d, var3: %d \n", totedge, tottria, totquad); + error("too many faces"); + MEM_freeN(vertdata); + MEM_freeN(colvertdata); + fclose(fp); + return; + } + + /* nieuw object */ + 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; + } + } + + /* mcol is per vlak 4 kleuren */ + 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(); + free_editMesh(); + + 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; + unsigned short val, numlen; + 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 ******************* */ + + +#define IV_MAXSTACK 500000 +#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; + + /* terugzoeken naar laatste materiaal */ + 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) +{ + /* zoek naar "field", tel lengte data en maak datablok. return skipdata */ + 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; + + /* lezen tot aan eerste karakter */ + 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... */ + + i=strpbrk(cpa, ", \n")-cpa; + + 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) +{ + /* in data schrijven: baseadr met offset index (aantal nr)*/ + 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; + int file, filelen, count, face, nr = 0; + 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"); + + /* eerste preprocess: commentar eruit */ + 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++; + } + + + /* we gaan alles ordenen: welke zijn de nodes en de fields? */ + md= maindata; + count= 0; + while(count<filelen) { + if( *md=='{' ) { /* terug lezen */ + + cpa= md-1; + while( *cpa==32 || *cpa==13 || *cpa==10 || *cpa==9) { /* spaties/enters/tab weg */ + *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 { + /* naar 't einde */ + while( *md != '}') { + md++; + count++; + if(count<filelen) break; + } + } + + + if(ok) { + BLI_addtail(&ivbase, iv); + md+= skipdata; + count+= skipdata; + } + else MEM_freeN(iv); + + } + md++; + count++; + } + + /* nodes samenvoegen */ + iv= ivbase.first; + + while(iv) { + ivn= iv->next; + + if( strncmp(iv->nodename, "Indexed", 7)==0) { + /* terugzoeken: zelfde naam? */ + + 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) { + /* iv bij ivp voegen */ + + 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; + } + + + /* Nodes omzetten naar DispLists */ + 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); + + /* terugzoeken naar data */ + 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) { + + /* tel het aantal lijnen */ + tot= 0; + index= iv->data[0]; + for(a=0; a<iv->datalen[0]-1; a++) { + if(index[0]!= -1 && index[1]!= -1) tot++; + index++; + } + + tot*= 2; /* aantal vertices */ + 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]; + for(a=0; a<iv->datalen[0]-1; a++) { + 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); + + /* terugzoeken naar data */ + 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) { + /* tel het aantal driehoeken */ + tot= 0; + + index= iv->data[0]; + polytype= (int) index[0]; + + for(a=0; a<iv->datalen[0]; a++) { + if(index[0]== polytype) tot++; /* een soort? */ + index++; + } + + + tot*= polytype; /* aantal vertices */ + 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); + + /* terugzoeken naar data */ + 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) { + /* tel het aantal driehoeken */ + tot= 0; + face= 0; + + index= iv->data[0]; /* afmeting strip */ + + 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; + + index= iv->data[0]; /* afmeting strip */ + 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 */ + for(b=0; b<index[0]-2; b++) { + 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); + + /* terugzoeken naar data */ + 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) { + + /* tel het aantal driehoeken */ + face= 0; + index= iv->data[0]; + for(a=0; a<iv->datalen[0]-2; a++) { + if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) face++; + index++; + } + + /* aantal vertices */ + 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; + + for(a=0; a<iv->datalen[0]-2; a++) { + + if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) { + + /* deze truuk is om poly's met meer dan 3 vertices correct te vullen */ + 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); + + /* terugzoeken naar data */ + 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) { + + /* tel het aantal driehoeken */ + face= 0; + index= iv->data[0]; + for(a=0; a<iv->datalen[0]-2; a++) { + if(index[0]!= -1 && index[1]!= -1 && index[2]!= -1) face++; + index++; + } + + /* aantal vertices */ + 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; + + for(a=iv->datalen[0]-2; a>0; a--) { + + 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); + + /* terugzoeken naar data */ + 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); + + /* terugzoeken naar data */ + 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++; + } + + /* iv->datalen[2] / [3] is aantal knots */ + 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; + } + + /* vrijgeven */ + 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]; + int a, b, startve, *idata, totedge=0, tottria=0, totquad=0, totvert=0, totvlak, totcol=0, colnr; + int p1, p2, p3, p4; + + /* eerst tellen */ + INIT_MINMAX(min, max); + + dl= dlfirst; + while(dl) { + + /* PATCH 1 (polyfill) kan hier niet, er wordt geen listbase meegegeven. eerder doen! */ + /* 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--; + } + } + } + } + + /* kleuren */ + if(dl->col > totcol) totcol= dl->col; + + /* afmeting en tellen */ + 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; + } + if(totvert>=65000 || tottria>=65000) { + if (totvert>=65000) { + 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; + + /* kleuren */ + 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; + } + + /* materialen */ + 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); + } + } + + totvlak= totquad+tottria+totedge; + + printf("Import: %d vertices %d faces\n", totvert, totvlak); + + if(totvert) me->mvert= MEM_callocN(totvert*sizeof(MVert), "mvert"); + if(totvlak) me->mface= MEM_callocN(totvlak*sizeof(MFace), "mface"); + me->totvert= totvert; + me->totface= totvlak; + + 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; + } + + G.obedit= ob; + make_editMesh(); + load_editMesh(); + free_editMesh(); + + G.obedit= 0; + tex_space_mesh(me); + +} + +static void displist_to_objects(ListBase *lbase) +{ + DispList *dl, *first, *prev, *next; + ListBase tempbase; + int maxaantal, curcol, totvert=0, vert; + + /* eerst dit: is nu nog actief */ + 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) { + /* oplossing: bij elkaar in aparte listbase zetten */ + ; + } + /* PATCH 2: poly's van 2 punten */ + if(dl->type==DL_POLY && dl->nr==2) dl->type= DL_SEGM; + + dl= next; + } + + /* vertices tellen */ + + 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) { + + /* probeer kleuren bij elkaar te zetten */ + 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; + } + + /* in tempbase zitten alle kleuren 'curcol' */ + 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; + } + // 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}; + + +static void write_videoscape_mesh(Object *ob, char *str) +{ + Mesh *me; + Material *ma; + MVert *mvert; + MFace *mface; + FILE *fp; + EditVert *eve; + EditVlak *evl; + 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; + eve= G.edve.first; + 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; + } + evl= G.edvl.first; + 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; + unsigned short numlen; + 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); + if(file>-1) if(saveover(str)==0) return; + + 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; + } + + + /* weggooien als nog hogere nummers bestaan */ + 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; + int a, b, totcol; + 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; + + 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]); + fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[3][0], tface->uv[3][1]); + if(mface->v3) fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[2][0], tface->uv[2][1]); + if(mface->v4) fprintf(fp, "\t\t\t\t %f %f,\n", tface->uv[1][0], tface->uv[1][1]); + } + 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"); + fprintf(fp, "\t\t}\n"); + + } + + 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"); + + if(saveover(str)==0) return; + + fp= fopen(str, "w"); + + if(fp==NULL) { + 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"); + + if (BLI_exists(str)) + if(saveover(str)==0) + return; + + fp= fopen(str, "w"); + + if(fp==NULL) { + 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++; + } +} + +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; + + fgets(tmp, 255, dxf_fp); + + dos_clean(tmp); + + if(sscanf(tmp, "%d\n", &ret)!=1) return -2; + + fgets(tmp, 255, dxf_fp); + + 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. +*/ + +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 + +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); + } + + 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= 1; /* Its a line dude */ + me->totface= 0; + + me->mvert= MEM_callocN(me->totvert*sizeof(MVert), "mverts"); + me->mface= NULL; + + 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(); + free_editMesh(); + 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(); + free_editMesh(); + 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 */ + + if(!lwasline || strcmp(layname, oldllay)!=0) dxf_close_line(); + if(linemhold != NULL && linemhold->totvert>65000) dxf_close_line(); + + if (linemhold==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(oldllay, layname); + + 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)]; + 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; + + G.obedit= p2dhold; + make_editMesh(); + load_editMesh(); + free_editMesh(); + waitcursor(1); /* patch yah... */ + + G.obedit= 0; + tex_space_mesh(p2dhold->data); + + p2dhold=NULL; +} + +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); + } + + if (flag&1) { + if(!lwasp2d || strcmp(layname, oldplay)!=0) dxf_close_2dpoly(); + if(p2dmhold != NULL && p2dmhold->totvert>65000) dxf_close_2dpoly(); + + 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; + } else { + 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); + } + + me->totface++; + ftmp= MEM_callocN(me->totface*sizeof(MFace), "mface"); + + 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= (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); + + lwasp2d=1; + } else if (flag&64) { + 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 */ + if(me->totvert > 65000) while(group_isnt(0, "SEQEND")) read_group(id, val); + + 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; + + if(vids[3]) + mface->v4= vids[3]-1; + + mface->edcode= 3; + mface->mat_nr= 0; + + if(vids[3]) + test_index_mface(mface, 4); + else + test_index_mface(mface, 3); + } 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(); + free_editMesh(); + waitcursor(1); /* patch yah... */ + G.obedit= 0; + } + tex_space_mesh(me); + } +} + + /* 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(); + free_editMesh(); + 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(); + if(f3dmhold != NULL && f3dmhold->totvert>65000) dxf_close_3dface(); + + 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); + + 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); + 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); + if(group_is(0, "POLYLINE")) { + dxf_read_polyline(1); + if(error_exit) return; + lwasf3d=0; + lwasline=0; + + 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; + } else if (group_is(0, "ENDBLK")) { + break; + } + } + } else if (group_is(0, "ENDBLK")) { + break; + } + } + while(id!=0) read_group(id, val); + } 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); + 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); + } + + 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; + if(U.flag & MAT_ON_OB) ob->colbits= -1; + + 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(); + free_editMesh(); + 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); + } 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; + } 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(); +} diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c new file mode 100644 index 00000000000..4f6b6c4b0c2 --- /dev/null +++ b/source/blender/blenkernel/intern/font.c @@ -0,0 +1,656 @@ + +/* font.c MIXED MODEL + * + * maart 95 + * + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <stdio.h> +#include <string.h> +#include <math.h> +#include <stdlib.h> +#ifdef WIN32 +#include "BLI_winstuff.h" +#endif +#include "MEM_guardedalloc.h" + +#include "BLI_arithb.h" +#include "BLI_blenlib.h" +#include "BLI_vfontdata.h" + +#include "DNA_packedFile_types.h" +#include "DNA_curve_types.h" +#include "DNA_mesh_types.h" +#include "DNA_object_types.h" +#include "DNA_view3d_types.h" +#include "DNA_vfont_types.h" +#include "DNA_scene_types.h" + +#include "BKE_utildefines.h" +#include "BKE_bad_level_calls.h" + +#include "BKE_packedFile.h" + +#include "BKE_library.h" +#include "BKE_font.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_screen.h" +#include "BKE_anim.h" +#include "BKE_curve.h" +#include "BKE_displist.h" + +/* Nieuwe opzet voor vectorfont: + * + * geen PDrawfont meer, alles meteen naar Nurb en BezTriple + * + */ + +struct chartrans { + float xof, yof; + float rot; + short linenr,charnr; +}; + +void free_vfont(struct VFont *vf) +{ + int i; + + if (vf == 0) return; + + if (vf->data) { + for (i = 0; i < MAX_VF_CHARS; i++){ + while (vf->data->nurbsbase[i].first) { + Nurb *nu = vf->data->nurbsbase[i].first; + if (nu->bezt) MEM_freeN(nu->bezt); + BLI_freelinkN(&vf->data->nurbsbase[i], nu); + } + } + + MEM_freeN(vf->data); + vf->data = NULL; + } + + if (vf->packedfile) { + freePackedFile(vf->packedfile); + vf->packedfile = NULL; + } +} + +static void *builtin_font_data= NULL; +static int builtin_font_size= 0; + +void BKE_font_register_builtin(void *mem, int size) +{ + builtin_font_data= mem; + builtin_font_size= size; +} + +static PackedFile *get_builtin_packedfile(void) +{ + if (!builtin_font_data) { + printf("Internal error, builtin font not loaded"); + + return NULL; + } else { + void *mem= MEM_mallocN(builtin_font_size, "vfd_builtin"); + + memcpy(mem, builtin_font_data, builtin_font_size); + + return newPackedFileMemory(mem, builtin_font_size); + } +} + +static VFontData *vfont_get_data(VFont *vfont) +{ + if (!vfont->data) { + PackedFile *pf; + + if (BLI_streq(vfont->name, "<builtin>")) { + pf= get_builtin_packedfile(); + } else { + if (vfont->packedfile) { + pf= vfont->packedfile; + } else { + pf= newPackedFile(vfont->name); + } + } + + if (pf) { + vfont->data= BLI_vfontdata_from_psfont(pf); + + if (pf != vfont->packedfile) { + freePackedFile(pf); + } + } + } + + return vfont->data; +} + +VFont *load_vfont(char *name) +{ + char filename[FILE_MAXFILE]; + VFont *vfont= NULL; + PackedFile *pf; + int is_builtin; + + if (BLI_streq(name, "<builtin>")) { + strcpy(filename, name); + + pf= get_builtin_packedfile(); + is_builtin= 1; + } else { + char dir[FILE_MAXDIR]; + + strcpy(dir, name); + BLI_splitdirstring(dir, filename); + + pf= newPackedFile(name); + is_builtin= 0; + } + + if (pf) { + VFontData *vfd; + + waitcursor(1); + + vfd= BLI_vfontdata_from_psfont(pf); + + if (vfd) { + vfont = alloc_libblock(&G.main->vfont, ID_VF, filename); + vfont->data = vfd; + + BLI_strncpy(vfont->name, name, sizeof(vfont->name)); + + // if autopack is on store the packedfile in de font structure + if (!is_builtin && (G.fileflags & G_AUTOPACK)) { + vfont->packedfile = pf; + } + } + if (!vfont || vfont->packedfile != pf) { + freePackedFile(pf); + } + + waitcursor(0); + } + + return vfont; +} + +static void buildchar(Curve *cu, unsigned char ascii, float ofsx, float ofsy, float rot) +{ + BezTriple *bezt1, *bezt2; + Nurb *nu1, *nu2; + float *fp, fsize, shear, x, si, co; + VFontData *vfd; + int i; + + vfd= vfont_get_data(cu->vfont); + if (!vfd) return; + + /* maak een kopie op afstand ofsx, ofsy met shear*/ + fsize= cu->fsize; + shear= cu->shear; + si= (float)sin(rot); + co= (float)cos(rot); + + nu1 = vfd->nurbsbase[ascii].first; + while(nu1) + { + bezt1 = nu1->bezt; + if (bezt1){ + nu2 =(Nurb*) MEM_mallocN(sizeof(Nurb),"duplichar_nurb"); + if (nu2 == 0) break; + memcpy(nu2, nu1, sizeof(struct Nurb)); + nu2->resolu= cu->resolu; + nu2->bp = 0; + nu2->knotsu = nu2->knotsv = 0; + nu2->flag= ME_SMOOTH; + /* nu2->trim.first = 0; */ + /* nu2->trim.last = 0; */ + i = nu2->pntsu; + + bezt2 = (BezTriple*)MEM_mallocN(i * sizeof(BezTriple),"duplichar_bezt2"); + if (bezt2 == 0){ + MEM_freeN(nu2); + break; + } + memcpy(bezt2, bezt1, i * sizeof(struct BezTriple)); + nu2->bezt = bezt2; + + if (shear != 0.0) { + bezt2 = nu2->bezt; + + for (i= nu2->pntsu; i > 0; i--) { + bezt2->vec[0][0] += shear * bezt2->vec[0][1]; + bezt2->vec[1][0] += shear * bezt2->vec[1][1]; + bezt2->vec[2][0] += shear * bezt2->vec[2][1]; + bezt2++; + } + } + if(rot!=0.0) { + bezt2= nu2->bezt; + for (i=nu2->pntsu; i > 0; i--) { + fp= bezt2->vec[0]; + + x= fp[0]; + fp[0]= co*x + si*fp[1]; + fp[1]= -si*x + co*fp[1]; + x= fp[3]; + fp[3]= co*x + si*fp[4]; + fp[4]= -si*x + co*fp[4]; + x= fp[6]; + fp[6]= co*x + si*fp[7]; + fp[7]= -si*x + co*fp[7]; + + bezt2++; + } + } + bezt2 = nu2->bezt; + + for (i= nu2->pntsu; i > 0; i--) { + fp= bezt2->vec[0]; + + fp[0]= (fp[0]+ofsx)*fsize; + fp[1]= (fp[1]+ofsy)*fsize; + fp[3]= (fp[3]+ofsx)*fsize; + fp[4]= (fp[4]+ofsy)*fsize; + fp[6]= (fp[6]+ofsx)*fsize; + fp[7]= (fp[7]+ofsy)*fsize; + bezt2++; + } + + BLI_addtail(&(cu->nurb), nu2); + } + nu1 = nu1->next; + } +} + + +struct chartrans *text_to_curve(Object *ob, int mode) +{ + VFont *vfont; + VFontData *vfd; + Curve *cu, *cucu; + struct chartrans *chartransdata, *ct; + float distfac, tabfac, ctime, dtime, tvec[4], vec[4], rotvec[3], minx, maxx, miny, maxy; + float cmat[3][3], timeofs, si, co, sizefac; + float *f, maxlen=0, xof, yof, xtrax, linedist, *linedata, *linedata2; + int i, slen, oldflag; + short cnr=0, lnr=0; + char ascii, *mem; + + /* opmerking: berekeningen altijd tot en met de '\0' van de string omdat + de cursor op die plek moet kunnen staan */ + + if(ob->type!=OB_FONT) return 0; + + cu= ob->data; + + vfont= cu->vfont; + if (vfont==0) return 0; + if (cu->str==0) return 0; + + vfd= vfont_get_data(vfont); + if (!vfd) return 0; + + /* aantal regels tellen */ + mem= cu->str; + slen = strlen(mem); + cu->lines= 1; + for (i= 0; i<=slen; i++, mem++) { + ascii = *mem; + if(ascii== '\n' || ascii== '\r') cu->lines++; + } + + /* bereken ofset en rotatie van iedere letter */ + ct = chartransdata = + (struct chartrans*)MEM_callocN((slen+1)* sizeof(struct chartrans),"buildtext"); + linedata= MEM_mallocN(sizeof(float)*cu->lines,"buildtext2"); + linedata2= MEM_mallocN(sizeof(float)*cu->lines,"buildtext2"); + xof= cu->xof; + yof= cu->yof; + + xtrax= 0.5f*cu->spacing-0.5f; + linedist= cu->linedist; + + for (i = 0 ; i<=slen ; i++) { + ascii = cu->str[i]; + if(ascii== '\n' || ascii== '\r' || ascii==0) { + ct->xof= xof; + ct->yof= yof; + ct->linenr= lnr; + ct->charnr= cnr; + + /* alleen lege regels mogen kleiner dan 1 zijn */ + if( linedist<1.0) { + if(i<slen && (cu->str[i+1]=='\r' || cu->str[i+1]=='\n')) yof-= linedist; + else yof-= 1.0; + } + else yof-= linedist; + + maxlen= MAX2(maxlen, xof); + linedata[lnr]= xof; + linedata2[lnr]= cnr; + xof= cu->xof; + lnr++; + cnr= 0; + } + else if(ascii==9) { /* TAB */ + ct->xof= xof; + ct->yof= yof; + ct->linenr= lnr; + ct->charnr= cnr++; + + tabfac= (xof-cu->xof+0.01f); + tabfac= (float)(2.0*ceil(tabfac/2.0)); + xof= cu->xof+tabfac; + } + else { + ct->xof= xof; + ct->yof= yof; + ct->linenr= lnr; + ct->charnr= cnr++; + + xof += vfd->width[ascii] + xtrax; + } + ct++; + } + + /* met alle fontsettings plekken letters berekenen */ + if(cu->spacemode!=CU_LEFT && lnr>1) { + ct= chartransdata; + + if(cu->spacemode==CU_RIGHT) { + for(i=0;i<lnr;i++) linedata[i]= maxlen-linedata[i]; + for (i=0; i<=slen; i++) { + ct->xof+= linedata[ct->linenr]; + ct++; + } + } else if(cu->spacemode==CU_MIDDLE) { + for(i=0;i<lnr;i++) linedata[i]= (maxlen-linedata[i])/2; + for (i=0; i<=slen; i++) { + ct->xof+= linedata[ct->linenr]; + ct++; + } + } else if(cu->spacemode==CU_FLUSH) { + for(i=0;i<lnr;i++) + if(linedata2[i]>1) + linedata[i]= (maxlen-linedata[i])/(linedata2[i]-1); + for (i=0; i<=slen; i++) { + ct->xof+= ct->charnr*linedata[ct->linenr]; + ct++; + } + } + } + + /* TEXT ON CURVE */ + if(cu->textoncurve) { + cucu= cu->textoncurve->data; + + oldflag= cucu->flag; + cucu->flag |= (CU_PATH+CU_FOLLOW); + + if(cucu->path==0) calc_curvepath(cu->textoncurve); + if(cucu->path) { + + + Mat3CpyMat4(cmat, cu->textoncurve->obmat); + sizefac= Normalise(cmat[0])/cu->fsize; + + minx=miny= 1.0e20f; + maxx=maxy= -1.0e20f; + ct= chartransdata; + for (i=0; i<=slen; i++, ct++) { + if(minx>ct->xof) minx= ct->xof; + if(maxx<ct->xof) maxx= ct->xof; + if(miny>ct->yof) miny= ct->yof; + if(maxy<ct->yof) maxy= ct->yof; + } + + /* we zetten de x-coordinaat exact op de curve, de y wordt geroteerd */ + + /* de lengte correctie */ + distfac= sizefac*cucu->path->totdist/(maxx-minx); + timeofs= 0.0; + + if(distfac > 1.0) { + /* pad langer dan tekst: spacemode doet mee */ + distfac= 1.0f/distfac; + + if(cu->spacemode==CU_RIGHT) { + timeofs= 1.0f-distfac; + } + else if(cu->spacemode==CU_MIDDLE) { + timeofs= (1.0f-distfac)/2.0f; + } + else if(cu->spacemode==CU_FLUSH) distfac= 1.0f; + + } + else distfac= 1.0; + + distfac/= (maxx-minx); + + timeofs+= distfac*cu->xof; /* niet cyclic */ + + ct= chartransdata; + for (i=0; i<=slen; i++, ct++) { + + /* roteren rond centrum letter */ + ascii = cu->str[i]; + dtime= distfac*0.35f*vfd->width[ascii]; /* Waarom is 0.5 te groot? */ + dtime= distfac*0.0f*vfd->width[ascii]; /* Waarom is 0.5 te groot? */ + + ctime= timeofs + distfac*( ct->xof - minx); + CLAMP(ctime, 0.0, 1.0); + + /* de goede plek EN de goede rotatie apart berekenen */ + where_on_path(cu->textoncurve, ctime, vec, tvec); + where_on_path(cu->textoncurve, ctime+dtime, tvec, rotvec); + + VecMulf(vec, sizefac); + + ct->rot= (float)(M_PI-atan2(rotvec[1], rotvec[0])); + + si= (float)sin(ct->rot); + co= (float)cos(ct->rot); + + yof= ct->yof; + + ct->xof= vec[0] + si*yof; + ct->yof= vec[1] + co*yof; + + } + cucu->flag= oldflag; + } + } + + + if(mode==FO_CURSUP || mode==FO_CURSDOWN) { + /* 2: curs omhoog + 3: curs omlaag */ + ct= chartransdata+cu->pos; + + if(mode==FO_CURSUP && ct->linenr==0); + else if(mode==FO_CURSDOWN && ct->linenr==lnr); + else { + if(mode==FO_CURSUP) lnr= ct->linenr-1; + else lnr= ct->linenr+1; + cnr= ct->charnr; + /* zoek karakter met lnr en cnr */ + cu->pos= 0; + ct= chartransdata; + for (i= 0; i<slen; i++) { + if(ct->linenr==lnr) { + if(ct->charnr==cnr) break; + if( (ct+1)->charnr==0) break; + } + else if(ct->linenr>lnr) break; + cu->pos++; + ct++; + } + } + } + + /* eerst cursor */ + if(ob==G.obedit) { + ct= chartransdata+cu->pos; + si= (float)sin(ct->rot); + co= (float)cos(ct->rot); + + f= G.textcurs[0]; + + f[0]= cu->fsize*(-0.1f*co + ct->xof); + f[1]= cu->fsize*(0.1f*si + ct->yof); + + f[2]= cu->fsize*(0.1f*co + ct->xof); + f[3]= cu->fsize*(-0.1f*si + ct->yof); + + f[4]= cu->fsize*( 0.1f*co + 0.8f*si + ct->xof); + f[5]= cu->fsize*(-0.1f*si + 0.8f*co + ct->yof); + + f[6]= cu->fsize*(-0.1f*co + 0.8f*si + ct->xof); + f[7]= cu->fsize*( 0.1f*si + 0.8f*co + ct->yof); + + } + + if(mode==0) { + /* nurbdata maken */ + + freeNurblist(&cu->nurb); + + ct= chartransdata; + for (i= 0; i<slen; i++) { + ascii = cu->str[i]; + buildchar(cu, ascii, ct->xof, ct->yof, ct->rot); + ct++; + } + } + + MEM_freeN(linedata); + MEM_freeN(linedata2); + + if(mode==FO_DUPLI) { + return chartransdata; + } + + MEM_freeN(chartransdata); + return 0; +} + + +/* ***************** DUPLI ***************** */ + +static Object *find_family_object(Object **obar, char *family, char ch) +{ + Object *ob; + int flen; + + if( obar[ch] ) return obar[ch]; + + flen= strlen(family); + + ob= G.main->object.first; + while(ob) { + if( ob->id.name[flen+2]==ch ) { + if( strncmp(ob->id.name+2, family, flen)==0 ) break; + } + ob= ob->id.next; + } + + obar[ch]= ob; + + return ob; +} + + +void font_duplilist(Object *par) +{ + extern ListBase duplilist; + Object *ob, *newob, *obar[256]; + Curve *cu; + struct chartrans *ct, *chartransdata; + float vec[3], pmat[4][4], fsize, xof, yof; + int slen, a; + + Mat4CpyMat4(pmat, par->obmat); + + /* in par staat een familienaam, deze gebruiken om objecten te vinden */ + + chartransdata= text_to_curve(par, FO_DUPLI); + if(chartransdata==0) return; + + memset(obar, 0, 256*4); + + cu= par->data; + slen= strlen(cu->str); + fsize= cu->fsize; + xof= cu->xof; + yof= cu->yof; + + ct= chartransdata; + set_displist_onlyzero(1); + + for(a=0; a<slen; a++, ct++) { + + ob= find_family_object(obar, cu->family, cu->str[a]); + if(ob) { + + makeDispList(ob); + + vec[0]= fsize*(ct->xof - xof); + vec[1]= fsize*(ct->yof - yof); + vec[2]= 0.0; + + Mat4MulVecfl(pmat, vec); + + newob= MEM_mallocN(sizeof(Object), "newobj dupli"); + memcpy(newob, ob, sizeof(Object)); + newob->flag |= OB_FROMDUPLI; + newob->id.newid= (ID *)par; /* duplicator bewaren */ + newob->totcol= par->totcol; /* voor give_current_material */ + + Mat4CpyMat4(newob->obmat, par->obmat); + VECCOPY(newob->obmat[3], vec); + + newob->parent= 0; + newob->track= 0; + + BLI_addtail(&duplilist, newob); + } + + } + set_displist_onlyzero(0); + MEM_freeN(chartransdata); +} diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c new file mode 100644 index 00000000000..6f01d028326 --- /dev/null +++ b/source/blender/blenkernel/intern/group.c @@ -0,0 +1,329 @@ +/* group.c sept 2000 + * - cleaned up mar-01 nzc + * + * + * ton roosendaal + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <stdio.h> +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_ID.h" +#include "DNA_group_types.h" +#include "DNA_object_types.h" +#include "DNA_ipo_types.h" + +#include "BLI_blenlib.h" +#include "BKE_global.h" +#include "BKE_main.h" + +#include "BKE_library.h" +#include "BKE_group.h" +#include "BKE_object.h" +#include "BKE_ipo.h" + +void free_object_key(ObjectKey *ok) +{ + if(ok->ipo) ok->ipo->id.us--; + + MEM_freeN(ok); +} + +void free_group_object(GroupObject *go) +{ + ObjectKey *ok; + + while(go->okey.first) { + ok= go->okey.first; + BLI_remlink(&go->okey, ok); + free_object_key(ok); + } + MEM_freeN(go); +} + + +void free_group(Group *group) +{ + /* don't free group itself */ + GroupObject *go; + + BLI_freelistN(&group->gkey); + + while(group->gobject.first) { + go= group->gobject.first; + BLI_remlink(&group->gobject, go); + free_group_object(go); + } + +} + +Group *add_group() +{ + Group *group; + + group = alloc_libblock(&G.main->group, ID_GR, "Group"); + return group; +} + +/* assumes 'ok' is unitialized */ +void object_to_obkey(Object *ob, ObjectKey *ok) +{ + ok->partype= ob->partype; + ok->par1= ob->par1; + ok->par2= ob->par2; + ok->par3= ob->par3; + + ok->parent= ob->parent; + ok->track= ob->track; + + ok->ipo= copy_ipo(ob->ipo); + + memcpy(ok->loc, ob->loc, 7*3*sizeof(float)); + memcpy(ok->quat, ob->quat, 2*4*sizeof(float)); + memcpy(ok->obmat, ob->obmat, 3*4*4*sizeof(float)); + + ok->lay= ob->lay; + ok->transflag= ob->transflag; + ok->trackflag= ob->transflag; + ok->upflag= ob->upflag; + ok->sf= ob->sf; + ok->ctime= ob->ctime; + + +} + +void obkey_to_object(ObjectKey *ok, Object *ob) +{ + ob->partype= ok->partype; + ob->par1= ok->par1; + ob->par2= ok->par2; + ob->par3= ok->par3; + + ob->parent= ok->parent; + ob->track= ok->track; + + /* pretty tricky, this makes ob->ipo blocks with users 'hanging around' */ + if(ob->ipo) { + free_libblock_us(&G.main->ipo, ob->ipo); + } + ob->ipo= copy_ipo(ok->ipo); + + memcpy(ob->loc, ok->loc, 7*3*sizeof(float)); + memcpy(ob->quat, ok->quat, 2*4*sizeof(float)); + memcpy(ob->obmat, ok->obmat, 3*4*4*sizeof(float)); + + ob->lay= ok->lay; + ob->transflag= ok->transflag; + ob->trackflag= ok->transflag; + ob->upflag= ok->upflag; + ob->sf= ok->sf; + ob->ctime= ok->ctime; +} + +/* current ob position */ +void add_object_key(GroupObject *go, GroupKey *gk) +{ + ObjectKey *ok; + + /* check if there already is a key */ + ok= go->okey.first; + while(ok) { + if(ok->gkey == gk) break; + ok= ok->next; + } + + if(ok) { + BLI_remlink(&go->okey, ok); + free_object_key(ok); + } + ok= MEM_mallocN(sizeof(ObjectKey), "objectkey"); + ok->gkey= gk; + + object_to_obkey(go->ob, ok); + + BLI_addtail(&go->okey, ok); + +} + +/* external */ +void add_to_group(Group *group, Object *ob) +{ + GroupObject *go; + GroupKey *gk; + + /* check if the object has been added already */ + go= group->gobject.first; + while(go) { + if(go->ob==ob) return; + go= go->next; + } + + go= MEM_callocN(sizeof(GroupObject), "groupobject"); + BLI_addtail( &group->gobject, go); + + go->ob= ob; + + /* keys? */ + gk= group->gkey.first; + while(gk) { + add_object_key(go, gk); + gk= gk->next; + } +} + +void rem_from_group(Group *group, Object *ob) +{ + GroupObject *go, *gon; + ObjectKey *ok; + + go= group->gobject.first; + while(go) { + gon= go->next; + if(go->ob==ob) { + BLI_remlink(&group->gobject, go); + free_group_object(go); + } + else { + ok= go->okey.first; + while(ok) { + if(ok->parent==ob) ok->parent= NULL; + if(ok->track==ob) ok->track= NULL; + ok= ok->next; + } + } + go= gon; + } +} + +void add_group_key(Group *group) +{ + GroupObject *go; + GroupKey *gk; + int nr=10; + extern char colname_array[][20]; /* material.c */ + + gk= group->gkey.first; + while(gk) { + nr++; + gk= gk->next; + } + + gk= MEM_callocN(sizeof(GroupKey), "groupkey"); + BLI_addtail(&group->gkey, gk); + strcpy(gk->name, colname_array[ nr % 120 ]); + + go= group->gobject.first; + while(go) { + add_object_key(go, gk); + go= go->next; + } + + group->active= gk; +} + +void set_object_key(Object *ob, ObjectKey *ok) +{ + obkey_to_object(ok, ob); +} + +void set_group_key(Group *group) +{ + /* sets active */ + GroupObject *go; + ObjectKey *ok; + + if(group->active==NULL) return; + + go= group->gobject.first; + while(go) { + ok= go->okey.first; + while(ok) { + if(ok->gkey==group->active) { + set_object_key(go->ob, ok); + break; + } + ok= ok->next; + } + go= go->next; + } + +} + +Group *find_group(Object *ob) +{ + Group *group= G.main->group.first; + GroupObject *go; + + while(group) { + + go= group->gobject.first; + while(go) { + if(go->ob==ob) return group; + go= go->next; + } + group= group->id.next; + } + return NULL; +} + +void set_group_key_name(Group *group, char *name) +{ + GroupKey *gk; + + if(group==NULL) return; + + gk= group->gkey.first; + while(gk) { + if(strcmp(name, gk->name)==0) break; + gk= gk->next; + } + + if(gk) { + group->active= gk; + set_group_key(group); + } +} + +void set_group_key_frame(Group *group, float frame) +{ + GroupObject *go; + + if(group==NULL) return; + + go= group->gobject.first; + while(go) { + where_is_object_time(go->ob, frame); + go= go->next; + } +} diff --git a/source/blender/blenkernel/intern/ika.c b/source/blender/blenkernel/intern/ika.c new file mode 100644 index 00000000000..885c64f0397 --- /dev/null +++ b/source/blender/blenkernel/intern/ika.c @@ -0,0 +1,596 @@ + +/* ika.c MIXED MODEL + * + * april 96 + * + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <math.h> +#include <stdlib.h> + +#include "MEM_guardedalloc.h" + +/* types */ +#include "DNA_ika_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_view3d_types.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +/* functions */ +#include "BKE_blender.h" +#include "BKE_library.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_object.h" +#include "BKE_ika.h" + +/* Let's go! */ +#define TOLER 0.000076 +#define CLAMP(a, b, c) if((a)<(b)) (a)=(b); else if((a)>(c)) (a)=(c) + + +void unlink_ika(Ika *ika) +{ + /* loskoppelen: */ + + +} + +/* niet Ika zelf vrijgeven */ +void free_ika(Ika *ika) +{ + + /* unimplemented!!! */ + unlink_ika(ika); + + BLI_freelistN(&ika->limbbase); + + if(ika->def) MEM_freeN(ika->def); +} + +Ika *add_ika() +{ + Ika *ika; + + ika= alloc_libblock(&G.main->ika, ID_IK, "Ika"); + ika->flag = IK_GRABEFF | IK_XYCONSTRAINT; + + ika->xyconstraint= 0.5f; + ika->mem= 0.3f; + ika->iter= 6; + + return ika; +} + +Ika *copy_ika(Ika *ika) +{ + Ika *ikan; + + ikan= copy_libblock(ika); + + duplicatelist(&ikan->limbbase, &ika->limbbase); + + ikan->def= MEM_dupallocN(ikan->def); + + return ikan; +} + +void make_local_ika(Ika *ika) +{ + Object *ob; + Ika *ikan; + int local=0, lib=0; + + /* - zijn er alleen lib users: niet doen + * - zijn er alleen locale users: flag zetten + * - mixed: copy + */ + + if(ika->id.lib==0) return; + if(ika->id.us==1) { + ika->id.lib= 0; + ika->id.flag= LIB_LOCAL; + new_id(0, (ID *)ika, 0); + return; + } + + ob= G.main->object.first; + while(ob) { + if(ob->data==ika) { + if(ob->id.lib) lib= 1; + else local= 1; + } + ob= ob->id.next; + } + + if(local && lib==0) { + ika->id.lib= 0; + ika->id.flag= LIB_LOCAL; + new_id(0, (ID *)ika, 0); + } + else if(local && lib) { + ikan= copy_ika(ika); + ikan->id.us= 0; + + ob= G.main->object.first; + while(ob) { + if(ob->data==ika) { + + if(ob->id.lib==0) { + ob->data= ikan; + ikan->id.us++; + ika->id.us--; + } + } + ob= ob->id.next; + } + } +} + +int count_limbs(Object *ob) +{ + int tot=0; + Ika *ika; + Limb *li; + + if(ob->type!=OB_IKA) return 0; + ika= ob->data; + + li= ika->limbbase.first; + while(li) { + tot++; + li= li->next; + } + return tot; +} + +/* ************************************************** */ + + +/* aan hand van eff[] de len en alpha */ +void calc_limb(Limb *li) +{ + Limb *prev= li; + float vec[2], alpha= 0.0; + + /* alpha van 'parents' */ + while( (prev=prev->prev) ) { + alpha+= prev->alpha; + } + + if(li->prev) { + vec[0]= -li->prev->eff[0]; + vec[1]= -li->prev->eff[1]; + } + else vec[0]= vec[1]= 0.0; + + vec[0]+= li->eff[0]; + vec[1]+= li->eff[1]; + + li->alpha= (float)atan2(vec[1], vec[0]) - alpha; + li->len= (float)sqrt(vec[0]*vec[0] + vec[1]*vec[1]); + +} + +/* aan hand van len en alpha worden de eindpunten berekend */ +void calc_ika(Ika *ika, Limb *li) +{ + float alpha=0.0, co, si; + + if(li) { + Limb *prev= li; + while((prev=prev->prev)) { + alpha+= prev->alpha; + } + } + else li= ika->limbbase.first; + + while(li) { + if(li->alpha != li->alpha) li->alpha= 0.0f; /* NaN patch */ + + alpha+= li->alpha; + + co= (float)cos(alpha); + si= (float)sin(alpha); + + li->eff[0]= co*li->len; + li->eff[1]= si*li->len; + + if(li->prev) { + li->eff[0]+= li->prev->eff[0]; + li->eff[1]+= li->prev->eff[1]; + } + + if(li->next==0) { + ika->eff[0]= li->eff[0]; + ika->eff[1]= li->eff[1]; + } + + li= li->next; + } +} + +void init_defstate_ika(Object *ob) +{ + Ika *ika; + Limb *li; + + ika= ob->data; + ika->totx= 0.0; + ika->toty= 0.0; + li= ika->limbbase.first; + + calc_ika(ika, 0); /* correcte eindpunten */ + + while(li) { + li->alphao= li->alpha; + li->leno= li->len; + + li= li->next; + } + ika->eff[2]= 0.0; + VecMat4MulVecfl(ika->effg, ob->obmat, ika->eff); +} + +void itterate_limb(Ika *ika, Limb *li) +{ + float da, n1[2], n2[2], len1, len2; + + if(li->prev) { + n1[0]= ika->eff[0] - li->prev->eff[0]; + n1[1]= ika->eff[1] - li->prev->eff[1]; + n2[0]= ika->effn[0] - li->prev->eff[0]; + n2[1]= ika->effn[1] - li->prev->eff[1]; + } + else { + n1[0]= ika->eff[0]; + n1[1]= ika->eff[1]; + n2[0]= ika->effn[0]; + n2[1]= ika->effn[1]; + } + len1= (float)sqrt(n1[0]*n1[0] + n1[1]*n1[1]); + len2= (float)sqrt(n2[0]*n2[0] + n2[1]*n2[1]); + + da= (1.0f-li->fac)*saacos( (n1[0]*n2[0]+n1[1]*n2[1])/(len1*len2) ); + + if(n1[0]*n2[1] < n1[1]*n2[0]) da= -da; + + li->alpha+= da; + +} + +void rotate_ika(Object *ob, Ika *ika) +{ + Limb *li; + float len2, da, n1[2], n2[2]; + + /* terug roteren */ + euler_rot(ob->rot, -ika->toty, 'y'); + ika->toty= 0.0; + + where_is_object(ob); + + Mat4Invert(ob->imat, ob->obmat); + VecMat4MulVecfl(ika->effn, ob->imat, ika->effg); + + li= ika->limbbase.last; + if(li==0) return; + + n1[0]= ika->eff[0]; + n2[0]= ika->effn[0]; + n2[1]= ika->effn[2]; + + len2= (float)sqrt(n2[0]*n2[0] + n2[1]*n2[1]); + + if(len2>TOLER) { + da= (n2[0])/(len2); + if(n1[0]<0.0) da= -da; + + /* als de x comp bijna nul is kan dit gebeuren */ + if(da<=-1.0+TOLER || da>=1.0) ; + else { + + da= saacos( da ); + if(n1[0]*n2[1] > 0.0) da= -da; + + euler_rot(ob->rot, da, 'y'); + ika->toty= da; + } + } +} + +void rotate_ika_xy(Object *ob, Ika *ika) +{ + Limb *li; + float ang, da, n1[3], n2[3], axis[3], quat[4]; + + /* terug roteren */ + euler_rot(ob->rot, -ika->toty, 'y'); + euler_rot(ob->rot, -ika->totx, 'x'); + + where_is_object(ob); + + Mat4Invert(ob->imat, ob->obmat); + VecMat4MulVecfl(ika->effn, ob->imat, ika->effg); + + li= ika->limbbase.last; + if(li==0) return; + + /* ika->eff = old situation */ + /* ika->effn = desired situation */ + + *(n1)= *(ika->effn); + *(n1+1)= *(ika->effn+1); + *(n1+2)= 0.0; + + *(n2)= *(ika->effn); + *(n2+1)= *(ika->effn+1); + *(n2+2)= *(ika->effn+2); + + Normalise(n1); + Normalise(n2); + + ang= n1[0]*n2[0] + n1[1]*n2[1] + n1[2]*n2[2]; + ang= saacos(ang); + + if(ang<-0.0000001 || ang>0.00000001) { + Crossf(axis, n1, n2); + Normalise(axis); + quat[0]= (float)cos(0.5*ang); + da= (float)sin(0.5*ang); + quat[1]= da*axis[0]; + quat[2]= da*axis[1]; + quat[3]= da*axis[2]; + + QuatToEul(quat, axis); + + ika->totx= axis[0]; + CLAMP(ika->totx, -ika->xyconstraint, ika->xyconstraint); + ika->toty= axis[1]; + CLAMP(ika->toty, -ika->xyconstraint, ika->xyconstraint); + } + + euler_rot(ob->rot, ika->totx, 'x'); + euler_rot(ob->rot, ika->toty, 'y'); +} + +void itterate_ika(Object *ob) +{ + Ika *ika; + Limb *li; + int it = 0; + + ika= ob->data; + if((ika->flag & IK_GRABEFF)==0) return; + + disable_where_script(1); + /* memory: grote tijdsprongen afvangen */ + it= abs(ika->lastfra - G.scene->r.cfra); + ika->lastfra= G.scene->r.cfra; + if(it>10) { + + /* one itteration extra */ + itterate_ika(ob); + } + else { + li= ika->limbbase.first; + while(li) { + li->alpha= (1.0f-ika->mem)*li->alpha + ika->mem*li->alphao; + if(li->fac==1.0f) li->fac= 0.05f; /* oude files: kan weg in juni 96 */ + li= li->next; + } + } + calc_ika(ika, 0); + + /* effector heeft parent? */ + if(ika->parent) { + + if(ika->partype==PAROBJECT) { + if(ika->parent->ctime != (float) G.scene->r.cfra) where_is_object(ika->parent); + *(ika->effg)= *(ika->parent->obmat[3]); + *(ika->effg+1)= *(ika->parent->obmat[3]+1); + *(ika->effg+2)= *(ika->parent->obmat[3]+2); + } + else { + what_does_parent1(ika->parent, ika->partype, ika->par1, 0, 0); + *(ika->effg)= *(workob.obmat[3]); + *(ika->effg+1)= *(workob.obmat[3]+1); + *(ika->effg+2)= *(workob.obmat[3]+2); + } + } + + + /* y-as goed draaien */ + if(ika->flag & IK_XYCONSTRAINT) + rotate_ika_xy(ob, ika); + else + rotate_ika(ob, ika); + + it= ika->iter; + while(it--) { + + where_is_object(ob); + Mat4Invert(ob->imat, ob->obmat); + VecMat4MulVecfl(ika->effn, ob->imat, ika->effg); + /* forward: dan gaan ook de eerste limbs */ + li= ika->limbbase.first; + while(li) { + + itterate_limb(ika, li); + + /* zet je calc_ika() buiten deze lus: lange kettingen instabiel */ + calc_ika(ika, li); + + li= li->next; + } + + where_is_object(ob); + Mat4Invert(ob->imat, ob->obmat); + VecMat4MulVecfl(ika->effn, ob->imat, ika->effg); + + /* backward */ + li= ika->limbbase.last; + while(li) { + + itterate_limb(ika, li); + + /* zet je calc_ika() buiten deze lus: lange kettingen instabiel */ + calc_ika(ika, li); + + li= li->prev; + } + } + + disable_where_script(0); +} + + +void do_all_ikas() +{ + Base *base = 0; + + base= G.scene->base.first; + while(base) { + + if(base->object->type==OB_IKA) itterate_ika(base->object); + + base= base->next; + } +} + +void do_all_visible_ikas() +{ + Base *base = 0; + + base= G.scene->base.first; + while(base) { + if(base->lay & G.scene->lay) { + if(base->object->type==OB_IKA) itterate_ika(base->object); + } + base= base->next; + } +} + +/* ******************** DEFORM ************************ */ + + +void init_skel_deform(Object *par, Object *ob) +{ + Deform *def; + Ika *ika; + int a; + + /* deform: + * + * ob_vec * ob_obmat * def_imat (weight fie) * def_obmat * ob_imat = ob_vec' + * + * <----- premat ----> <---- postmat ----> + */ + + if(par->type!=OB_IKA) return; + + Mat4Invert(ob->imat, ob->obmat); + + ika= par->data; + a= ika->totdef; + def= ika->def; + while(a--) { + + what_does_parent1(def->ob, def->partype, def->par1, def->par2, def->par3); + + Mat4MulMat4(def->premat, ob->obmat, def->imat); + Mat4MulMat4(def->postmat, workob.obmat, ob->imat); + + def++; + } +} + + +void calc_skel_deform(Ika *ika, float *co) +{ + Deform *def; + int a; + float totw=0.0, weight, fac, len, vec[3], totvec[3]; + + def= ika->def; + if(def==0) return; + a= ika->totdef; + totvec[0]=totvec[1]=totvec[2]= 0.0; + + while(a--) { + + VecMat4MulVecfl(vec, def->premat, co); + + len= (float)sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); + + if(def->vec[0]==0.0f) len= 2.0f*len; + else len= len + (float)sqrt( (vec[0]+def->vec[0])*(vec[0]+def->vec[0]) + vec[1]*vec[1] + vec[2]*vec[2]); + + /* def->vec[0]= len limb */ + + weight= 1.0f/(0.001f+len); + weight*= weight; + weight*= weight; + weight*= def->fac; + + len -= def->vec[0]; + + if(def->dist != 0.0) { + if(len >= def->dist) { + weight= 0.0; + } + else { + fac= (def->dist - len)/def->dist; + weight*= fac; + } + } + if(weight > 0.0) { + Mat4MulVecfl(def->postmat, vec); + + VecMulf(vec, weight); + VecAddf(totvec, totvec, vec); + + totw+= weight; + } + def++; + } + + if(totw==0.0) return; + + co[0]= totvec[0]/totw; + co[1]= totvec[1]/totw; + co[2]= totvec[2]/totw; + +} diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c new file mode 100644 index 00000000000..7e3e5eca3aa --- /dev/null +++ b/source/blender/blenkernel/intern/image.c @@ -0,0 +1,1486 @@ +/* image.c MIX MODEL + * + * maart 95 + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <math.h> +#ifndef WIN32 +#include <unistd.h> +#else +#include <io.h> +#endif + +#include "MEM_guardedalloc.h" + +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" + +#include "DNA_texture_types.h" +#include "DNA_image_types.h" +#include "DNA_packedFile_types.h" + +#include "BLI_blenlib.h" + +#include "BKE_bad_level_calls.h" +#include "BKE_utildefines.h" + +#include "BKE_global.h" +#include "BKE_main.h" + +#include "BKE_image.h" +#include "BKE_bmfont.h" +#include "BKE_screen.h" +#include "BKE_texture.h" +#include "BKE_packedFile.h" +#include "BKE_library.h" + +void clipx_rctf_swap(rctf *stack, short *count, float x1, float x2); +void clipy_rctf_swap(rctf *stack, short *count, float y1, float y2); +float square_rctf(rctf *rf); +float clipx_rctf(rctf *rf, float x1, float x2); +float clipy_rctf(rctf *rf, float y1, float y2); +void boxsample(struct ImBuf *ibuf, + float minx, float miny, float maxx, float maxy, + float *rcol, float *gcol, float *bcol, float *acol); +void boxsampleclip(struct ImBuf *ibuf, rctf *rf, float *rcol, + float *gcol, float *bcol, float *acol); +void filtersample(struct ImBuf *ibuf, + float fx, float fy, + float *rcol, float *gcol, float *bcol, float *acol); + + + +/* If defined: check arguments on call */ +/* #define IMAGE_C_ARG_CHECK */ + +/* Communicate with texture channels. */ +extern float Tin, Tr, Tg, Tb, Ta; + +int Talpha; +int imaprepeat, imapextend; + + +/* + * + * Talpha==TRUE betekent: lees alpha uit plaatje. Dit betekent niet dat Ta + * niet gebruikt moet worden, hier kan info over rand van image in staan! + * + */ + +void free_image_buffers(Image *ima) +{ + int a; + + if(ima->ibuf) { + if (ima->ibuf->userdata) { + MEM_freeN(ima->ibuf->userdata); + ima->ibuf->userdata = 0; + } + IMB_freeImBuf(ima->ibuf); + ima->ibuf= 0; + } + if(ima->anim) IMB_free_anim(ima->anim); + ima->anim= 0; + + for(a=0; a<BLI_ARRAY_NELEMS(ima->mipmap); a++) { + if(ima->mipmap[a]) IMB_freeImBuf(ima->mipmap[a]); + ima->mipmap[a]= 0; + } + + free_realtime_image(ima); +} + + +void free_image(Image *ima) +{ + + free_image_buffers(ima); + if (ima->packedfile) { + freePackedFile(ima->packedfile); + ima->packedfile = NULL; + } +} + + +Image *add_image(char *name) +{ + Image *ima; + int file, len; + char *libname, str[256], strtest[256]; + + strcpy(str, name); + BLI_convertstringcode(str, G.sce, G.scene->r.cfra); + + file= open(str, O_BINARY|O_RDONLY); + if(file== -1) return 0; + close(file); + + /* eerst zoeken naar eenzelfde ima */ + ima= G.main->image.first; + while(ima) { + strcpy(strtest, ima->name); + BLI_convertstringcode(strtest, G.sce, G.scene->r.cfra); + if( strcmp(strtest, str)==0 ) { + if(ima->anim==0 || ima->id.us==0) { + strcpy(ima->name, name); /* for stringcode */ + ima->id.us++; + ima->ok= 1; + return ima; + } + } + ima= ima->id.next; + } + + len= strlen(name); + + while (len > 0 && name[len - 1] != '/' && name[len - 1] != '\\') len--; + libname= name+len; + + ima= alloc_libblock(&G.main->image, ID_IM, libname); + strcpy(ima->name, name); + ima->ok= 1; + + ima->xrep= ima->yrep= 1; + + return ima; +} + +void free_unused_animimages() +{ + Image *ima, *nima; + + ima= G.main->image.first; + while(ima) { + nima= ima->id.next; + if(ima->id.us==0) { + if(ima->flag & IMA_FROMANIM) free_libblock(&G.main->image, ima); + } + ima= nima; + } +} + + +/* *********** LEZEN EN SCHRIJVEN ************** */ + +void makepicstring(char *string, int frame) +{ + short i,len; + char num[10], *extension; + + if (string==0) return; + + extension= ""; + + strcpy(string, G.scene->r.pic); + BLI_convertstringcode(string, G.sce, G.scene->r.cfra); + + len= strlen(string); + + /* kan ook: sprintf(num, "%04d", frame); */ + + i=4-sprintf(num,"%d",frame); + for(;i>0;i--){ + string[len]='0'; + len++; + } + string[len]=0; + strcat(string,num); + + if(G.scene->r.imtype== R_IRIS) { + extension= ".rgb"; + } + else if(G.scene->r.imtype==R_IRIZ) { + extension= ".rgb"; + } + else if(G.scene->r.imtype==R_PNG) { + extension= ".png"; + } + else if(G.scene->r.imtype==R_TARGA) { + extension= ".tga"; + } + else if(G.scene->r.imtype==R_RAWTGA) { + extension= ".tga"; + } + else if(G.scene->r.imtype==R_JPEG90) { + extension= ".jpg"; + } + + if(G.scene->r.scemode & R_EXTENSION) strcat(string, extension); + +} + +/* ******** IMAGWRAPPING INIT ************* */ + +void converttopremul(struct ImBuf *ibuf) +{ + int x, y, val; + char *cp; + + if(ibuf==0) return; + if(ibuf->depth==24) { /* alpha op 255 zetten */ + + cp= (char *)(ibuf->rect); + for(y=0; y<ibuf->y; y++) { + for(x=0; x<ibuf->x; x++, cp+=4) { + cp[3]= 255; + } + } + return; + } + + cp= (char *)(ibuf->rect); + for(y=0; y<ibuf->y; y++) { + for(x=0; x<ibuf->x; x++, cp+=4) { + if(cp[3]==0) { + cp[0]= cp[1]= cp[2]= 0; + } + else if(cp[3]!=255) { + val= cp[3]; + cp[0]= (cp[0]*val)>>8; + cp[1]= (cp[1]*val)>>8; + cp[2]= (cp[2]*val)>>8; + } + } + } +} + + + +void makemipmap(Image *ima) +{ + struct ImBuf *ibuf; + int minsize, curmap=0; + + ibuf= ima->ibuf; + minsize= MIN2(ibuf->x, ibuf->y); + + while(minsize>3 && curmap<BLI_ARRAY_NELEMS(ima->mipmap)) { + + ibuf= IMB_dupImBuf(ibuf); + IMB_filter(ibuf); + ima->mipmap[curmap]= (struct ImBuf *)IMB_onehalf(ibuf); + IMB_freeImBuf(ibuf); + ibuf= ima->mipmap[curmap]; + + curmap++; + minsize= MIN2(ibuf->x, ibuf->y); + } +} + +struct anim *openanim(char * name, int flags) +{ + struct anim * anim; + struct ImBuf * ibuf; + + anim = IMB_open_anim(name, flags); + if (anim == 0) return(0); + + + ibuf = IMB_anim_absolute(anim, 0); + if (ibuf == 0) { + printf("anim_absolute 0 failed\n"); + IMB_free_anim(anim); + return(0); + } + IMB_freeImBuf(ibuf); + + return(anim); +} + +int calcimanr(int cfra, Tex *tex) +{ + int imanr, len, a, fra, dur; + + /* hier (+fie_ima/2-1) zorgt ervoor dat correct wordt gedeeld */ + + if(tex->frames==0) return 1; + + cfra= cfra-tex->sfra+1; + + /* cyclic */ + if(tex->len==0) len= (tex->fie_ima*tex->frames)/2; + else len= tex->len; + + if(tex->imaflag & TEX_ANIMCYCLIC) { + cfra= ( (cfra) % len ); + if(cfra < 0) cfra+= len; + if(cfra==0) cfra= len; + } + + if(cfra<1) cfra= 1; + else if(cfra>len) cfra= len; + + /* omzetten current frame naar current field */ + cfra= 2*(cfra); + if(R.flag & R_SEC_FIELD) cfra++; + + + /* transformeren naar images space */ + imanr= (cfra+tex->fie_ima-2)/tex->fie_ima; + + if(imanr>tex->frames) imanr= tex->frames; + imanr+= tex->offset; + + /* zijn er plaatjes die langer duren? */ + for(a=0; a<4; a++) { + if(tex->fradur[a][0]) { + + fra= tex->fradur[a][0]; + dur= tex->fradur[a][1]-1; + + while(dur>0 && imanr>fra) { + imanr--; + dur--; + } + } + } + + + return imanr; +} + +void do_laseroptics_patch(ImBuf *ibuf) +{ + char *rt; + float fac; + int a, val; + + rt= (char *)ibuf->rect; + a= ibuf->x*ibuf->y; + + if(ibuf->flags & IB_fields) a+= a; + + while(a--) { + + fac= (rt[1]+rt[2]+rt[3])/765.0f; + val= (int)((255.0/0.8)*(fac-0.1)); + + if(val<0) val= 0; else if(val>255) val= 255; + + rt[0]= rt[1]= rt[2]= rt[3]= val; + + rt+= 4; + } +} + +void de_interlace_ng(struct ImBuf *ibuf) /* neogeo fields */ +{ + struct ImBuf * tbuf1, * tbuf2; + + if (ibuf == 0) return; + if (ibuf->flags & IB_fields) return; + ibuf->flags |= IB_fields; + + if (ibuf->rect) { + /* kopieen aanmaken */ + tbuf1 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, (int)IB_rect, (unsigned char)0); + tbuf2 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, (int)IB_rect, (unsigned char)0); + + ibuf->x *= 2; + /* These rectop calls are broken!!! I added a trailing 0 arg... */ + IMB_rectop(tbuf1, ibuf, 0, 0, 0, 0, 32767, 32767, IMB_rectcpy, 0); + IMB_rectop(tbuf2, ibuf, 0, 0, tbuf2->x, 0, 32767, 32767, IMB_rectcpy, 0); + + ibuf->x /= 2; + IMB_rectop(ibuf, tbuf1, 0, 0, 0, 0, 32767, 32767, IMB_rectcpy, 0); + IMB_rectop(ibuf, tbuf2, 0, tbuf2->y, 0, 0, 32767, 32767, IMB_rectcpy, 0); + + IMB_freeImBuf(tbuf1); + IMB_freeImBuf(tbuf2); + } + ibuf->y /= 2; +} + +void de_interlace_st(struct ImBuf *ibuf) /* standard fields */ +{ + struct ImBuf * tbuf1, * tbuf2; + + if (ibuf == 0) return; + if (ibuf->flags & IB_fields) return; + ibuf->flags |= IB_fields; + + if (ibuf->rect) { + /* kopieen aanmaken */ + tbuf1 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, IB_rect, 0); + tbuf2 = IMB_allocImBuf(ibuf->x, (short)(ibuf->y >> 1), (unsigned char)32, IB_rect, 0); + + ibuf->x *= 2; + /* These are brolenm as well... */ + IMB_rectop(tbuf1, ibuf, 0, 0, 0, 0, 32767, 32767, IMB_rectcpy, 0); + IMB_rectop(tbuf2, ibuf, 0, 0, tbuf2->x, 0, 32767, 32767, IMB_rectcpy, 0); + + ibuf->x /= 2; + IMB_rectop(ibuf, tbuf2, 0, 0, 0, 0, 32767, 32767, IMB_rectcpy, 0); + IMB_rectop(ibuf, tbuf1, 0, tbuf2->y, 0, 0, 32767, 32767, IMB_rectcpy, 0); + + IMB_freeImBuf(tbuf1); + IMB_freeImBuf(tbuf2); + } + ibuf->y /= 2; +} + +/* +load_image handles reading the image from disk or from the packedfile. +*/ + +void load_image(Image * ima, int flags, char *relabase, int framenum) +{ + char name[FILE_MAXDIR + FILE_MAXFILE]; + + if (ima->ibuf == NULL) { + + // is there a PackedFile with this image ?; + if (ima->packedfile) { + ima->ibuf = IMB_ibImageFromMemory((int *) ima->packedfile->data, ima->packedfile->size, flags); + } else { + strcpy(name, ima->name); + BLI_convertstringcode(name, relabase, framenum); + + ima->ibuf = IMB_loadiffname(name , flags); + } + // check if the image is a font image... + // printf("Checking for font\n"); + + if (ima->ibuf) { + detectBitmapFont(ima->ibuf); + } + } +} + +void ima_ibuf_is_nul(Tex *tex) +{ + void (*de_interlacefunc)(struct ImBuf *ibuf); + Image *ima; + int a, fra; + char str[FILE_MAXDIR+FILE_MAXFILE], *cp; + + ima= tex->ima; + if(ima==0) return; + + waitcursor(1); + + strcpy(str, ima->name); + BLI_convertstringcode(str, G.sce, G.scene->r.cfra); + + if(tex->imaflag & TEX_STD_FIELD) de_interlacefunc= de_interlace_st; + else de_interlacefunc= de_interlace_ng; + + if(tex->imaflag & TEX_ANIM5) { + + if(ima->anim==0) ima->anim = openanim(str, IB_cmap | IB_rect); + if (ima->anim) { + + ima->lastquality= R.osa; + fra= ima->lastframe-1; + if(fra<0) fra= 0; + ima->ibuf = IMB_anim_absolute(ima->anim, fra); + + /* patch ivm textbutton met naam ima (B_NAMEIMA) */ + if(ima->ibuf) { + strcpy(ima->ibuf->name, ima->name); + if (tex->imaflag & TEX_FIELDS) de_interlacefunc(ima->ibuf); + } + } + else error("Not an anim"); + + } else { + // create a packedfile for this image when autopack is on + // for performance (IMB_loadiffname uses mmap) we don't do this by default + if ((ima->packedfile == NULL) && (G.fileflags & G_AUTOPACK)) { + ima->packedfile = newPackedFile(str); + } + + load_image(ima, IB_rect, G.sce, G.scene->r.cfra); + + if (tex->imaflag & TEX_FIELDS) de_interlacefunc(ima->ibuf); + + ima->lastquality= R.osa; + } + + if(ima->ibuf) { + + /* stringcodes ook in ibuf. ibuf->name wordt als 'undo' gebruikt (buttons.c) */ + strcpy(ima->ibuf->name, ima->name); + + if(ima->ibuf->cmap) { + + if(tex->imaflag & TEX_ANIM5) { + + if(tex->imaflag & TEX_MORKPATCH) { + /**** PATCH OM KLEUR 2 GOED TE KUNNEN ZETTEN MORKRAMIA */ + if(ima->ibuf->maxcol > 4) { + cp= (char *)(ima->ibuf->cmap+2); + cp[0]= 0x80; + } + } + + IMB_applycmap(ima->ibuf); + IMB_convert_rgba_to_abgr(ima->ibuf->x*ima->ibuf->y, ima->ibuf->rect); + + } + + converttopremul(ima->ibuf); + } + + if(R.osa) { + + if(tex->imaflag & TEX_ANTISCALE) { + IMB_clever_double(ima->ibuf); + IMB_antialias(ima->ibuf); + } + else if(tex->imaflag & TEX_ANTIALI) IMB_antialias(ima->ibuf); + } + + if(tex->imaflag & TEX_LASOPPATCH) { + do_laseroptics_patch(ima->ibuf); + } + + } + + if(ima->ibuf==0) ima->ok= 0; + + for(a=0; a<BLI_ARRAY_NELEMS(ima->mipmap); a++) { + if(ima->mipmap[a]) IMB_freeImBuf(ima->mipmap[a]); + ima->mipmap[a]= 0; + } + + if((R.flag & R_RENDERING)==0) waitcursor(0); + +} + + + +/* *********** IMAGEWRAPPING ****************** */ + + +int imagewrap(Tex *tex, float *texvec) +{ + Image *ima; + struct ImBuf *ibuf; + float fx, fy, val1, val2, val3; + int ofs, x, y; + char *rect; + + ima= tex->ima; + + if(ima==0 || ima->ok== 0) { + Tin= Ta= Tr= Tg= Tb= 0.0; + return 0; + } + + if(ima->ibuf==0) ima_ibuf_is_nul(tex); + + if (ima->ok) { + + ibuf = ima->ibuf; + + if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) { + ibuf->rect+= (ibuf->x*ibuf->y); + } + + if(tex->imaflag & TEX_IMAROT) { + fy= texvec[0]; + fx= texvec[1]; + } + else { + fx= texvec[0]; + fy= texvec[1]; + } + + x = (int)(fx*ibuf->x); + y = (int)(fy*ibuf->y); + + if(tex->extend == TEX_CLIPCUBE) { + if(x<0 || y<0 || x>=ibuf->x || y>=ibuf->y || texvec[2]<-1.0 || texvec[2]>1.0) { + Tin= 0; + return 0; + } + } + else if(tex->extend == TEX_CLIP) { + if(x<0 || y<0 || x>=ibuf->x || y>=ibuf->y) { + Tin= 0; + return 0; + } + } + else { + if(tex->extend==TEX_EXTEND) { + if(x>=ibuf->x) x = ibuf->x-1; + else if(x<0) x= 0; + } + else { + x= x % ibuf->x; + if(x<0) x+= ibuf->x; + } + if(tex->extend==TEX_EXTEND) { + if(y>=ibuf->y) y = ibuf->y-1; + else if(y<0) y= 0; + } + else { + y= y % ibuf->y; + if(y<0) y+= ibuf->y; + } + } + + ofs = y * ibuf->x + x; + rect = (char *)( ibuf->rect+ ofs); + + Talpha= 0; + if(tex->imaflag & TEX_USEALPHA) { + if(tex->imaflag & TEX_CALCALPHA); + else Talpha= 1; + } + + Tr = ((float)rect[0])/255.0f; + Tg = ((float)rect[1])/255.0f; + Tb = ((float)rect[2])/255.0f; + + if(tex->nor) { + /* bump: drie samples nemen */ + val1= Tr+Tg+Tb; + + if(x<ibuf->x-1) { + rect+=4; + val2= ((float)(rect[0]+rect[1]+rect[2]))/255.0f; + rect-=4; + } + else val2= val1; + + if(y<ibuf->y-1) { + rect+= 4*ibuf->x; + val3= ((float)(rect[0]+rect[1]+rect[2]))/255.0f; + } + else val3= val1; + + /* niet x en y verwisselen! */ + tex->nor[0]= (val1-val2); + tex->nor[1]= (val1-val3); + } + + BRICONRGB; + + if(Talpha) Ta= Tin= ((float)rect[3])/255.0f; + else if(tex->imaflag & TEX_CALCALPHA) { + Ta= Tin= MAX3(Tr, Tg, Tb); + } + else Ta= Tin= 1.0; + + if(tex->flag & TEX_NEGALPHA) Ta= 1.0f-Ta; + + if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) { + ibuf->rect-= (ibuf->x*ibuf->y); + } + } + + if(tex->flag & TEX_COLORBAND) do_colorband(tex->coba); + + if(tex->nor) return 3; + else return 1; +} + +void clipx_rctf_swap(rctf *stack, short *count, float x1, float x2) +/* rctf *stack; */ +/* short *count; */ +/* float x1, x2; */ +{ + rctf *rf, *newrct; + short a; + + a= *count; + rf= stack; + for(;a>0;a--) { + if(rf->xmin<x1) { + if(rf->xmax<x1) { + rf->xmin+= (x2-x1); + rf->xmax+= (x2-x1); + } + else { + if(rf->xmax>x2) rf->xmax= x2; + newrct= stack+ *count; + (*count)++; + + newrct->xmax= x2; + newrct->xmin= rf->xmin+(x2-x1); + newrct->ymin= rf->ymin; + newrct->ymax= rf->ymax; + + if(newrct->xmin==newrct->xmax) (*count)--; + + rf->xmin= x1; + } + } + else if(rf->xmax>x2) { + if(rf->xmin>x2) { + rf->xmin-= (x2-x1); + rf->xmax-= (x2-x1); + } + else { + if(rf->xmin<x1) rf->xmin= x1; + newrct= stack+ *count; + (*count)++; + + newrct->xmin= x1; + newrct->xmax= rf->xmax-(x2-x1); + newrct->ymin= rf->ymin; + newrct->ymax= rf->ymax; + + if(newrct->xmin==newrct->xmax) (*count)--; + + rf->xmax= x2; + } + } + rf++; + } + +} + +void clipy_rctf_swap(rctf *stack, short *count, float y1, float y2) +/* rctf *stack; */ +/* short *count; */ +/* float y1, y2; */ +{ + rctf *rf, *newrct; + short a; + + a= *count; + rf= stack; + for(;a>0;a--) { + if(rf->ymin<y1) { + if(rf->ymax<y1) { + rf->ymin+= (y2-y1); + rf->ymax+= (y2-y1); + } + else { + if(rf->ymax>y2) rf->ymax= y2; + newrct= stack+ *count; + (*count)++; + + newrct->ymax= y2; + newrct->ymin= rf->ymin+(y2-y1); + newrct->xmin= rf->xmin; + newrct->xmax= rf->xmax; + + if(newrct->ymin==newrct->ymax) (*count)--; + + rf->ymin= y1; + } + } + else if(rf->ymax>y2) { + if(rf->ymin>y2) { + rf->ymin-= (y2-y1); + rf->ymax-= (y2-y1); + } + else { + if(rf->ymin<y1) rf->ymin= y1; + newrct= stack+ *count; + (*count)++; + + newrct->ymin= y1; + newrct->ymax= rf->ymax-(y2-y1); + newrct->xmin= rf->xmin; + newrct->xmax= rf->xmax; + + if(newrct->ymin==newrct->ymax) (*count)--; + + rf->ymax= y2; + } + } + rf++; + } + +} + + + +float square_rctf(rctf *rf) +/* rctf *rf; */ +{ + float x, y; + + x= rf->xmax- rf->xmin; + y= rf->ymax- rf->ymin; + return (x*y); +} + +float clipx_rctf(rctf *rf, float x1, float x2) +/* rctf *rf; */ +/* float x1, x2; */ +{ + float size; + + size= rf->xmax - rf->xmin; + + if(rf->xmin<x1) { + rf->xmin= x1; + } + if(rf->xmax>x2) { + rf->xmax= x2; + } + if(rf->xmin > rf->xmax) { + rf->xmin = rf->xmax; + return 0.0; + } + else if(size!=0.0) { + return (rf->xmax - rf->xmin)/size; + } + return 1.0; +} + +float clipy_rctf(rctf *rf, float y1, float y2) +/* rctf *rf; */ +/* float y1, y2; */ +{ + float size; + + size= rf->ymax - rf->ymin; +/* PRINT(f, size); */ + if(rf->ymin<y1) { + rf->ymin= y1; + } + if(rf->ymax>y2) { + rf->ymax= y2; + } +/* PRINT(f, size); */ + if(rf->ymin > rf->ymax) { + rf->ymin = rf->ymax; + return 0.0; + } + else if(size!=0.0) { + return (rf->ymax - rf->ymin)/size; + } + return 1.0; + +} + +void boxsampleclip(struct ImBuf *ibuf, rctf *rf, float *rcol, + float *gcol, float *bcol, float *acol) /* return kleur 0.0-1.0 */ +/* struct ImBuf *ibuf; */ +/* rctf *rf; */ +/* float *rcol, *gcol, *bcol, *acol; */ +{ + /* sample box, is reeds geclipt en minx enz zijn op ibuf size gezet. + * Vergroot uit met antialiased edges van de pixels */ + + float muly,mulx,div; + int ofs; + int x, y, startx, endx, starty, endy; + char *rect; + + startx= (int)floor(rf->xmin); + endx= (int)floor(rf->xmax); + starty= (int)floor(rf->ymin); + endy= (int)floor(rf->ymax); + + if(startx < 0) startx= 0; + if(starty < 0) starty= 0; + if(endx>=ibuf->x) endx= ibuf->x-1; + if(endy>=ibuf->y) endy= ibuf->y-1; + + if(starty==endy && startx==endx) { + + ofs = starty*ibuf->x + startx; + rect = (char *)(ibuf->rect +ofs); + *rcol= ((float)rect[0])/255.0f; + *gcol= ((float)rect[1])/255.0f; + *bcol= ((float)rect[2])/255.0f; + /* alpha is globaal, reeds gezet in functie imagewraposa() */ + if(Talpha) { + *acol= ((float)rect[3])/255.0f; + } + } + else { + div= *rcol= *gcol= *bcol= *acol= 0.0; + for(y=starty;y<=endy;y++) { + ofs = y*ibuf->x +startx; + rect = (char *)(ibuf->rect+ofs); + + muly= 1.0; + + if(starty==endy); + else { + if(y==starty) muly= 1.0f-(rf->ymin - y); + if(y==endy) muly= (rf->ymax - y); + } + if(startx==endx) { + mulx= muly; + if(Talpha) *acol+= mulx*rect[3]; + *rcol+= mulx*rect[0]; + *gcol+= mulx*rect[1]; + *bcol+= mulx*rect[2]; + div+= mulx; + } + else { + for(x=startx;x<=endx;x++) { + mulx= muly; + if(x==startx) mulx*= 1.0f-(rf->xmin - x); + if(x==endx) mulx*= (rf->xmax - x); + + if(mulx==1.0) { + if(Talpha) *acol+= rect[3]; + *rcol+= rect[0]; + *gcol+= rect[1]; + *bcol+= rect[2]; + div+= 1.0; + } + else { + if(Talpha) *acol+= mulx*rect[3]; + *rcol+= mulx*rect[0]; + *gcol+= mulx*rect[1]; + *bcol+= mulx*rect[2]; + div+= mulx; + } + rect+=4; + } + } + } + if(div!=0.0) { + div*= 255.0; + + *bcol/= div; + *gcol/= div; + *rcol/= div; + + if(Talpha) *acol/= div; + } + else { + *rcol= *gcol= *bcol= *acol= 0.0; + } + } +} + +void boxsample(struct ImBuf *ibuf, + float minx, float miny, float maxx, float maxy, + float *rcol, float *gcol, float *bcol, float *acol) /* return kleur 0.0-1.0 */ +/* struct ImBuf *ibuf; */ +/* float minx, miny, maxx, maxy; */ +/* float *rcol, *gcol, *bcol, *acol; */ +{ + /* Sample box, doet clip. minx enz lopen van 0.0 - 1.0 . + * Vergroot uit met antialiased edges van de pixels. + * Als global imaprepeat is gezet, worden + * de weggeclipte stukken ook gesampled. + */ + rctf *rf, stack[8]; + float opp, tot, r, g, b, a, alphaclip= 1.0; + short count=1; + + rf= stack; + rf->xmin= minx*(ibuf->x); + rf->xmax= maxx*(ibuf->x); + rf->ymin= miny*(ibuf->y); + rf->ymax= maxy*(ibuf->y); + + if(imapextend); + else if(imaprepeat) clipx_rctf_swap(stack, &count, 0.0, (float)(ibuf->x)); + else { + alphaclip= clipx_rctf(rf, 0.0, (float)(ibuf->x)); + + if(alphaclip<=0.0) { + *rcol= *bcol= *gcol= *acol= 0.0; + return; + } + } + + if(imapextend); + else if(imaprepeat) clipy_rctf_swap(stack, &count, 0.0, (float)(ibuf->y)); + else { + alphaclip*= clipy_rctf(rf, 0.0, (float)(ibuf->y)); + + if(alphaclip<=0.0) { + *rcol= *bcol= *gcol= *acol= 0.0; + return; + } + } + + if(count>1) { + tot= *rcol= *bcol= *gcol= *acol= 0.0; + while(count--) { + boxsampleclip(ibuf, rf, &r, &g, &b, &a); + + opp= square_rctf(rf); + tot+= opp; + + *rcol+= opp*r; + *gcol+= opp*g; + *bcol+= opp*b; + if(Talpha) *acol+= opp*a; + rf++; + } + if(tot!= 0.0) { + *rcol/= tot; + *gcol/= tot; + *bcol/= tot; + if(Talpha) *acol/= tot; + } + } + else { + boxsampleclip(ibuf, rf, rcol, gcol, bcol, acol); + } + + if(Talpha==0) *acol= 1.0; + + if(alphaclip!=1.0) { + /* this is for laer investigation, premul or not? */ + /* *rcol*= alphaclip; */ + /* *gcol*= alphaclip; */ + /* *bcol*= alphaclip; */ + *acol*= alphaclip; + } +} + +void filtersample(struct ImBuf *ibuf, + float fx, float fy, + float *rcol, float *gcol, float *bcol, float *acol) + /* return kleur 0.0-1.0 */ +/* struct ImBuf *ibuf; */ /* fx en fy tussen 0.0 en 1.0 */ +/* float fx, fy; */ +/* float *rcol, *gcol, *bcol, *acol; */ +{ + /* met weighted filter 3x3 + * de linker of rechter kolom is altijd 0 + * en de bovenste of onderste rij is altijd 0 + */ + + int fac, fac1, fac2, fracx, fracy, filt[4]; + int ix, iy, x4; + unsigned int r=0, g=0, b=0, a=0; + char *rowcol, *rfilt[4]; + + ix= (int)( 256.0*fx ); + fracx= (ix & 255); + ix= (ix>>8); + iy= (int)( 256.0*fy ); + fracy= (iy & 255); + iy= (iy>>8); + + if(ix>=ibuf->x) ix= ibuf->x-1; + if(iy>=ibuf->y) iy= ibuf->y-1; + + rowcol= (char *)(ibuf->rect+ iy*ibuf->x +ix); + + rfilt[0]= rfilt[1]= rfilt[2]= rfilt[3]= rowcol; + x4= 4*ibuf->x; + + if(fracx<128) { + if(ix>0) { + rfilt[0]-= 4; + rfilt[2]-=4; + } + else if(imaprepeat) { + rfilt[0]+= x4-4; + rfilt[2]+= x4-4; + } + + if(fracy<128) { + /* geval linksonder */ + fac1= 128+fracy; + fac2= 128-fracy; + + if(iy>0) { + rfilt[3]-= x4; + rfilt[2]-= x4; + } + else if(imaprepeat) { + fac= x4*(ibuf->y-1) ; + rfilt[3]+= fac; + rfilt[2]+= fac; + } + } + else { + /* geval linksboven */ + fac2= 384-fracy; + fac1= fracy-128; + + if(iy<ibuf->y-1) { + rfilt[1]+= x4; + rfilt[0]+= x4; + } + else if(imaprepeat) { + fac= x4*(ibuf->y-1) ; + rfilt[1]-= fac; + rfilt[0]-= fac; + } + } + + filt[1]=filt[3]= 128+ fracx; + filt[0]=filt[2]= 128- fracx; + filt[0]*= fac1; + filt[1]*= fac1; + filt[2]*= fac2; + filt[3]*= fac2; + } + else { + if(fracy<128) { + /* geval rechtsonder */ + fac1= 128+fracy; + fac2= 128-fracy; + + if(iy>0) { + rfilt[3]-= x4; + rfilt[2]-= x4; + } + else if(imaprepeat) { + fac= x4*(ibuf->y-1) ; + rfilt[3]+= fac; + rfilt[2]+= fac; + } + } + else { + /* geval rechtsboven */ + fac2= 384-fracy; + fac1= fracy-128; + + if(iy<ibuf->y-1) { + rfilt[1]+= x4; + rfilt[0]+= x4; + } + else if(imaprepeat) { + fac= x4*(ibuf->y-1) ; + rfilt[1]-= fac; + rfilt[0]-= fac; + } + } + filt[0]=filt[2]= 384-fracx; + filt[1]=filt[3]= fracx-128; + filt[0]*= fac1; + filt[1]*= fac1; + filt[2]*= fac2; + filt[3]*= fac2; + + if(ix<ibuf->x-1) { + rfilt[1]+= 4; + rfilt[3]+=4; + } + else if(imaprepeat) { + rfilt[1]-= x4-4; + rfilt[3]-= x4-4; + } + } + + for(fac=3; fac>=0; fac--) { + rowcol= rfilt[fac]; + r+= filt[fac]*rowcol[0]; + g+= filt[fac]*rowcol[1]; + b+= filt[fac]*rowcol[2]; + if(Talpha) a+= filt[fac]*rowcol[3]; /* alpha is globaal */ + } + *rcol= ((float)r)/16777216.0f; + *gcol= ((float)g)/16777216.0f; + *bcol= ((float)b)/16777216.0f; + if(Talpha) *acol= ((float)a)/16777216.0f; + +} + + +int imagewraposa(Tex *tex, float *texvec, float *dxt, float *dyt) +{ + struct Image *ima; + struct ImBuf *ibuf, *previbuf; + float fx, fy, minx, maxx, miny, maxy, dx, dy, fac1, fac2, fac3, fac4; + float maxd, pixsize, val1, val2, val3; + int curmap; + +#ifdef IMAGE_C_ARG_CHECK + if (!tex) { + printf("imagewraposa: null pointer to texture\n"); + } +#endif + + ima= tex->ima; +#ifdef IMAGE_C_ARG_CHECK + if (!ima) { + printf("imagewraposa: null pointer to image\n"); + } +#endif + + Tin= Ta= Tr= Tg= Tb= 0.0; + + if(ima==0 || ima->ok== 0) { + return 0; + } + + if(ima->ibuf==0) ima_ibuf_is_nul(tex); + + if (ima->ok) { + + if(tex->imaflag & TEX_MIPMAP) { + if(ima->mipmap[0]==0) makemipmap(ima); + } + + ibuf = ima->ibuf; + + if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) { + ibuf->rect+= (ibuf->x*ibuf->y); + } + + Talpha= 0; + if(tex->imaflag & TEX_USEALPHA) { + if(tex->imaflag & TEX_CALCALPHA); + else Talpha= 1; + } + + if(tex->imaflag & TEX_IMAROT) { + fy= texvec[0]; + fx= texvec[1]; + } + else { + fx= texvec[0]; + fy= texvec[1]; + } + + + if(ibuf->flags & IB_fields) { + if(R.r.mode & R_FIELDS) { /* field render */ + if(R.flag & R_SEC_FIELD) { /* correctie voor tweede field */ + /* fac1= 0.5/( (float)ibuf->y ); */ + /* fy-= fac1; */ + } + else { /* eerste field */ + fac1= 0.5f/( (float)ibuf->y ); + fy+= fac1; + } + } + } + + /* pixel coordinaten */ + + minx= MIN3(dxt[0],dyt[0],dxt[0]+dyt[0] ); + maxx= MAX3(dxt[0],dyt[0],dxt[0]+dyt[0] ); + miny= MIN3(dxt[1],dyt[1],dxt[1]+dyt[1] ); + maxy= MAX3(dxt[1],dyt[1],dxt[1]+dyt[1] ); + + /* tex_sharper afgeschaft */ + + minx= tex->filtersize*(maxx-minx)/2.0f; + miny= tex->filtersize*(maxy-miny)/2.0f; + + if(tex->imaflag & TEX_IMAROT) SWAP(float, minx, miny); + + if(minx>0.25) minx= 0.25; + else if(minx<0.00001f) minx= 0.00001f; /* zijvlakken van eenheidskubus */ + if(miny>0.25) miny= 0.25; + else if(miny<0.00001f) miny= 0.00001f; + + + /* repeat en clip */ + + /* let op: imaprepeat is globale waarde (zie boxsample) */ + imaprepeat= (tex->extend==TEX_REPEAT); + imapextend= (tex->extend==TEX_EXTEND); + + + if(tex->extend == TEX_CLIPCUBE) { + if(fx+minx<0.0 || fy+miny<0.0 || fx-minx>1.0 || fy-miny>1.0 || texvec[2]<-1.0 || texvec[2]>1.0) { + Tin= 0; + return 0; + } + } + else if(tex->extend == TEX_CLIP) { + if(fx+minx<0.0 || fy+miny<0.0 || fx-minx>1.0 || fy-miny>1.0) { + Tin= 0.0; + return 0; + } + } + else { + if(tex->extend==TEX_EXTEND) { + if(fx>1.0) fx = 1.0; + else if(fx<0.0) fx= 0.0; + } + else { + if(fx>1.0) fx -= (int)(fx); + else if(fx<0.0) fx+= 1-(int)(fx); + } + + if(tex->extend==TEX_EXTEND) { + if(fy>1.0) fy = 1.0; + else if(fy<0.0) fy= 0.0; + } + else { + if(fy>1.0) fy -= (int)(fy); + else if(fy<0.0) fy+= 1-(int)(fy); + } + } + + /* keuze: */ + if(tex->imaflag & TEX_MIPMAP) { + + dx= minx; + dy= miny; + maxd= MAX2(dx, dy); + if(maxd>0.5) maxd= 0.5; + + pixsize = 1.0f/ (float) MIN2(ibuf->x, ibuf->y); + + curmap= 0; + previbuf= ibuf; + while(curmap<BLI_ARRAY_NELEMS(ima->mipmap) && ima->mipmap[curmap]) { + if(maxd < pixsize) break; + previbuf= ibuf; + ibuf= ima->mipmap[curmap]; + pixsize= 1.0f / (float)MIN2(ibuf->x, ibuf->y); /* hier stond 1.0 */ + curmap++; + } + + if(previbuf!=ibuf || (tex->imaflag & TEX_INTERPOL)) { + /* minmaal 1 pixel sampelen */ + if (minx < 0.5f / ima->ibuf->x) minx = 0.5f / ima->ibuf->x; + if (miny < 0.5f / ima->ibuf->y) miny = 0.5f / ima->ibuf->y; + } + + if(tex->nor) { + /* beetje extra filter */ + minx*= 1.35f; + miny*= 1.35f; + + boxsample(ibuf, fx-2.0f*minx, fy-2.0f*miny, fx+minx, fy+miny, &Tr, &Tg, &Tb, &Ta); + val1= Tr+Tg+Tb; + boxsample(ibuf, fx-minx, fy-2.0f*miny, fx+2.0f*minx, fy+miny, &fac1, &fac2, &fac3, &fac4); + val2= fac1+fac2+fac3; + boxsample(ibuf, fx-2.0f*minx, fy-miny, fx+minx, fy+2.0f*miny, &fac1, &fac2, &fac3, &fac4); + val3= fac1+fac2+fac3; + + if(previbuf!=ibuf) { /* interpoleren */ + + boxsample(previbuf, fx-2.0f*minx, fy-2.0f*miny, fx+minx, fy+miny, &fac1, &fac2, &fac3, &fac4); + + /* rgb berekenen */ + dx= 2.0f*(pixsize-maxd)/pixsize; + if(dx>=1.0f) { + Ta= fac4; Tb= fac3; + Tg= fac2; Tr= fac1; + } + else { + dy= 1.0f-dx; + Tb= dy*Tb+ dx*fac3; + Tg= dy*Tg+ dx*fac2; + Tr= dy*Tr+ dx*fac1; + if(Talpha) Ta= dy*Ta+ dx*fac4; + } + + val1= dy*val1+ dx*(fac1+fac2+fac3); + boxsample(previbuf, fx-minx, fy-2.0f*miny, fx+2.0f*minx, fy+miny, &fac1, &fac2, &fac3, &fac4); + val2= dy*val2+ dx*(fac1+fac2+fac3); + boxsample(previbuf, fx-2.0f*minx, fy-miny, fx+minx, fy+2.0f*miny, &fac1, &fac2, &fac3, &fac4); + val3= dy*val3+ dx*(fac1+fac2+fac3); + } + + /* niet x en y verwisselen! */ + tex->nor[0]= (val1-val2); + tex->nor[1]= (val1-val3); + + } + else { + maxx= fx+minx; + minx= fx-minx; + maxy= fy+miny; + miny= fy-miny; + + boxsample(ibuf, minx, miny, maxx, maxy, &Tr, &Tg, &Tb, &Ta); + + if(previbuf!=ibuf) { /* interpoleren */ + boxsample(previbuf, minx, miny, maxx, maxy, &fac1, &fac2, &fac3, &fac4); + + fx= 2.0f*(pixsize-maxd)/pixsize; + + if(fx>=1.0) { + Ta= fac4; Tb= fac3; + Tg= fac2; Tr= fac1; + } else { + fy= 1.0f-fx; + Tb= fy*Tb+ fx*fac3; + Tg= fy*Tg+ fx*fac2; + Tr= fy*Tr+ fx*fac1; + if(Talpha) Ta= fy*Ta+ fx*fac4; + } + } + } + } + else { + if((tex->imaflag & TEX_INTERPOL)) { + /* minmaal 1 pixel sampelen */ + if (minx < 0.5f / ima->ibuf->x) minx = 0.5f / ima->ibuf->x; + if (miny < 0.5f / ima->ibuf->y) miny = 0.5f / ima->ibuf->y; + } + + if(tex->nor) { + + /* beetje extra filter */ + minx*= 1.35f; + miny*= 1.35f; + + boxsample(ibuf, fx-2.0f*minx, fy-2.0f*miny, fx+minx, fy+miny, &Tr, &Tg, &Tb, &Ta); + val1= Tr+Tg+Tb; + + boxsample(ibuf, fx-minx, fy-2.0f*miny, fx+2.0f*minx, fy+miny, &fac1, &fac2, &fac3, &fac4); + val2= fac1+fac2+fac3; + + boxsample(ibuf, fx-2.0f*minx, fy-miny, fx+miny, fy+2.0f*miny, &fac1, &fac2, &fac3, &fac4); + val3= fac1+fac2+fac3; + + /* niet x en y verwisselen! */ + tex->nor[0]= (val1-val2); + tex->nor[1]= (val1-val3); + + } + else { + boxsample(ibuf, fx-minx, fy-miny, fx+minx, fy+miny, &Tr, &Tg, &Tb, &Ta); + } + + } + + BRICONRGB; + + if(tex->imaflag & TEX_CALCALPHA) { + Ta= Tin= MAX3(Tr, Tg, Tb); + } + else Tin= Ta; + if(tex->flag & TEX_NEGALPHA) Ta= 1.0f-Ta; + + if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) { + ibuf->rect-= (ibuf->x*ibuf->y); + } + + } + else { + Tin= 0.0f; + return 0; + } + + if(tex->flag & TEX_COLORBAND) do_colorband(tex->coba); + + if(tex->nor) return 3; + else return 1; +} + diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c new file mode 100644 index 00000000000..cab1efba716 --- /dev/null +++ b/source/blender/blenkernel/intern/ipo.c @@ -0,0 +1,1878 @@ +/* ipo.c MIXED MODEL + * + * jan 95 + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <math.h> +#include <stdio.h> +#include <string.h> +#ifdef WIN32 +#include "BLI_winstuff.h" +#endif +#include "MEM_guardedalloc.h" + +#include "DNA_ika_types.h" +#include "DNA_sequence_types.h" +#include "DNA_camera_types.h" +#include "DNA_sound_types.h" +#include "DNA_lamp_types.h" +#include "DNA_view3d_types.h" +#include "DNA_key_types.h" +#include "DNA_scene_types.h" +#include "DNA_texture_types.h" +#include "DNA_material_types.h" +#include "DNA_object_types.h" +#include "DNA_curve_types.h" +#include "DNA_ipo_types.h" +#include "DNA_action_types.h" +#include "BLI_blenlib.h" +#include "BLI_arithb.h" + +#include "BKE_bad_level_calls.h" +#include "BKE_utildefines.h" + +#include "BKE_main.h" +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_curve.h" +#include "BKE_object.h" +#include "BKE_blender.h" +#include "BKE_ipo.h" +#include "BKE_constraint.h" + +#define SMALL -1.0e-10 + +/* Dit array is ervoor zodat defines zoals OB_LOC_X niet persee 0 hoeft te zijn. + Ook voor toekomstige backward compatibility. + Zo kan met een for-next lus alles worden afgelopen */ + +int co_ar[CO_TOTIPO]= { + CO_ENFORCE +}; + +int ob_ar[OB_TOTIPO]= { + OB_LOC_X, OB_LOC_Y, OB_LOC_Z, OB_DLOC_X, OB_DLOC_Y, OB_DLOC_Z, + OB_ROT_X, OB_ROT_Y, OB_ROT_Z, OB_DROT_X, OB_DROT_Y, OB_DROT_Z, + OB_SIZE_X, OB_SIZE_Y, OB_SIZE_Z, OB_DSIZE_X, OB_DSIZE_Y, OB_DSIZE_Z, + OB_LAY, OB_TIME, OB_EFF_X, OB_EFF_Y, OB_EFF_Z, OB_COL_A +}; + +int ac_ar[AC_TOTIPO]= { + AC_LOC_X, AC_LOC_Y, AC_LOC_Z, + AC_QUAT_W, AC_QUAT_X, AC_QUAT_Y, AC_QUAT_Z, + AC_SIZE_X, AC_SIZE_Y, AC_SIZE_Z +}; + +int ma_ar[MA_TOTIPO]= { + MA_COL_R, MA_COL_G, MA_COL_B, + MA_SPEC_R, MA_SPEC_G, MA_SPEC_B, + MA_MIR_R, MA_MIR_G, MA_MIR_B, + MA_REF, MA_ALPHA, MA_EMIT, MA_AMB, + MA_SPEC, MA_HARD, MA_SPTR, MA_ANG, + MA_MODE, MA_HASIZE, + + MA_MAP1+MAP_OFS_X, MA_MAP1+MAP_OFS_Y, MA_MAP1+MAP_OFS_Z, + MA_MAP1+MAP_SIZE_X, MA_MAP1+MAP_SIZE_Y, MA_MAP1+MAP_SIZE_Z, + MA_MAP1+MAP_R, MA_MAP1+MAP_G, MA_MAP1+MAP_B, + MA_MAP1+MAP_DVAR, MA_MAP1+MAP_COLF, MA_MAP1+MAP_NORF, MA_MAP1+MAP_VARF +}; + +int seq_ar[SEQ_TOTIPO]= { + SEQ_FAC1 +}; + +int cu_ar[CU_TOTIPO]= { + CU_SPEED +}; + +int key_ar[KEY_TOTIPO]= { + KEY_SPEED, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 +}; + +int wo_ar[WO_TOTIPO]= { + WO_HOR_R, WO_HOR_G, WO_HOR_B, WO_ZEN_R, WO_ZEN_G, WO_ZEN_B, + WO_EXPOS, WO_MISI, WO_MISTDI, WO_MISTSTA, WO_MISTHI, + WO_STAR_R, WO_STAR_G, WO_STAR_B, WO_STARDIST, WO_STARSIZE, + + MA_MAP1+MAP_OFS_X, MA_MAP1+MAP_OFS_Y, MA_MAP1+MAP_OFS_Z, + MA_MAP1+MAP_SIZE_X, MA_MAP1+MAP_SIZE_Y, MA_MAP1+MAP_SIZE_Z, + MA_MAP1+MAP_R, MA_MAP1+MAP_G, MA_MAP1+MAP_B, + MA_MAP1+MAP_DVAR, MA_MAP1+MAP_COLF, MA_MAP1+MAP_NORF, MA_MAP1+MAP_VARF +}; + +int la_ar[LA_TOTIPO]= { + LA_ENERGY, LA_COL_R, LA_COL_G, LA_COL_B, + LA_DIST, LA_SPOTSI, LA_SPOTBL, + LA_QUAD1, LA_QUAD2, LA_HALOINT, + + MA_MAP1+MAP_OFS_X, MA_MAP1+MAP_OFS_Y, MA_MAP1+MAP_OFS_Z, + MA_MAP1+MAP_SIZE_X, MA_MAP1+MAP_SIZE_Y, MA_MAP1+MAP_SIZE_Z, + MA_MAP1+MAP_R, MA_MAP1+MAP_G, MA_MAP1+MAP_B, + MA_MAP1+MAP_DVAR, MA_MAP1+MAP_COLF, MA_MAP1+MAP_NORF, MA_MAP1+MAP_VARF +}; + +int cam_ar[CAM_TOTIPO]= { + CAM_LENS, CAM_STA, CAM_END +}; + +int snd_ar[SND_TOTIPO]= { + SND_VOLUME, SND_PITCH, SND_PANNING, SND_ATTEN +}; + + + +float frame_to_float(int cfra) /* zie ook bsystem_time in object.c */ +{ + extern float bluroffs; /* object.c */ + float ctime; + + ctime= (float)cfra; + if(R.flag & R_SEC_FIELD) { + if((R.r.mode & R_FIELDSTILL)==0) ctime+= 0.5; + } + ctime+= bluroffs; + ctime*= G.scene->r.framelen; + + return ctime; +} + +/* niet ipo zelf vrijgeven */ +void free_ipo(Ipo *ipo) +{ + IpoCurve *icu; + + icu= ipo->curve.first; + while(icu) { + if(icu->bezt) MEM_freeN(icu->bezt); + icu= icu->next; + } + BLI_freelistN(&ipo->curve); +} + +Ipo *add_ipo(char *name, int idcode) +{ + Ipo *ipo; + + ipo= alloc_libblock(&G.main->ipo, ID_IP, name); + ipo->blocktype= idcode; + + return ipo; +} + +Ipo *copy_ipo(Ipo *ipo) +{ + Ipo *ipon; + IpoCurve *icu; + + if(ipo==0) return 0; + + ipon= copy_libblock(ipo); + + duplicatelist(&(ipon->curve), &(ipo->curve)); + + icu= ipon->curve.first; + while(icu) { + icu->bezt= MEM_dupallocN(icu->bezt); + icu= icu->next; + } + + return ipon; +} + +void make_local_obipo(Ipo *ipo) +{ + Object *ob; + Ipo *ipon; + int local=0, lib=0; + + /* - zijn er alleen lib users: niet doen + * - zijn er alleen locale users: flag zetten + * - mixed: copy + */ + + ob= G.main->object.first; + while(ob) { + if(ob->ipo==ipo) { + if(ob->id.lib) lib= 1; + else local= 1; + } + ob= ob->id.next; + } + + if(local && lib==0) { + ipo->id.lib= 0; + ipo->id.flag= LIB_LOCAL; + new_id(0, (ID *)ipo, 0); + } + else if(local && lib) { + ipon= copy_ipo(ipo); + ipon->id.us= 0; + + ob= G.main->object.first; + while(ob) { + if(ob->ipo==ipo) { + + if(ob->id.lib==0) { + ob->ipo= ipon; + ipon->id.us++; + ipo->id.us--; + } + } + ob= ob->id.next; + } + } +} + +void make_local_matipo(Ipo *ipo) +{ + Material *ma; + Ipo *ipon; + int local=0, lib=0; + + /* - zijn er alleen lib users: niet doen + * - zijn er alleen locale users: flag zetten + * - mixed: copy + */ + + ma= G.main->mat.first; + while(ma) { + if(ma->ipo==ipo) { + if(ma->id.lib) lib= 1; + else local= 1; + } + ma= ma->id.next; + } + + if(local && lib==0) { + ipo->id.lib= 0; + ipo->id.flag= LIB_LOCAL; + new_id(0, (ID *)ipo, 0); + } + else if(local && lib) { + ipon= copy_ipo(ipo); + ipon->id.us= 0; + + ma= G.main->mat.first; + while(ma) { + if(ma->ipo==ipo) { + + if(ma->id.lib==0) { + ma->ipo= ipon; + ipon->id.us++; + ipo->id.us--; + } + } + ma= ma->id.next; + } + } +} + +void make_local_keyipo(Ipo *ipo) +{ + Key *key; + Ipo *ipon; + int local=0, lib=0; + + /* - zijn er alleen lib users: niet doen + * - zijn er alleen locale users: flag zetten + * - mixed: copy + */ + + key= G.main->key.first; + while(key) { + if(key->ipo==ipo) { + if(key->id.lib) lib= 1; + else local= 1; + } + key= key->id.next; + } + + if(local && lib==0) { + ipo->id.lib= 0; + ipo->id.flag= LIB_LOCAL; + new_id(0, (ID *)ipo, 0); + } + else if(local && lib) { + ipon= copy_ipo(ipo); + ipon->id.us= 0; + + key= G.main->key.first; + while(key) { + if(key->ipo==ipo) { + + if(key->id.lib==0) { + key->ipo= ipon; + ipon->id.us++; + ipo->id.us--; + } + } + key= key->id.next; + } + } +} + + +void make_local_ipo(Ipo *ipo) +{ + + if(ipo->id.lib==0) return; + if(ipo->id.us==1) { + ipo->id.lib= 0; + ipo->id.flag= LIB_LOCAL; + new_id(0, (ID *)ipo, 0); + return; + } + + if(ipo->blocktype==ID_OB) make_local_obipo(ipo); + else if(ipo->blocktype==ID_MA) make_local_matipo(ipo); + else if(ipo->blocktype==ID_KE) make_local_keyipo(ipo); + +} + + +void calchandles_ipocurve(IpoCurve *icu) +{ + BezTriple *bezt, *prev, *next; + int a; + + a= icu->totvert; + if(a<2) return; + + bezt= icu->bezt; + prev= 0; + next= bezt+1; + + while(a--) { + + if(bezt->vec[0][0]>bezt->vec[1][0]) bezt->vec[0][0]= bezt->vec[1][0]; + if(bezt->vec[2][0]<bezt->vec[1][0]) bezt->vec[2][0]= bezt->vec[1][0]; + + calchandleNurb(bezt, prev, next, 1); /* 1==speciale autohandle */ + + prev= bezt; + if(a==1) { + next= 0; + } + else next++; + + /* voor automatische ease in en out */ + if(bezt->h1==HD_AUTO && bezt->h2==HD_AUTO) { + if(a==0 || a==icu->totvert-1) { + if(icu->extrap==IPO_HORIZ) { + bezt->vec[0][1]= bezt->vec[2][1]= bezt->vec[1][1]; + } + } + } + + bezt++; + } +} + +void testhandles_ipocurve(IpoCurve *icu) +{ + /* Te gebruiken als er iets aan de handles is veranderd. + * Loopt alle BezTriples af met de volgende regels: + * FASE 1: types veranderen? + * Autocalchandles: worden ligned als NOT(000 || 111) + * Vectorhandles worden 'niets' als (selected en andere niet) + * FASE 2: handles herberekenen + */ + BezTriple *bezt; + int flag, a; + + bezt= icu->bezt; + if(bezt==0) return; + + a= icu->totvert; + while(a--) { + flag= 0; + if(bezt->f1 & 1) flag++; + if(bezt->f2 & 1) flag += 2; + if(bezt->f3 & 1) flag += 4; + + if( !(flag==0 || flag==7) ) { + if(bezt->h1==HD_AUTO) { /* auto */ + bezt->h1= HD_ALIGN; + } + if(bezt->h2==HD_AUTO) { /* auto */ + bezt->h2= HD_ALIGN; + } + + if(bezt->h1==HD_VECT) { /* vector */ + if(flag < 4) bezt->h1= 0; + } + if(bezt->h2==HD_VECT) { /* vector */ + if( flag > 3) bezt->h2= 0; + } + } + bezt++; + } + + calchandles_ipocurve(icu); +} + + +void sort_time_ipocurve(IpoCurve *icu) +{ + BezTriple *bezt; + int a, ok= 1; + + while(ok) { + ok= 0; + + if(icu->bezt) { + bezt= icu->bezt; + a= icu->totvert; + while(a--) { + if(a>0) { + if( bezt->vec[1][0] > (bezt+1)->vec[1][0]) { + SWAP(BezTriple, *bezt, *(bezt+1)); + ok= 1; + } + } + if(bezt->vec[0][0]>=bezt->vec[1][0] && bezt->vec[2][0]<=bezt->vec[1][0]) { + SWAP(float, bezt->vec[0][0], bezt->vec[2][0]); + SWAP(float, bezt->vec[0][1], bezt->vec[2][1]); + } + else { + if(bezt->vec[0][0]>bezt->vec[1][0]) bezt->vec[0][0]= bezt->vec[1][0]; + if(bezt->vec[2][0]<bezt->vec[1][0]) bezt->vec[2][0]= bezt->vec[1][0]; + } + bezt++; + } + } + else { + + } + } +} + +int test_time_ipocurve(IpoCurve *icu) +{ + BezTriple *bezt; + int a; + + if(icu->bezt) { + bezt= icu->bezt; + a= icu->totvert-1; + while(a--) { + if( bezt->vec[1][0] > (bezt+1)->vec[1][0]) { + return 1; + } + bezt++; + } + } + else { + + } + + return 0; +} + +void correct_bezpart(float *v1, float *v2, float *v3, float *v4) +{ + /* de totale lengte van de handles mag niet langer zijn + * dan de horizontale afstand tussen de punten (v1-v4) + */ + float h1[2], h2[2], len1, len2, len, fac; + + h1[0]= v1[0]-v2[0]; + h1[1]= v1[1]-v2[1]; + h2[0]= v4[0]-v3[0]; + h2[1]= v4[1]-v3[1]; + + len= v4[0]- v1[0]; + len1= (float)fabs(h1[0]); + len2= (float)fabs(h2[0]); + + if(len1+len2==0.0) return; + if(len1+len2 > len) { + fac= len/(len1+len2); + + v2[0]= (v1[0]-fac*h1[0]); + v2[1]= (v1[1]-fac*h1[1]); + + v3[0]= (v4[0]-fac*h2[0]); + v3[1]= (v4[1]-fac*h2[1]); + + } +} + +/* *********************** ARITH *********************** */ + +int findzero(float x, float q0, float q1, float q2, float q3, float *o) +{ + double c0, c1, c2, c3, a, b, c, p, q, d, t, phi; + int nr= 0; + + c0= q0-x; + c1= 3*(q1-q0); + c2= 3*(q0-2*q1+q2); + c3= q3-q0+3*(q1-q2); + + if(c3!=0.0) { + a= c2/c3; + b= c1/c3; + c= c0/c3; + a= a/3; + + p= b/3-a*a; + q= (2*a*a*a-a*b+c)/2; + d= q*q+p*p*p; + + if(d>0.0) { + t= sqrt(d); + o[0]= (float)(Sqrt3d(-q+t)+Sqrt3d(-q-t)-a); + if(o[0]>= SMALL && o[0]<=1.000001) return 1; + else return 0; + } + else if(d==0.0) { + t= Sqrt3d(-q); + o[0]= (float)(2*t-a); + if(o[0]>=SMALL && o[0]<=1.000001) nr++; + o[nr]= (float)(-t-a); + if(o[nr]>=SMALL && o[nr]<=1.000001) return nr+1; + else return nr; + } + else { + phi= acos(-q/sqrt(-(p*p*p))); + t= sqrt(-p); + p= cos(phi/3); + q= sqrt(3-3*p*p); + o[0]= (float)(2*t*p-a); + if(o[0]>=SMALL && o[0]<=1.000001) nr++; + o[nr]= (float)(-t*(p+q)-a); + if(o[nr]>=SMALL && o[nr]<=1.000001) nr++; + o[nr]= (float)(-t*(p-q)-a); + if(o[nr]>=SMALL && o[nr]<=1.000001) return nr+1; + else return nr; + } + } + else { + a=c2; + b=c1; + c=c0; + + if(a!=0.0) { + p=b*b-4*a*c; + if(p>0) { + p= sqrt(p); + o[0]= (float)((-b-p)/(2*a)); + if(o[0]>=SMALL && o[0]<=1.000001) nr++; + o[nr]= (float)((-b+p)/(2*a)); + if(o[nr]>=SMALL && o[nr]<=1.000001) return nr+1; + else return nr; + } + else if(p==0) { + o[0]= (float)(-b/(2*a)); + if(o[0]>=SMALL && o[0]<=1.000001) return 1; + else return 0; + } + } + else if(b!=0.0) { + o[0]= (float)(-c/b); + if(o[0]>=SMALL && o[0]<=1.000001) return 1; + else return 0; + } + else if(c==0.0) { + o[0]= 0.0; + return 1; + } + return 0; + } +} + +void berekeny(float f1, float f2, float f3, float f4, float *o, int b) +{ + float t, c0, c1, c2, c3; + int a; + + c0= f1; + c1= 3.0f*(f2 - f1); + c2= 3.0f*(f1 - 2.0f*f2 + f3); + c3= f4 - f1 + 3.0f*(f2-f3); + + for(a=0; a<b; a++) { + t= o[a]; + o[a]= c0+t*c1+t*t*c2+t*t*t*c3; + } +} +void berekenx(float *f, float *o, int b) +{ + float t, c0, c1, c2, c3; + int a; + + c0= f[0]; + c1= 3*(f[3]-f[0]); + c2= 3*(f[0]-2*f[3]+f[6]); + c3= f[9]-f[0]+3*(f[3]-f[6]); + for(a=0; a<b; a++) { + t= o[a]; + o[a]= c0+t*c1+t*t*c2+t*t*t*c3; + } +} + +float eval_icu(IpoCurve *icu, float ipotime) +{ + BezTriple *bezt, *prevbezt; + float v1[2], v2[2], v3[2], v4[2], opl[32], dx, fac; + float cycdx, cycdy, ofs, cycyofs, cvalue = 0.0; + int a, b; + + cycyofs= 0.0; + + if(icu->bezt) { + prevbezt= icu->bezt; + bezt= prevbezt+1; + a= icu->totvert-1; + + /* cyclic? */ + if(icu->extrap & IPO_CYCL) { + ofs= icu->bezt->vec[1][0]; + cycdx= (icu->bezt+icu->totvert-1)->vec[1][0] - ofs; + cycdy= (icu->bezt+icu->totvert-1)->vec[1][1] - icu->bezt->vec[1][1]; + if(cycdx!=0.0) { + + if(icu->extrap & IPO_DIR) { + cycyofs= (float)floor((ipotime-ofs)/cycdx); + cycyofs*= cycdy; + } + + ipotime= (float)(fmod(ipotime-ofs, cycdx)+ofs); + if(ipotime<ofs) ipotime+= cycdx; + } + } + + /* uiteinden? */ + + if(prevbezt->vec[1][0]>=ipotime) { + if( (icu->extrap & IPO_DIR) && icu->ipo!=IPO_CONST) { + dx= prevbezt->vec[1][0]-ipotime; + fac= prevbezt->vec[1][0]-prevbezt->vec[0][0]; + if(fac!=0.0) { + fac= (prevbezt->vec[1][1]-prevbezt->vec[0][1])/fac; + cvalue= prevbezt->vec[1][1]-fac*dx; + } + else cvalue= prevbezt->vec[1][1]; + } + else cvalue= prevbezt->vec[1][1]; + + cvalue+= cycyofs; + } + else if( (prevbezt+a)->vec[1][0]<=ipotime) { + if( (icu->extrap & IPO_DIR) && icu->ipo!=IPO_CONST) { + prevbezt+= a; + dx= ipotime-prevbezt->vec[1][0]; + fac= prevbezt->vec[2][0]-prevbezt->vec[1][0]; + + if(fac!=0) { + fac= (prevbezt->vec[2][1]-prevbezt->vec[1][1])/fac; + cvalue= prevbezt->vec[1][1]+fac*dx; + } + else cvalue= prevbezt->vec[1][1]; + } + else cvalue= (prevbezt+a)->vec[1][1]; + + cvalue+= cycyofs; + } + else { + while(a--) { + if(prevbezt->vec[1][0]<=ipotime && bezt->vec[1][0]>=ipotime) { + if(icu->ipo==IPO_CONST) { + cvalue= prevbezt->vec[1][1]+cycyofs; + } + else if(icu->ipo==IPO_LIN) { + fac= bezt->vec[1][0]-prevbezt->vec[1][0]; + if(fac==0) cvalue= cycyofs+prevbezt->vec[1][1]; + else { + fac= (ipotime-prevbezt->vec[1][0])/fac; + cvalue= cycyofs+prevbezt->vec[1][1]+ fac*(bezt->vec[1][1]-prevbezt->vec[1][1]); + } + } + else { + v1[0]= prevbezt->vec[1][0]; + v1[1]= prevbezt->vec[1][1]; + v2[0]= prevbezt->vec[2][0]; + v2[1]= prevbezt->vec[2][1]; + + v3[0]= bezt->vec[0][0]; + v3[1]= bezt->vec[0][1]; + v4[0]= bezt->vec[1][0]; + v4[1]= bezt->vec[1][1]; + + correct_bezpart(v1, v2, v3, v4); + + b= findzero(ipotime, v1[0], v2[0], v3[0], v4[0], opl); + if(b) { + berekeny(v1[1], v2[1], v3[1], v4[1], opl, 1); + cvalue= opl[0]+cycyofs; + break; + } + } + } + prevbezt= bezt; + bezt++; + } + } + } + + if(icu->ymin < icu->ymax) { + if(cvalue < icu->ymin) cvalue= icu->ymin; + else if(cvalue > icu->ymax) cvalue= icu->ymax; + } + + return cvalue; +} + +void calc_icu(IpoCurve *icu, float ctime) +{ + icu->curval= eval_icu(icu, ctime); +} + +float calc_ipo_time(Ipo *ipo, float ctime) +{ + + if(ipo && ipo->blocktype==ID_OB) { + IpoCurve *icu= ipo->curve.first; + + while(icu) { + if (icu->adrcode==OB_TIME) { + calc_icu(icu, ctime); + return 10.0f*icu->curval; + } + icu= icu->next; + } + } + + return ctime; +} + +void calc_ipo(Ipo *ipo, float ctime) +{ + IpoCurve *icu; + + icu= ipo->curve.first; + while(icu) { + + if( (icu->flag & IPO_LOCK)==0) calc_icu(icu, ctime); + + icu= icu->next; + } +} + +/* ************************************** */ +/* DO THE IPO! */ +/* ************************************** */ + +void write_ipo_poin(void *poin, int type, float val) +{ + + switch(type) { + case IPO_FLOAT: + *( (float *)poin)= val; + break; + case IPO_FLOAT_DEGR: + *( (float *)poin)= (float)(val*M_PI_2/9.0); + break; + case IPO_INT: + case IPO_INT_BIT: + case IPO_LONG: + *( (int *)poin)= (int)val; + break; + case IPO_SHORT: + case IPO_SHORT_BIT: + *( (short *)poin)= (short)val; + break; + case IPO_CHAR: + case IPO_CHAR_BIT: + *( (char *)poin)= (char)val; + break; + } +} + +float read_ipo_poin(void *poin, int type) +{ + float val = 0.0; + + switch(type) { + case IPO_FLOAT: + val= *( (float *)poin); + break; + case IPO_FLOAT_DEGR: + val= *( (float *)poin); + val = (float)(val/(M_PI_2/9.0)); + break; + case IPO_INT: + case IPO_INT_BIT: + case IPO_LONG: + val= (float)(*( (int *)poin)); + break; + case IPO_SHORT: + case IPO_SHORT_BIT: + val= *( (short *)poin); + break; + case IPO_CHAR: + case IPO_CHAR_BIT: + val= *( (char *)poin); + break; + } + return val; +} + +void *give_mtex_poin(MTex *mtex, int adrcode ) +{ + void *poin=0; + + switch(adrcode) { + case MAP_OFS_X: + poin= &(mtex->ofs[0]); break; + case MAP_OFS_Y: + poin= &(mtex->ofs[1]); break; + case MAP_OFS_Z: + poin= &(mtex->ofs[2]); break; + case MAP_SIZE_X: + poin= &(mtex->size[0]); break; + case MAP_SIZE_Y: + poin= &(mtex->size[1]); break; + case MAP_SIZE_Z: + poin= &(mtex->size[2]); break; + case MAP_R: + poin= &(mtex->r); break; + case MAP_G: + poin= &(mtex->g); break; + case MAP_B: + poin= &(mtex->b); break; + case MAP_DVAR: + poin= &(mtex->def_var); break; + case MAP_COLF: + poin= &(mtex->colfac); break; + case MAP_NORF: + poin= &(mtex->norfac); break; + case MAP_VARF: + poin= &(mtex->varfac); break; + } + + return poin; +} + +/* GS reads the memory pointed at in a specific ordering. There are, + * however two definitions for it. I have jotted them down here, both, + * but I think the first one is actually used. The thing is that + * big-endian systems might read this the wrong way round. OTOH, we + * constructed the IDs that are read out with this macro explicitly as + * well. I expect we'll sort it out soon... */ + +/* from blendef: */ +#define GS(a) (*((short *)(a))) + +/* from misc_util: flip the bytes from x */ +/* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */ + +void *get_ipo_poin(ID *id, IpoCurve *icu, int *type) +{ + void *poin= 0; + Object *ob; + Material *ma; + MTex *mtex; + Ika *ika= 0; + Lamp *la; + Sequence *seq; + World *wo; + bAction *act; + bActionChannel *achan; + bPoseChannel *pchan; + + *type= IPO_FLOAT; + + + if( GS(id->name)==ID_OB) { + + ob= (Object *)id; + + if(ob->type==OB_IKA) ika= ob->data; + + switch(icu->adrcode) { + case OB_LOC_X: + poin= &(ob->loc[0]); break; + case OB_LOC_Y: + poin= &(ob->loc[1]); break; + case OB_LOC_Z: + poin= &(ob->loc[2]); break; + case OB_DLOC_X: + poin= &(ob->dloc[0]); break; + case OB_DLOC_Y: + poin= &(ob->dloc[1]); break; + case OB_DLOC_Z: + poin= &(ob->dloc[2]); break; + + case OB_ROT_X: + poin= &(ob->rot[0]); *type= IPO_FLOAT_DEGR; break; + case OB_ROT_Y: + poin= &(ob->rot[1]); *type= IPO_FLOAT_DEGR; break; + case OB_ROT_Z: + poin= &(ob->rot[2]); *type= IPO_FLOAT_DEGR; break; + case OB_DROT_X: + poin= &(ob->drot[0]); *type= IPO_FLOAT_DEGR; break; + case OB_DROT_Y: + poin= &(ob->drot[1]); *type= IPO_FLOAT_DEGR; break; + case OB_DROT_Z: + poin= &(ob->drot[2]); *type= IPO_FLOAT_DEGR; break; + + case OB_SIZE_X: + poin= &(ob->size[0]); break; + case OB_SIZE_Y: + poin= &(ob->size[1]); break; + case OB_SIZE_Z: + poin= &(ob->size[2]); break; + case OB_DSIZE_X: + poin= &(ob->dsize[0]); break; + case OB_DSIZE_Y: + poin= &(ob->dsize[1]); break; + case OB_DSIZE_Z: + poin= &(ob->dsize[2]); break; + + case OB_LAY: + poin= &(ob->lay); *type= IPO_INT_BIT; break; + + case OB_EFF_X: /* OB_COL_R */ + if(ika) poin= &(ika->effg[0]); + else poin= &(ob->col[0]); + break; + case OB_EFF_Y: /* OB_COL_G */ + if(ika) poin= &(ika->effg[1]); + else poin= &(ob->col[1]); + break; + case OB_EFF_Z: /* OB_COL_B */ + if(ika) poin= &(ika->effg[2]); + else poin= &(ob->col[2]); + break; + case OB_COL_A: + poin= &(ob->col[3]); + break; + } + } + else if (GS(id->name)==ID_AC){ + act= (bAction *)id; + achan = act->achan; + pchan = act->pchan; + if (!pchan || !achan) + return NULL; + switch (icu->adrcode){ + case AC_QUAT_W: + poin= &(pchan->quat[0]); break; + case AC_QUAT_X: + poin= &(pchan->quat[1]); break; + case AC_QUAT_Y: + poin= &(pchan->quat[2]); break; + case AC_QUAT_Z: + poin= &(pchan->quat[3]); break; + case AC_LOC_X: + poin= &(pchan->loc[0]); break; + case AC_LOC_Y: + poin= &(pchan->loc[1]); break; + case AC_LOC_Z: + poin= &(pchan->loc[2]); break; + case AC_SIZE_X: + poin= &(pchan->size[0]); break; + case AC_SIZE_Y: + poin= &(pchan->size[1]); break; + case AC_SIZE_Z: + poin= &(pchan->size[2]); break; + }; + } + + else if( GS(id->name)==ID_MA) { + + ma= (Material *)id; + + switch(icu->adrcode) { + case MA_COL_R: + poin= &(ma->r); break; + case MA_COL_G: + poin= &(ma->g); break; + case MA_COL_B: + poin= &(ma->b); break; + case MA_SPEC_R: + poin= &(ma->specr); break; + case MA_SPEC_G: + poin= &(ma->specg); break; + case MA_SPEC_B: + poin= &(ma->specb); break; + case MA_MIR_R: + poin= &(ma->mirr); break; + case MA_MIR_G: + poin= &(ma->mirg); break; + case MA_MIR_B: + poin= &(ma->mirb); break; + case MA_REF: + poin= &(ma->ref); break; + case MA_ALPHA: + poin= &(ma->alpha); break; + case MA_EMIT: + poin= &(ma->emit); break; + case MA_AMB: + poin= &(ma->amb); break; + case MA_SPEC: + poin= &(ma->spec); break; + case MA_HARD: + poin= &(ma->har); *type= IPO_SHORT; break; + case MA_SPTR: + poin= &(ma->spectra); break; + case MA_ANG: + poin= &(ma->ang); break; + case MA_MODE: + poin= &(ma->mode); *type= IPO_INT_BIT; break; + case MA_HASIZE: + poin= &(ma->hasize); break; + } + + if(poin==0) { + mtex= 0; + if(icu->adrcode & MA_MAP1) mtex= ma->mtex[0]; + else if(icu->adrcode & MA_MAP2) mtex= ma->mtex[1]; + else if(icu->adrcode & MA_MAP3) mtex= ma->mtex[2]; + else if(icu->adrcode & MA_MAP4) mtex= ma->mtex[3]; + else if(icu->adrcode & MA_MAP5) mtex= ma->mtex[4]; + else if(icu->adrcode & MA_MAP6) mtex= ma->mtex[5]; + else if(icu->adrcode & MA_MAP7) mtex= ma->mtex[6]; + else if(icu->adrcode & MA_MAP8) mtex= ma->mtex[7]; + + if(mtex) { + poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) ); + } + } + } + else if( GS(id->name)==ID_SEQ) { + seq= (Sequence *)id; + + switch(icu->adrcode) { + case SEQ_FAC1: + poin= &(seq->facf0); break; + } + } + else if( GS(id->name)==ID_CU) { + + poin= &(icu->curval); + + } + else if( GS(id->name)==ID_KE) { + + poin= &(icu->curval); + + } + else if(GS(id->name)==ID_WO) { + + wo= (World *)id; + + switch(icu->adrcode) { + case WO_HOR_R: + poin= &(wo->horr); break; + case WO_HOR_G: + poin= &(wo->horg); break; + case WO_HOR_B: + poin= &(wo->horb); break; + case WO_ZEN_R: + poin= &(wo->zenr); break; + case WO_ZEN_G: + poin= &(wo->zeng); break; + case WO_ZEN_B: + poin= &(wo->zenb); break; + + case WO_EXPOS: + poin= &(wo->exposure); break; + + case WO_MISI: + poin= &(wo->misi); break; + case WO_MISTDI: + poin= &(wo->mistdist); break; + case WO_MISTSTA: + poin= &(wo->miststa); break; + case WO_MISTHI: + poin= &(wo->misthi); break; + + case WO_STAR_R: + poin= &(wo->starr); break; + case WO_STAR_G: + poin= &(wo->starg); break; + case WO_STAR_B: + poin= &(wo->starb); break; + + case WO_STARDIST: + poin= &(wo->stardist); break; + case WO_STARSIZE: + poin= &(wo->starsize); break; + } + + if(poin==0) { + mtex= 0; + if(icu->adrcode & MA_MAP1) mtex= wo->mtex[0]; + else if(icu->adrcode & MA_MAP2) mtex= wo->mtex[1]; + else if(icu->adrcode & MA_MAP3) mtex= wo->mtex[2]; + else if(icu->adrcode & MA_MAP4) mtex= wo->mtex[3]; + else if(icu->adrcode & MA_MAP5) mtex= wo->mtex[4]; + else if(icu->adrcode & MA_MAP6) mtex= wo->mtex[5]; + else if(icu->adrcode & MA_MAP7) mtex= wo->mtex[6]; + else if(icu->adrcode & MA_MAP8) mtex= wo->mtex[7]; + + if(mtex) { + poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) ); + } + } + } + else if( GS(id->name)==ID_LA) { + + la= (Lamp *)id; + + switch(icu->adrcode) { + case LA_ENERGY: + poin= &(la->energy); break; + case LA_COL_R: + poin= &(la->r); break; + case LA_COL_G: + poin= &(la->g); break; + case LA_COL_B: + poin= &(la->b); break; + case LA_DIST: + poin= &(la->dist); break; + case LA_SPOTSI: + poin= &(la->spotsize); break; + case LA_SPOTBL: + poin= &(la->spotblend); break; + case LA_QUAD1: + poin= &(la->att1); break; + case LA_QUAD2: + poin= &(la->att2); break; + case LA_HALOINT: + poin= &(la->haint); break; + } + + if(poin==0) { + mtex= 0; + if(icu->adrcode & MA_MAP1) mtex= la->mtex[0]; + else if(icu->adrcode & MA_MAP2) mtex= la->mtex[1]; + else if(icu->adrcode & MA_MAP3) mtex= la->mtex[2]; + else if(icu->adrcode & MA_MAP4) mtex= la->mtex[3]; + else if(icu->adrcode & MA_MAP5) mtex= la->mtex[4]; + else if(icu->adrcode & MA_MAP6) mtex= la->mtex[5]; + else if(icu->adrcode & MA_MAP7) mtex= la->mtex[6]; + else if(icu->adrcode & MA_MAP8) mtex= la->mtex[7]; + + if(mtex) { + poin= give_mtex_poin(mtex, icu->adrcode & (MA_MAP1-1) ); + } + } + } + else if(GS(id->name)==ID_CA) { + Camera *ca= (Camera *)id; + + switch(icu->adrcode) { + case CAM_LENS: + poin= &(ca->lens); break; + case CAM_STA: + poin= &(ca->clipsta); break; + case CAM_END: + poin= &(ca->clipend); break; + } + } + else if(GS(id->name)==ID_SO) { + bSound *snd= (bSound *)id; + + switch(icu->adrcode) { + case SND_VOLUME: + poin= &(snd->volume); break; + case SND_PITCH: + poin= &(snd->pitch); break; + case SND_PANNING: + poin= &(snd->panning); break; + case SND_ATTEN: + poin= &(snd->attenuation); break; + } + } + + return poin; +} + +void set_icu_vars(IpoCurve *icu) +{ + + icu->ymin= icu->ymax= 0.0; + icu->ipo= IPO_BEZ; + + if(icu->blocktype==ID_OB) { + + if(icu->adrcode==OB_LAY) { + icu->ipo= IPO_CONST; + icu->vartype= IPO_BITS; + } + + } + else if(icu->blocktype==ID_MA) { + + if(icu->adrcode < MA_MAP1) { + switch(icu->adrcode) { + case MA_HASIZE: + icu->ymax= 10000.0; break; + case MA_HARD: + icu->ymax= 128.0; break; + case MA_SPEC: + icu->ymax= 2.0; break; + case MA_MODE: + icu->ipo= IPO_CONST; + icu->vartype= IPO_BITS; + break; + + default: + icu->ymax= 1.0; + break; + } + } + else { + switch(icu->adrcode & (MA_MAP1-1)) { + case MAP_OFS_X: + case MAP_OFS_Y: + case MAP_OFS_Z: + case MAP_SIZE_X: + case MAP_SIZE_Y: + case MAP_SIZE_Z: + icu->ymax= 1000.0; + icu->ymin= -1000.0; + + break; + case MAP_R: + case MAP_G: + case MAP_B: + case MAP_DVAR: + case MAP_COLF: + case MAP_VARF: + icu->ymax= 1.0; + break; + case MAP_NORF: + icu->ymax= 5.0; + break; + } + } + } + else if(icu->blocktype==ID_SEQ) { + + icu->ymax= 1.0; + + } + else if(icu->blocktype==ID_CU) { + + icu->ymax= 1.0; + + } + else if(icu->blocktype==ID_WO) { + + if(icu->adrcode < MA_MAP1) { + switch(icu->adrcode) { + case WO_EXPOS: + icu->ymax= 5.0; break; + case WO_MISTDI: + case WO_MISTSTA: + case WO_MISTHI: + case WO_STARDIST: + case WO_STARSIZE: + break; + + default: + icu->ymax= 1.0; + break; + } + } + else { + switch(icu->adrcode & (MA_MAP1-1)) { + case MAP_OFS_X: + case MAP_OFS_Y: + case MAP_OFS_Z: + case MAP_SIZE_X: + case MAP_SIZE_Y: + case MAP_SIZE_Z: + icu->ymax= 100.0; + icu->ymin= -100.0; + + break; + case MAP_R: + case MAP_G: + case MAP_B: + case MAP_DVAR: + case MAP_COLF: + case MAP_NORF: + case MAP_VARF: + icu->ymax= 1.0; + } + } + } + else if(icu->blocktype==ID_LA) { + if(icu->adrcode < MA_MAP1) { + switch(icu->adrcode) { + case LA_ENERGY: + case LA_DIST: + break; + + case LA_COL_R: + case LA_COL_G: + case LA_COL_B: + case LA_SPOTBL: + case LA_QUAD1: + case LA_QUAD2: + icu->ymax= 1.0; break; + case LA_SPOTSI: + icu->ymax= 180.0; break; + case LA_HALOINT: + icu->ymax= 5.0; break; + } + } + else { + switch(icu->adrcode & (MA_MAP1-1)) { + case MAP_OFS_X: + case MAP_OFS_Y: + case MAP_OFS_Z: + case MAP_SIZE_X: + case MAP_SIZE_Y: + case MAP_SIZE_Z: + icu->ymax= 100.0; + icu->ymin= -100.0; + break; + case MAP_R: + case MAP_G: + case MAP_B: + case MAP_DVAR: + case MAP_COLF: + case MAP_NORF: + case MAP_VARF: + icu->ymax= 1.0; + } + } + } + else if(icu->blocktype==ID_CA) { + + switch(icu->adrcode) { + case CAM_LENS: + icu->ymin= 5.0; + icu->ymax= 1000.0; break; + case CAM_STA: + icu->ymin= 0.001f; + break; + case CAM_END: + icu->ymin= 0.1f; + } + } + else if(icu->blocktype==ID_SO) { + + switch(icu->adrcode) { + case SND_VOLUME: + icu->ymin= 0.0; + icu->ymax= 1.0; + break; + case SND_PITCH: + icu->ymin= -12.0; + icu->ymin= 12.0; + break; + case SND_PANNING: + icu->ymin= 0.0; + icu->ymax= 1.0; + break; + case SND_ATTEN: + icu->ymin= 0.0; + icu->ymin= 1.0; + break; + } + } +} + + +void execute_ipo(ID *id, Ipo *ipo) +{ + IpoCurve *icu; + void *poin; + int type; + + if(ipo==0) return; + + icu= ipo->curve.first; + while(icu) { + poin= get_ipo_poin(id, icu, &type); + if(poin) write_ipo_poin(poin, type, icu->curval); + icu= icu->next; + } +} + +/* exception: it does calc for objects... + * now find out why this routine was used anyway! + */ +void do_ipo_nocalc(Ipo *ipo) +{ + Object *ob; + Material *ma; + World *wo; + Lamp *la; + Camera *ca; + bSound *snd; + + if(ipo==0) return; + + switch(ipo->blocktype) { + case ID_OB: + ob= G.main->object.first; + while(ob) { + if(ob->ipo==ipo) { + do_ob_ipo(ob); + /* execute_ipo((ID *)ob, ipo); */ + } + ob= ob->id.next; + } + break; + case ID_MA: + ma= G.main->mat.first; + while(ma) { + if(ma->ipo==ipo) execute_ipo((ID *)ma, ipo); + ma= ma->id.next; + } + break; + case ID_WO: + wo= G.main->world.first; + while(wo) { + if(wo->ipo==ipo) execute_ipo((ID *)wo, ipo); + wo= wo->id.next; + } + break; + case ID_LA: + la= G.main->lamp.first; + while(la) { + if(la->ipo==ipo) execute_ipo((ID *)la, ipo); + la= la->id.next; + } + break; + case ID_CA: + ca= G.main->camera.first; + while(ca) { + if(ca->ipo==ipo) execute_ipo((ID *)ca, ipo); + ca= ca->id.next; + } + break; + case ID_SO: + snd= G.main->sound.first; + while(snd) { + if(snd->ipo==ipo) execute_ipo((ID *)snd, ipo); + snd= snd->id.next; + } + break; + } +} + +void do_ipo(Ipo *ipo) +{ + if(ipo) { + float ctime= frame_to_float(G.scene->r.cfra); + calc_ipo(ipo, ctime); + + do_ipo_nocalc(ipo); + } +} + + + +void do_mat_ipo(Material *ma) +{ + float ctime; + + if(ma==0 || ma->ipo==0) return; + + ctime= frame_to_float(G.scene->r.cfra); + /* if(ob->ipoflag & OB_OFFS_OB) ctime-= ob->sf; */ + + calc_ipo(ma->ipo, ctime); + + execute_ipo((ID *)ma, ma->ipo); +} + +void do_ob_ipo(Object *ob) +{ + float ctime; + unsigned int lay; + + if(ob->ipo==0) return; + + /* hier NIET ob->ctime zetten: bijv bij parent in onzichtb. layer */ + + ctime= bsystem_time(ob, 0, (float) G.scene->r.cfra, 0.0); + + calc_ipo(ob->ipo, ctime); + + /* Patch: de localview onthouden */ + lay= ob->lay & 0xFF000000; + + execute_ipo((ID *)ob, ob->ipo); + + ob->lay |= lay; + if(ob->id.name[2]=='S' && ob->id.name[3]=='C' && ob->id.name[4]=='E') { + if(strcmp(G.scene->id.name+2, ob->id.name+6)==0) { + G.scene->lay= ob->lay; + copy_view3d_lock(0); + /* hier geen REDRAW: gaat rondzingen! */ + } + } +} + +void do_seq_ipo(Sequence *seq) +{ + float ctime, div; + + /* seq_ipo gaat iets anders: beide fields direkt berekenen */ + + if(seq->ipo) { + ctime= frame_to_float(G.scene->r.cfra - seq->startdisp); + div= (seq->enddisp - seq->startdisp)/100.0f; + if(div==0) return; + + /* tweede field */ + calc_ipo(seq->ipo, (ctime+0.5f)/div); + execute_ipo((ID *)seq, seq->ipo); + seq->facf1= seq->facf0; + + /* eerste field */ + calc_ipo(seq->ipo, ctime/div); + execute_ipo((ID *)seq, seq->ipo); + + } + else seq->facf1= seq->facf0= 1.0f; +} + +int has_ipo_code(Ipo *ipo, int code) +{ + IpoCurve *icu; + + if(ipo==0) return 0; + + icu= ipo->curve.first; + while(icu) { + + if(icu->adrcode==code) return 1; + + icu= icu->next; + } + return 0; +} + +void do_all_ipos() +{ + Base *base; + Material *ma; + World *wo; + Ipo *ipo; + Lamp *la; + Camera *ca; + bSound *snd; + float ctime; + int set; + + ctime= frame_to_float(G.scene->r.cfra); + + ipo= G.main->ipo.first; + while(ipo) { + if(ipo->id.us && ipo->blocktype!=ID_OB) { + calc_ipo(ipo, ctime); + } + ipo= ipo->id.next; + } + + /* NEW: current scene ob ipo's */ + base= G.scene->base.first; + set= 0; + while(base) { + + /* Do object ipos */ + do_constraint_channels(&base->object->constraints, &base->object->constraintChannels, ctime); + + if(base->object->ipo) { + /* per object ipo ook de calc_ipo doen: ivm mogelijke timeoffs */ + do_ob_ipo(base->object); + if(base->object->type==OB_MBALL) where_is_object(base->object); + } + base= base->next; + + if(base==0 && set==0 && G.scene->set) { + set= 1; + base= G.scene->set->base.first; + } + } + + ma= G.main->mat.first; + while(ma) { + if(ma->ipo) execute_ipo((ID *)ma, ma->ipo); + ma= ma->id.next; + } + + wo= G.main->world.first; + while(wo) { + if(wo->ipo) execute_ipo((ID *)wo, wo->ipo); + wo= wo->id.next; + } + + la= G.main->lamp.first; + while(la) { + if(la->ipo) execute_ipo((ID *)la, la->ipo); + la= la->id.next; + } + + ca= G.main->camera.first; + while(ca) { + if(ca->ipo) execute_ipo((ID *)ca, ca->ipo); + ca= ca->id.next; + } + + snd= G.main->sound.first; + while(snd) { + if(snd->ipo) execute_ipo((ID *)snd, snd->ipo); + snd= snd->id.next; + } + + /* voor het geval dat... LET OP: 2x */ + base= G.scene->base.first; + while(base) { + + /* alleen layer updaten als ipo */ + if( has_ipo_code(base->object->ipo, OB_LAY) ) { + base->lay= base->object->lay; + } + + base= base->next; + } + + /* voor het geval dat...*/ + if(G.scene->set) { + base= G.scene->set->base.first; + while(base) { + + /* alleen layer updaten als ipo */ + if( has_ipo_code(base->object->ipo, OB_LAY) ) { + base->lay= base->object->lay; + } + + base= base->next; + } + } +} + + +int calc_ipo_spec(Ipo *ipo, int adrcode, float *ctime) +{ + IpoCurve *icu; + + if(ipo==0) return 0; + + icu= ipo->curve.first; + while(icu) { + if(icu->adrcode == adrcode) { + if(icu->flag & IPO_LOCK); + else calc_icu(icu, *ctime); + + *ctime= icu->curval; + return 1; + } + icu= icu->next; + } + + return 0; +} + + +/* ************************** */ + +void clear_delta_obipo(Ipo *ipo) +{ + Object *ob; + + if(ipo==0) return; + + ob= G.main->object.first; + while(ob) { + if(ob->id.lib==0) { + if(ob->ipo==ipo) { + memset(&ob->dloc, 0, 12); + memset(&ob->drot, 0, 12); + memset(&ob->dsize, 0, 12); + } + } + ob= ob->id.next; + } +} + +void add_to_cfra_elem(ListBase *lb, BezTriple *bezt) +{ + CfraElem *ce, *cen; + + ce= lb->first; + while(ce) { + + if( ce->cfra==bezt->vec[1][0] ) { + /* doen ivm dubbele keys */ + if(bezt->f2 & 1) ce->sel= bezt->f2; + return; + } + else if(ce->cfra > bezt->vec[1][0]) break; + + ce= ce->next; + } + + cen= MEM_callocN(sizeof(CfraElem), "add_to_cfra_elem"); + if(ce) BLI_insertlinkbefore(lb, ce, cen); + else BLI_addtail(lb, cen); + + cen->cfra= bezt->vec[1][0]; + cen->sel= bezt->f2; +} + + + +void make_cfra_list(Ipo *ipo, ListBase *elems) +{ + IpoCurve *icu; + CfraElem *ce; + BezTriple *bezt; + int a; + + if(ipo->blocktype==ID_OB) { + icu= ipo->curve.first; + while(icu) { + if(icu->flag & IPO_VISIBLE) { + switch(icu->adrcode) { + case OB_DLOC_X: + case OB_DLOC_Y: + case OB_DLOC_Z: + case OB_DROT_X: + case OB_DROT_Y: + case OB_DROT_Z: + case OB_DSIZE_X: + case OB_DSIZE_Y: + case OB_DSIZE_Z: + + case OB_LOC_X: + case OB_LOC_Y: + case OB_LOC_Z: + case OB_ROT_X: + case OB_ROT_Y: + case OB_ROT_Z: + case OB_SIZE_X: + case OB_SIZE_Y: + case OB_SIZE_Z: + bezt= icu->bezt; + if(bezt) { + a= icu->totvert; + while(a--) { + add_to_cfra_elem(elems, bezt); + bezt++; + } + } + break; + } + } + icu= icu->next; + } + } + if(ipo->showkey==0) { + /* alle keys deselecteren */ + ce= elems->first; + while(ce) { + ce->sel= 0; + ce= ce->next; + } + } +} + +/* *********************** INTERFACE FOR KETSJI ********** */ + + +int IPO_GetChannels(Ipo *ipo, IPO_Channel *channels) +{ + /* channels is max 32 items, allocated by calling function */ + + IpoCurve *icu; + int total=0; + + if(ipo==NULL) return 0; + + icu= ipo->curve.first; + while(icu) { + + channels[total]= icu->adrcode; + total++; + if(total>31) break; + + icu= icu->next; + } + + return total; +} + + + +/* Get the float value for channel 'channel' at time 'ctime' */ + +float IPO_GetFloatValue(Ipo *ipo, IPO_Channel channel, float ctime) +{ + if(ipo==NULL) return 0; + + calc_ipo_spec(ipo, channel, &ctime); + + if (OB_ROT_X <= channel && channel <= OB_DROT_Z) { + ctime *= (float)(M_PI_2/9.0); + } + + return ctime; +} + + +void test_ipo_get() +{ + Object *ob; + int tot; + IPO_Channel chan[32]; + + ob = (G.scene->basact ? G.scene->basact->object : 0); + + if(ob==NULL) return; + if(ob->ipo==NULL) return; + + tot= IPO_GetChannels(ob->ipo, chan); + printf("tot %d \n", tot); + + while(tot--) { + printf("var1 %d \n", chan[tot]); + } + + printf("var1 %f \n", IPO_GetFloatValue(ob->ipo, chan[0], 10.0)); +} diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c new file mode 100644 index 00000000000..d3ea2da204b --- /dev/null +++ b/source/blender/blenkernel/intern/key.c @@ -0,0 +1,1212 @@ + +/* key.c MIXED MODEL + * + * mei 95 + * + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <math.h> +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_key_types.h" +#include "DNA_ipo_types.h" +#include "DNA_mesh_types.h" +#include "DNA_object_types.h" +#include "DNA_curve_types.h" +#include "DNA_lattice_types.h" + +#include "BLI_blenlib.h" +#include "BKE_utildefines.h" +#include "BKE_bad_level_calls.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_library.h" +#include "BKE_blender.h" +#include "BKE_curve.h" +#include "BKE_object.h" +#include "BKE_mesh.h" +#include "BKE_key.h" +#include "BKE_ipo.h" +#include "BKE_lattice.h" + + +#define KEY_BPOINT 1 +#define KEY_BEZTRIPLE 2 + +int slurph_opt= 1; + + +void free_key(Key *key) +{ + KeyBlock *kb; + + if(key->ipo) key->ipo->id.us--; + + + while( (kb= key->block.first) ) { + + if(kb->data) MEM_freeN(kb->data); + + BLI_remlink(&key->block, kb); + MEM_freeN(kb); + } + +} + +/* GS reads the memory pointed at in a specific ordering. There are, + * however two definitions for it. I have jotted them down here, both, + * but I think the first one is actually used. The thing is that + * big-endian systems might read this the wrong way round. OTOH, we + * constructed the IDs that are read out with this macro explicitly as + * well. I expect we'll sort it out soon... */ + +/* from blendef: */ +#define GS(a) (*((short *)(a))) + +/* from misc_util: flip the bytes from x */ +/* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */ + +Key *add_key(ID *id) /* algemeen */ +{ + Key *key; + char *el; + + key= alloc_libblock(&G.main->key, ID_KE, "Key"); + + key->type= KEY_NORMAL; + key->from= id; + + if( GS(id->name)==ID_ME) { + el= key->elemstr; + + el[0]= 3; + el[1]= IPO_FLOAT; + el[2]= 0; + + key->elemsize= 12; + } + else if( GS(id->name)==ID_LT) { + el= key->elemstr; + + el[0]= 3; + el[1]= IPO_FLOAT; + el[2]= 0; + + key->elemsize= 12; + } + else if( GS(id->name)==ID_CU) { + el= key->elemstr; + + el[0]= 4; + el[1]= IPO_BPOINT; + el[2]= 0; + + key->elemsize= 16; + } + + return key; +} + +Key *copy_key(Key *key) +{ + Key *keyn; + KeyBlock *kbn, *kb; + + if(key==0) return 0; + + keyn= copy_libblock(key); + + keyn->ipo= copy_ipo(key->ipo); + + duplicatelist(&keyn->block, &key->block); + + kb= key->block.first; + kbn= keyn->block.first; + while(kbn) { + + if(kbn->data) kbn->data= MEM_dupallocN(kbn->data); + if( kb==key->refkey ) keyn->refkey= kbn; + + kbn= kbn->next; + kb= kb->next; + } + + return keyn; +} + +void make_local_key(Key *key) +{ + + /* - zijn er alleen lib users: niet doen + * - zijn er alleen locale users: flag zetten + * - mixed: copy + */ + if(key==0) return; + + key->id.lib= 0; + new_id(0, (ID *)key, 0); + make_local_ipo(key->ipo); +} + + +void sort_keys(Key *key) +{ + KeyBlock *kb; + int doit=1; + + while(doit) { + doit= 0; + + kb= key->block.first; + while(kb) { + if(kb->next) { + if(kb->pos > kb->next->pos) { + BLI_remlink(&key->block, kb); + + /* insertlink(lb, prevlink, newlink): newlink komt na prevlink */ + BLI_insertlink(&key->block, kb->next, kb); + + doit= 1; + break; + } + } + kb= kb->next; + } + } + +} + +/**************** do the key ****************/ + + +void set_four_ipo(float d, float *data, int type) +{ + float d2, d3, fc; + + if(type==KEY_LINEAR) { + data[0]= 0.0f; + data[1]= 1.0f-d; + data[2]= d; + data[3]= 0.0f; + } + else { + d2= d*d; + d3= d2*d; + + if(type==KEY_CARDINAL) { + + fc= 0.71f; + + data[0]= -fc*d3 +2.0f*fc*d2 -fc*d; + data[1]= (2.0f-fc)*d3 +(fc-3.0f)*d2 +1.0f; + data[2]= (fc-2.0f)*d3 +(3.0f-2.0f*fc)*d2 +fc*d; + data[3]= fc*d3 -fc*d2; + } + else if(type==KEY_BSPLINE) { + + data[0]= -0.1666f*d3 +0.5f*d2 -0.5f*d +0.16666f; + data[1]= 0.5f*d3 -d2 +0.6666f; + data[2]= -0.5f*d3 +0.5f*d2 +0.5f*d +0.1666f; + data[3]= 0.1666f*d3 ; + } + } +} + +void set_afgeleide_four_ipo(float d, float *data, int type) +{ + float d2, fc; + + if(type==KEY_LINEAR) { + + } + else { + d2= d*d; + + if(type==KEY_CARDINAL) { + + fc= 0.71f; + + data[0]= -3.0f*fc*d2 +4.0f*fc*d -fc; + data[1]= 3.0f*(2.0f-fc)*d2 +2.0f*(fc-3.0f)*d; + data[2]= 3.0f*(fc-2.0f)*d2 +2.0f*(3.0f-2.0f*fc)*d +fc; + data[3]= 3.0f*fc*d2 -2.0f*fc*d; + } + else if(type==KEY_BSPLINE) { + + data[0]= -0.1666f*3.0f*d2 +d -0.5f; + data[1]= 1.5f*d2 -2.0f*d; + data[2]= -1.5f*d2 +d +0.5f; + data[3]= 0.1666f*3.0f*d2 ; + } + } +} + +int setkeys(float fac, ListBase *lb, KeyBlock *k[], float *t, int cycl) +{ + /* return 1 betekent k[2] is de positie, 0 is interpoleren */ + KeyBlock *k1, *firstkey; + float d, dpos, ofs=0, lastpos, temp, fval[4]; + short bsplinetype; + + firstkey= lb->first; + k1= lb->last; + lastpos= k1->pos; + dpos= lastpos - firstkey->pos; + + if(fac < firstkey->pos) fac= firstkey->pos; + else if(fac > k1->pos) fac= k1->pos; + + k1=k[0]=k[1]=k[2]=k[3]= firstkey; + t[0]=t[1]=t[2]=t[3]= k1->pos; + + /* if(fac<0.0 || fac>1.0) return 1; */ + + if(k1->next==0) return 1; + + if(cycl) { /* voorsorteren */ + k[2]= k1->next; + k[3]= k[2]->next; + if(k[3]==0) k[3]=k1; + while(k1) { + if(k1->next==0) k[0]=k1; + k1=k1->next; + } + k1= k[1]; + t[0]= k[0]->pos; + t[1]+= dpos; + t[2]= k[2]->pos + dpos; + t[3]= k[3]->pos + dpos; + fac+= dpos; + ofs= dpos; + if(k[3]==k[1]) { + t[3]+= dpos; + ofs= 2.0f*dpos; + } + if(fac<t[1]) fac+= dpos; + k1= k[3]; + } + else { /* voorsorteren */ + /* waarom dit voorsorteren niet eerder gedaan? voor juist interpoleren in begin noodz. */ + k[2]= k1->next; + t[2]= k[2]->pos; + k[3]= k[2]->next; + if(k[3]==0) k[3]= k[2]; + t[3]= k[3]->pos; + k1= k[3]; + } + + while( t[2]<fac ) { /* goede plek vinden */ + if(k1->next==0) { + if(cycl) { + k1= firstkey; + ofs+= dpos; + } + else if(t[2]==t[3]) break; + } + else k1= k1->next; + + t[0]= t[1]; + k[0]= k[1]; + t[1]= t[2]; + k[1]= k[2]; + t[2]= t[3]; + k[2]= k[3]; + t[3]= k1->pos+ofs; + k[3]= k1; + + if(ofs>2.1+lastpos) break; + } + + bsplinetype= 0; + if(k[1]->type==KEY_BSPLINE || k[2]->type==KEY_BSPLINE) bsplinetype= 1; + + + if(cycl==0) { + if(bsplinetype==0) { /* B spline gaat niet door de punten */ + if(fac<=t[1]) { /* fac voor 1e key */ + t[2]= t[1]; + k[2]= k[1]; + return 1; + } + if(fac>=t[2] ) { /* fac na 2e key */ + return 1; + } + } + else if(fac>t[2]) { /* laatste key */ + fac= t[2]; + k[3]= k[2]; + t[3]= t[2]; + } + } + + d= t[2]-t[1]; + if(d==0.0) { + if(bsplinetype==0) { + return 1; /* beide keys gelijk */ + } + } + else d= (fac-t[1])/d; + + /* interpolatie */ + + set_four_ipo(d, t, k[1]->type); + + if(k[1]->type != k[2]->type) { + set_four_ipo(d, fval, k[2]->type); + + temp= 1.0f-d; + t[0]= temp*t[0]+ d*fval[0]; + t[1]= temp*t[1]+ d*fval[1]; + t[2]= temp*t[2]+ d*fval[2]; + t[3]= temp*t[3]+ d*fval[3]; + } + + return 0; + +} + +void flerp(int aantal, float *in, float *f0, float *f1, float *f2, float *f3, float *t) +{ + int a; + + for(a=0; a<aantal; a++) { + in[a]= t[0]*f0[a]+t[1]*f1[a]+t[2]*f2[a]+t[3]*f3[a]; + } +} + +void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *k, int mode) +{ + float ktot = 0.0, kd = 0.0; + int elemsize, poinsize = 0, a, *ofsp, ofs[32], flagflo=0; + char *k1; + char *cp, elemstr[8]; + + if(key->from==0) return; + + if( GS(key->from->name)==ID_ME ) { + ofs[0]= sizeof(MVert); + ofs[1]= 0; + poinsize= ofs[0]; + } + else if( GS(key->from->name)==ID_LT ) { + ofs[0]= sizeof(BPoint); + ofs[1]= 0; + poinsize= ofs[0]; + } + else if( GS(key->from->name)==ID_CU ) { + if(mode==KEY_BPOINT) ofs[0]= sizeof(BPoint); + else ofs[0]= sizeof(BezTriple); + + ofs[1]= 0; + poinsize= ofs[0]; + } + + + if(end>tot) end= tot; + + k1= k->data; + + if(tot != k->totelem) { + ktot= 0.0; + flagflo= 1; + if(k->totelem) { + kd= k->totelem/(float)tot; + } + else return; + } + + /* deze uitzondering is om slurphing mogelijk te maken */ + if(start!=0) { + + poin+= poinsize*start; + + if(flagflo) { + ktot+= start*kd; + a= (int)floor(ktot); + if(a) { + ktot-= a; + k1+= a*key->elemsize; + } + } + else k1+= start*key->elemsize; + } + + + if(mode==KEY_BEZTRIPLE) { + elemstr[0]= 1; + elemstr[1]= IPO_BEZTRIPLE; + elemstr[2]= 0; + } + + /* alleen in dit stuk, hierboven niet! */ + elemsize= key->elemsize; + if(mode==KEY_BEZTRIPLE) elemsize*= 3; + + for(a=start; a<end; a++) { + cp= key->elemstr; + if(mode==KEY_BEZTRIPLE) cp= elemstr; + + ofsp= ofs; + + while( cp[0] ) { + + switch(cp[1]) { + case IPO_FLOAT: + + memcpy(poin, k1, 4*cp[0]); + poin+= ofsp[0]; + + break; + case IPO_BPOINT: + memcpy(poin, k1, 3*4); + memcpy(poin+16, k1+12, 4); + + poin+= ofsp[0]; + + break; + case IPO_BEZTRIPLE: + memcpy(poin, k1, 4*12); + poin+= ofsp[0]; + + break; + } + + cp+= 2; ofsp++; + } + + /* gaan we moeilijk doen */ + if(flagflo) { + ktot+= kd; + while(ktot>=1.0) { + ktot-= 1.0; + k1+= elemsize; + } + } + else k1+= elemsize; + + if(mode==KEY_BEZTRIPLE) a+=2; + } +} + +void cp_cu_key(Curve *cu, KeyBlock *kb, int start, int end) +{ + Nurb *nu; + int a, step = 0, tot, a1, a2; + char *poin; + + tot= count_curveverts(&cu->nurb); + nu= cu->nurb.first; + a= 0; + while(nu) { + if(nu->bp) { + + step= nu->pntsu*nu->pntsv; + + /* uitzondering omdat keys graag met volledige blokken werken */ + poin= (char *)nu->bp->vec; + poin -= a*sizeof(BPoint); + + a1= MAX2(a, start); + a2= MIN2(a+step, end); + + if(a1<a2) cp_key(a1, a2, tot, poin, cu->key, kb, KEY_BPOINT); + } + else if(nu->bezt) { + + step= 3*nu->pntsu; + + poin= (char *)nu->bezt->vec; + poin -= a*sizeof(BezTriple); + + a1= MAX2(a, start); + a2= MIN2(a+step, end); + + if(a1<a2) cp_key(a1, a2, tot, poin, cu->key, kb, KEY_BEZTRIPLE); + + } + a+= step; + nu=nu->next; + } +} + + +void rel_flerp(int aantal, float *in, float *ref, float *out, float fac) +{ + int a; + + for(a=0; a<aantal; a++) { + in[a]-= fac*(ref[a]-out[a]); + } +} + + + +void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, float ctime, int mode) +{ + KeyBlock *kb; + IpoCurve *icu; + float fac[32], fval; + int *ofsp, ofs[3], elemsize, a, b; + char *cp, *poin, *reffrom, *from, elemstr[8]; + + if(key->from==0) return; + if(key->ipo==0) return; + + if( GS(key->from->name)==ID_ME ) { + ofs[0]= sizeof(MVert); + ofs[1]= 0; + } + else if( GS(key->from->name)==ID_LT ) { + ofs[0]= sizeof(BPoint); + ofs[1]= 0; + } + else if( GS(key->from->name)==ID_CU ) { + if(mode==KEY_BPOINT) ofs[0]= sizeof(BPoint); + else ofs[0]= sizeof(BezTriple); + + ofs[1]= 0; + } + + if(end>tot) end= tot; + + /* in geval beztriple */ + elemstr[0]= 1; /* aantal ipofloats */ + elemstr[1]= IPO_BEZTRIPLE; + elemstr[2]= 0; + + /* alleen in dit stuk, hierboven niet! */ + elemsize= key->elemsize; + if(mode==KEY_BEZTRIPLE) elemsize*= 3; + + /* step one: fetch ipo values */ + icu= key->ipo->curve.first; + for(a=0; a<KEY_TOTIPO; a++) fac[a]= 0.0; + while(icu) { + fac[icu->adrcode]= icu->curval; + icu= icu->next; + } + + /* step 2 init */ + cp_key(start, end, tot, basispoin, key, key->refkey, mode); + + /* step 3: do it */ + + a= 1; + kb= key->block.first; + while(kb) { + + if(kb!=key->refkey) { + fval= fac[a]; + a++; + if(a==32) break; + + /* no difference allowed */ + if(kb->totelem==tot) { + + poin= basispoin; + reffrom= key->refkey->data; + from= kb->data; + + poin+= start*ofs[0]; + reffrom+= elemsize*start; + from+= elemsize*start; + + for(b=start; b<end; b++) { + + cp= key->elemstr; + if(mode==KEY_BEZTRIPLE) cp= elemstr; + + ofsp= ofs; + + while( cp[0] ) { /* cp[0]==aantal */ + + switch(cp[1]) { + case IPO_FLOAT: + rel_flerp(cp[0], (float *)poin, (float *)reffrom, (float *)from, fval); + + break; + case IPO_BPOINT: + rel_flerp(3, (float *)poin, (float *)reffrom, (float *)from, fval); + rel_flerp(1, (float *)(poin+16), (float *)(reffrom+16), (float *)(from+16), fval); + + break; + case IPO_BEZTRIPLE: + rel_flerp(9, (float *)poin, (float *)reffrom, (float *)from, fval); + + break; + } + + poin+= ofsp[0]; + + cp+= 2; + ofsp++; + } + + reffrom+= elemsize; + from+= elemsize; + + } + } + } + kb= kb->next; + } +} + + +void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock **k, float *t, int mode) +{ + float k1tot = 0.0, k2tot = 0.0, k3tot = 0.0, k4tot = 0.0; + float k1d = 0.0, k2d = 0.0, k3d = 0.0, k4d = 0.0; + int a, ofs[32], *ofsp; + int flagdo= 15, flagflo=0, elemsize, poinsize=0; + char *k1, *k2, *k3, *k4; + char *cp, elemstr[8];; + + if(key->from==0) return; + + if( GS(key->from->name)==ID_ME ) { + ofs[0]= sizeof(MVert); + ofs[1]= 0; + poinsize= ofs[0]; + } + else if( GS(key->from->name)==ID_LT ) { + ofs[0]= sizeof(BPoint); + ofs[1]= 0; + poinsize= ofs[0]; + } + else if( GS(key->from->name)==ID_CU ) { + if(mode==KEY_BPOINT) ofs[0]= sizeof(BPoint); + else ofs[0]= sizeof(BezTriple); + + ofs[1]= 0; + poinsize= ofs[0]; + } + + if(end>tot) end= tot; + + k1= k[0]->data; + k2= k[1]->data; + k3= k[2]->data; + k4= k[3]->data; + + /* testen op meer of minder punten (per key!) */ + if(tot != k[0]->totelem) { + k1tot= 0.0; + flagflo |= 1; + if(k[0]->totelem) { + k1d= k[0]->totelem/(float)tot; + } + else flagdo -= 1; + } + if(tot != k[1]->totelem) { + k2tot= 0.0; + flagflo |= 2; + if(k[0]->totelem) { + k2d= k[1]->totelem/(float)tot; + } + else flagdo -= 2; + } + if(tot != k[2]->totelem) { + k3tot= 0.0; + flagflo |= 4; + if(k[0]->totelem) { + k3d= k[2]->totelem/(float)tot; + } + else flagdo -= 4; + } + if(tot != k[3]->totelem) { + k4tot= 0.0; + flagflo |= 8; + if(k[0]->totelem) { + k4d= k[3]->totelem/(float)tot; + } + else flagdo -= 8; + } + + /* deze uitzondering is om slurphing mogelijk te maken */ + if(start!=0) { + + poin+= poinsize*start; + + if(flagdo & 1) { + if(flagflo & 1) { + k1tot+= start*k1d; + a= (int)floor(k1tot); + if(a) { + k1tot-= a; + k1+= a*key->elemsize; + } + } + else k1+= start*key->elemsize; + } + if(flagdo & 2) { + if(flagflo & 2) { + k2tot+= start*k2d; + a= (int)floor(k2tot); + if(a) { + k2tot-= a; + k2+= a*key->elemsize; + } + } + else k2+= start*key->elemsize; + } + if(flagdo & 4) { + if(flagflo & 4) { + k3tot+= start*k3d; + a= (int)floor(k3tot); + if(a) { + k3tot-= a; + k3+= a*key->elemsize; + } + } + else k3+= start*key->elemsize; + } + if(flagdo & 8) { + if(flagflo & 8) { + k4tot+= start*k4d; + a= (int)floor(k4tot); + if(a) { + k4tot-= a; + k4+= a*key->elemsize; + } + } + else k4+= start*key->elemsize; + } + + } + + /* in geval beztriple */ + elemstr[0]= 1; /* aantal ipofloats */ + elemstr[1]= IPO_BEZTRIPLE; + elemstr[2]= 0; + + /* alleen in dit stuk, hierboven niet! */ + elemsize= key->elemsize; + if(mode==KEY_BEZTRIPLE) elemsize*= 3; + + for(a=start; a<end; a++) { + + cp= key->elemstr; + if(mode==KEY_BEZTRIPLE) cp= elemstr; + + ofsp= ofs; + + while( cp[0] ) { /* cp[0]==aantal */ + + switch(cp[1]) { + case IPO_FLOAT: + flerp(cp[0], (float *)poin, (float *)k1, (float *)k2, (float *)k3, (float *)k4, t); + poin+= ofsp[0]; + + break; + case IPO_BPOINT: + flerp(3, (float *)poin, (float *)k1, (float *)k2, (float *)k3, (float *)k4, t); + flerp(1, (float *)(poin+16), (float *)(k1+12), (float *)(k2+12), (float *)(k3+12), (float *)(k4+12), t); + + poin+= ofsp[0]; + + break; + case IPO_BEZTRIPLE: + flerp(9, (void *)poin, (void *)k1, (void *)k2, (void *)k3, (void *)k4, t); + poin+= ofsp[0]; + + break; + } + + + cp+= 2; + ofsp++; + } + /* gaan we moeilijk doen: als keys van lengte verschillen */ + if(flagdo & 1) { + if(flagflo & 1) { + k1tot+= k1d; + while(k1tot>=1.0) { + k1tot-= 1.0; + k1+= elemsize; + } + } + else k1+= elemsize; + } + if(flagdo & 2) { + if(flagflo & 2) { + k2tot+= k2d; + while(k2tot>=1.0) { + k2tot-= 1.0; + k2+= elemsize; + } + } + else k2+= elemsize; + } + if(flagdo & 4) { + if(flagflo & 4) { + k3tot+= k3d; + while(k3tot>=1.0) { + k3tot-= 1.0; + k3+= elemsize; + } + } + else k3+= elemsize; + } + if(flagdo & 8) { + if(flagflo & 8) { + k4tot+= k4d; + while(k4tot>=1.0) { + k4tot-= 1.0; + k4+= elemsize; + } + } + else k4+= elemsize; + } + + if(mode==KEY_BEZTRIPLE) a+= 2; + } +} + + + +void do_mesh_key(Mesh *me) +{ + KeyBlock *k[4]; + float cfra, ctime, t[4], delta, loc[3], size[3]; + int a, flag = 0, step; + + if(me->totvert==0) return; + if(me->key==0) return; + if(me->key->block.first==0) return; + + if(me->key->slurph && me->key->type!=KEY_RELATIVE ) { + delta= me->key->slurph; + delta/= me->totvert; + + step= 1; + if(me->totvert>100 && slurph_opt) { + step= me->totvert/50; + delta*= step; + /* in do_key en cp_key wordt a>tot afgevangen */ + } + + cfra= G.scene->r.cfra; + + for(a=0; a<me->totvert; a+=step, cfra+= delta) { + + ctime= bsystem_time(0, 0, cfra, 0.0); + if(calc_ipo_spec(me->key->ipo, KEY_SPEED, &ctime)==0) { + ctime /= 100.0; + CLAMP(ctime, 0.0, 1.0); + } + + flag= setkeys(ctime, &me->key->block, k, t, 0); + if(flag==0) { + + do_key(a, a+step, me->totvert, (char *)me->mvert->co, me->key, k, t, 0); + } + else { + cp_key(a, a+step, me->totvert, (char *)me->mvert->co, me->key, k[2], 0); + } + } + + if(flag && k[2]==me->key->refkey) tex_space_mesh(me); + else boundbox_mesh(me, loc, size); + + } + else { + + ctime= bsystem_time(0, 0, (float)G.scene->r.cfra, 0.0); + if(calc_ipo_spec(me->key->ipo, KEY_SPEED, &ctime)==0) { + ctime /= 100.0; + CLAMP(ctime, 0.0, 1.0); + } + + if(me->key->type==KEY_RELATIVE) { + do_rel_key(0, me->totvert, me->totvert, (char *)me->mvert->co, me->key, ctime, 0); + } + else { + flag= setkeys(ctime, &me->key->block, k, t, 0); + if(flag==0) { + + do_key(0, me->totvert, me->totvert, (char *)me->mvert->co, me->key, k, t, 0); + } + else { + cp_key(0, me->totvert, me->totvert, (char *)me->mvert->co, me->key, k[2], 0); + + } + + if(flag && k[2]==me->key->refkey) tex_space_mesh(me); + else boundbox_mesh(me, loc, size); + } + } +} + +void do_cu_key(Curve *cu, KeyBlock **k, float *t) +{ + Nurb *nu; + int a, step = 0, tot; + char *poin; + + tot= count_curveverts(&cu->nurb); + nu= cu->nurb.first; + a= 0; + while(nu) { + if(nu->bp) { + + step= nu->pntsu*nu->pntsv; + + /* uitzondering omdat keys graag met volledige blokken werken */ + poin= (char *)nu->bp->vec; + poin -= a*sizeof(BPoint); + + do_key(a, a+step, tot, poin, cu->key, k, t, KEY_BPOINT); + } + else if(nu->bezt) { + + step= 3*nu->pntsu; + + poin= (char *)nu->bezt->vec; + poin -= a*sizeof(BezTriple); + + do_key(a, a+step, tot, poin, cu->key, k, t, KEY_BEZTRIPLE); + + } + a+= step; + nu=nu->next; + } +} + +void do_rel_cu_key(Curve *cu, float ctime) +{ + Nurb *nu; + int a, step = 0, tot; + char *poin; + + tot= count_curveverts(&cu->nurb); + nu= cu->nurb.first; + a= 0; + while(nu) { + if(nu->bp) { + + step= nu->pntsu*nu->pntsv; + + /* uitzondering omdat keys graag met volledige blokken werken */ + poin= (char *)nu->bp->vec; + poin -= a*sizeof(BPoint); + + do_rel_key(a, a+step, tot, poin, cu->key, ctime, KEY_BPOINT); + } + else if(nu->bezt) { + + step= 3*nu->pntsu; + + poin= (char *)nu->bezt->vec; + poin -= a*sizeof(BezTriple); + + do_rel_key(a, a+step, tot, poin, cu->key, ctime, KEY_BEZTRIPLE); + + } + a+= step; + nu=nu->next; + } +} + +void do_curve_key(Curve *cu) +{ + KeyBlock *k[4]; + float cfra, ctime, t[4], delta; + int a, flag = 0, step = 0, tot; + + tot= count_curveverts(&cu->nurb); + + if(tot==0) return; + if(cu->key==0) return; + if(cu->key->block.first==0) return; + + if(cu->key->slurph) { + delta= cu->key->slurph; + delta/= tot; + + step= 1; + if(tot>100 && slurph_opt) { + step= tot/50; + delta*= step; + /* in do_key en cp_key wordt a>tot afgevangen */ + } + + cfra= G.scene->r.cfra; + + for(a=0; a<tot; a+=step, cfra+= delta) { + + ctime= bsystem_time(0, 0, cfra, 0.0); + if(calc_ipo_spec(cu->key->ipo, KEY_SPEED, &ctime)==0) { + ctime /= 100.0; + CLAMP(ctime, 0.0, 1.0); + } + + flag= setkeys(ctime, &cu->key->block, k, t, 0); + if(flag==0) { + + /* do_key(a, a+step, tot, (char *)cu->mvert->co, cu->key, k, t, 0); */ + } + else { + /* cp_key(a, a+step, tot, (char *)cu->mvert->co, cu->key, k[2],0); */ + } + } + + if(flag && k[2]==cu->key->refkey) tex_space_curve(cu); + + + } + else { + + ctime= bsystem_time(0, 0, (float)G.scene->r.cfra, 0.0); + if(calc_ipo_spec(cu->key->ipo, KEY_SPEED, &ctime)==0) { + ctime /= 100.0; + CLAMP(ctime, 0.0, 1.0); + } + + if(cu->key->type==KEY_RELATIVE) { + do_rel_cu_key(cu, ctime); + } + else { + flag= setkeys(ctime, &cu->key->block, k, t, 0); + + if(flag==0) do_cu_key(cu, k, t); + else cp_cu_key(cu, k[2], 0, tot); + + if(flag && k[2]==cu->key->refkey) tex_space_curve(cu); + } + } +} + +void do_latt_key(Lattice *lt) +{ + KeyBlock *k[4]; + float delta, cfra, ctime, t[4]; + int a, tot, flag; + + if(lt->key==0) return; + if(lt->key->block.first==0) return; + + tot= lt->pntsu*lt->pntsv*lt->pntsw; + + if(lt->key->slurph) { + delta= lt->key->slurph; + delta/= (float)tot; + + cfra= G.scene->r.cfra; + + for(a=0; a<tot; a++, cfra+= delta) { + + ctime= bsystem_time(0, 0, cfra, 0.0); + if(calc_ipo_spec(lt->key->ipo, KEY_SPEED, &ctime)==0) { + ctime /= 100.0; + CLAMP(ctime, 0.0, 1.0); + } + + flag= setkeys(ctime, <->key->block, k, t, 0); + if(flag==0) { + + do_key(a, a+1, tot, (char *)lt->def->vec, lt->key, k, t, 0); + } + else { + cp_key(a, a+1, tot, (char *)lt->def->vec, lt->key, k[2], 0); + } + } + } + else { + ctime= bsystem_time(0, 0, (float)G.scene->r.cfra, 0.0); + if(calc_ipo_spec(lt->key->ipo, KEY_SPEED, &ctime)==0) { + ctime /= 100.0; + CLAMP(ctime, 0.0, 1.0); + } + + if(lt->key->type==KEY_RELATIVE) { + do_rel_key(0, tot, tot, (char *)lt->def->vec, lt->key, ctime, 0); + } + else { + + flag= setkeys(ctime, <->key->block, k, t, 0); + if(flag==0) { + do_key(0, tot, tot, (char *)lt->def->vec, lt->key, k, t, 0); + } + else { + cp_key(0, tot, tot, (char *)lt->def->vec, lt->key, k[2], 0); + } + } + } + + if(lt->flag & LT_OUTSIDE) outside_lattice(lt); +} + + + +void do_all_keys() +{ + Key *key; + int idcode; + + key= G.main->key.first; + while(key) { + if(key->from) { + idcode= GS(key->from->name); + + if(idcode==ID_ME) do_mesh_key( (Mesh *)key->from); + else if(idcode==ID_CU) do_curve_key( (Curve *)key->from); + else if(idcode==ID_LT) do_latt_key( (Lattice *)key->from); + } + key= key->id.next; + } +} + +void do_ob_key(Object *ob) +{ + if(ob->type==OB_MESH) do_mesh_key( ob->data); + else if(ob->type==OB_CURVE) do_curve_key( ob->data); + else if(ob->type==OB_SURF) do_curve_key( ob->data); + else if(ob->type==OB_LATTICE) do_latt_key( ob->data); +} + +void do_spec_key(Key *key) +{ + int idcode; + + if(key==0) return; + + idcode= GS(key->from->name); + + if(idcode==ID_ME) do_mesh_key( (Mesh *)key->from); + else if(idcode==ID_CU) do_curve_key( (Curve *)key->from); + else if(idcode==ID_LT) do_latt_key( (Lattice *)key->from); + +} diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c new file mode 100644 index 00000000000..a6895d2a8ea --- /dev/null +++ b/source/blender/blenkernel/intern/lattice.c @@ -0,0 +1,633 @@ +/** + * lattice.c MIXED MODEL + * june 2001 ton + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <stdio.h> +#include <string.h> +#include <math.h> +#include <stdlib.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" + +#include "DNA_armature_types.h" +#include "DNA_mesh_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_lattice_types.h" +#include "DNA_curve_types.h" +#include "DNA_key_types.h" +#include "DNA_ika_types.h" + +#include "BKE_utildefines.h" +#include "BKE_armature.h" +#include "BKE_library.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_screen.h" +#include "BKE_displist.h" +#include "BKE_lattice.h" +#include "BKE_key.h" +#include "BKE_object.h" +#include "BKE_ika.h" + +Lattice *editLatt=0, *deformLatt=0; + +float *latticedata=0, latmat[4][4]; +int lt_applyflag= 0; + +void resizelattice(Lattice *lt) +{ + BPoint *bp; + int u, v, w; + float vec[3], fu, fv, fw, du=0.0, dv=0.0, dw=0.0; + + + MEM_freeN(lt->def); + lt->def= MEM_callocN(lt->pntsu*lt->pntsv*lt->pntsw*sizeof(BPoint), "lattice bp"); + + bp= lt->def; + + while(lt->pntsu*lt->pntsv*lt->pntsw > 32000) { + if( lt->pntsu>=lt->pntsv && lt->pntsu>=lt->pntsw) lt->pntsu--; + else if( lt->pntsv>=lt->pntsu && lt->pntsv>=lt->pntsw) lt->pntsv--; + else lt->pntsw--; + } + + calc_lat_fudu(lt->flag, lt->pntsu, &fu, &du); + calc_lat_fudu(lt->flag, lt->pntsv, &fv, &dv); + calc_lat_fudu(lt->flag, lt->pntsw, &fw, &dw); + + vec[2]= fw; + for(w=0; w<lt->pntsw; w++) { + vec[1]= fv; + for(v=0; v<lt->pntsv; v++) { + vec[0]= fu; + for(u=0; u<lt->pntsu; u++, bp++) { + VECCOPY(bp->vec, vec); + vec[0]+= du; + } + vec[1]+= dv; + } + vec[2]+= dw; + } +} + +Lattice *add_lattice() +{ + Lattice *lt; + + lt= alloc_libblock(&G.main->latt, ID_LT, "Lattice"); + + lt->pntsu=lt->pntsv=lt->pntsw= 2; + lt->flag= LT_GRID; + + lt->typeu= lt->typev= lt->typew= KEY_BSPLINE; + + /* tijdelijk */ + lt->def= MEM_callocN(sizeof(BPoint), "lattvert"); + + resizelattice(lt); /* maakt een regelmatige lattice */ + + return lt; +} + +Lattice *copy_lattice(Lattice *lt) +{ + Lattice *ltn; + + ltn= copy_libblock(lt); + ltn->def= MEM_dupallocN(lt->def); + + id_us_plus((ID *)ltn->ipo); + + ltn->key= copy_key(ltn->key); + if(ltn->key) ltn->key->from= (ID *)ltn; + + return ltn; +} + +void free_lattice(Lattice *lt) +{ + if(lt->def) MEM_freeN(lt->def); +} + + +void make_local_lattice(Lattice *lt) +{ + Object *ob; + Lattice *ltn; + int local=0, lib=0; + + /* - zijn er alleen lib users: niet doen + * - zijn er alleen locale users: flag zetten + * - mixed: copy + */ + + if(lt->id.lib==0) return; + if(lt->id.us==1) { + lt->id.lib= 0; + lt->id.flag= LIB_LOCAL; + new_id(0, (ID *)lt, 0); + return; + } + + ob= G.main->object.first; + while(ob) { + if(ob->data==lt) { + if(ob->id.lib) lib= 1; + else local= 1; + } + ob= ob->id.next; + } + + if(local && lib==0) { + lt->id.lib= 0; + lt->id.flag= LIB_LOCAL; + new_id(0, (ID *)lt, 0); + } + else if(local && lib) { + ltn= copy_lattice(lt); + ltn->id.us= 0; + + ob= G.main->object.first; + while(ob) { + if(ob->data==lt) { + + if(ob->id.lib==0) { + ob->data= ltn; + ltn->id.us++; + lt->id.us--; + } + } + ob= ob->id.next; + } + } +} + + + +void calc_lat_fudu(int flag, int res, float *fu, float *du) +{ + + if(res==1) { + *fu= 0.0; + *du= 0.0; + } + else if(flag & LT_GRID) { + *fu= -0.5f*(res-1); + *du= 1.0f; + } + else { + *fu= -1.0f; + *du= 2.0f/(res-1); + } + +} + +void init_latt_deform(Object *oblatt, Object *ob) +{ + /* we maken een array met alle verschillen */ + BPoint *bp; + float *fp, imat[4][4]; + float vec[3], fu, fv, fw, du=0.0, dv=0.0, dw=0.0; + int u, v, w; + + if(oblatt==G.obedit) deformLatt= editLatt; + else deformLatt= oblatt->data; + + fp= latticedata= MEM_mallocN(sizeof(float)*3*deformLatt->pntsu*deformLatt->pntsv*deformLatt->pntsw, "latticedata"); + + bp= deformLatt->def; + + if(ob) where_is_object(ob); + + /* bijv bij particle systeem: ob==0 */ + if(ob==0) { + /* in deformspace, matrix berekenen */ + Mat4Invert(latmat, oblatt->obmat); + + /* terug: in deform array verwerken */ + Mat4Invert(imat, latmat); + } + else { + /* in deformspace, matrix berekenen */ + Mat4Invert(imat, oblatt->obmat); + Mat4MulMat4(latmat, ob->obmat, imat); + + /* terug: in deform array verwerken */ + Mat4Invert(imat, latmat); + } + calc_lat_fudu(deformLatt->flag, deformLatt->pntsu, &fu, &du); + calc_lat_fudu(deformLatt->flag, deformLatt->pntsv, &fv, &dv); + calc_lat_fudu(deformLatt->flag, deformLatt->pntsw, &fw, &dw); + + /* we berekenen hier steeds de u v w lattice coordinaten, weinig reden ze te onthouden */ + + vec[2]= fw; + for(w=0; w<deformLatt->pntsw; w++) { + vec[1]= fv; + for(v=0; v<deformLatt->pntsv; v++) { + vec[0]= fu; + for(u=0; u<deformLatt->pntsu; u++, bp++) { + + VecSubf(fp, bp->vec, vec); + Mat4Mul3Vecfl(imat, fp); + + vec[0]+= du; + fp+= 3; + } + vec[1]+= dv; + } + vec[2]+= dw; + } +} + +void calc_latt_deform(float *co) +{ + Lattice *lt; + float fu, du, u, v, w, tu[4], tv[4], tw[4]; + float *fpw, *fpv, *fpu, vec[3]; + int ui, vi, wi, uu, vv, ww; + + if(latticedata==0) return; + + lt= deformLatt; /* kortere notatie! */ + + /* co is in lokale coords, met latmat behandelen */ + + VECCOPY(vec, co); + Mat4MulVecfl(latmat, vec); + + /* u v w coords */ + + if(lt->pntsu>1) { + calc_lat_fudu(lt->flag, lt->pntsu, &fu, &du); + u= (vec[0]-fu)/du; + ui= (int)floor(u); + u -= ui; + set_four_ipo(u, tu, lt->typeu); + } + else { + tu[0]= tu[2]= tu[3]= 0.0; tu[1]= 1.0; + ui= 0; + } + + if(lt->pntsv>1) { + calc_lat_fudu(lt->flag, lt->pntsv, &fu, &du); + v= (vec[1]-fu)/du; + vi= (int)floor(v); + v -= vi; + set_four_ipo(v, tv, lt->typev); + } + else { + tv[0]= tv[2]= tv[3]= 0.0; tv[1]= 1.0; + vi= 0; + } + + if(lt->pntsw>1) { + calc_lat_fudu(lt->flag, lt->pntsw, &fu, &du); + w= (vec[2]-fu)/du; + wi= (int)floor(w); + w -= wi; + set_four_ipo(w, tw, lt->typew); + } + else { + tw[0]= tw[2]= tw[3]= 0.0; tw[1]= 1.0; + wi= 0; + } + + for(ww= wi-1; ww<=wi+2; ww++) { + w= tw[ww-wi+1]; + + if(w!=0.0) { + if(ww>0) { + if(ww<lt->pntsw) fpw= latticedata + 3*ww*lt->pntsu*lt->pntsv; + else fpw= latticedata + 3*(lt->pntsw-1)*lt->pntsu*lt->pntsv; + } + else fpw= latticedata; + + for(vv= vi-1; vv<=vi+2; vv++) { + v= w*tv[vv-vi+1]; + + if(v!=0.0) { + if(vv>0) { + if(vv<lt->pntsv) fpv= fpw + 3*vv*lt->pntsu; + else fpv= fpw + 3*(lt->pntsv-1)*lt->pntsu; + } + else fpv= fpw; + + for(uu= ui-1; uu<=ui+2; uu++) { + u= v*tu[uu-ui+1]; + + if(u!=0.0) { + if(uu>0) { + if(uu<lt->pntsu) fpu= fpv + 3*uu; + else fpu= fpv + 3*(lt->pntsu-1); + } + else fpu= fpv; + + co[0]+= u*fpu[0]; + co[1]+= u*fpu[1]; + co[2]+= u*fpu[2]; + } + } + } + } + } + } +} + + +void end_latt_deform() +{ + + MEM_freeN(latticedata); + latticedata= 0; +} + + +int object_deform(Object *ob) +{ + Mesh *me; + Curve *cu; + DispList *dl; + MVert *mvert; + float *fp; + int a, tot; + + if(ob->parent==0) return 0; + + /* altijd proberen in deze fie de hele deform te doen: apply! */ + + if(ob->parent->type==OB_LATTICE) { + + init_latt_deform(ob->parent, ob); + + if(ob->type==OB_MESH) { + me= ob->data; + + dl= find_displist_create(&ob->disp, DL_VERTS); + + mvert= me->mvert; + if(dl->verts) MEM_freeN(dl->verts); + dl->nr= me->totvert; + dl->verts= fp= MEM_mallocN(3*sizeof(float)*me->totvert, "deform1"); + + for(a=0; a<me->totvert; a++, mvert++, fp+=3) { + if(lt_applyflag) calc_latt_deform(mvert->co); + else { + VECCOPY(fp, mvert->co); + calc_latt_deform(fp); + } + } + } + else if ELEM(ob->type, OB_CURVE, OB_SURF) { + + cu= ob->data; + if(lt_applyflag) { + Nurb *nu; + BPoint *bp; + + nu= cu->nurb.first; + while(nu) { + if(nu->bp) { + a= nu->pntsu*nu->pntsv; + bp= nu->bp; + while(a--) { + calc_latt_deform(bp->vec); + bp++; + } + } + nu= nu->next; + } + } + + /* when apply, do this too, looks more interactive */ + dl= cu->disp.first; + while(dl) { + + fp= dl->verts; + + if(dl->type==DL_INDEX3) tot=dl->parts; + else tot= dl->nr*dl->parts; + + for(a=0; a<tot; a++, fp+=3) { + calc_latt_deform(fp); + } + + dl= dl->next; + } + } + end_latt_deform(); + + boundbox_displist(ob); + + return 1; + } + else if(ob->parent->type==OB_ARMATURE) { + if (ob->partype != PARSKEL){ + return 0; + } + + init_armature_deform (ob->parent, ob); + + switch (ob->type){ + case OB_MESH: + me= ob->data; + + dl= find_displist_create(&ob->disp, DL_VERTS); + + mvert= me->mvert; + if(dl->verts) MEM_freeN(dl->verts); + dl->nr= me->totvert; + dl->verts= fp= MEM_mallocN(3*sizeof(float)*me->totvert, "deform1"); + + for(a=0; a<me->totvert; a++, mvert++, fp+=3) { + if(lt_applyflag){ + calc_armature_deform(ob->parent, mvert->co, a); + } + else { + VECCOPY(fp, mvert->co); + calc_armature_deform(ob->parent, fp, a); + } + } + + break; + default: + break; + } + + boundbox_displist(ob); + return 1; + } + else if(ob->parent->type==OB_IKA) { + + Ika *ika; + + if(ob->partype!=PARSKEL) return 0; + + ika= ob->parent->data; + if(ika->def==0) return 0; + + init_skel_deform(ob->parent, ob); + + if(ob->type==OB_MESH) { + me= ob->data; + + dl= find_displist_create(&ob->disp, DL_VERTS); + + mvert= me->mvert; + if(dl->verts) MEM_freeN(dl->verts); + dl->nr= me->totvert; + dl->verts= fp= MEM_mallocN(3*sizeof(float)*me->totvert, "deform1"); + + for(a=0; a<me->totvert; a++, mvert++, fp+=3) { + if(lt_applyflag) calc_skel_deform(ika, mvert->co); + else { + VECCOPY(fp, mvert->co); + calc_skel_deform(ika, fp); + } + } + } + else if ELEM(ob->type, OB_CURVE, OB_SURF) { + + cu= ob->data; + if(lt_applyflag) { + Nurb *nu; + BPoint *bp; + + nu= cu->nurb.first; + while(nu) { + if(nu->bp) { + a= nu->pntsu*nu->pntsv; + bp= nu->bp; + while(a--) { + calc_skel_deform(ika, bp->vec); + bp++; + } + } + nu= nu->next; + } + } + + /* when apply, do this too, looks more interactive */ + dl= cu->disp.first; + while(dl) { + + fp= dl->verts; + tot= dl->nr*dl->parts; + for(a=0; a<tot; a++, fp+=3) { + calc_skel_deform(ika, fp); + } + + dl= dl->next; + } + } + + boundbox_displist(ob); + + return 1; + } + + return 0; + +} + +BPoint *latt_bp(Lattice *lt, int u, int v, int w) +{ + return lt->def+ u + v*lt->pntsu + w*lt->pntsu*lt->pntsv; +} + +void outside_lattice(Lattice *lt) +{ + BPoint *bp, *bp1, *bp2; + int u, v, w; + float fac1, du=0.0, dv=0.0, dw=0.0; + + bp= lt->def; + + if(lt->pntsu>1) du= 1.0f/((float)lt->pntsu-1); + if(lt->pntsv>1) dv= 1.0f/((float)lt->pntsv-1); + if(lt->pntsw>1) dw= 1.0f/((float)lt->pntsw-1); + + for(w=0; w<lt->pntsw; w++) { + + for(v=0; v<lt->pntsv; v++) { + + for(u=0; u<lt->pntsu; u++, bp++) { + if(u==0 || v==0 || w==0 || u==lt->pntsu-1 || v==lt->pntsv-1 || w==lt->pntsw-1); + else { + + bp->hide= 1; + bp->f1 &= ~SELECT; + + /* u extrema */ + bp1= latt_bp(lt, 0, v, w); + bp2= latt_bp(lt, lt->pntsu-1, v, w); + + fac1= du*u; + bp->vec[0]= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0]; + bp->vec[1]= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1]; + bp->vec[2]= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2]; + + /* v extrema */ + bp1= latt_bp(lt, u, 0, w); + bp2= latt_bp(lt, u, lt->pntsv-1, w); + + fac1= dv*v; + bp->vec[0]+= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0]; + bp->vec[1]+= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1]; + bp->vec[2]+= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2]; + + /* w extrema */ + bp1= latt_bp(lt, u, v, 0); + bp2= latt_bp(lt, u, v, lt->pntsw-1); + + fac1= dw*w; + bp->vec[0]+= (1.0f-fac1)*bp1->vec[0] + fac1*bp2->vec[0]; + bp->vec[1]+= (1.0f-fac1)*bp1->vec[1] + fac1*bp2->vec[1]; + bp->vec[2]+= (1.0f-fac1)*bp1->vec[2] + fac1*bp2->vec[2]; + + VecMulf(bp->vec, 0.3333333f); + + } + } + + } + + } + +} diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c new file mode 100644 index 00000000000..97ede69280c --- /dev/null +++ b/source/blender/blenkernel/intern/library.c @@ -0,0 +1,905 @@ + +/* library.c aug 94 MIXED MODEL + * + * jan 95 + * + * afhandeling ID's en libraries + * allocceren en vrijgeven alle library data + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include <stdlib.h> + +#ifdef WIN32 +#include "BLI_winstuff.h" +#endif + +#include "MEM_guardedalloc.h" + +/* all types are needed here, in order to do memory operations */ +#include "DNA_ID.h" +#include "DNA_listBase.h" +#include "DNA_scene_types.h" +#include "DNA_object_types.h" +#include "DNA_mesh_types.h" +#include "DNA_lattice_types.h" +#include "DNA_curve_types.h" +#include "DNA_meta_types.h" +#include "DNA_material_types.h" +#include "DNA_texture_types.h" +#include "DNA_ika_types.h" +#include "DNA_image_types.h" +#include "DNA_wave_types.h" +#include "DNA_lamp_types.h" +#include "DNA_camera_types.h" +#include "DNA_ipo_types.h" +#include "DNA_key_types.h" +#include "DNA_world_types.h" +#include "DNA_screen_types.h" +#include "DNA_vfont_types.h" +#include "DNA_text_types.h" +#include "DNA_sound_types.h" +#include "DNA_group_types.h" +#include "DNA_armature_types.h" +#include "DNA_action_types.h" + +#include "BLI_blenlib.h" +#include "BLI_dynstr.h" + +#include "BKE_bad_level_calls.h" +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_global.h" +#include "BKE_sound.h" +#include "BKE_object.h" +#include "BKE_screen.h" +#include "BKE_mesh.h" +#include "BKE_material.h" +#include "BKE_curve.h" +#include "BKE_mball.h" + #include "BKE_text.h" +#include "BKE_texture.h" +#include "BKE_scene.h" +#include "BKE_image.h" +#include "BKE_ika.h" +#include "BKE_ipo.h" +#include "BKE_key.h" +#include "BKE_world.h" +#include "BKE_font.h" +#include "BKE_group.h" +#include "BKE_lattice.h" +#include "BKE_armature.h" +#include "BKE_action.h" + +#define MAX_IDPUP 30 /* was 24 */ +#define MAX_LIBARRAY 100 /* was 30 */ + +/* ************* ALGEMEEN ************************ */ + +void id_lib_extern(ID *id) +{ + if(id) { + if(id->flag & LIB_INDIRECT) { + id->flag -= LIB_INDIRECT; + id->flag |= LIB_EXTERN; + } + } +} + +void id_us_plus(ID *id) +{ + if(id) { + id->us++; + if(id->flag & LIB_INDIRECT) { + id->flag -= LIB_INDIRECT; + id->flag |= LIB_EXTERN; + } + } +} + +ListBase *wich_libbase(Main *mainlib, short type) +{ + switch( type ) { + case ID_SCE: + return &(mainlib->scene); + case ID_LI: + return &(mainlib->library); + case ID_OB: + return &(mainlib->object); + case ID_ME: + return &(mainlib->mesh); + case ID_CU: + return &(mainlib->curve); + case ID_MB: + return &(mainlib->mball); + case ID_MA: + return &(mainlib->mat); + case ID_TE: + return &(mainlib->tex); + case ID_IM: + return &(mainlib->image); + case ID_IK: + return &(mainlib->ika); + case ID_WV: + return &(mainlib->wave); + case ID_LT: + return &(mainlib->latt); + case ID_LA: + return &(mainlib->lamp); + case ID_CA: + return &(mainlib->camera); + case ID_IP: + return &(mainlib->ipo); + case ID_KE: + return &(mainlib->key); + case ID_WO: + return &(mainlib->world); + case ID_SCR: + return &(mainlib->screen); + case ID_VF: + return &(mainlib->vfont); + case ID_TXT: + return &(mainlib->text); + case ID_SO: + return &(mainlib->sound); + case ID_SAMPLE: + /* declared as an external in sound.h !!! */ + return (samples); + case ID_GR: + return &(mainlib->group); + case ID_AR: + return &(mainlib->armature); + case ID_AC: + return &(mainlib->action); + } + return 0; +} + +int set_listbasepointers(Main *main, ListBase **lb) +{ + /* BACKWARDS! let op volgorde van vrijgeven! (mesh<->mat) */ + + lb[0]= &(main->ipo); + lb[1]= &(main->key); + lb[2]= &(main->image); + lb[3]= &(main->tex); + lb[4]= &(main->mat); + lb[5]= &(main->vfont); + + /* Important!: When adding a new object type, + * the specific data should be inserted here + */ + + lb[6]= &(main->armature); + lb[7]= &(main->action); + + lb[8]= &(main->mesh); + lb[9]= &(main->curve); + lb[10]= &(main->mball); + lb[11]= &(main->ika); + lb[12]= &(main->wave); + lb[13]= &(main->latt); + lb[14]= &(main->lamp); + lb[15]= &(main->camera); + + lb[16]= &(main->world); + lb[17]= &(main->screen); + lb[18]= &(main->object); + lb[19]= &(main->scene); + lb[20]= &(main->library); + lb[21]= &(main->text); + lb[22]= &(main->sound); + lb[23]= &(main->group); + + lb[24]= samples; + lb[25]= 0; + + return 25; +} + +/* *********** ALLOC EN FREE ***************** + +free_libblock(ListBase *lb, ID *id ) + lijstbasis en datablok geven, alleen ID wordt uitgelezen + +void *alloc_libblock(ListBase *lb, type, name) + hangt in lijst en geeft nieuw ID + + ***************************** */ + +static ID *alloc_libblock_notest(short type) +{ + ID *id= 0; + + switch( type ) { + case ID_SCE: + id= MEM_callocN(sizeof(Scene), "scene"); + break; + case ID_LI: + id= MEM_callocN(sizeof(Library), "library"); + break; + case ID_OB: + id= MEM_callocN(sizeof(Object), "object"); + break; + case ID_ME: + id= MEM_callocN(sizeof(Mesh), "mesh"); + break; + case ID_CU: + id= MEM_callocN(sizeof(Curve), "curve"); + break; + case ID_MB: + id= MEM_callocN(sizeof(MetaBall), "mball"); + break; + case ID_MA: + id= MEM_callocN(sizeof(Material), "mat"); + break; + case ID_TE: + id= MEM_callocN(sizeof(Tex), "tex"); + break; + case ID_IM: + id= MEM_callocN(sizeof(Image), "image"); + break; + case ID_IK: + id= MEM_callocN(sizeof(Ika), "ika"); + break; + case ID_WV: + id= MEM_callocN(sizeof(Wave), "wave"); + break; + case ID_LT: + id= MEM_callocN(sizeof(Lattice), "latt"); + break; + case ID_LA: + id= MEM_callocN(sizeof(Lamp), "lamp"); + break; + case ID_CA: + id= MEM_callocN(sizeof(Camera), "camera"); + break; + case ID_IP: + id= MEM_callocN(sizeof(Ipo), "ipo"); + break; + case ID_KE: + id= MEM_callocN(sizeof(Key), "key"); + break; + case ID_WO: + id= MEM_callocN(sizeof(World), "world"); + break; + case ID_SCR: + id= MEM_callocN(sizeof(bScreen), "screen"); + break; + case ID_VF: + id= MEM_callocN(sizeof(VFont), "vfont"); + break; + case ID_TXT: + id= MEM_callocN(sizeof(Text), "text"); + break; + case ID_SO: + id= MEM_callocN(sizeof(bSound), "sound"); + break; + case ID_SAMPLE: + id = MEM_callocN(sizeof(bSample), "sound"); + break; + case ID_GR: + id= MEM_callocN(sizeof(Group), "sound"); + break; + case ID_AR: + id = MEM_callocN(sizeof(bArmature), "armature"); + break; + case ID_AC: + id = MEM_callocN(sizeof(bAction), "action"); + break; + } + return id; +} + +// used everywhere in blenkernel and text.c +void *alloc_libblock(ListBase *lb, short type, char *name) +{ + ID *id= 0; + + id= alloc_libblock_notest(type); + if(id) { + BLI_addtail(lb, id); + id->us= 1; + *( (short *)id->name )= type; + new_id(lb, id, name); + /* alfabetisch opnieuw invoegen: zit in new_id */ + } + return id; +} + +/* GS reads the memory pointed at in a specific ordering. There are, + * however two definitions for it. I have jotted them down here, both, + * but I think the first one is actually used. The thing is that + * big-endian systems might read this the wrong way round. OTOH, we + * constructed the IDs that are read out with this macro explicitly as + * well. I expect we'll sort it out soon... */ + +/* from blendef: */ +#define GS(a) (*((short *)(a))) + +/* from misc_util: flip the bytes from x */ +/*#define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */ + +// used everywhere in blenkernel and text.c +void *copy_libblock(void *rt) +{ + ID *idn, *id; + ListBase *lb; + char *cp, *cpn; + int idn_len; + + id= rt; + + lb= wich_libbase(G.main, GS(id->name)); + idn= alloc_libblock(lb, GS(id->name), id->name+2); + + idn_len= MEM_allocN_len(idn); + if(idn_len - sizeof(ID) > 0) { + cp= (char *)id; + cpn= (char *)idn; + memcpy(cpn+sizeof(ID), cp+sizeof(ID), idn_len - sizeof(ID)); + } + + id->newid= idn; + idn->flag |= LIB_NEW; + + return idn; +} + +static void free_library(Library *lib) +{ + /* no freeing needed for libraries yet */ +} + +// used in headerbuttons.c image.c mesh.c screen.c sound.c and library.c +void free_libblock(ListBase *lb, void *idv) +{ + ID *id= idv; + + switch( GS(id->name) ) { /* GetShort uit util.h */ + case ID_SCE: + free_scene((Scene *)id); + break; + case ID_LI: + free_library((Library *)id); + break; + case ID_OB: + free_object((Object *)id); + break; + case ID_ME: + free_mesh((Mesh *)id); + break; + case ID_CU: + free_curve((Curve *)id); + break; + case ID_MB: + free_mball((MetaBall *)id); + break; + case ID_MA: + free_material((Material *)id); + break; + case ID_TE: + free_texture((Tex *)id); + break; + case ID_IM: + free_image((Image *)id); + break; + case ID_IK: + free_ika((Ika *)id); + break; + case ID_WV: + /* free_wave(id); */ + break; + case ID_LT: + free_lattice((Lattice *)id); + break; + case ID_LA: + free_lamp((Lamp *)id); + break; + case ID_CA: +/* free_camera(id); */ + /* cast wasn't here before... spooky... */ + free_camera((Camera*) id); + break; + case ID_IP: + free_ipo((Ipo *)id); + break; + case ID_KE: + free_key((Key *)id); + break; + case ID_WO: + free_world((World *)id); + break; + case ID_SCR: + free_screen((bScreen *)id); + break; + case ID_VF: + free_vfont((VFont *)id); + break; + case ID_TXT: + free_text((Text *)id); + break; + case ID_SO: + sound_free_sound((bSound *)id); + break; + case ID_SAMPLE: + sound_free_sample((bSample *)id); + break; + case ID_GR: + free_group((Group *)id); + break; + case ID_AR: + free_armature((bArmature *)id); + break; + case ID_AC: + free_action((bAction *)id); + break; + } + + BLI_remlink(lb, id); + MEM_freeN(id); + + /* should not be here!! this is an interface-thing */ + allspace(OOPS_TEST, 0); +} + +void free_libblock_us(ListBase *lb, void *idv) /* test users */ +{ + ID *id= idv; + + id->us--; + + if(id->us<0) { + if(id->lib) printf("ERROR block %s %s users %d\n", id->lib->name, id->name, id->us); + else printf("ERROR block %s users %d\n", id->name, id->us); + } + if(id->us==0) { + if( GS(id->name)==ID_OB ) unlink_object((Object *)id); + + free_libblock(lb, id); + } +} + + +void free_main(Main *mainvar) +{ + /* ook aanroepen bij file inlezen, erase all, etc */ + ListBase *lbarray[MAX_LIBARRAY]; + int a; + + a= set_listbasepointers(mainvar, lbarray); + while(a--) { + ListBase *lb= lbarray[a]; + ID *id; + + while (id= lb->first) { + free_libblock(lb, id); + } + } + + MEM_freeN(mainvar); +} + +/* ***************** ID ************************ */ + +// only used in exotic.c +ID *find_id(char *type, char *name) /* type: "OB" of "MA" etc */ +{ + ID *id; + ListBase *lb; + + lb= wich_libbase(G.main, GS(type)); + + id= lb->first; + while(id) { + if( strcmp(id->name+2, name)==0 ) return id; + id= id->next; + } + return 0; +} + +static void get_flags_for_id(ID *id, char *buf) { + int isfake= id->flag & LIB_FAKEUSER; + + /* Writeout the flags for the entry, note there + * is a small hack that writes 5 spaces instead + * of 4 if no flags are displayed... this makes + * things usually line up ok - better would be + * to have that explicit, oh well - zr + */ + + if (id->us<0) + sprintf(buf, "-1W "); + else if (!id->lib && !isfake && id->us) + sprintf(buf, " "); + else + sprintf(buf, "%c%c%c ", id->lib?'L':' ', isfake?'F':' ', (id->us==0)?'O':' '); +} + +static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, short *nr) +{ + int i, nids= BLI_countlist(lb); + + *nr= -1; + + if (nids>MAX_IDPUP) { + BLI_dynstr_append(pupds, "DataBrowse %x-2"); + } else { + ID *id; + + for (i=0, id= lb->first; id; id= id->next, i++) { + char buf[32]; + + if (id==link) + *nr= i+1; + + get_flags_for_id(id, buf); + + BLI_dynstr_append(pupds, buf); + BLI_dynstr_append(pupds, id->name+2); + + if(id->next) + BLI_dynstr_append(pupds, "|"); + } + } +} + + /* Silly routine, the only difference between the one + * above is that it only adds items with a matching + * blocktype... this should be unified somehow... - zr + */ +static void IPOnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, short *nr, int blocktype) +{ + ID *id; + int i, nids; + + for (id= lb->first, nids= 0; id; id= id->next) { + Ipo *ipo= (Ipo*) id; + + if (ipo->blocktype==blocktype) + nids++; + } + + if (nids>MAX_IDPUP) { + BLI_dynstr_append(pupds, "DataBrowse %x-2"); + } else { + for (i=0, id= lb->first; id; id= id->next) { + Ipo *ipo= (Ipo*) id; + + if (ipo->blocktype==blocktype) { + char buf[32]; + + if (id==link) + *nr= i+1; + + get_flags_for_id(id, buf); + + BLI_dynstr_append(pupds, buf); + BLI_dynstr_append(pupds, id->name+2); + + if(id->next) + BLI_dynstr_append(pupds, "|"); + + i++; + } + } + } +} + +// used by headerbuttons.c buttons.c editobject.c editseq.c +void IDnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb, ID *link, short *nr) +{ + DynStr *pupds= BLI_dynstr_new(); + + if (title) { + BLI_dynstr_append(pupds, title); + BLI_dynstr_append(pupds, "%t|"); + } + + IDnames_to_dyn_pupstring(pupds, lb, link, nr); + + if (extraops) { + if (BLI_dynstr_get_len(pupds)) + BLI_dynstr_append(pupds, "|"); + BLI_dynstr_append(pupds, extraops); + } + + *str= BLI_dynstr_get_cstring(pupds); + BLI_dynstr_free(pupds); +} + +// only used by headerbuttons.c +void IPOnames_to_pupstring(char **str, char *title, char *extraops, ListBase *lb, ID *link, short *nr, int blocktype) +{ + DynStr *pupds= BLI_dynstr_new(); + + if (title) { + BLI_dynstr_append(pupds, title); + BLI_dynstr_append(pupds, "%t|"); + } + + IPOnames_to_dyn_pupstring(pupds, lb, link, nr, blocktype); + + if (extraops) { + if (BLI_dynstr_get_len(pupds)) + BLI_dynstr_append(pupds, "|"); + BLI_dynstr_append(pupds, extraops); + } + + *str= BLI_dynstr_get_cstring(pupds); + BLI_dynstr_free(pupds); +} + +// used by buttons.c library.c mball.c +void splitIDname(char *name, char *left, int *nr) +{ + int a; + + *nr= 0; + strncpy(left, name, 21); + + a= strlen(name); + if(a>1 && name[a-1]=='.') return; + + while(a--) { + if( name[a]=='.' ) { + left[a]= 0; + *nr= atol(name+a+1); + return; + } + if( isdigit(name[a])==0 ) break; + + left[a]= 0; + } + strcpy(left, name); +} + +static void sort_alpha_id(ListBase *lb, ID *id) +{ + ID *idtest; + + /* alfabetisch opnieuw invoegen */ + if(lb->first!=lb->last) { + BLI_remlink(lb, id); + + idtest= lb->first; + while(idtest) { + if(strcasecmp(idtest->name, id->name)>0 || idtest->lib) { + BLI_insertlinkbefore(lb, idtest, id); + break; + } + idtest= idtest->next; + } + /* als laatste */ + if(idtest==0) { + BLI_addtail(lb, id); + } + } + +} + +int new_id(ListBase *lb, ID *id, char *tname) +/* alleen locale blokken: externe en indirekte hebben al een unieke ID */ +/* return 1: nieuwe naam gemaakt */ +{ + ID *idtest; + int nr= 0, nrtest, maxtest=32, a; + char aname[32], *name, left[24], leftest[24], in_use[32]; + + /* - naam splitsen + * - zoeken + */ + + if(id->lib) return 0; + + if(tname==0) name= id->name+2; + else { + /* tname can be const */ + strncpy(aname, tname, 21); + name= aname; + + if( strlen(name) > 21 ) name[21]= 0; + } + + if(lb==0) lb= wich_libbase(G.main, GS(id->name)); + + /* eerste fase: bestaat de id al? */ + idtest= lb->first; + while(idtest) { + + if(id!=idtest && idtest->lib==0) { + + /* niet alphabetic testen! */ + /* optim */ + if( idtest->name[2] == name[0] ) { + if(strcmp(name, idtest->name+2)==0) break; + } + } + + idtest= idtest->next; + } + + /* if there is no double return */ + if(idtest==0) { + strcpy(id->name+2, name); + return 0; + } + + memset(in_use, 0, maxtest); + + splitIDname(name, left, &nr); + if(nr>999 && strlen(left)>16) left[16]= 0; + else if(strlen(left)>17) left[17]= 0; + + + idtest= lb->first; + while(idtest) { + + if(id!=idtest && idtest->lib==0) { + + splitIDname(idtest->name+2, leftest, &nrtest); + if(strcmp(left, leftest)==0) { + + if(nrtest<maxtest) in_use[nrtest]= 1; + if(nr <= nrtest) nr= nrtest+1; + } + } + + idtest= idtest->next; + } + + for(a=0; a<maxtest; a++) { + if(a>=nr) break; + if( in_use[a]==0 ) { + nr= a; + break; + } + } + + if(nr==0) sprintf(id->name+2, "%s", left); + else { + if (nr >= 1000 && strlen(left) > 16) { + // this would overflow name buffer + left[16]= 0; + return (new_id(lb, id, left)); + } + /* this format specifier is fucked... */ + sprintf(id->name+2, "%s.%0.3d", left, nr); + } + + sort_alpha_id(lb, id); + + return 1; +} + +// next to indirect usage in read/writefile also in editobject.c scene.c +void clear_id_newpoins() +{ + ListBase *lbarray[MAX_LIBARRAY]; + ID *id; + int a; + + a= set_listbasepointers(G.main, lbarray); + while(a--) { + id= lbarray[a]->first; + while(id) { + id->newid= 0; + id->flag &= ~LIB_NEW; + id= id->next; + } + } +} + +void all_local(void) +{ + ListBase *lbarray[MAX_LIBARRAY], tempbase={0, 0}; + ID *id, *idn; + int a; + + a= set_listbasepointers(G.main, lbarray); + while(a--) { + id= lbarray[a]->first; + + while(id) { + id->newid= 0; + id->flag &= ~(LIB_EXTERN|LIB_INDIRECT|LIB_NEW); + + idn= id->next; /* id wordt mogelijk opnieuw ingevoegd */ + if(id->lib) { + id->lib= 0; + new_id(lbarray[a], id, 0); /* new_id doet dit alleen bij dubbele namen */ + sort_alpha_id(lbarray[a], id); + } + else { + /* patch: testen of de zaak wel alphabetisch is */ +/* + if(idn) { + if(strcasecmp(id->name, idn->name)>0) { + remlink(lbarray[a], id); + addtail(&tempbase, id); + } + else if(id->prev) { + idp= id->prev; + if(strcasecmp(idp->name, id->name)>0) { + remlink(lbarray[a], id); + addtail(&tempbase, id); + } + } + } +*/ + } + + id= idn; + } + + /* patch2: zorgen dat de zaak wel alphabetisch is */ + while( (id=tempbase.first) ) { + BLI_remlink(&tempbase, id); + BLI_addtail(lbarray[a], id); + new_id(lbarray[a], id, 0); + } + } +} + + +void test_idbutton(char *name) +{ + /* vanuit buttons: als naam al bestaat: new_id aanroepen */ + ListBase *lb; + ID *idtest; + + + lb= wich_libbase(G.main, GS(name-2) ); + if(lb==0) return; + + /* zoek welke id */ + idtest= lb->first; + while(idtest) { + if( strcmp(idtest->name+2, name)==0) break; + idtest= idtest->next; + } + + if(idtest) if( new_id(lb, idtest, name)==0 ) sort_alpha_id(lb, idtest); +} + +void rename_id(ID *id, char *name) +{ + ListBase *lb; + + strncpy(id->name+2, name, 21); + lb= wich_libbase(G.main, GS(id->name) ); + + new_id(lb, id, name); +} + diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c new file mode 100644 index 00000000000..71d0e95031d --- /dev/null +++ b/source/blender/blenkernel/intern/material.c @@ -0,0 +1,747 @@ + +/* material.c MIX MODEL + * + * maart 95 + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <string.h> +#include "MEM_guardedalloc.h" + +#include "DNA_material_types.h" +#include "DNA_texture_types.h" +#include "DNA_mesh_types.h" +#include "DNA_object_types.h" +#include "DNA_curve_types.h" +#include "DNA_meta_types.h" +#include "DNA_scene_types.h" + +#include "BLI_blenlib.h" + +#include "BKE_bad_level_calls.h" +#include "BKE_utildefines.h" + +#include "BKE_global.h" +#include "BKE_main.h" + +#include "BKE_mesh.h" +#include "BKE_library.h" +#include "BKE_displist.h" +#include "BPY_extern.h" +#include "BKE_material.h" + +void free_material(Material *ma) +{ + int a; + MTex *mtex; + + BPY_free_scriptlink(&ma->scriptlink); + + if(ma->ren) MEM_freeN(ma->ren); + ma->ren= 0; + + for(a=0; a<8; a++) { + mtex= ma->mtex[a]; + if(mtex && mtex->tex) mtex->tex->id.us--; + if(mtex) MEM_freeN(mtex); + } +} + +void init_material(Material *ma) +{ + ma->lay= 1; + ma->r= ma->g= ma->b= ma->ref= 0.8f; + ma->specr= ma->specg= ma->specb= 1.0f; + ma->mirr= ma->mirg= ma->mirb= 1.0f; + ma->amb= 0.5f; + ma->alpha= 1.0f; + ma->spec= ma->hasize= 0.5f; + ma->har= 50; + ma->starc= ma->ringc= 4; + ma->linec= 12; + ma->flarec= 1; + ma->flaresize= ma->subsize= 1.0f; + ma->friction= 0.5f; + + ma->mode= MA_TRACEBLE+MA_SHADOW; +} + +Material *add_material(char *name) +{ + Material *ma; + + ma= alloc_libblock(&G.main->mat, ID_MA, name); + + init_material(ma); + + return ma; +} + +Material *copy_material(Material *ma) +{ + Material *man; + int a; + + man= copy_libblock(ma); + + id_us_plus((ID *)man->ipo); + + for(a=0; a<8; a++) { + if(ma->mtex[a]) { + man->mtex[a]= MEM_mallocN(sizeof(MTex), "copymaterial"); + memcpy(man->mtex[a], ma->mtex[a], sizeof(MTex)); + id_us_plus((ID *)man->mtex[a]->tex); + } + } + + BPY_copy_scriptlink(&ma->scriptlink); + + return man; +} + +void make_local_material(Material *ma) +{ + Object *ob; + Mesh *me; + Curve *cu; + MetaBall *mb; + Material *man; + int a, local=0, lib=0; + + /* - zijn er alleen lib users: niet doen + * - zijn er alleen locale users: flag zetten + * - mixed: copy + */ + + if(ma->id.lib==0) return; + if(ma->id.us==1) { + ma->id.lib= 0; + ma->id.flag= LIB_LOCAL; + new_id(0, (ID *)ma, 0); + for(a=0; a<8; a++) { + if(ma->mtex[a]) id_lib_extern((ID *)ma->mtex[a]->tex); + } + + return; + } + + /* test objects */ + ob= G.main->object.first; + while(ob) { + if(ob->mat) { + for(a=0; a<ob->totcol; a++) { + if(ob->mat[a]==ma) { + if(ob->id.lib) lib= 1; + else local= 1; + } + } + } + ob= ob->id.next; + } + /* test meshes */ + me= G.main->mesh.first; + while(me) { + if(me->mat) { + for(a=0; a<me->totcol; a++) { + if(me->mat[a]==ma) { + if(me->id.lib) lib= 1; + else local= 1; + } + } + } + me= me->id.next; + } + /* test curves */ + cu= G.main->curve.first; + while(cu) { + if(cu->mat) { + for(a=0; a<cu->totcol; a++) { + if(cu->mat[a]==ma) { + if(cu->id.lib) lib= 1; + else local= 1; + } + } + } + cu= cu->id.next; + } + /* test mballs */ + mb= G.main->mball.first; + while(mb) { + if(mb->mat) { + for(a=0; a<mb->totcol; a++) { + if(mb->mat[a]==ma) { + if(mb->id.lib) lib= 1; + else local= 1; + } + } + } + mb= mb->id.next; + } + + if(local && lib==0) { + ma->id.lib= 0; + ma->id.flag= LIB_LOCAL; + + for(a=0; a<8; a++) { + if(ma->mtex[a]) id_lib_extern((ID *)ma->mtex[a]->tex); + } + + new_id(0, (ID *)ma, 0); + } + else if(local && lib) { + man= copy_material(ma); + man->id.us= 0; + + /* do objects */ + ob= G.main->object.first; + while(ob) { + if(ob->mat) { + for(a=0; a<ob->totcol; a++) { + if(ob->mat[a]==ma) { + if(ob->id.lib==0) { + ob->mat[a]= man; + man->id.us++; + ma->id.us--; + } + } + } + } + ob= ob->id.next; + } + /* do meshes */ + me= G.main->mesh.first; + while(me) { + if(me->mat) { + for(a=0; a<me->totcol; a++) { + if(me->mat[a]==ma) { + if(me->id.lib==0) { + me->mat[a]= man; + man->id.us++; + ma->id.us--; + } + } + } + } + me= me->id.next; + } + /* do curves */ + cu= G.main->curve.first; + while(cu) { + if(cu->mat) { + for(a=0; a<cu->totcol; a++) { + if(cu->mat[a]==ma) { + if(cu->id.lib==0) { + cu->mat[a]= man; + man->id.us++; + ma->id.us--; + } + } + } + } + cu= cu->id.next; + } + /* do mballs */ + mb= G.main->mball.first; + while(mb) { + if(mb->mat) { + for(a=0; a<mb->totcol; a++) { + if(mb->mat[a]==ma) { + if(mb->id.lib==0) { + mb->mat[a]= man; + man->id.us++; + ma->id.us--; + } + } + } + } + mb= mb->id.next; + } + } +} + +Material ***give_matarar(Object *ob) +{ + Mesh *me; + Curve *cu; + MetaBall *mb; + + if(ob->type==OB_MESH) { + me= ob->data; + return &(me->mat); + } + else if ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF) { + cu= ob->data; + return &(cu->mat); + } + else if(ob->type==OB_MBALL) { + mb= ob->data; + return &(mb->mat); + } + return 0; +} + +short *give_totcolp(Object *ob) +{ + Mesh *me; + Curve *cu; + MetaBall *mb; + + if(ob->type==OB_MESH) { + me= ob->data; + return &(me->totcol); + } + else if ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF) { + cu= ob->data; + return &(cu->totcol); + } + else if(ob->type==OB_MBALL) { + mb= ob->data; + return &(mb->totcol); + } + return 0; +} + +Material *give_current_material(Object *ob, int act) +{ + Material ***matarar, *ma; + + if(ob==0) return 0; + if(ob->totcol==0) return 0; + + if(act>ob->totcol) act= ob->totcol; + else if(act==0) act= 1; + + if( BTST(ob->colbits, act-1) ) { /* aan object */ + ma= ob->mat[act-1]; + } + else { /* aan data */ + matarar= give_matarar(ob); + + if(matarar && *matarar) ma= (*matarar)[act-1]; + else ma= 0; + + } + + return ma; +} + +ID *material_from(Object *ob, int act) +{ + + if(ob==0) return 0; + + if(ob->totcol==0) return ob->data; + if(act==0) act= 1; + + if( BTST(ob->colbits, act-1) ) return (ID *)ob; + else return ob->data; +} + +/* GS reads the memory pointed at in a specific ordering. There are, + * however two definitions for it. I have jotted them down here, both, + * but I think the first one is actually used. The thing is that + * big-endian systems might read this the wrong way round. OTOH, we + * constructed the IDs that are read out with this macro explicitly as + * well. I expect we'll sort it out soon... */ + +/* from blendef: */ +#define GS(a) (*((short *)(a))) + +/* from misc_util: flip the bytes from x */ +/* #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1]) */ + +void test_object_materials(ID *id) +{ + /* ob mat-array evenlang maken als obdata mat-array */ + Object *ob; + Mesh *me; + Curve *cu; + MetaBall *mb; + Material **newmatar; + int totcol=0; + + if(id==0) return; + + if( GS(id->name)==ID_ME ) { + me= (Mesh *)id; + totcol= me->totcol; + } + else if( GS(id->name)==ID_CU ) { + cu= (Curve *)id; + totcol= cu->totcol; + } + else if( GS(id->name)==ID_MB ) { + mb= (MetaBall *)id; + totcol= mb->totcol; + } + else return; + + ob= G.main->object.first; + while(ob) { + + if(ob->data==id) { + + if(totcol==0) { + if(ob->totcol) { + MEM_freeN(ob->mat); + ob->mat= 0; + } + } + else if(ob->totcol<totcol) { + newmatar= MEM_callocN(sizeof(void *)*totcol, "newmatar"); + if(ob->totcol) { + memcpy(newmatar, ob->mat, sizeof(void *)*ob->totcol); + MEM_freeN(ob->mat); + } + ob->mat= newmatar; + } + ob->totcol= totcol; + if(ob->totcol && ob->actcol==0) ob->actcol= 1; + if(ob->actcol>ob->totcol) ob->actcol= ob->totcol; + } + ob= ob->id.next; + } +} + + +void assign_material(Object *ob, Material *ma, int act) +{ + Material *mao, **matar, ***matarar; + short *totcolp; + + if(act>MAXMAT) return; + if(act<1) act= 1; + + /* test arraylens */ + + totcolp= give_totcolp(ob); + matarar= give_matarar(ob); + + if(totcolp==0 || matarar==0) return; + + if( act > *totcolp) { + matar= MEM_callocN(sizeof(void *)*act, "matarray1"); + if( *totcolp) { + memcpy(matar, *matarar, sizeof(void *)*( *totcolp )); + MEM_freeN(*matarar); + } + *matarar= matar; + *totcolp= act; + } + + if(act > ob->totcol) { + matar= MEM_callocN(sizeof(void *)*act, "matarray2"); + if( ob->totcol) { + memcpy(matar, ob->mat, sizeof(void *)*( ob->totcol )); + MEM_freeN(ob->mat); + } + ob->mat= matar; + ob->totcol= act; + } + + /* doe 't */ + + if( BTST(ob->colbits, act-1) ) { /* aan object */ + mao= ob->mat[act-1]; + if(mao) mao->id.us--; + ob->mat[act-1]= ma; + } + else { /* aan data */ + mao= (*matarar)[act-1]; + if(mao) mao->id.us--; + (*matarar)[act-1]= ma; + } + id_us_plus((ID *)ma); + test_object_materials(ob->data); +} + +void new_material_to_objectdata(Object *ob) +{ + Material *ma; + + if(ob==0) return; + if(ob->totcol>=MAXMAT) return; + + ma= give_current_material(ob, ob->actcol); + if(ma==0) { + ma= add_material("Material"); + ma->id.us= 0; + } + + if(ob->actcol) { + if( BTST(ob->colbits, ob->actcol-1) ) { + ob->colbits= BSET(ob->colbits, ob->totcol); + } + } + + assign_material(ob, ma, ob->totcol+1); + ob->actcol= ob->totcol; +} + + +void init_render_material(Material *ma) +{ + MTex *mtex; + int a, needuv=0; + + if(ma->ren) return; + + if(ma->flarec==0) ma->flarec= 1; + + ma->ren= MEM_mallocN(sizeof(Material), "initrendermaterial"); + memcpy(ma->ren, ma, sizeof(Material)); + + /* alle texcoflags van mtex adden */ + ma= ma->ren; + ma->texco= 0; + ma->mapto= 0; + for(a=0; a<8; a++) { + mtex= ma->mtex[a]; + if(mtex && mtex->tex) { + + /* force std. ref mapping for envmap */ + if(mtex->tex->type==TEX_ENVMAP) { +/* mtex->texco= TEXCO_REFL; */ +/* mtex->projx= PROJ_X; */ +/* mtex->projy= PROJ_Y; */ +/* mtex->projz= PROJ_Z; */ +/* mtex->mapping= MTEX_FLAT; */ + } + /* hier niet testen op mtex->object en mtex->texco op TEXCO_ORCO zetten: mtex is linked! */ + + ma->texco |= mtex->texco; + ma->mapto |= mtex->mapto; + if(R.osa) { + if ELEM3(mtex->tex->type, TEX_IMAGE, TEX_PLUGIN, TEX_ENVMAP) ma->texco |= TEXCO_OSA; + } + + if(ma->texco & (511)) needuv= 1; + + if(mtex->object) mtex->object->flag |= OB_DO_IMAT; + + } + } + if(ma->mode & MA_ZTRA) { + /* if(ma->alpha==0.0 || ma->alpha==1.0) */ + R.flag |= R_ZTRA; + } + if(ma->mode & MA_VERTEXCOLP) ma->mode |= MA_VERTEXCOL; + + if(ma->mode & (MA_VERTEXCOL|MA_FACETEXTURE)) { + needuv= 1; + if(R.osa) ma->texco |= TEXCO_OSA; /* for texfaces */ + } + if(needuv) ma->texco |= NEED_UV; + + ma->ambr= ma->amb*R.wrld.ambr; + ma->ambg= ma->amb*R.wrld.ambg; + ma->ambb= ma->amb*R.wrld.ambb; + +} + +void init_render_materials() +{ + Material *ma; + + ma= G.main->mat.first; + while(ma) { + if(ma->id.us) init_render_material(ma); + ma= ma->id.next; + } + +} + +void end_render_material(Material *ma) +{ + + if(ma->ren) MEM_freeN(ma->ren); + ma->ren= 0; + + if(ma->mode & (MA_VERTEXCOLP|MA_FACETEXTURE)) { + if( !(ma->mode & MA_HALO) ) { + ma->r= ma->g= ma->b= 1.0; + } + } +} + +void end_render_materials() +{ + Material *ma; + + ma= G.main->mat.first; + while(ma) { + if(ma->id.us) end_render_material(ma); + ma= ma->id.next; + } + +} + + +/* ****************** */ + +char colname_array[125][20]= { +"Black","DarkRed","HalveRed","Red","Red", +"DarkGreen","DarkOlive","Brown","Chocolate","OrangeRed", +"HalveGreen","GreenOlive","DryOlive","Goldenrod","DarkOrange", +"LightGreen","Chartreuse","YellowGreen","Yellow","Gold", +"Green","LawnGreen","GreenYellow","LightOlive","Yellow", +"DarkBlue","DarkPurple","HotPink","VioletPink","RedPink", +"SlateGray","DarkGrey","PalePurple","IndianRed","Tomato", +"SeaGreen","PaleGreen","GreenKhaki","LightBrown","LightSalmon", +"SpringGreen","PaleGreen","MediumOlive","YellowBrown","LightGold", +"LightGreen","LightGreen","LightGreen","GreenYellow","PaleYellow", +"HalveBlue","DarkSky","HalveMagenta","VioletRed","DeepPink", +"SteelBlue","SkyBlue","Orchid","LightHotPink","HotPink", +"SeaGreen","SlateGray","MediumGrey","Burlywood","LightPink", +"SpringGreen","Aquamarine","PaleGreen","Khaki","PaleOrange", +"SpringGreen","SeaGreen","PaleGreen","PaleWhite","YellowWhite", +"LightBlue","Purple","MediumOrchid","Magenta","Magenta", +"RoyalBlue","SlateBlue","MediumOrchid","Orchid","Magenta", +"DeepSkyBlue","LightSteelBlue","LightSkyBlue","Violet","LightPink", +"Cyaan","DarkTurquoise","SkyBlue","Grey","Snow", +"Mint","Mint","Aquamarine","MintCream","Ivory", +"Blue","Blue","DarkMagenta","DarkOrchid","Magenta", +"SkyBlue","RoyalBlue","LightSlateBlue","MediumOrchid","Magenta", +"DodgerBlue","SteelBlue","MediumPurple","PalePurple","Plum", +"DeepSkyBlue","PaleBlue","LightSkyBlue","PalePurple","Thistle", +"Cyan","ColdBlue","PaleTurquoise","GhostWhite","White" +}; + +void automatname(Material *ma) +{ + int nr, r, g, b; + float ref; + + if(ma==0) return; + if(ma->mode & MA_SHLESS) ref= 1.0; + else ref= ma->ref; + + r= (int)(4.99*(ref*ma->r)); + g= (int)(4.99*(ref*ma->g)); + b= (int)(4.99*(ref*ma->b)); + nr= r + 5*g + 25*b; + if(nr>124) nr= 124; + new_id(&G.main->mat, (ID *)ma, colname_array[nr]); + +} + + +void delete_material_index() +{ + Material *mao, ***matarar; + Object *ob, *obt; + Mesh *me; + Curve *cu; + Nurb *nu; + MFace *mface; + short *totcolp; + int a, actcol; + + if(G.obedit) { + error("Unable to perform function in EditMode"); + return; + } + ob= ((G.scene->basact)? (G.scene->basact->object) : 0) ; + if(ob==0 || ob->totcol==0) return; + + /* neem als uitgangspunt de mesh/curve/mball, verwijder 1 index, EN bij alle ob's + * die ook zelfde ob->data hebben + * + * Daarna ook indexen in mesh/curve/mball wijzigen!!! + */ + + totcolp= give_totcolp(ob); + matarar= give_matarar(ob); + + /* we deleten de actcol */ + if(ob->totcol) { + mao= (*matarar)[ob->actcol-1]; + if(mao) mao->id.us--; + } + + for(a=ob->actcol; a<ob->totcol; a++) { + (*matarar)[a-1]= (*matarar)[a]; + } + (*totcolp)--; + + if(*totcolp==0) { + MEM_freeN(*matarar); + *matarar= 0; + } + + actcol= ob->actcol; + obt= G.main->object.first; + while(obt) { + + if(obt->data==ob->data) { + + /* LET OP: actcol hier niet van ob of van obt pakken (kan nul worden) */ + mao= obt->mat[actcol-1]; + if(mao) mao->id.us--; + + for(a=actcol; a<obt->totcol; a++) obt->mat[a-1]= obt->mat[a]; + obt->totcol--; + if(obt->actcol > obt->totcol) obt->actcol= obt->totcol; + + if(obt->totcol==0) { + MEM_freeN(obt->mat); + obt->mat= 0; + } + } + obt= obt->id.next; + } + allqueue(REDRAWBUTSMAT, 0); + + + /* indexen van mesh goedzetten */ + + if(ob->type==OB_MESH) { + me= get_mesh(ob); + mface= me->mface; + a= me->totface; + while(a--) { + if(mface->mat_nr && mface->mat_nr>=actcol-1) mface->mat_nr--; + mface++; + } + makeDispList(ob); + } + else if ELEM(ob->type, OB_CURVE, OB_SURF) { + cu= ob->data; + nu= cu->nurb.first; + + while(nu) { + if(nu->mat_nr && nu->mat_nr>=actcol-1) nu->mat_nr--; + nu= nu->next; + } + makeDispList(ob); + } +} diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c new file mode 100644 index 00000000000..9f09191f9d2 --- /dev/null +++ b/source/blender/blenkernel/intern/mball.c @@ -0,0 +1,1540 @@ +/* mball.c MIXED MODEL + * + * mei 95 + * + * + * + * METABALLS ontstaan vanuit een Object (naam zonder nr), hier zit de DispList en boundbox, + * alle objecten met zelfde naam (en een nr) worden hieraan toegevoegd. + * + * De texture coordinaten zitten als loos element in de displist. + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <stdio.h> +#include <string.h> +#include <math.h> +#include <stdlib.h> +#include "MEM_guardedalloc.h" + +#include "DNA_material_types.h" +#include "DNA_object_types.h" +#include "DNA_meta_types.h" +#include "DNA_scene_types.h" +#include "DNA_mesh_types.h" + + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" + +#include "BKE_utildefines.h" +#include "BKE_bad_level_calls.h" + +#include "BKE_global.h" +#include "BKE_main.h" + +/* #include "BKE_object.h" */ +#include "BKE_scene.h" +#include "BKE_blender.h" +#include "BKE_library.h" +#include "BKE_displist.h" +#include "BKE_mball.h" + +/* Functions */ + + + +void unlink_mball(MetaBall *mb) +{ + int a; + + for(a=0; a<mb->totcol; a++) { + if(mb->mat[a]) mb->mat[a]->id.us--; + mb->mat[a]= 0; + } + + +} + + +/* niet mball zelf vrijgeven */ +void free_mball(MetaBall *mb) +{ + + unlink_mball(mb); + + if(mb->mat) MEM_freeN(mb->mat); + if(mb->bb) MEM_freeN(mb->bb); + BLI_freelistN(&mb->elems); + if(mb->disp.first) freedisplist(&mb->disp); +} + +MetaBall *add_mball() +{ + MetaBall *mb; + + mb= alloc_libblock(&G.main->mball, ID_MB, "Meta"); + + mb->size[0]= mb->size[1]= mb->size[2]= 1.0; + mb->texflag= AUTOSPACE; + + mb->wiresize= 0.4f; + mb->rendersize= 0.2f; + mb->thresh= 0.6f; + + return mb; +} + +MetaBall *copy_mball(MetaBall *mb) +{ + MetaBall *mbn; + int a; + + mbn= copy_libblock(mb); + + duplicatelist(&mbn->elems, &mb->elems); + + mbn->mat= MEM_dupallocN(mb->mat); + for(a=0; a<mbn->totcol; a++) { + id_us_plus((ID *)mbn->mat[a]); + } + mbn->bb= MEM_dupallocN(mb->bb); + + return mbn; +} + +void make_local_mball(MetaBall *mb) +{ + Object *ob; + MetaBall *mbn; + int local=0, lib=0; + + /* - zijn er alleen lib users: niet doen + * - zijn er alleen locale users: flag zetten + * - mixed: copy + */ + + if(mb->id.lib==0) return; + if(mb->id.us==1) { + mb->id.lib= 0; + mb->id.flag= LIB_LOCAL; + return; + } + + ob= G.main->object.first; + while(ob) { + if(ob->data==mb) { + if(ob->id.lib) lib= 1; + else local= 1; + } + ob= ob->id.next; + } + + if(local && lib==0) { + mb->id.lib= 0; + mb->id.flag= LIB_LOCAL; + } + else if(local && lib) { + mbn= copy_mball(mb); + mbn->id.us= 0; + + ob= G.main->object.first; + while(ob) { + if(ob->data==mb) { + + if(ob->id.lib==0) { + ob->data= mbn; + mbn->id.us++; + mb->id.us--; + } + } + ob= ob->id.next; + } + } +} + + +void tex_space_mball(Object *ob) +{ + DispList *dl; + BoundBox *bb; + float *data, min[3], max[3], loc[3], size[3]; + int tot, doit=0; + + if(ob->bb==0) ob->bb= MEM_callocN(sizeof(BoundBox), "mb boundbox"); + bb= ob->bb; + + /* Weird one, this. */ +/* INIT_MINMAX(min, max); */ + (min)[0]= (min)[1]= (min)[2]= 1.0e30f; + (max)[0]= (max)[1]= (max)[2]= -1.0e30f; + + dl= ob->disp.first; + while(dl) { + tot= dl->nr; + if(tot) doit= 1; + data= dl->verts; + while(tot--) { + /* Also weird... but longer. From utildefines. */ + DO_MINMAX(data, min, max); + data+= 3; + } + dl= dl->next; + } + + if(doit) { + loc[0]= (min[0]+max[0])/2.0f; + loc[1]= (min[1]+max[1])/2.0f; + loc[2]= (min[2]+max[2])/2.0f; + + size[0]= (max[0]-min[0])/2.0f; + size[1]= (max[1]-min[1])/2.0f; + size[2]= (max[2]-min[2])/2.0f; + } + else { + loc[0]= loc[1]= loc[2]= 0.0f; + size[0]= size[1]= size[2]= 1.0f; + } + + bb->vec[0][0]=bb->vec[1][0]=bb->vec[2][0]=bb->vec[3][0]= loc[0]-size[0]; + bb->vec[4][0]=bb->vec[5][0]=bb->vec[6][0]=bb->vec[7][0]= loc[0]+size[0]; + + bb->vec[0][1]=bb->vec[1][1]=bb->vec[4][1]=bb->vec[5][1]= loc[1]-size[1]; + bb->vec[2][1]=bb->vec[3][1]=bb->vec[6][1]=bb->vec[7][1]= loc[1]+size[1]; + + bb->vec[0][2]=bb->vec[3][2]=bb->vec[4][2]=bb->vec[7][2]= loc[2]-size[2]; + bb->vec[1][2]=bb->vec[2][2]=bb->vec[5][2]=bb->vec[6][2]= loc[2]+size[2]; + +} + +void make_orco_mball(Object *ob) +{ + BoundBox *bb; + DispList *dl; + float *data; + float loc[3], size[3]; + int a; + + /* size en loc restoren */ + bb= ob->bb; + loc[0]= (bb->vec[0][0]+bb->vec[4][0])/2.0f; + size[0]= bb->vec[4][0]-loc[0]; + loc[1]= (bb->vec[0][1]+bb->vec[2][1])/2.0f; + size[1]= bb->vec[2][1]-loc[1]; + loc[2]= (bb->vec[0][2]+bb->vec[1][2])/2.0f; + size[2]= bb->vec[1][2]-loc[2]; + + dl= ob->disp.first; + data= dl->verts; + a= dl->nr; + while(a--) { + data[0]= (data[0]-loc[0])/size[0]; + data[1]= (data[1]-loc[1])/size[1]; + data[2]= (data[2]-loc[2])/size[2]; + + data+= 3; + } +} + + +Object *find_basis_mball(Object *basis) +{ + Base *base; + int basisnr; + char basisname[32]; + + splitIDname(basis->id.name+2, basisname, &basisnr); + + for (base= G.scene->base.first; base && basisnr; base= base->next) { + Object *ob= base->object; + + if (ob!=basis && ob->type==OB_MBALL) { + char obname[32]; + int obnr; + + splitIDname(ob->id.name+2, obname, &obnr); + + if ((strcmp(obname, basisname)==0) && obnr<basisnr) { + basis= ob; + basisnr= obnr; + } + } + } + + return basis; +} + + +/* ******************** ARITH ************************* */ + +/* DANKBAAR GEBRUIK GEMAAKT VAN (EN COMPLEET VERANDERD) : + * C code from the article + * "An Implicit Surface Polygonizer" + * by Jules Bloomenthal, jbloom@beauty.gmu.edu + * in "Graphics Gems IV", Academic Press, 1994 + + * Authored by Jules Bloomenthal, Xerox PARC. + * Copyright (c) Xerox Corporation, 1991. All rights reserved. + * Permission is granted to reproduce, use and distribute this code for + * any and all purposes, provided that this notice appears in all copies. */ + +#define RES 12 /* # converge iterations */ + +#define L 0 /* left direction: -x, -i */ +#define R 1 /* right direction: +x, +i */ +#define B 2 /* bottom direction: -y, -j */ +#define T 3 /* top direction: +y, +j */ +#define N 4 /* near direction: -z, -k */ +#define F 5 /* far direction: +z, +k */ +#define LBN 0 /* left bottom near corner */ +#define LBF 1 /* left bottom far corner */ +#define LTN 2 /* left top near corner */ +#define LTF 3 /* left top far corner */ +#define RBN 4 /* right bottom near corner */ +#define RBF 5 /* right bottom far corner */ +#define RTN 6 /* right top near corner */ +#define RTF 7 /* right top far corner */ + +/* the LBN corner of cube (i, j, k), corresponds with location + * (start.x+(i-0.5)*size, start.y+(j-0.5)*size, start.z+(k-0.5)*size) */ + +#define HASHBIT (5) +#define HASHSIZE (size_t)(1<<(3*HASHBIT)) /* hash table size (32768) */ + +#define HASH(i,j,k) ((((( (i) & 31)<<5) | ( (j) & 31))<<5 ) | ( (k) & 31) ) + +#define MB_BIT(i, bit) (((i)>>(bit))&1) +#define FLIP(i,bit) ((i)^1<<(bit)) /* flip the given bit of i */ + +typedef struct point { /* a three-dimensional point */ + float x, y, z; /* its coordinates */ +} MB_POINT; + +typedef struct vertex { /* surface vertex */ + MB_POINT position, normal; /* position and surface normal */ +} VERTEX; + +typedef struct vertices { /* list of vertices in polygonization */ + int count, max; /* # vertices, max # allowed */ + VERTEX *ptr; /* dynamically allocated */ +} VERTICES; + +typedef struct corner { /* corner of a cube */ + int i, j, k; /* (i, j, k) is index within lattice */ + float x, y, z, value; /* location and function value */ + struct corner *next; +} CORNER; + +typedef struct cube { /* partitioning cell (cube) */ + int i, j, k; /* lattice location of cube */ + CORNER *corners[8]; /* eight corners */ +} CUBE; + +typedef struct cubes { /* linked list of cubes acting as stack */ + CUBE cube; /* a single cube */ + struct cubes *next; /* remaining elements */ +} CUBES; + +typedef struct centerlist { /* list of cube locations */ + int i, j, k; /* cube location */ + struct centerlist *next; /* remaining elements */ +} CENTERLIST; + +typedef struct edgelist { /* list of edges */ + int i1, j1, k1, i2, j2, k2; /* edge corner ids */ + int vid; /* vertex id */ + struct edgelist *next; /* remaining elements */ +} EDGELIST; + +typedef struct intlist { /* list of integers */ + int i; /* an integer */ + struct intlist *next; /* remaining elements */ +} INTLIST; + +typedef struct intlists { /* list of list of integers */ + INTLIST *list; /* a list of integers */ + struct intlists *next; /* remaining elements */ +} INTLISTS; + +typedef struct process { /* parameters, function, storage */ + /* what happens here? floats, I think. */ + /* float (*function)(void); */ /* implicit surface function */ + float (*function)(float, float, float); + float size, delta; /* cube size, normal delta */ + int bounds; /* cube range within lattice */ + MB_POINT start; /* start point on surface */ + CUBES *cubes; /* active cubes */ + VERTICES vertices; /* surface vertices */ + CENTERLIST **centers; /* cube center hash table */ + CORNER **corners; /* corner value hash table */ + EDGELIST **edges; /* edge and vertex id hash table */ +} PROCESS; + +/* Some declarations are in order !!! */ + +/* these should go into a header ! But the compiler doesn't like that, + * for some reason */ + +void freepolygonize(PROCESS *p); +void docube(CUBE *cube, PROCESS *p); +void testface(int i, int j, int k, CUBE* old, + int bit, int c1, int c2, int c3, int c4, PROCESS *p); +CORNER *setcorner (PROCESS* p, int i, int j, int k); +int vertid (CORNER *c1, CORNER *c2, PROCESS *p); +int setcenter(CENTERLIST *table[], int i, int j, int k); +int otherface (int edge, int face); +void makecubetable (void); +void setedge (EDGELIST *table[], + int i1, int j1, + int k1, int i2, + int j2, int k2, + int vid); +int getedge (EDGELIST *table[], + int i1, int j1, int k1, + int i2, int j2, int k2); +void addtovertices (VERTICES *vertices, VERTEX v); +void vnormal (MB_POINT *point, PROCESS *p, MB_POINT *v); +void converge (MB_POINT *p1, MB_POINT *p2, float v, + float (*function)(float, float, float), MB_POINT *p); +void polygonize(PROCESS *mbproc); +float init_meta(Object *ob); + +/* **************** METABALL ************************ */ + +/* void converge (MB_POINT *p1, MB_POINT *p2, float v, float (*function)(void), MB_POINT *p); */ + +void calc_mballco(MetaElem *ml, float *vec) +{ + if(ml->mat) { + Mat4MulVecfl(ml->mat, vec); + } +} + + +float thresh= 0.6f; +int totelem=0; +MetaElem **mainb; + +float densfunc(MetaElem *ball, float x, float y, float z) +{ + float dist2 = 0.0, dx, dy, dz; + float vec[3]; + + if(ball->imat) { + vec[0]= x; + vec[1]= y; + vec[2]= z; + Mat4MulVecfl(ball->imat, vec); + dx= ball->x - vec[0]; + dy= ball->y - vec[1]; + dz= ball->z - vec[2]; + } + else { + dx= ball->x - x; + dy= ball->y - y; + dz= ball->z - z; + } + + if(ball->type==MB_BALL) { + dist2= (dx*dx + dy*dy + dz*dz); + } + else if(ball->type & MB_TUBEZ) { + if(ball->type==MB_TUBEZ) { + if( dz > ball->len) dz-= ball->len; + else if(dz< -ball->len) dz+= ball->len; + else dz= 0.0; + } + else if(ball->type==MB_TUBEY) { + if( dy > ball->len) dy-= ball->len; + else if(dy< -ball->len) dy+= ball->len; + else dy= 0.0; + } + else { + if( dx > ball->len) dx-= ball->len; + else if(dx< -ball->len) dx+= ball->len; + else dx= 0.0; + } + dist2= (dx*dx + dy*dy + dz*dz); + } + /* else if(ball->type==MB_CIRCLE) { */ + /* dist2= 0.5-dz; */ + /* } */ + + if(ball->flag & MB_NEGATIVE) { + + dist2= 1.0f-(dist2/ball->rad2); + if(dist2 < 0.0) return 0.5f; + + return 0.5f-ball->s*dist2*dist2*dist2; + + } + else { + dist2= 1.0f-(dist2/ball->rad2); + if(dist2 < 0.0) return -0.5f; + + return ball->s*dist2*dist2*dist2 -0.5f; + + /* return ball->s*sin( dist2); */ + + } + +} + + +float metaball(float x, float y, float z) +/* float x, y, z; */ +{ + float dens=0; + int a; + + for(a=0; a<totelem; a++) { + dens+= densfunc( mainb[a], x, y, z); + } + + return thresh - dens; +} + +/* ******************************************** */ + +int *indices=0; +int totindex, curindex; + + +void accum_mballfaces(int i1, int i2, int i3, int i4) +{ + int *newi, *cur; + /* static int i=0; I would like to delete altogether, but I don't dare to, yet */ + + if(totindex==curindex) { + totindex+= 256; + newi= MEM_mallocN(4*sizeof(int)*totindex, "vertindex"); + + if(indices) { + memcpy(newi, indices, 4*sizeof(int)*(totindex-256)); + MEM_freeN(indices); + } + indices= newi; + } + + cur= indices+4*curindex; + + /* voorkomen dat nulcodes voorkomen */ + if(i3==0) { + if(i4) { + i3= i4; + i4= i1; + i1= i2; + i2= 0; + } + else { + i3= i2; + i2= i1; + i1= 0; + } + } + + cur[0]= i1; + cur[1]= i2; + cur[2]= i3; + cur[3]= i4; + + curindex++; + +} + +/* ******************* MEMORY MANAGEMENT *********************** */ + +struct pgn_elements { + struct pgn_elements *next, *prev; + char *data; + +}; + +void *new_pgn_element(int size) +{ + /* gedurende het polygonizeren worden duizenden elementen aangemaakt en + * nooit (tussendoor) vrijgegeven. Alleen op eind is vrijgeven nodig. + */ + int blocksize= 16384; + static int offs= 0; /* het huidige vrije adres */ + static struct pgn_elements *cur= 0; + static ListBase lb= {0, 0}; + void *adr; + + if(size>10000 || size==0) { + printf("incorrect use of new_pgn_element\n"); + /* exit(0); */ + } + else if(size== -1) { + cur= lb.first; + while(cur) { + MEM_freeN(cur->data); + cur= cur->next; + } + BLI_freelistN(&lb); + + return NULL; + } + + size= 4*( (size+3)/4 ); + + if(cur) { + if(size+offs < blocksize) { + adr= (void *) (cur->data+offs); + offs+= size; + return adr; + } + } + + cur= MEM_callocN( sizeof(struct pgn_elements), "newpgn"); + cur->data= MEM_callocN(blocksize, "newpgn"); + BLI_addtail(&lb, cur); + + offs= size; + return cur->data; +} + +void freepolygonize(PROCESS *p) +{ + MEM_freeN(p->corners); + MEM_freeN(p->edges); + MEM_freeN(p->centers); + + new_pgn_element(-1); + + if(p->vertices.ptr) MEM_freeN(p->vertices.ptr); +} + +/**** Cubical Polygonization (optional) ****/ + + +#define LB 0 /* left bottom edge */ +#define LT 1 /* left top edge */ +#define LN 2 /* left near edge */ +#define LF 3 /* left far edge */ +#define RB 4 /* right bottom edge */ +#define RT 5 /* right top edge */ +#define RN 6 /* right near edge */ +#define RF 7 /* right far edge */ +#define BN 8 /* bottom near edge */ +#define BF 9 /* bottom far edge */ +#define TN 10 /* top near edge */ +#define TF 11 /* top far edge */ + +static INTLISTS *cubetable[256]; + +/* edge: LB, LT, LN, LF, RB, RT, RN, RF, BN, BF, TN, TF */ +static int corner1[12] = { + LBN,LTN,LBN,LBF,RBN,RTN,RBN,RBF,LBN,LBF,LTN,LTF}; +static int corner2[12] = { + LBF,LTF,LTN,LTF,RBF,RTF,RTN,RTF,RBN,RBF,RTN,RTF}; +static int leftface[12] = { + B, L, L, F, R, T, N, R, N, B, T, F}; +/* face on left when going corner1 to corner2 */ +static int rightface[12] = { + L, T, N, L, B, R, R, F, B, F, N, T}; +/* face on right when going corner1 to corner2 */ + + +/* docube: triangulate the cube directly, without decomposition */ + +void docube(CUBE *cube, PROCESS *p) +{ + INTLISTS *polys; + CORNER *c1, *c2; + int i, index = 0, count, indexar[8]; + + for (i = 0; i < 8; i++) if (cube->corners[i]->value > 0.0) index += (1<<i); + + for (polys = cubetable[index]; polys; polys = polys->next) { + INTLIST *edges; + + count = 0; + + for (edges = polys->list; edges; edges = edges->next) { + c1 = cube->corners[corner1[edges->i]]; + c2 = cube->corners[corner2[edges->i]]; + + indexar[count] = vertid(c1, c2, p); + count++; + } + if(count>2) { + switch(count) { + case 3: + accum_mballfaces(indexar[2], indexar[1], indexar[0], 0); + break; + case 4: + if(indexar[0]==0) accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]); + else accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]); + break; + case 5: + if(indexar[0]==0) accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]); + else accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]); + + accum_mballfaces(indexar[4], indexar[3], indexar[0], 0); + break; + case 6: + if(indexar[0]==0) { + accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]); + accum_mballfaces(indexar[0], indexar[5], indexar[4], indexar[3]); + } + else { + accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]); + accum_mballfaces(indexar[5], indexar[4], indexar[3], indexar[0]); + } + break; + case 7: + if(indexar[0]==0) { + accum_mballfaces(indexar[0], indexar[3], indexar[2], indexar[1]); + accum_mballfaces(indexar[0], indexar[5], indexar[4], indexar[3]); + } + else { + accum_mballfaces(indexar[3], indexar[2], indexar[1], indexar[0]); + accum_mballfaces(indexar[5], indexar[4], indexar[3], indexar[0]); + } + + accum_mballfaces(indexar[6], indexar[5], indexar[0], 0); + + break; + } + } + } +} + + +/* testface: given cube at lattice (i, j, k), and four corners of face, + * if surface crosses face, compute other four corners of adjacent cube + * and add new cube to cube stack */ + +void testface(int i, int j, int k, CUBE* old, int bit, int c1, int c2, int c3, int c4, PROCESS *p) +/* CUBE *old; */ +/* PROCESS *p; */ +/* int i, j, k, bit, c1, c2, c3, c4; */ +{ + CUBE newc; + CUBES *oldcubes = p->cubes; + CORNER *corn1, *corn2, *corn3, *corn4; + int n, pos; + + corn1= old->corners[c1]; + corn2= old->corners[c2]; + corn3= old->corners[c3]; + corn4= old->corners[c4]; + + pos = corn1->value > 0.0 ? 1 : 0; + + /* test if no surface crossing */ + if( (corn2->value > 0) == pos && (corn3->value > 0) == pos && (corn4->value > 0) == pos) return; + /* test if cube out of bounds */ + if ( abs(i) > p->bounds || abs(j) > p->bounds || abs(k) > p->bounds) return; + /* test if already visited (always as last) */ + if (setcenter(p->centers, i, j, k)) return; + + + /* create new cube and add cube to top of stack: */ + p->cubes = (CUBES *) new_pgn_element(sizeof(CUBES)); + p->cubes->next = oldcubes; + + newc.i = i; + newc.j = j; + newc.k = k; + for (n = 0; n < 8; n++) newc.corners[n] = NULL; + + newc.corners[FLIP(c1, bit)] = corn1; + newc.corners[FLIP(c2, bit)] = corn2; + newc.corners[FLIP(c3, bit)] = corn3; + newc.corners[FLIP(c4, bit)] = corn4; + + if(newc.corners[0]==0) newc.corners[0] = setcorner(p, i, j, k); + if(newc.corners[1]==0) newc.corners[1] = setcorner(p, i, j, k+1); + if(newc.corners[2]==0) newc.corners[2] = setcorner(p, i, j+1, k); + if(newc.corners[3]==0) newc.corners[3] = setcorner(p, i, j+1, k+1); + if(newc.corners[4]==0) newc.corners[4] = setcorner(p, i+1, j, k); + if(newc.corners[5]==0) newc.corners[5] = setcorner(p, i+1, j, k+1); + if(newc.corners[6]==0) newc.corners[6] = setcorner(p, i+1, j+1, k); + if(newc.corners[7]==0) newc.corners[7] = setcorner(p, i+1, j+1, k+1); + + p->cubes->cube= newc; +} + +/* setcorner: return corner with the given lattice location + set (and cache) its function value */ + +CORNER *setcorner (PROCESS* p, int i, int j, int k) +/* int i, j, k; */ +/* PROCESS *p; */ +{ + /* for speed, do corner value caching here */ + CORNER *c; + int index; + + /* bestaat corner al? */ + index = HASH(i, j, k); + c = p->corners[index]; + + for (; c != NULL; c = c->next) { + if (c->i == i && c->j == j && c->k == k) { + return c; + } + } + + c = (CORNER *) new_pgn_element(sizeof(CORNER)); + + c->i = i; + c->x = p->start.x+((float)i-0.5f)*p->size; + c->j = j; + c->y = p->start.y+((float)j-0.5f)*p->size; + c->k = k; + c->z = p->start.z+((float)k-0.5f)*p->size; + c->value = p->function(c->x, c->y, c->z); + + c->next = p->corners[index]; + p->corners[index] = c; + + return c; +} + + +/* nextcwedge: return next clockwise edge from given edge around given face */ + +int nextcwedge (int edge, int face) +{ + switch (edge) { + case LB: + return (face == L)? LF : BN; + case LT: + return (face == L)? LN : TF; + case LN: + return (face == L)? LB : TN; + case LF: + return (face == L)? LT : BF; + case RB: + return (face == R)? RN : BF; + case RT: + return (face == R)? RF : TN; + case RN: + return (face == R)? RT : BN; + case RF: + return (face == R)? RB : TF; + case BN: + return (face == B)? RB : LN; + case BF: + return (face == B)? LB : RF; + case TN: + return (face == T)? LT : RN; + case TF: + return (face == T)? RT : LF; + } + return 0; +} + + +/* otherface: return face adjoining edge that is not the given face */ + +int otherface (int edge, int face) +/* int edge, face; */ +{ + int other = leftface[edge]; + return face == other? rightface[edge] : other; +} + + +/* makecubetable: create the 256 entry table for cubical polygonization */ + +void makecubetable (void) +{ + static int isdone= 0; + int i, e, c, done[12], pos[8]; + + if(isdone) return; + isdone= 1; + + for (i = 0; i < 256; i++) { + for (e = 0; e < 12; e++) done[e] = 0; + for (c = 0; c < 8; c++) pos[c] = MB_BIT(i, c); + for (e = 0; e < 12; e++) + if (!done[e] && (pos[corner1[e]] != pos[corner2[e]])) { + INTLIST *ints = 0; + INTLISTS *lists = (INTLISTS *) MEM_callocN(sizeof(INTLISTS), "mball_intlist"); + int start = e, edge = e; + + /* get face that is to right of edge from pos to neg corner: */ + int face = pos[corner1[e]]? rightface[e] : leftface[e]; + + while (1) { + edge = nextcwedge(edge, face); + done[edge] = 1; + if (pos[corner1[edge]] != pos[corner2[edge]]) { + INTLIST *tmp = ints; + + ints = (INTLIST *) MEM_callocN(sizeof(INTLIST), "mball_intlist"); + ints->i = edge; + ints->next = tmp; /* add edge to head of list */ + + if (edge == start) break; + face = otherface(edge, face); + } + } + lists->list = ints; /* add ints to head of table entry */ + lists->next = cubetable[i]; + cubetable[i] = lists; + } + } +} + +void BKE_freecubetable(void) +{ + int i; + INTLISTS *lists, *nlists; + INTLIST *ints, *nints; + + for (i = 0; i < 256; i++) { + lists= cubetable[i]; + while(lists) { + nlists= lists->next; + + ints= lists->list; + while(ints) { + nints= ints->next; + MEM_freeN(ints); + ints= nints; + } + + MEM_freeN(lists); + lists= nlists; + } + cubetable[i]= 0; + } +} + +/**** Storage ****/ + +/* setcenter: set (i,j,k) entry of table[] + * return 1 if already set; otherwise, set and return 0 */ + +int setcenter(CENTERLIST *table[], int i, int j, int k) +/* CENTERLIST *table[]; */ +/* int i, j, k; */ +{ + int index; + CENTERLIST *newc, *l, *q; + + index= HASH(i, j, k); + q= table[index]; + + for (l = q; l != NULL; l = l->next) { + if (l->i == i && l->j == j && l->k == k) return 1; + } + + newc = (CENTERLIST *) new_pgn_element(sizeof(CENTERLIST)); + newc->i = i; + newc->j = j; + newc->k = k; + newc->next = q; + table[index] = newc; + + return 0; +} + + +/* setedge: set vertex id for edge */ + +void setedge (EDGELIST *table[], + int i1, int j1, + int k1, int i2, + int j2, int k2, + int vid) +/* EDGELIST *table[]; */ +/* int i1, j1, k1, i2, j2, k2, vid; */ +{ + unsigned int index; + EDGELIST *newe; + + if (i1>i2 || (i1==i2 && (j1>j2 || (j1==j2 && k1>k2)))) { + int t=i1; + i1=i2; + i2=t; + t=j1; + j1=j2; + j2=t; + t=k1; + k1=k2; + k2=t; + } + index = HASH(i1, j1, k1) + HASH(i2, j2, k2); + newe = (EDGELIST *) new_pgn_element(sizeof(EDGELIST)); + newe->i1 = i1; + newe->j1 = j1; + newe->k1 = k1; + newe->i2 = i2; + newe->j2 = j2; + newe->k2 = k2; + newe->vid = vid; + newe->next = table[index]; + table[index] = newe; +} + + +/* getedge: return vertex id for edge; return -1 if not set */ + +int getedge (EDGELIST *table[], + int i1, int j1, int k1, + int i2, int j2, int k2) +/* EDGELIST *table[]; */ +/* int i1, j1, k1, i2, j2, k2; */ +{ + EDGELIST *q; + + if (i1>i2 || (i1==i2 && (j1>j2 || (j1==j2 && k1>k2)))) { + int t=i1; + i1=i2; + i2=t; + t=j1; + j1=j2; + j2=t; + t=k1; + k1=k2; + k2=t; + } + q = table[HASH(i1, j1, k1)+HASH(i2, j2, k2)]; + for (; q != NULL; q = q->next) + if (q->i1 == i1 && q->j1 == j1 && q->k1 == k1 && + q->i2 == i2 && q->j2 == j2 && q->k2 == k2) + return q->vid; + return -1; +} + + +/**** Vertices ****/ + +#undef R + + + +/* vertid: return index for vertex on edge: + * c1->value and c2->value are presumed of different sign + * return saved index if any; else compute vertex and save */ + +/* addtovertices: add v to sequence of vertices */ + +void addtovertices (VERTICES *vertices, VERTEX v) +/* VERTICES *vertices; */ +/* VERTEX v; */ +{ + if (vertices->count == vertices->max) { + int i; + VERTEX *newv; + vertices->max = vertices->count == 0 ? 10 : 2*vertices->count; + newv = (VERTEX *) MEM_callocN(vertices->max * sizeof(VERTEX), "addtovertices"); + + for (i = 0; i < vertices->count; i++) newv[i] = vertices->ptr[i]; + + if (vertices->ptr != NULL) MEM_freeN(vertices->ptr); + vertices->ptr = newv; + } + vertices->ptr[vertices->count++] = v; +} + +/* vnormal: compute unit length surface normal at point */ + +void vnormal (MB_POINT *point, PROCESS *p, MB_POINT *v) +/* MB_POINT *point, *v; */ +/* PROCESS *p; */ +{ + float delta= 0.2f*p->delta; + float f = p->function(point->x, point->y, point->z); + + v->x = p->function(point->x+delta, point->y, point->z)-f; + v->y = p->function(point->x, point->y+delta, point->z)-f; + v->z = p->function(point->x, point->y, point->z+delta)-f; + f = (float)sqrt(v->x*v->x + v->y*v->y + v->z*v->z); + + if (f != 0.0) { + v->x /= f; + v->y /= f; + v->z /= f; + } + + if(FALSE) { + /* if(R.flag & R_RENDERING) { */ + MB_POINT temp; + + delta*= 2.0; + + f = p->function(point->x, point->y, point->z); + + temp.x = p->function(point->x+delta, point->y, point->z)-f; + temp.y = p->function(point->x, point->y+delta, point->z)-f; + temp.z = p->function(point->x, point->y, point->z+delta)-f; + f = (float)sqrt(temp.x*temp.x + temp.y*temp.y + temp.z*temp.z); + + if (f != 0.0) { + temp.x /= f; + temp.y /= f; + temp.z /= f; + + v->x+= temp.x; + v->y+= temp.y; + v->z+= temp.z; + + f = (float)sqrt(v->x*v->x + v->y*v->y + v->z*v->z); + + if (f != 0.0) { + v->x /= f; + v->y /= f; + v->z /= f; + } + } + } + +} + + +int vertid (CORNER *c1, CORNER *c2, PROCESS *p) +/* CORNER *c1, *c2; */ +/* PROCESS *p; */ +{ + VERTEX v; + MB_POINT a, b; + int vid = getedge(p->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k); + + if (vid != -1) return vid; /* previously computed */ + a.x = c1->x; + a.y = c1->y; + a.z = c1->z; + b.x = c2->x; + b.y = c2->y; + b.z = c2->z; + + converge(&a, &b, c1->value, p->function, &v.position); /* position */ + vnormal(&v.position, p, &v.normal); + + addtovertices(&p->vertices, v); /* save vertex */ + vid = p->vertices.count-1; + setedge(p->edges, c1->i, c1->j, c1->k, c2->i, c2->j, c2->k, vid); + + return vid; +} + + + + +/* converge: from two points of differing sign, converge to zero crossing */ +/* watch it: p1 and p2 are used to calculate */ + +void converge (MB_POINT *p1, MB_POINT *p2, float v, + float (*function)(float, float, float), MB_POINT *p) +{ + int i = 0; + MB_POINT *pos, *neg; + + if (v < 0) { + pos= p2; + neg= p1; + } + else { + pos= p1; + neg= p2; + } + while (1) { + p->x = 0.5f*(pos->x + neg->x); + p->y = 0.5f*(pos->y + neg->y); + p->z = 0.5f*(pos->z + neg->z); + + if (i++ == RES) return; + + if ((function(p->x, p->y, p->z)) > 0.0) { + pos->x = p->x; + pos->y = p->y; + pos->z = p->z; + } + else { + neg->x = p->x; + neg->y = p->y; + neg->z = p->z; + } + } +} + +/* ************************************** */ + + +void polygonize(PROCESS *mbproc) +{ + MB_POINT in, out; + CUBE c; + CUBES *ncube; +/* CORNER *setcorner(); */ + int a, n, i, j, k; + + mbproc->vertices.count = mbproc->vertices.max = 0; + mbproc->vertices.ptr = NULL; + + /* allocate hash tables and build cube polygon table: */ + mbproc->centers = MEM_callocN(HASHSIZE * sizeof(CENTERLIST *), "mbproc->centers"); + mbproc->corners = MEM_callocN(HASHSIZE * sizeof(CORNER *), "mbproc->corners"); + mbproc->edges = MEM_callocN(2*HASHSIZE * sizeof(EDGELIST *), "mbproc->edges"); + makecubetable(); + + /* find first point on balls */ + for(a=0; a<totelem; a++) { + + in.x= mainb[a]->x; + in.y= mainb[a]->y; + in.z= mainb[a]->z; + calc_mballco(mainb[a], (float *)&in); + + /* added factor 2.0 to be sure it always finds the ball... still unsure why! */ + + out.x= in.x + 2.0f*mainb[a]->rad; + out.y= in.y + 2.0f*mainb[a]->rad; + out.z= in.z + 2.0f*mainb[a]->rad; + calc_mballco(mainb[a], (float *)&out); + + converge(&in, &out, -1.0, mbproc->function, &mbproc->start); + + /* NEW1: zorg voor correcte uitgangspositie */ + i= (int)floor(mbproc->start.x/mbproc->size ); + j= (int)floor(mbproc->start.y/mbproc->size ); + k= (int)floor(mbproc->start.z/mbproc->size ); + + mbproc->start.x= mbproc->start.y= mbproc->start.z= 0.0; + +/* dit gaat niet altijd goed: soms wordt een bal niet gevonden. waarom? */ + + /* test if cube has been found before */ + if( setcenter(mbproc->centers, i, j, k)==0 ) { + + /* push cube on stack: */ + ncube= (CUBES *) new_pgn_element(sizeof(CUBES)); + ncube->next= mbproc->cubes; + mbproc->cubes= ncube; + + ncube->cube.i= i; + ncube->cube.j= j; + ncube->cube.k= k; + + /* set corners of initial cube: */ + for (n = 0; n < 8; n++) + ncube->cube.corners[n] = setcorner(mbproc, i+MB_BIT(n,2), j+MB_BIT(n,1), k+MB_BIT(n,0)); + } + + /* we do a triple test and add a cube if necessary */ + i++; + + /* test if cube has been found before */ + if( setcenter(mbproc->centers, i, j, k)==0 ) { + + /* push cube on stack: */ + ncube= (CUBES *) new_pgn_element(sizeof(CUBES)); + ncube->next= mbproc->cubes; + mbproc->cubes= ncube; + + ncube->cube.i= i; + ncube->cube.j= j; + ncube->cube.k= k; + + /* set corners of initial cube: */ + for (n = 0; n < 8; n++) + ncube->cube.corners[n] = setcorner(mbproc, i+MB_BIT(n,2), j+MB_BIT(n,1), k+MB_BIT(n,0)); + } + + i--; + j++; + + /* test if cube has been found before */ + if( setcenter(mbproc->centers, i, j, k)==0 ) { + + /* push cube on stack: */ + ncube= (CUBES *) new_pgn_element(sizeof(CUBES)); + ncube->next= mbproc->cubes; + mbproc->cubes= ncube; + + ncube->cube.i= i; + ncube->cube.j= j; + ncube->cube.k= k; + + /* set corners of initial cube: */ + for (n = 0; n < 8; n++) + ncube->cube.corners[n] = setcorner(mbproc, i+MB_BIT(n,2), j+MB_BIT(n,1), k+MB_BIT(n,0)); + } + + j--; + k++; + + /* test if cube has been found before */ + if( setcenter(mbproc->centers, i, j, k)==0 ) { + + /* push cube on stack: */ + ncube= (CUBES *) new_pgn_element(sizeof(CUBES)); + ncube->next= mbproc->cubes; + mbproc->cubes= ncube; + + ncube->cube.i= i; + ncube->cube.j= j; + ncube->cube.k= k; + + /* set corners of initial cube: */ + for (n = 0; n < 8; n++) + ncube->cube.corners[n] = setcorner(mbproc, i+MB_BIT(n,2), j+MB_BIT(n,1), k+MB_BIT(n,0)); + } + + i++; + j++; + + /* test if cube has been found before */ + if( setcenter(mbproc->centers, i, j, k)==0 ) { + + /* push cube on stack: */ + ncube= (CUBES *) new_pgn_element(sizeof(CUBES)); + ncube->next= mbproc->cubes; + mbproc->cubes= ncube; + + ncube->cube.i= i; + ncube->cube.j= j; + ncube->cube.k= k; + + /* set corners of initial cube: */ + for (n = 0; n < 8; n++) + ncube->cube.corners[n] = setcorner(mbproc, i+MB_BIT(n,2), j+MB_BIT(n,1), k+MB_BIT(n,0)); + } + } + + while (mbproc->cubes != NULL) { /* process active cubes till none left */ + c = mbproc->cubes->cube; + + /* polygonize the cube directly: */ + docube(&c, mbproc); + + /* pop current cube from stack */ + mbproc->cubes = mbproc->cubes->next; + + /* test six face directions, maybe add to stack: */ + testface(c.i-1, c.j, c.k, &c, 2, LBN, LBF, LTN, LTF, mbproc); + testface(c.i+1, c.j, c.k, &c, 2, RBN, RBF, RTN, RTF, mbproc); + testface(c.i, c.j-1, c.k, &c, 1, LBN, LBF, RBN, RBF, mbproc); + testface(c.i, c.j+1, c.k, &c, 1, LTN, LTF, RTN, RTF, mbproc); + testface(c.i, c.j, c.k-1, &c, 0, LBN, LTN, RBN, RTN, mbproc); + testface(c.i, c.j, c.k+1, &c, 0, LBF, LTF, RBF, RTF, mbproc); + } + +} + +float init_meta(Object *ob) /* return totsize */ +{ + Base *base; + Object *bob; + MetaBall *mb; + MetaElem *ml; + float size, totsize, (*mat)[4] = NULL, (*imat)[4] = NULL, obinv[4][4], vec[3]; + int a, obnr; + char obname[32]; + + Mat4Invert(obinv, ob->obmat); + totelem= 0; + + splitIDname(ob->id.name+2, obname, &obnr); + + /* hoofdarray maken */ + + next_object(0, 0, 0); + while(next_object(1, &base, &bob)) { + + if(bob->type==OB_MBALL) { + ml= 0; + if(bob==ob) { + mat= imat= 0; + mb= ob->data; + + if(ob==G.obedit) ml= editelems.first; + else if(G.obedit && G.obedit->type==OB_MBALL && G.obedit->data==mb) ml= editelems.first; + else ml= mb->elems.first; + } + else { + char name[32]; + int nr; + + splitIDname(bob->id.name+2, name, &nr); + if( strcmp(obname, name)==0 ) { + mb= bob->data; + + if(G.obedit && G.obedit->type==OB_MBALL && G.obedit->data==mb) + ml= editelems.first; + else ml= mb->elems.first; + + /* mat is de matrix om van deze mball in de basis-mbal te komen */ + mat= new_pgn_element(4*4*sizeof(float)); + Mat4MulMat4(mat, bob->obmat, obinv); + + imat= new_pgn_element(4*4*sizeof(float)); + Mat4Invert(imat, mat); + + } + } + while(ml && totelem<MB_MAXELEM) { + a= totelem; + + /* kopie maken i.v.m. duplicates */ + mainb[a]= new_pgn_element(sizeof(MetaElem)); + *(mainb[a])= *ml; + + /* if(mainb[a]->flag & MB_NEGATIVE) mainb[a]->s= 1.0-mainb[a]->s; */ + mainb[a]->rad2= mainb[a]->rad*mainb[a]->rad; + + mainb[a]->mat= (float*) mat; + mainb[a]->imat= (float*) imat; + + ml= ml->next; + totelem++; + + } + } + } + + /* totsize (= 'manhattan' straal) berekenen */ + totsize= 0.0; + for(a=0; a<totelem; a++) { + + vec[0]= mainb[a]->x + mainb[a]->rad; + vec[1]= mainb[a]->y + mainb[a]->rad; + vec[2]= mainb[a]->z + mainb[a]->rad; + + if(mainb[a]->type==MB_TUBEX) vec[0]+= mainb[a]->len; + if(mainb[a]->type==MB_TUBEY) vec[1]+= mainb[a]->len; + if(mainb[a]->type==MB_TUBEZ) vec[2]+= mainb[a]->len; + + calc_mballco(mainb[a], vec); + + size= (float)fabs( vec[0] ); + if( size > totsize ) totsize= size; + size= (float)fabs( vec[1] ); + if( size > totsize ) totsize= size; + size= (float)fabs( vec[2] ); + if( size > totsize ) totsize= size; + + vec[0]= mainb[a]->x - mainb[a]->rad; + vec[1]= mainb[a]->y - mainb[a]->rad; + vec[2]= mainb[a]->z - mainb[a]->rad; + + calc_mballco(mainb[a], vec); + + size= (float)fabs( vec[0] ); + if( size > totsize ) totsize= size; + size= (float)fabs( vec[1] ); + if( size > totsize ) totsize= size; + size= (float)fabs( vec[2] ); + if( size > totsize ) totsize= size; + } + + for(a=0; a<totelem; a++) { + thresh+= densfunc( mainb[a], 2.0f*totsize, 2.0f*totsize, 2.0f*totsize); + } + + return totsize; +} + +void metaball_polygonize(Object *ob) +{ + PROCESS mbproc; + MetaBall *mb; + DispList *dl; + int a, nr_cubes; + float *ve, *no, totsize, width; + + mb= ob->data; + + freedisplist(&ob->disp); + curindex= totindex= 0; + indices= 0; + thresh= mb->thresh; + + if(G.moving && mb->flag==MB_UPDATE_FAST) return; + + mainb= MEM_mallocN(sizeof(void *)*MB_MAXELEM, "mainb"); + + totsize= init_meta(ob); + if(totelem==0) { + MEM_freeN(mainb); + return; + } + + /* width is afmeting per polygoniseerkubus */ + if(R.flag & R_RENDERING) width= mb->rendersize; + else { + width= mb->wiresize; + if(G.moving && mb->flag==MB_UPDATE_HALFRES) width*= 2; + } + /* nr_cubes is voor de veiligheid, minmaal de totsize */ + nr_cubes= (int)(0.5+totsize/width); + + /* init process */ + mbproc.function = metaball; + mbproc.size = width; + mbproc.bounds = nr_cubes; + mbproc.cubes= 0; + mbproc.delta = width/(float)(RES*RES); + + polygonize(&mbproc); + + MEM_freeN(mainb); + + if(curindex) { + + dl= MEM_callocN(sizeof(DispList), "mbaldisp"); + BLI_addtail(&ob->disp, dl); + dl->type= DL_INDEX4; + dl->nr= mbproc.vertices.count; + dl->parts= curindex; + + dl->index= indices; + indices= 0; + + a= mbproc.vertices.count; + dl->verts= ve= MEM_mallocN(sizeof(float)*3*a, "mballverts"); + dl->nors= no= MEM_mallocN(sizeof(float)*3*a, "mballnors"); + + for(a=0; a<mbproc.vertices.count; a++, no+=3, ve+=3) { + ve[0]= mbproc.vertices.ptr[a].position.x; + ve[1]= mbproc.vertices.ptr[a].position.y; + ve[2]= mbproc.vertices.ptr[a].position.z; + + no[0]= mbproc.vertices.ptr[a].normal.x; + no[1]= mbproc.vertices.ptr[a].normal.y; + no[2]= mbproc.vertices.ptr[a].normal.z; + } + } + + freepolygonize(&mbproc); + +} + + diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c new file mode 100644 index 00000000000..720d02ee7bb --- /dev/null +++ b/source/blender/blenkernel/intern/mesh.c @@ -0,0 +1,1120 @@ + +/* mesh.c MIXED MODEL + * + * jan/maart 95 + * + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifdef WIN32 +#include "BLI_winstuff.h" +#endif + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <math.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_ID.h" +#include "DNA_curve_types.h" +#include "DNA_material_types.h" +#include "DNA_object_types.h" +#include "DNA_image_types.h" +#include "DNA_key_types.h" +#include "DNA_mesh_types.h" + +#include "BKE_main.h" +#include "BKE_global.h" +#include "BKE_mesh.h" +#include "BKE_subsurf.h" +#include "BKE_displist.h" +#include "BKE_library.h" +#include "BKE_material.h" +#include "BKE_key.h" +/* these 2 are only used by conversion functions */ +#include "BKE_curve.h" +/* -- */ +#include "BKE_object.h" +#include "BKE_utildefines.h" +#include "BKE_bad_level_calls.h" + +#include "BLI_blenlib.h" +#include "BLI_editVert.h" +#include "BLI_arithb.h" + + + +int update_realtime_texture(TFace *tface, double time) +{ + Image *ima; + int inc = 0; + float diff; + int newframe; + + ima = tface->tpage; + + if (!ima) + return 0; + + if (ima->lastupdate<0) + ima->lastupdate = 0; + + if (ima->lastupdate>time) + ima->lastupdate=(float)time; + + if(ima->tpageflag & IMA_TWINANIM) { + if(ima->twend >= ima->xrep*ima->yrep) ima->twend= ima->xrep*ima->yrep-1; + + /* check: zit de bindcode niet het array? Vrijgeven. (nog doen) */ + + diff = (float)(time-ima->lastupdate); + + inc = (int)(diff*(float)ima->animspeed); + + ima->lastupdate+=((float)inc/(float)ima->animspeed); + + newframe = ima->lastframe+inc; + + if (newframe > (int)ima->twend) + newframe = (int)ima->twsta-1 + (newframe-ima->twend)%(ima->twend-ima->twsta); + + ima->lastframe = newframe; + } + return inc; +} + +float get_mvert_weight (Object *ob, int vert, int defgroup) +{ + int i; + Mesh *me; + float result; + + me=ob->data; + + if (!me->dvert) + return 0.0F; + + result=0.0F; + + for (i=0; i<me->dvert[vert].totweight; i++){ + if (me->dvert[vert].dw[i].def_nr==defgroup) + result+=me->dvert[vert].dw[i].weight; + } + + return result; +} + +void unlink_mesh(Mesh *me) +{ + int a; + + if(me==0) return; + + for(a=0; a<me->totcol; a++) { + if(me->mat[a]) me->mat[a]->id.us--; + me->mat[a]= 0; + } + if(me->key) me->key->id.us--; + me->key= 0; + + if(me->texcomesh) me->texcomesh= 0; +} + + +/* niet mesh zelf vrijgeven */ +void free_mesh(Mesh *me) +{ + + unlink_mesh(me); + + if(me->mat) MEM_freeN(me->mat); + if(me->orco) MEM_freeN(me->orco); + if(me->mface) MEM_freeN(me->mface); + if(me->tface) MEM_freeN(me->tface); + if(me->mvert) MEM_freeN(me->mvert); + if(me->dvert) free_dverts(me->dvert, me->totvert); + if(me->mcol) MEM_freeN(me->mcol); + if(me->msticky) MEM_freeN(me->msticky); + if(me->bb) MEM_freeN(me->bb); + if(me->disp.first) freedisplist(&me->disp); +} + +void copy_dverts(MDeformVert *dst, MDeformVert *src, int copycount) +{ + /* Assumes dst is already set up */ + int i; + + if (!src || !dst) + return; + + memcpy (dst, src, copycount * sizeof(MDeformVert)); + + for (i=0; i<copycount; i++){ + if (src[i].dw){ + dst[i].dw = MEM_callocN (sizeof(MDeformWeight)*src[i].totweight, "copy_deformWeight"); + memcpy (dst[i].dw, src[i].dw, sizeof (MDeformWeight)*src[i].totweight); + } + } + +} +void free_dverts(MDeformVert *dvert, int totvert) +{ + /* Instead of freeing the verts directly, + call this function to delete any special + vert data */ + int i; + + if (!dvert) + return; + + /* Free any special data from the verts */ + for (i=0; i<totvert; i++){ + if (dvert[i].dw) MEM_freeN (dvert[i].dw); + } + MEM_freeN (dvert); +} + +Mesh *add_mesh() +{ + Mesh *me; + + me= alloc_libblock(&G.main->mesh, ID_ME, "Mesh"); + + me->size[0]= me->size[1]= me->size[2]= 1.0; + me->smoothresh= 30; + me->texflag= AUTOSPACE; + me->flag= ME_TWOSIDED; + me->subdiv= 1; + me->subdivr = 1; + me->bb= unit_boundbox(); + + return me; +} + +Mesh *copy_mesh(Mesh *me) +{ + Mesh *men; + int a; + + men= copy_libblock(me); + + men->mat= MEM_dupallocN(me->mat); + for(a=0; a<men->totcol; a++) { + id_us_plus((ID *)men->mat[a]); + } + id_us_plus((ID *)men->texcomesh); + men->mface= MEM_dupallocN(me->mface); + + men->tface= MEM_dupallocN(me->tface); + + men->dface= 0; + men->mvert= MEM_dupallocN(me->mvert); + memcpy (men->mvert, me->mvert, sizeof (MVert)*me->totvert); + if (me->dvert){ + men->dvert = MEM_mallocN (sizeof (MDeformVert)*me->totvert, "MDeformVert"); + copy_dverts(men->dvert, me->dvert, me->totvert); + } + + men->mcol= MEM_dupallocN(me->mcol); + men->msticky= MEM_dupallocN(me->msticky); + men->texcomesh= 0; + men->orco= 0; + men->bb= MEM_dupallocN(men->bb); + + copy_displist(&men->disp, &me->disp); + + men->key= copy_key(me->key); + if(men->key) men->key->from= (ID *)men; + + return men; +} + +void make_local_tface(Mesh *me) +{ + TFace *tface; + Image *ima; + int a; + + if(me->tface==0) return; + + a= me->totface; + tface= me->tface; + while(a--) { + + /* speciaal geval: ima altijd meteen lokaal */ + if(tface->tpage) { + ima= tface->tpage; + if(ima->id.lib) { + ima->id.lib= 0; + ima->id.flag= LIB_LOCAL; + new_id(0, (ID *)ima, 0); + } + } + tface++; + } + +} + +void make_local_mesh(Mesh *me) +{ + Object *ob; + Mesh *men; + int local=0, lib=0; + + /* - zijn er alleen lib users: niet doen + * - zijn er alleen locale users: flag zetten + * - mixed: copy + */ + + if(me->id.lib==0) return; + if(me->id.us==1) { + me->id.lib= 0; + me->id.flag= LIB_LOCAL; + new_id(0, (ID *)me, 0); + + if(me->tface) make_local_tface(me); + + return; + } + + ob= G.main->object.first; + while(ob) { + if( me==get_mesh(ob) ) { + if(ob->id.lib) lib= 1; + else local= 1; + } + ob= ob->id.next; + } + + if(local && lib==0) { + me->id.lib= 0; + me->id.flag= LIB_LOCAL; + new_id(0, (ID *)me, 0); + + if(me->tface) make_local_tface(me); + + } + else if(local && lib) { + men= copy_mesh(me); + men->id.us= 0; + + ob= G.main->object.first; + while(ob) { + if( me==get_mesh(ob) ) { + if(ob->id.lib==0) { + set_mesh(ob, men); + } + } + ob= ob->id.next; + } + } +} + +void boundbox_mesh(Mesh *me, float *loc, float *size) +{ + MVert *mvert; + BoundBox *bb; + float min[3], max[3]; + float mloc[3], msize[3]; + int a; + + if(me->bb==0) me->bb= MEM_callocN(sizeof(BoundBox), "boundbox"); + bb= me->bb; + + INIT_MINMAX(min, max); + + if (!loc) loc= mloc; + if (!size) size= msize; + + mvert= me->mvert; + for(a=0; a<me->totvert; a++, mvert++) { + DO_MINMAX(mvert->co, min, max); + } + + if(me->totvert) { + loc[0]= (min[0]+max[0])/2.0f; + loc[1]= (min[1]+max[1])/2.0f; + loc[2]= (min[2]+max[2])/2.0f; + + size[0]= (max[0]-min[0])/2.0f; + size[1]= (max[1]-min[1])/2.0f; + size[2]= (max[2]-min[2])/2.0f; + } + else { + loc[0]= loc[1]= loc[2]= 0.0; + size[0]= size[1]= size[2]= 0.0; + } + + bb->vec[0][0]=bb->vec[1][0]=bb->vec[2][0]=bb->vec[3][0]= loc[0]-size[0]; + bb->vec[4][0]=bb->vec[5][0]=bb->vec[6][0]=bb->vec[7][0]= loc[0]+size[0]; + + bb->vec[0][1]=bb->vec[1][1]=bb->vec[4][1]=bb->vec[5][1]= loc[1]-size[1]; + bb->vec[2][1]=bb->vec[3][1]=bb->vec[6][1]=bb->vec[7][1]= loc[1]+size[1]; + + bb->vec[0][2]=bb->vec[3][2]=bb->vec[4][2]=bb->vec[7][2]= loc[2]-size[2]; + bb->vec[1][2]=bb->vec[2][2]=bb->vec[5][2]=bb->vec[6][2]= loc[2]+size[2]; +} + +void tex_space_mesh(Mesh *me) +{ + KeyBlock *kb; + float *fp, loc[3], size[3], min[3], max[3]; + int a; + + boundbox_mesh(me, loc, size); + + if(me->texflag & AUTOSPACE) { + if(me->key) { + kb= me->key->refkey; + if (kb) { + + INIT_MINMAX(min, max); + + fp= kb->data; + for(a=0; a<kb->totelem; a++, fp+=3) { + DO_MINMAX(fp, min, max); + } + if(kb->totelem) { + loc[0]= (min[0]+max[0])/2.0f; loc[1]= (min[1]+max[1])/2.0f; loc[2]= (min[2]+max[2])/2.0f; + size[0]= (max[0]-min[0])/2.0f; size[1]= (max[1]-min[1])/2.0f; size[2]= (max[2]-min[2])/2.0f; + } + else { + loc[0]= loc[1]= loc[2]= 0.0; + size[0]= size[1]= size[2]= 0.0; + } + + } + } + + VECCOPY(me->loc, loc); + VECCOPY(me->size, size); + me->rot[0]= me->rot[1]= me->rot[2]= 0.0; + + if(me->size[0]==0.0) me->size[0]= 1.0; + else if(me->size[0]>0.0 && me->size[0]<0.00001) me->size[0]= 0.00001; + else if(me->size[0]<0.0 && me->size[0]> -0.00001) me->size[0]= -0.00001; + + if(me->size[1]==0.0) me->size[1]= 1.0; + else if(me->size[1]>0.0 && me->size[1]<0.00001) me->size[1]= 0.00001; + else if(me->size[1]<0.0 && me->size[1]> -0.00001) me->size[1]= -0.00001; + + if(me->size[2]==0.0) me->size[2]= 1.0; + else if(me->size[2]>0.0 && me->size[2]<0.00001) me->size[2]= 0.00001; + else if(me->size[2]<0.0 && me->size[2]> -0.00001) me->size[2]= -0.00001; + } + +} + +void make_orco_displist_mesh(Object *ob, int subdivlvl) +{ + Mesh *me; + DispList *dl; + DispListMesh *dlm; + int i; + + me= ob->data; + + /* if there's a key, set the first one */ + if(me->key && me->texcomesh==0) { + cp_key(0, me->totvert, me->totvert, (char*) me->mvert->co, me->key, me->key->refkey, 0); + } + + /* Rebuild the displist */ + dl= subsurf_mesh_to_displist(me, NULL, (short)subdivlvl); + + /* Restore correct key */ + do_ob_key(ob); + + /* XXX Assume dl is a DL_MESH (it is), + * should be explicit -zr + */ + dlm= dl->mesh; + + me->orco= MEM_mallocN(dlm->totvert*3*sizeof(float), "mesh displist orco"); + + for (i=0; i<dlm->totvert; i++) { + float *fp= &me->orco[i*3]; + VECCOPY(fp, dlm->mvert[i].co); + } + + for(i=0; i<dlm->totvert; i++) { + float *fp= &me->orco[i*3]; + fp[0]= (fp[0]-me->loc[0])/me->size[0]; + fp[1]= (fp[1]-me->loc[1])/me->size[1]; + fp[2]= (fp[2]-me->loc[2])/me->size[2]; + } + + free_disp_elem(dl); +} + +void make_orco_mesh(Mesh *me) +{ + MVert *mvert; + KeyBlock *kb; + float *orco, *fp; + int a, totvert; + + totvert= me->totvert; + if(totvert==0) return; + orco= me->orco= MEM_mallocN(sizeof(float)*3*totvert, "orco mesh"); + + if(me->key && me->texcomesh==0) { + kb= me->key->refkey; + if (kb) { /***** BUG *****/ + fp= kb->data; + + for(a=0; a<totvert; a++, orco+=3) { + orco[0]= (fp[0]-me->loc[0])/me->size[0]; + orco[1]= (fp[1]-me->loc[1])/me->size[1]; + orco[2]= (fp[2]-me->loc[2])/me->size[2]; + + /* mvert alleen ophogen als totvert <= kb->totelem */ + if(a<kb->totelem) fp+=3; + } + } + } + else { + if(me->texcomesh) { + me= me->texcomesh; + } + + mvert= me->mvert; + for(a=0; a<totvert; a++, orco+=3) { + orco[0]= (mvert->co[0]-me->loc[0])/me->size[0]; + orco[1]= (mvert->co[1]-me->loc[1])/me->size[1]; + orco[2]= (mvert->co[2]-me->loc[2])/me->size[2]; + + /* mvert alleen ophogen als totvert <= me->totvert */ + if(a<me->totvert) mvert++; + } + } +} + +/** rotates the vertices of a face in case v[2] or v[3] (vertex index) + * is = 0. + * Helaas, the MFace structure has no pointer to its + * texture face, therefore, texture can not be fixed inside + * this function. + * + * see also blender/src/editmesh.c, fix_faceindices() + + * THIS FUNCTION WILL BE DINOSOURCE. For the moment, another hack + is added to fix texture coordinates / vertex colors: + + void test_index_face(MFace *mface, TFace *tface, int nr) + */ + +void test_index_mface(MFace *mface, int nr) +{ + int a; + + + /* first test if the face is legal */ + + if(mface->v3 && mface->v3==mface->v4) { + mface->v4= 0; + nr--; + } + if(mface->v2 && mface->v2==mface->v3) { + mface->v3= mface->v4; + mface->v4= 0; + nr--; + } + if(mface->v1==mface->v2) { + mface->v2= mface->v3; + mface->v3= mface->v4; + mface->v4= 0; + nr--; + } + + /* voorkom dat een nul op de verkeerde plek staat */ + if(nr==2) { + if(mface->v2==0) SWAP(int, mface->v1, mface->v2); + } + else if(nr==3) { + if(mface->v3==0) { + SWAP(int, mface->v1, mface->v2); + SWAP(int, mface->v2, mface->v3); + + a= mface->edcode; + mface->edcode= 0; + if(a & ME_V1V2) mface->edcode |= ME_V3V1; + if(a & ME_V2V3) mface->edcode |= ME_V1V2; + if(a & ME_V3V1) mface->edcode |= ME_V2V3; + + a= mface->puno; + mface->puno &= ~15; + if(a & ME_FLIPV1) mface->puno |= ME_FLIPV2; + if(a & ME_FLIPV2) mface->puno |= ME_FLIPV3; + if(a & ME_FLIPV3) mface->puno |= ME_FLIPV1; + } + } + else if(nr==4) { + if(mface->v3==0 || mface->v4==0) { + SWAP(int, mface->v1, mface->v3); + SWAP(int, mface->v2, mface->v4); + a= mface->edcode; + mface->edcode= 0; + if(a & ME_V1V2) mface->edcode |= ME_V3V4; + if(a & ME_V2V3) mface->edcode |= ME_V2V3; + if(a & ME_V3V4) mface->edcode |= ME_V1V2; + if(a & ME_V4V1) mface->edcode |= ME_V4V1; + + a= mface->puno; + mface->puno &= ~15; + if(a & ME_FLIPV1) mface->puno |= ME_FLIPV3; + if(a & ME_FLIPV2) mface->puno |= ME_FLIPV4; + if(a & ME_FLIPV3) mface->puno |= ME_FLIPV1; + if(a & ME_FLIPV4) mface->puno |= ME_FLIPV2; + } + } +} + +/** This function should die as soon as there is another mesh + structure. Functionality is the same as + + void test_index_mface() + + but it fixes texture coordinates as well. +*/ + +#define UVCOPY(t, s) memcpy(t, s, 2 * sizeof(float)); +void test_index_face(MFace *mface, TFace *tface, int nr) +{ + int a; + float tmpuv[2]; + unsigned int tmpcol; + + + /* first test if the face is legal */ + + if(mface->v3 && mface->v3==mface->v4) { + mface->v4= 0; + nr--; + } + if(mface->v2 && mface->v2==mface->v3) { + mface->v3= mface->v4; + mface->v4= 0; + nr--; + } + if(mface->v1==mface->v2) { + mface->v2= mface->v3; + mface->v3= mface->v4; + mface->v4= 0; + nr--; + } + + /* voorkom dat een nul op de verkeerde plek staat */ + if(nr==2) { + if(mface->v2==0) SWAP(int, mface->v1, mface->v2); + } + else if(nr==3) { + if(mface->v3==0) { + SWAP(int, mface->v1, mface->v2); + SWAP(int, mface->v2, mface->v3); + /* rotate face UV coordinates, too */ + UVCOPY(tmpuv, tface->uv[0]); + UVCOPY(tface->uv[0], tface->uv[1]); + UVCOPY(tface->uv[1], tface->uv[2]); + UVCOPY(tface->uv[2], tmpuv); + /* same with vertex colours */ + tmpcol = tface->col[0]; + tface->col[0] = tface->col[1]; + tface->col[1] = tface->col[2]; + tface->col[2] = tmpcol; + + + a= mface->edcode; + mface->edcode= 0; + if(a & ME_V1V2) mface->edcode |= ME_V3V1; + if(a & ME_V2V3) mface->edcode |= ME_V1V2; + if(a & ME_V3V1) mface->edcode |= ME_V2V3; + + a= mface->puno; + mface->puno &= ~15; + if(a & ME_FLIPV1) mface->puno |= ME_FLIPV2; + if(a & ME_FLIPV2) mface->puno |= ME_FLIPV3; + if(a & ME_FLIPV3) mface->puno |= ME_FLIPV1; + } + } + else if(nr==4) { + if(mface->v3==0 || mface->v4==0) { + SWAP(int, mface->v1, mface->v3); + SWAP(int, mface->v2, mface->v4); + /* swap UV coordinates */ + UVCOPY(tmpuv, tface->uv[0]); + UVCOPY(tface->uv[0], tface->uv[2]); + UVCOPY(tface->uv[2], tmpuv); + UVCOPY(tmpuv, tface->uv[1]); + UVCOPY(tface->uv[1], tface->uv[3]); + UVCOPY(tface->uv[3], tmpuv); + /* swap vertex colours */ + tmpcol = tface->col[0]; + tface->col[0] = tface->col[2]; + tface->col[2] = tmpcol; + tmpcol = tface->col[1]; + tface->col[1] = tface->col[3]; + tface->col[3] = tmpcol; + + a= mface->edcode; + mface->edcode= 0; + if(a & ME_V1V2) mface->edcode |= ME_V3V4; + if(a & ME_V2V3) mface->edcode |= ME_V2V3; + if(a & ME_V3V4) mface->edcode |= ME_V1V2; + if(a & ME_V4V1) mface->edcode |= ME_V4V1; + + a= mface->puno; + mface->puno &= ~15; + if(a & ME_FLIPV1) mface->puno |= ME_FLIPV3; + if(a & ME_FLIPV2) mface->puno |= ME_FLIPV4; + if(a & ME_FLIPV3) mface->puno |= ME_FLIPV1; + if(a & ME_FLIPV4) mface->puno |= ME_FLIPV2; + } + } +} + +void flipnorm_mesh(Mesh *me) +{ + MFace *mface; + MVert *mvert; + DispList *dl; + float *fp; + int a, temp; + + mvert= me->mvert; + a= me->totvert; + while(a--) { + mvert->no[0]= -mvert->no[0]; + mvert->no[1]= -mvert->no[1]; + mvert->no[2]= -mvert->no[2]; + mvert++; + } + + mface= me->mface; + a= me->totface; + while(a--) { + if(mface->v3) { + if(mface->v4) { + SWAP(int, mface->v4, mface->v1); + SWAP(int, mface->v3, mface->v2); + test_index_mface(mface, 4); + temp= mface->puno; + mface->puno &= ~15; + if(temp & ME_FLIPV1) mface->puno |= ME_FLIPV4; + if(temp & ME_FLIPV2) mface->puno |= ME_FLIPV3; + if(temp & ME_FLIPV3) mface->puno |= ME_FLIPV2; + if(temp & ME_FLIPV4) mface->puno |= ME_FLIPV1; + } + else { + SWAP(int, mface->v3, mface->v1); + test_index_mface(mface, 3); + temp= mface->puno; + mface->puno &= ~15; + if(temp & ME_FLIPV1) mface->puno |= ME_FLIPV3; + if(temp & ME_FLIPV2) mface->puno |= ME_FLIPV2; + if(temp & ME_FLIPV3) mface->puno |= ME_FLIPV1; + } + } + mface++; + } + + if(me->disp.first) { + dl= me->disp.first; + fp= dl->nors; + if(fp) { + a= dl->nr; + while(a--) { + fp[0]= -fp[0]; + fp[1]= -fp[1]; + fp[2]= -fp[2]; + fp+= 3; + } + } + } +} + +Mesh *get_mesh(Object *ob) +{ + + if(ob==0) return 0; + if(ob->type==OB_MESH) return ob->data; + else return 0; +} + +void set_mesh(Object *ob, Mesh *me) +{ + Mesh *old=0; + + if(ob==0) return; + + if(ob->type==OB_MESH) { + old= ob->data; + old->id.us--; + ob->data= me; + id_us_plus((ID *)me); + } + + test_object_materials((ID *)me); +} + +void mball_to_mesh(ListBase *lb, Mesh *me) +{ + DispList *dl; + MVert *mvert; + MFace *mface; + float *nors, *verts; + int a, *index; + + dl= lb->first; + if(dl==0) return; + + if(dl->type==DL_INDEX4) { + me->flag= ME_NOPUNOFLIP; + me->totvert= dl->nr; + me->totface= dl->parts; + + me->mvert=mvert= MEM_callocN(dl->nr*sizeof(MVert), "mverts"); + a= dl->nr; + nors= dl->nors; + verts= dl->verts; + while(a--) { + VECCOPY(mvert->co, verts); + mvert->no[0]= (short int)(nors[0]*32767.0); + mvert->no[1]= (short int)(nors[1]*32767.0); + mvert->no[2]= (short int)(nors[2]*32767.0); + mvert++; + nors+= 3; + verts+= 3; + } + + me->mface=mface= MEM_callocN(dl->parts*sizeof(MFace), "mface"); + a= dl->parts; + index= dl->index; + while(a--) { + mface->v1= index[0]; + mface->v2= index[1]; + mface->v3= index[2]; + mface->v4= index[3]; + + mface->puno= 0; + mface->edcode= ME_V1V2+ME_V2V3; + mface->flag = ME_SMOOTH; + + mface++; + index+= 4; + } + } +} + +void nurbs_to_mesh(Object *ob) +{ + Object *ob1; + DispList *dl; + Mesh *me; + Curve *cu; + MVert *mvert; + MFace *mface; + float *data; + int a, b, ofs, vertcount, startvert, totvert=0, totvlak=0; + int p1, p2, p3, p4, *index; + + cu= ob->data; + + if(ob->type==OB_CURVE) { + /* regel: dl->type INDEX3 altijd vooraan in lijst */ + dl= cu->disp.first; + if(dl->type!=DL_INDEX3) { + curve_to_filledpoly(ob->data, &cu->disp); + } + } + + /* tellen */ + dl= cu->disp.first; + while(dl) { + if(dl->type==DL_SEGM) { + totvert+= dl->parts*dl->nr; + totvlak+= dl->parts*(dl->nr-1); + } + else if(dl->type==DL_POLY) { + /* cyclic polys are filled. except when 3D */ + if(cu->flag & CU_3D) { + totvert+= dl->parts*dl->nr; + totvlak+= dl->parts*dl->nr; + } + } + else if(dl->type==DL_SURF) { + totvert+= dl->parts*dl->nr; + totvlak+= (dl->parts-1+((dl->flag & 2)==2))*(dl->nr-1+(dl->flag & 1)); + } + else if(dl->type==DL_INDEX3) { + totvert+= dl->nr; + totvlak+= dl->parts; + } + dl= dl->next; + } + if(totvert==0) { + error("can't convert"); + return; + } + + /* mesh maken */ + me= add_mesh(); + me->totvert= totvert; + me->totface= totvlak; + + me->totcol= cu->totcol; + me->mat= cu->mat; + cu->mat= 0; + cu->totcol= 0; + + mvert=me->mvert= MEM_callocN(me->totvert*sizeof(MVert), "cumesh1"); + mface=me->mface= MEM_callocN(me->totface*sizeof(MFace), "cumesh2"); + + /* verts en vlakken */ + vertcount= 0; + + dl= cu->disp.first; + while(dl) { + if(dl->type==DL_SEGM) { + startvert= vertcount; + a= dl->parts*dl->nr; + data= dl->verts; + while(a--) { + VECCOPY(mvert->co, data); + data+=3; + vertcount++; + mvert++; + } + + for(a=0; a<dl->parts; a++) { + ofs= a*dl->nr; + for(b=1; b<dl->nr; b++) { + mface->v1= startvert+ofs+b-1; + mface->v2= startvert+ofs+b; + mface->edcode= ME_V1V2; + test_index_mface(mface, 2); + mface++; + } + } + + } + else if(dl->type==DL_POLY) { + /* cyclic polys are filled */ + /* startvert= vertcount; + a= dl->parts*dl->nr; + data= dl->verts; + while(a--) { + VECCOPY(mvert->co, data); + data+=3; + vertcount++; + mvert++; + } + + for(a=0; a<dl->parts; a++) { + ofs= a*dl->nr; + for(b=0; b<dl->nr; b++) { + mface->v1= startvert+ofs+b; + if(b==dl->nr-1) mface->v2= startvert+ofs; + else mface->v2= startvert+ofs+b+1; + mface->edcode= ME_V1V2; + test_index_mface(mface, 2); + mface++; + } + } + */ + } + else if(dl->type==DL_INDEX3) { + startvert= vertcount; + a= dl->nr; + data= dl->verts; + while(a--) { + VECCOPY(mvert->co, data); + data+=3; + vertcount++; + mvert++; + } + + a= dl->parts; + index= dl->index; + while(a--) { + mface->v1= startvert+index[0]; + mface->v2= startvert+index[1]; + mface->v3= startvert+index[2]; + mface->v4= 0; + + mface->puno= 7; + mface->edcode= ME_V1V2+ME_V2V3; + test_index_mface(mface, 3); + + mface++; + index+= 3; + } + + + } + else if(dl->type==DL_SURF) { + startvert= vertcount; + a= dl->parts*dl->nr; + data= dl->verts; + while(a--) { + VECCOPY(mvert->co, data); + data+=3; + vertcount++; + mvert++; + } + + for(a=0; a<dl->parts; a++) { + + if( (dl->flag & 2)==0 && a==dl->parts-1) break; + + if(dl->flag & 1) { /* p2 -> p1 -> */ + p1= startvert+ dl->nr*a; /* p4 -> p3 -> */ + p2= p1+ dl->nr-1; /* -----> volgende rij */ + p3= p1+ dl->nr; + p4= p2+ dl->nr; + b= 0; + } + else { + p2= startvert+ dl->nr*a; + p1= p2+1; + p4= p2+ dl->nr; + p3= p1+ dl->nr; + b= 1; + } + if( (dl->flag & 2) && a==dl->parts-1) { + p3-= dl->parts*dl->nr; + p4-= dl->parts*dl->nr; + } + + for(; b<dl->nr; b++) { + mface->v1= p1; + mface->v2= p3; + mface->v3= p4; + mface->v4= p2; + mface->mat_nr= (unsigned char)dl->col; + mface->edcode= ME_V1V2+ME_V2V3; + test_index_mface(mface, 4); + mface++; + + p4= p3; + p3++; + p2= p1; + p1++; + } + } + + } + + dl= dl->next; + } + + if(ob->data) { + free_libblock(&G.main->curve, ob->data); + } + ob->data= me; + ob->type= OB_MESH; + + tex_space_mesh(me); + + /* andere users */ + ob1= G.main->object.first; + while(ob1) { + if(ob1->data==cu) { + ob1->type= OB_MESH; + + ob1->data= ob->data; + id_us_plus((ID *)ob->data); + } + ob1= ob1->id.next; + } + +} + +void edge_drawflags_mesh(Mesh *me) +{ + MFace *mface; + int a; + + mface= me->mface; + for(a=0; a<me->totface; a++, mface++) { + mface->edcode= ME_V1V2|ME_V2V3|ME_V3V4|ME_V4V1; + } +} + +void tface_to_mcol(Mesh *me) +{ + TFace *tface; + unsigned int *mcol; + int a; + + me->mcol= MEM_mallocN(4*sizeof(int)*me->totface, "nepmcol"); + mcol= (unsigned int *)me->mcol; + + a= me->totface; + tface= me->tface; + while(a--) { + memcpy(mcol, tface->col, 16); + mcol+= 4; + tface++; + } +} + +void mcol_to_tface(Mesh *me, int freedata) +{ + TFace *tface; + unsigned int *mcol; + int a; + + a= me->totface; + tface= me->tface; + mcol= (unsigned int *)me->mcol; + while(a--) { + memcpy(tface->col, mcol, 16); + mcol+= 4; + tface++; + } + + if(freedata) { + MEM_freeN(me->mcol); + me->mcol= 0; + } +} + +int mesh_uses_displist(Mesh *me) { + return (me->flag&ME_SUBSURF && (me->subdiv>0)); +} + +int rendermesh_uses_displist(Mesh *me) { + return (me->flag&ME_SUBSURF); +} diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c new file mode 100644 index 00000000000..40851b27c6c --- /dev/null +++ b/source/blender/blenkernel/intern/nla.c @@ -0,0 +1,118 @@ +/** + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <stdlib.h> + +#include "BKE_nla.h" +#include "BKE_blender.h" + +#include "BLI_blenlib.h" + +#include "DNA_space_types.h" +#include "DNA_nla_types.h" +#include "DNA_action_types.h" +#include "DNA_ID.h" +#include "DNA_ipo_types.h" + +#include "MEM_guardedalloc.h" + +void copy_actionstrip (bActionStrip **dst, bActionStrip **src){ + bActionStrip *dstrip; + bActionStrip *sstrip = *src; + + if (!*src){ + *dst=NULL; + return; + } + + *dst = MEM_dupallocN(sstrip); + + dstrip = *dst; + if (dstrip->act) + dstrip->act->id.us++; + + if (dstrip->ipo) + dstrip->ipo->id.us++; +} + +void copy_nlastrips (ListBase *dst, ListBase *src) +{ + bActionStrip *strip; + + dst->first=dst->last=NULL; + + duplicatelist (dst, src); + + /* Update specific data */ + if (!dst->first) + return; + + for (strip = dst->first; strip; strip=strip->next){ + if (strip->act) + strip->act->id.us++; + if (strip->ipo) + strip->ipo->id.us++; + } +} + + +void free_actionstrip(bActionStrip* strip) +{ + if (!strip) + return; + + if (strip->act){ + strip->act->id.us--; + strip->act = NULL; + } + if (strip->ipo){ + strip->ipo->id.us--; + strip->ipo = NULL; + } +} + +void free_nlastrips (ListBase *nlalist) +{ + bActionStrip *strip; + + if (!nlalist->first) + return; + + /* Do any specific freeing */ + for (strip=nlalist->first; strip; strip=strip->next) + { + free_actionstrip (strip); + }; + + /* Free the whole list */ + BLI_freelistN(nlalist); +} diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c new file mode 100644 index 00000000000..c6c91d00609 --- /dev/null +++ b/source/blender/blenkernel/intern/object.c @@ -0,0 +1,1681 @@ +/* object.c MIXED MODEL + * + * jan 95 + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + + + +#include <string.h> +#include <math.h> +#include <stdio.h> +#ifdef WIN32 +#include "BLI_winstuff.h" +#endif +#include "MEM_guardedalloc.h" + +#include "DNA_action_types.h" +#include "DNA_armature_types.h" +#include "DNA_camera_types.h" +#include "DNA_constraint_types.h" +#include "DNA_curve_types.h" +#include "DNA_group_types.h" +#include "DNA_ika_types.h" +#include "DNA_ipo_types.h" +#include "DNA_lamp_types.h" +#include "DNA_lattice_types.h" +#include "DNA_material_types.h" +#include "DNA_mesh_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_texture_types.h" +#include "DNA_userdef_types.h" +#include "DNA_view3d_types.h" +#include "DNA_world_types.h" + +#include "BKE_armature.h" +#include "BKE_action.h" +#include "BKE_deform.h" +#include "BKE_nla.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_editVert.h" + +#include "BKE_utildefines.h" +#include "BKE_bad_level_calls.h" + +#include "BKE_main.h" +#include "BKE_global.h" + +#include "BKE_object.h" +#include "BKE_blender.h" +#include "BKE_screen.h" +#include "BKE_ipo.h" +#include "BKE_ika.h" +#include "BKE_library.h" +#include "BKE_mesh.h" +#include "BKE_curve.h" +#include "BKE_mball.h" +#include "BKE_effect.h" +#include "BKE_sca.h" +#include "BPY_extern.h" +#include "BKE_displist.h" +#include "BKE_property.h" +#include "BKE_anim.h" +#include "BKE_group.h" +#include "BKE_lattice.h" +#include "BKE_constraint.h" +#include "BKE_scene.h" + +/* Local function protos */ +static void solve_parenting (Object *ob, Object *par, float slowmat[][4], int simul); + +float originmat[3][3]; /* na where_is_object(), kan her en der gebruikt worden */ +Object workob; + +void clear_workob(void) +{ + memset(&workob, 0, sizeof(Object)); + + workob.size[0]= workob.size[1]= workob.size[2]= 1.0; + +} + +void copy_baseflags() +{ + Base *base= G.scene->base.first; + + while(base) { + base->object->flag= base->flag; + base= base->next; + } +} + +void copy_objectflags() +{ + Base *base= G.scene->base.first; + + while(base) { + base->flag= base->object->flag; + base= base->next; + } +} + +void update_base_layer(Object *ob) +{ + Base *base= G.scene->base.first; + + while (base) { + if (base->object == ob) base->lay= ob->lay; + base= base->next; + } +} + +/* niet object zelf vrijgeven */ +void free_object(Object *ob) +{ + int a; + + /* specifieke data loskoppelen */ + if(ob->data) { + ID *id= ob->data; + id->us--; + if(id->us==0) { + if(ob->type==OB_MESH) unlink_mesh(ob->data); + else if(ob->type==OB_CURVE) unlink_curve(ob->data); + else if(ob->type==OB_MBALL) unlink_mball(ob->data); + } + ob->data= 0; + } + + for(a=0; a<ob->totcol; a++) { + if(ob->mat[a]) ob->mat[a]->id.us--; + } + if(ob->mat) MEM_freeN(ob->mat); + ob->mat= 0; + if(ob->bb) MEM_freeN(ob->bb); + ob->bb= 0; + if(ob->path) free_path(ob->path); + ob->path= 0; + if(ob->ipo) ob->ipo->id.us--; + if(ob->action) ob->action->id.us--; + if(ob->defbase.first) + BLI_freelistN(&ob->defbase); + if(ob->pose) { + clear_pose(ob->pose); + MEM_freeN(ob->pose); + } + free_effects(&ob->effect); + BLI_freelistN(&ob->network); + free_properties(&ob->prop); + + free_sensors(&ob->sensors); + free_controllers(&ob->controllers); + free_actuators(&ob->actuators); + + free_constraints(&ob->constraints); + free_constraint_channels(&ob->constraintChannels); + free_nlastrips(&ob->nlastrips); + + freedisplist(&ob->disp); + + BPY_free_scriptlink(&ob->scriptlink); +} + +void unlink_object(Object *ob) +{ + Object *obt; + Material *mat; + World *wrld; + bScreen *sc; + Scene *sce; + Curve *cu; + Tex *tex; + Group *group; + int a; + + unlink_controllers(&ob->controllers); + unlink_actuators(&ob->actuators); + + /* alle objecten aflopen: parents en bevels */ + obt= G.main->object.first; + while(obt) { + if(obt->id.lib==0) { + if(obt->parent==ob) { + obt->parent= 0; + if(ob->type==OB_LATTICE) freedisplist(&obt->disp); + } + if(obt->track==ob) obt->track= 0; + if ELEM(obt->type, OB_CURVE, OB_FONT) { + cu= obt->data; + if(cu->bevobj==ob) cu->bevobj= 0; + if(cu->textoncurve==ob) cu->textoncurve= 0; + } + if(obt->type==OB_IKA) { + Ika *ika= obt->data; + Deform *def= ika->def; + + if(ika->parent==ob) ika->parent= 0; + a= ika->totdef; + while(a--) { + if(def->ob==ob) { + ika->totdef= 0; + MEM_freeN(ika->def); + ika->def= 0; + break; + } + def++; + } + } + sca_remove_ob_poin(obt, ob); + } + obt= obt->id.next; + } + + /* materialen */ + mat= G.main->mat.first; + while(mat) { + + for(a=0; a<8; a++) { + if(mat->mtex[a] && ob==mat->mtex[a]->object) { + /* eigenlijk testen op lib */ + mat->mtex[a]->object= 0; + } + } + + mat= mat->id.next; + } + + /* textures */ + tex= G.main->tex.first; + while(tex) { + if(tex->env) { + if(tex->env->object == ob) tex->env->object= 0; + } + tex= tex->id.next; + } + + /* mballs */ + if(ob->type==OB_MBALL) { + obt= find_basis_mball(ob); + if(obt) freedisplist(&obt->disp); + } + + /* worlds */ + wrld= G.main->world.first; + while(wrld) { + if(wrld->id.lib==0) { + for(a=0; a<6; a++) { + if(wrld->mtex[a] && ob==wrld->mtex[a]->object) + wrld->mtex[a]->object =0; + } + } + + wrld= wrld->id.next; + } + + /* scene's */ + sce= G.main->scene.first; + while(sce) { + if(sce->id.lib==0) { + if(sce->camera==ob) sce->camera= 0; + } + sce= sce->id.next; + } + /* keys */ + + /* screens */ + sc= G.main->screen.first; + while(sc) { + ScrArea *sa= sc->areabase.first; + while(sa) { + SpaceLink *sl; + + for (sl= sa->spacedata.first; sl; sl= sl->next) { + if(sl->spacetype==SPACE_VIEW3D) { + View3D *v3d= (View3D*) sl; + + if(v3d->camera==ob) { + v3d->camera= 0; + if(v3d->persp>1) v3d->persp= 1; + } + if(v3d->localvd && v3d->localvd->camera==ob ) { + v3d->localvd->camera= 0; + if(v3d->localvd->persp>1) v3d->localvd->persp= 1; + } + } + } + + sa= sa->next; + } + sc= sc->id.next; + } + + /* groups */ + group= G.main->group.first; + while(group) { + rem_from_group(group, ob); + group= group->id.next; + } +} + +int exist_object(Object *obtest) +{ + Object *ob; + + ob= G.main->object.first; + while(ob) { + if(ob==obtest) return 1; + ob= ob->id.next; + } + return 0; +} + +void *add_camera() +{ + Camera *cam; + + cam= alloc_libblock(&G.main->camera, ID_CA, "Camera"); + + cam->lens= 35.0f; + cam->clipsta= 0.1f; + cam->clipend= 100.0f; + cam->drawsize= 0.5f; + cam->netsta= 0.5f; + cam->netend= 10.0f; + cam->hold= 50; + + return cam; +} + +Camera *copy_camera(Camera *cam) +{ + Camera *camn; + + camn= copy_libblock(cam); + id_us_plus((ID *)camn->ipo); + + BPY_copy_scriptlink(&camn->scriptlink); + + return camn; +} + + + +void make_local_camera(Camera *cam) +{ + Object *ob; + Camera *camn; + int local=0, lib=0; + + /* - zijn er alleen lib users: niet doen + * - zijn er alleen locale users: flag zetten + * - mixed: copy + */ + + if(cam->id.lib==0) return; + if(cam->id.us==1) { + cam->id.lib= 0; + cam->id.flag= LIB_LOCAL; + new_id(0, (ID *)cam, 0); + return; + } + + ob= G.main->object.first; + while(ob) { + if(ob->data==cam) { + if(ob->id.lib) lib= 1; + else local= 1; + } + ob= ob->id.next; + } + + if(local && lib==0) { + cam->id.lib= 0; + cam->id.flag= LIB_LOCAL; + new_id(0, (ID *)cam, 0); + } + else if(local && lib) { + camn= copy_camera(cam); + camn->id.us= 0; + + ob= G.main->object.first; + while(ob) { + if(ob->data==cam) { + + if(ob->id.lib==0) { + ob->data= camn; + camn->id.us++; + cam->id.us--; + } + } + ob= ob->id.next; + } + } +} + + + +void *add_lamp(void) +{ + Lamp *la; + + la= alloc_libblock(&G.main->lamp, ID_LA, "Lamp"); + + la->r= la->g= la->b= 1.0; + la->haint= la->energy= 1.0; + la->dist= 20.0f; + la->spotsize= 45.0f; + la->spotblend= 0.15f; + la->att2= 1.0f; + la->mode= LA_SHAD; + la->bufsize= 512; + la->clipsta= 0.5f; + la->clipend= 40.0f; + la->shadspotsize= 45.0f; + la->samp= 3; + la->bias= 1.0f; + la->soft= 3.0f; + + return la; +} + +Lamp *copy_lamp(Lamp *la) +{ + Lamp *lan; + int a; + + lan= copy_libblock(la); + + for(a=0; a<8; a++) { + if(lan->mtex[a]) { + lan->mtex[a]= MEM_mallocN(sizeof(MTex), "copylamptex"); + memcpy(lan->mtex[a], la->mtex[a], sizeof(MTex)); + id_us_plus((ID *)lan->mtex[a]->tex); + } + } + + id_us_plus((ID *)lan->ipo); + + BPY_copy_scriptlink(&la->scriptlink); + + return lan; +} + +void make_local_lamp(Lamp *la) +{ + Object *ob; + Lamp *lan; + int local=0, lib=0; + + /* - zijn er alleen lib users: niet doen + * - zijn er alleen locale users: flag zetten + * - mixed: copy + */ + + if(la->id.lib==0) return; + if(la->id.us==1) { + la->id.lib= 0; + la->id.flag= LIB_LOCAL; + new_id(0, (ID *)la, 0); + return; + } + + ob= G.main->object.first; + while(ob) { + if(ob->data==la) { + if(ob->id.lib) lib= 1; + else local= 1; + } + ob= ob->id.next; + } + + if(local && lib==0) { + la->id.lib= 0; + la->id.flag= LIB_LOCAL; + new_id(0, (ID *)la, 0); + } + else if(local && lib) { + lan= copy_lamp(la); + lan->id.us= 0; + + ob= G.main->object.first; + while(ob) { + if(ob->data==la) { + + if(ob->id.lib==0) { + ob->data= lan; + lan->id.us++; + la->id.us--; + } + } + ob= ob->id.next; + } + } +} + +void free_camera(Camera *ca) +{ + BPY_free_scriptlink(&ca->scriptlink); +} + +void free_lamp(Lamp *la) +{ + MTex *mtex; + int a; + + /* scriptlinks */ + + BPY_free_scriptlink(&la->scriptlink); + + for(a=0; a<8; a++) { + mtex= la->mtex[a]; + if(mtex && mtex->tex) mtex->tex->id.us--; + if(mtex) MEM_freeN(mtex); + } + la->ipo= 0; +} + +void *add_wave() +{ + return 0; +} + + +/* *************************************************** */ + +static void *add_obdata_from_type(int type) +{ + switch (type) { + case OB_MESH: G.totmesh++; return add_mesh(); + case OB_CURVE: G.totcurve++; return add_curve(OB_CURVE); + case OB_SURF: G.totcurve++; return add_curve(OB_SURF); + case OB_FONT: return add_curve(OB_FONT); + case OB_MBALL: return add_mball(); + case OB_CAMERA: return add_camera(); + case OB_LAMP: G.totlamp++; return add_lamp(); + case OB_IKA: return add_ika(); + case OB_LATTICE: return add_lattice(); + case OB_WAVE: return add_wave(); + case OB_ARMATURE: return add_armature(); + case OB_EMPTY: return NULL; + default: + printf("add_obdata_from_type: Internal error, bad type: %d\n", type); + return NULL; + } +} + +static char *get_obdata_defname(int type) +{ + switch (type) { + case OB_MESH: return "Mesh"; + case OB_CURVE: return "Curve"; + case OB_SURF: return "Surf"; + case OB_FONT: return "Font"; + case OB_MBALL: return "Mball"; + case OB_CAMERA: return "Camera"; + case OB_LAMP: return "Lamp"; + case OB_IKA: return "Ika"; + case OB_LATTICE: return "Lattice"; + case OB_WAVE: return "Wave"; + case OB_ARMATURE: return "Armature"; + case OB_EMPTY: return "Empty"; + default: + printf("get_obdata_defname: Internal error, bad type: %d\n", type); + return "Empty"; + } +} + +/* algemene add: in G.scene, met layer uit area en default naam */ +/* maakt alle minimaal nodige datablokken aan, zonder vertices etc. */ +Object *add_object(int type) +{ + Object *ob; + Base *base; + char name[32]; + + if (G.obpose) + exit_posemode(1); + + strcpy(name, get_obdata_defname(type)); + + ob= alloc_libblock(&G.main->object, ID_OB, name); + G.totobj++; + + /* default object vars */ + ob->type= type; + /* ob->transflag= OB_QUAT; */ + + QuatOne(ob->quat); + QuatOne(ob->dquat); + + ob->col[0]= ob->col[1]= ob->col[2]= 0.0; + ob->col[3]= 1.0; + + ob->loc[0]= ob->loc[1]= ob->loc[2]= 0.0; + ob->rot[0]= ob->rot[1]= ob->rot[2]= 0.0; + ob->size[0]= ob->size[1]= ob->size[2]= 1.0; + + Mat4One(ob->parentinv); + Mat4One(ob->obmat); + ob->dt= OB_SHADED; + if(U.flag & MAT_ON_OB) ob->colbits= -1; + + if(type==OB_CAMERA || type==OB_LAMP) { + ob->trackflag= OB_NEGZ; + ob->upflag= OB_POSY; + } + else { + 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; + + /* Gameengine defaults*/ + ob->mass= ob->inertia= 1.0f; + ob->formfactor= 0.4f; + ob->damping= 0.04f; + ob->rdamping= 0.1f; + ob->anisotropicFriction[0] = 1.0f; + ob->anisotropicFriction[1] = 1.0f; + ob->anisotropicFriction[2] = 1.0f; + ob->gameflag= OB_PROP; + + ob->data= add_obdata_from_type(type); + + ob->lay= G.scene->lay; + + base= scene_add_base(G.scene, ob); + scene_select_base(G.scene, base); + + return ob; +} + +void base_init_from_view3d(Base *base, View3D *v3d) +{ + Object *ob= base->object; + + if (v3d->localview) { + base->lay= ob->lay= v3d->layact + v3d->lay; + VECCOPY(ob->loc, v3d->cursor); + } else { + base->lay= ob->lay= v3d->layact; + VECCOPY(ob->loc, G.scene->cursor); + } + + v3d->viewquat[0]= -v3d->viewquat[0]; + if (ob->transflag & OB_QUAT) { + QUATCOPY(ob->quat, v3d->viewquat); + } else { + QuatToEul(v3d->viewquat, ob->rot); + } + v3d->viewquat[0]= -v3d->viewquat[0]; +} + +Object *copy_object(Object *ob) +{ + Object *obn; + int a; + bConstraintChannel *actcon; + + obn= copy_libblock(ob); + + if(ob->totcol) { + obn->mat= MEM_dupallocN(ob->mat); + } + + if(ob->bb) obn->bb= MEM_dupallocN(ob->bb); + obn->path= 0; + obn->flag &= ~OB_FROMGROUP; + + copy_effects(&obn->effect, &ob->effect); + + obn->network.first= obn->network.last= 0; + + BPY_copy_scriptlink(&ob->scriptlink); + + copy_properties(&obn->prop, &ob->prop); + copy_sensors(&obn->sensors, &ob->sensors); + copy_controllers(&obn->controllers, &ob->controllers); + copy_actuators(&obn->actuators, &ob->actuators); + + copy_pose(&obn->pose, ob->pose, 1); + copy_defgroups(&obn->defbase, &ob->defbase); + copy_nlastrips(&obn->nlastrips, &ob->nlastrips); + copy_constraints (&obn->constraints, &ob->constraints); + + actcon = clone_constraint_channels (&obn->constraintChannels, &ob->constraintChannels, ob->activecon); + /* If the active constraint channel was in this list, update it */ + if (actcon) + obn->activecon = actcon; + + /* usernummers ophogen */ + id_us_plus((ID *)obn->data); + id_us_plus((ID *)obn->ipo); + id_us_plus((ID *)obn->action); + for(a=0; a<obn->totcol; a++) id_us_plus((ID *)obn->mat[a]); + + obn->disp.first= obn->disp.last= 0; + + return obn; +} + +void expand_local_object(Object *ob) +{ + int a; + + id_lib_extern((ID *)ob->action); + id_lib_extern((ID *)ob->ipo); + id_lib_extern((ID *)ob->data); + + for(a=0; a<ob->totcol; a++) { + id_lib_extern((ID *)ob->mat[a]); + } +} + +void make_local_object(Object *ob) +{ + Object *obn; + Scene *sce; + Base *base; + int local=0, lib=0; + + /* - zijn er alleen lib users: niet doen + * - zijn er alleen locale users: flag zetten + * - mixed: copy + */ + + if(ob->id.lib==0) return; + if(ob->id.us==1) { + ob->id.lib= 0; + ob->id.flag= LIB_LOCAL; + new_id(0, (ID *)ob, 0); + + } + else { + sce= G.main->scene.first; + while(sce) { + base= sce->base.first; + while(base) { + if(base->object==ob) { + if(sce->id.lib) lib++; + else local++; + break; + } + base= base->next; + } + sce= sce->id.next; + } + + if(local && lib==0) { + ob->id.lib= 0; + ob->id.flag= LIB_LOCAL; + new_id(0, (ID *)ob, 0); + } + else if(local && lib) { + obn= copy_object(ob); + obn->id.us= 0; + + sce= G.main->scene.first; + while(sce) { + if(sce->id.lib==0) { + base= sce->base.first; + while(base) { + if(base->object==ob) { + base->object= obn; + obn->id.us++; + ob->id.us--; + } + base= base->next; + } + } + sce= sce->id.next; + } + } + } + + expand_local_object(ob); +} + +/* *************** CALC ****************** */ + +/* er zit ook een tijdberekening in de drawobject() */ + +float bluroffs= 0.0; +int no_speed_curve= 0; + +void set_mblur_offs(int blur) +{ + bluroffs= R.r.blurfac*((float)blur); + bluroffs/= (float)R.r.osa; +} + +void disable_speed_curve(int val) +{ + no_speed_curve= val; +} + +float bsystem_time(Object *ob, Object *par, float cfra, float ofs) +{ + /* geeft float terug ( zie ook frame_to_float in ipo.c) */ + + if(no_speed_curve==0) if(ob && ob->ipo) cfra= calc_ipo_time(ob->ipo, cfra); + + /* tweede field */ + if(R.flag & R_SEC_FIELD) { + if(R.r.mode & R_FIELDSTILL); else cfra+= .5; + } + + /* motion blur */ + cfra+= bluroffs; + + /* global time */ + cfra*= G.scene->r.framelen; + + /* ofset frames */ + if(ob && (ob->ipoflag & OB_OFFS_PARENT)) { + if((ob->partype & PARSLOW)==0) cfra-= ob->sf; + } + + cfra-= ofs; + + return cfra; +} + +void object_to_mat3(Object *ob, float mat[][3]) /* no parent */ +{ + float smat[3][3], vec[3]; + float rmat[3][3]; + float q1[4]; + + /* size */ + if(ob->ipo) { + vec[0]= ob->size[0]+ob->dsize[0]; + vec[1]= ob->size[1]+ob->dsize[1]; + vec[2]= ob->size[2]+ob->dsize[2]; + SizeToMat3(vec, smat); + } + else { + SizeToMat3(ob->size, smat); + } + + /* rot */ + if(ob->transflag & OB_QUAT) { + if(ob->ipo) { + QuatMul(q1, ob->quat, ob->dquat); + QuatToMat3(q1, rmat); + } + else { + QuatToMat3(ob->quat, rmat); + } + } + else { + if(ob->ipo) { + vec[0]= ob->rot[0]+ob->drot[0]; + vec[1]= ob->rot[1]+ob->drot[1]; + vec[2]= ob->rot[2]+ob->drot[2]; + EulToMat3(vec, rmat); + } + else { + EulToMat3(ob->rot, rmat); + } + } + Mat3MulMat3(mat, rmat, smat); +} + +void object_to_mat4(Object *ob, float mat[][4]) +{ + float tmat[3][3]; + + object_to_mat3(ob, tmat); + + Mat4CpyMat3(mat, tmat); + + VECCOPY(mat[3], ob->loc); + if(ob->ipo) { + mat[3][0]+= ob->dloc[0]; + mat[3][1]+= ob->dloc[1]; + mat[3][2]+= ob->dloc[2]; + } +} + +int enable_cu_speed= 1; + +void ob_parcurve(Object *ob, Object *par, float mat[][4]) +{ + Curve *cu; + float q[4], vec[4], dir[3], *quat, x1, ctime; + + Mat4One(mat); + + cu= par->data; + if(cu->path==0 || cu->path->data==0) calc_curvepath(par); + if(cu->path==0) return; + + /* uitzondering afvangen: curve paden die als duplicator worden gebruikt */ + if(enable_cu_speed) { + ctime= bsystem_time(ob, par, (float)G.scene->r.cfra, 0.0); + + if(calc_ipo_spec(cu->ipo, CU_SPEED, &ctime)==0) { + ctime /= cu->pathlen; + CLAMP(ctime, 0.0, 1.0); + } + } + else { + ctime= G.scene->r.cfra - ob->sf; + ctime /= cu->pathlen; + + CLAMP(ctime, 0.0, 1.0); + } + + if( where_on_path(par, ctime, vec, dir) ) { + + if(cu->flag & CU_FOLLOW) { + quat= vectoquat(dir, ob->trackflag, ob->upflag); + + Normalise(dir); + q[0]= (float)cos(0.5*vec[3]); + x1= (float)sin(0.5*vec[3]); + q[1]= -x1*dir[0]; + q[2]= -x1*dir[1]; + q[3]= -x1*dir[2]; + QuatMul(quat, q, quat); + + QuatToMat4(quat, mat); + } + + VECCOPY(mat[3], vec); + + } +} + +void ob_parbone(Object *ob, Object *par, float mat[][4]) +{ + Bone *bone; + bArmature *arm; + + Mat4One(mat); + arm=get_armature(par); + if (!arm) + return; + + /* Make sure the bone is still valid */ + bone = get_named_bone(arm, ob->parsubstr); + if (!bone){ + printf ("Lost bone %s\n", ob->parsubstr); + return; + } + + apply_pose_armature(arm, par->pose, 1); /* Hopefully can set doit parameter in the future */ + where_is_bone (par, bone); + + /* Translate by negative bone */ + get_objectspace_bone_matrix(bone, mat, 0, 1); + +} + +void ob_parlimb(Object *ob, Object *par, float mat[][4]) +{ + Ika *ika; + Limb *li; + float ang=0.0; + int cur=0; + + /* in lokale ob space */ + Mat4One(mat); + + ika= par->data; + li= ika->limbbase.first; + while(li) { + ang+= li->alpha; + if(cur==ob->par1 || li->next==0) break; + + cur++; + li= li->next; + } + + mat[0][0]= (float)cos(ang); + mat[1][0]= (float)-sin(ang); + mat[0][1]= (float)sin(ang); + mat[1][1]= (float)cos(ang); + + mat[3][0]= li->eff[0]; + mat[3][1]= li->eff[1]; + +} + +void give_parvert(Object *par, int nr, float *vec) +{ + Mesh *me; + MVert *mvert; + EditVert *eve; +/* extern ListBase editNurb; already in bad lev calls */ + Nurb *nu; + Curve *cu; + BPoint *bp; + DispList *dl; + BezTriple *bezt; + float *fp; + int a, count; + + vec[0]=vec[1]=vec[2]= 0.0; + + if(par->type==OB_MESH) { + if(par==G.obedit) { + if(nr >= G.totvert) nr= 0; + + count= 0; + eve= G.edve.first; + while(eve) { + if(count==nr) { + memcpy(vec, eve->co, 12); + break; + } + eve= eve->next; + count++; + } + } + else { + me= par->data; + if(me->totvert) { + if(nr >= me->totvert) nr= 0; + + /* is er deform */ + dl= find_displist(&par->disp, DL_VERTS); + if(dl) { + fp= dl->verts+3*nr; + VECCOPY(vec, fp); + } + else { + mvert= me->mvert + nr; + VECCOPY(vec, mvert->co); + } + } + } + } + else if ELEM(par->type, OB_CURVE, OB_SURF) { + + cu= par->data; + nu= cu->nurb.first; + if(par==G.obedit) nu= editNurb.first; + + count= 0; + while(nu) { + if((nu->type & 7)==CU_BEZIER) { + bezt= nu->bezt; + a= nu->pntsu; + while(a--) { + if(count==nr) { + VECCOPY(vec, bezt->vec[1]); + break; + } + count++; + bezt++; + } + } + else { + bp= nu->bp; + a= nu->pntsu*nu->pntsv; + while(a--) { + if(count==nr) { + memcpy(vec, bp->vec, 12); + break; + } + count++; + bp++; + } + } + nu= nu->next; + } + + } + else if(par->type==OB_IKA) { + Ika *ika= par->data; + Limb *li= ika->limbbase.first; + int cur= 1; + if(nr) { + while(li) { + if(cur==nr || li->next==0) break; + cur++; + li= li->next; + } + vec[0]= li->eff[0]; + vec[1]= li->eff[1]; + } + } + else return; +} + +void ob_parvert3(Object *ob, Object *par, float mat[][4]) +{ + float cmat[3][3], v1[3], v2[3], v3[3], q[4]; + + /* in lokale ob space */ + Mat4One(mat); + + if ELEM3(par->type, OB_MESH, OB_SURF, OB_CURVE) { + + give_parvert(par, ob->par1, v1); + give_parvert(par, ob->par2, v2); + give_parvert(par, ob->par3, v3); + + triatoquat(v1, v2, v3, q); + QuatToMat3(q, cmat); + Mat4CpyMat3(mat, cmat); + + if(ob->type==OB_CURVE) { + VECCOPY(mat[3], v1); + } + else { + VecAddf(mat[3], v1, v2); + VecAddf(mat[3], mat[3], v3); + VecMulf(mat[3], 0.3333333f); + } + } +} + +static int no_parent_ipo=0; +void set_no_parent_ipo(int val) +{ + no_parent_ipo= val; +} + +static float timefac= 1.0; /* 50 Hz, dtime:2 */ +void set_dtime(int dtime) +{ + timefac= ((float)(dtime-1))/2.0f; +} + +static int during_script_flag=0; +void disable_where_script(short on) +{ + during_script_flag= on; +} + +int during_script(void) { + return during_script_flag; +} + +void where_is_object_time(Object *ob, float ctime) +{ + Object *par; + float *fp1, *fp2, slowmat[4][4] = MAT4_UNITY; + float stime, fac1, fac2; + int a; + int pop; + + /* nieuwe versie: correcte parent+vertexparent en track+parent */ + /* deze berekent alleen de directe relatie met de parent en track */ + /* hij is sneller, maar moet wel de timeoffs in de gaten houden */ + + if(ob==0) return; + + if( ctime != ob->ctime) { + ob->ctime= ctime; + + if(ob->ipo) { + + stime= bsystem_time(ob, 0, ctime, 0.0); + + calc_ipo(ob->ipo, stime); + execute_ipo((ID *)ob, ob->ipo); + } + } + + + if(ob->type==OB_IKA) { + Ika *ika= ob->data; + if(ika->parent) where_is_object_time(ika->parent, ctime); + } + + if(ob->parent) { + par= ob->parent; + + if(ob->ipoflag & OB_OFFS_PARENT) ctime-= ob->sf; + + pop= 0; + if(no_parent_ipo==0 && ctime != par->ctime) { + + // alleen voor ipo systemen? + pushdata(par, sizeof(Object)); + pop= 1; + + where_is_object_time(par, ctime); + } + + solve_parenting(ob, par, slowmat, 0); + + if(pop) { + poplast(par); + } + + if(ob->partype & PARSLOW) { + // framerate meetellen + + fac1= (float)(timefac/(1.0+ fabs(ob->sf))); + if(fac1>=1.0) return; + fac2= 1.0f-fac1; + + fp1= ob->obmat[0]; + fp2= slowmat[0]; + for(a=0; a<16; a++, fp1++, fp2++) { + fp1[0]= fac1*fp1[0] + fac2*fp2[0]; + } + } + + } + else { + object_to_mat4(ob, ob->obmat); + } + + /* Handle tracking */ + if(ob->track) { + if( ctime != ob->track->ctime) where_is_object_time(ob->track, ctime); + solve_tracking (ob, ob->track->obmat); + + } + + solve_constraints (ob, TARGET_OBJECT, NULL, ctime); + + if(ob->scriptlink.totscript && !during_script()) { + BPY_do_pyscript((ID *)ob, SCRIPT_REDRAW); + } +} + +static void solve_parenting (Object *ob, Object *par, float slowmat[][4], int simul) +{ + float totmat[4][4]; + float tmat[4][4]; + float obmat[4][4]; + float vec[3]; + int ok; + + object_to_mat4(ob, obmat); + + if(ob->partype & PARSLOW) Mat4CpyMat4(slowmat, ob->obmat); + + + switch(ob->partype & PARTYPE) { + case PAROBJECT: + ok= 0; + if(par->type==OB_CURVE) { + if( ((Curve *)par->data)->flag & CU_PATH ) { + ob_parcurve(ob, par, tmat); + ok= 1; + } + } + + if(ok) Mat4MulSerie(totmat, par->obmat, tmat, + NULL, NULL, NULL, NULL, NULL, NULL); + else Mat4CpyMat4(totmat, par->obmat); + + break; + case PARBONE: + ob_parbone(ob, par, tmat); + Mat4MulSerie(totmat, par->obmat, tmat, + NULL, NULL, NULL, NULL, NULL, NULL); + break; + case PARLIMB: + ob_parlimb(ob, par, tmat); + Mat4MulSerie(totmat, par->obmat, tmat, + NULL, NULL, NULL, NULL, NULL, NULL); + break; + + case PARVERT1: + Mat4One(totmat); + if (simul){ + VECCOPY(totmat[3], par->obmat[3]); + } + else{ + give_parvert(par, ob->par1, vec); + VecMat4MulVecfl(totmat[3], par->obmat, vec); + } + break; + case PARVERT3: + ob_parvert3(ob, par, tmat); + + Mat4MulSerie(totmat, par->obmat, tmat, + NULL, NULL, NULL, NULL, NULL, NULL); + break; + + case PARSKEL: +#if 0 + if (ob!=G.obedit) + Mat4One(totmat); + else + Mat4CpyMat4(totmat, par->obmat); + break; +#else + Mat4CpyMat4(totmat, par->obmat); +#endif + } + + // totaal + Mat4MulSerie(tmat, totmat, ob->parentinv, + NULL, NULL, NULL, NULL, NULL, NULL); + Mat4MulSerie(ob->obmat, tmat, obmat, + NULL, NULL, NULL, NULL, NULL, NULL); + + if (simul){ + + } + else{ + // >>>>>>>>>>>>>>>>>> + // dit is een extern bruikbare originmat + Mat3CpyMat4(originmat, tmat); + + // origin, voor hulplijntje + if( (ob->partype & 15)==PARSKEL ) { + VECCOPY(ob->orig, par->obmat[3]); + } + else { + VECCOPY(ob->orig, totmat[3]); + } + } + +} +void solve_tracking (Object *ob, float targetmat[][4]) +{ + float *quat; + float vec[3]; + float totmat[3][3]; + float tmat[4][4]; + + VecSubf(vec, ob->obmat[3], targetmat[3]); + quat= vectoquat(vec, ob->trackflag, ob->upflag); + QuatToMat3(quat, totmat); + + if(ob->parent && (ob->transflag & OB_POWERTRACK)) { + /* 'tijdelijk' : parent info wissen */ + object_to_mat4(ob, tmat); + tmat[0][3]= ob->obmat[0][3]; + tmat[1][3]= ob->obmat[1][3]; + tmat[2][3]= ob->obmat[2][3]; + tmat[3][0]= ob->obmat[3][0]; + tmat[3][1]= ob->obmat[3][1]; + tmat[3][2]= ob->obmat[3][2]; + tmat[3][3]= ob->obmat[3][3]; + } + else Mat4CpyMat4(tmat, ob->obmat); + + Mat4MulMat34(ob->obmat, totmat, tmat); + +} + +void where_is_object(Object *ob) +{ + + /* deze zijn gememcopied */ + if(ob->flag & OB_FROMDUPLI) return; + + where_is_object_time(ob, (float)G.scene->r.cfra); +} + + +void where_is_object_simul(Object *ob) +/* It seems that this function is only called +for a lamp that is the child of another object */ +{ + Object *par; + Ipo *ipo; + float *fp1, *fp2; + float slowmat[4][4]; + float fac1, fac2; + int a; + + /* nieuwe versie: correcte parent+vertexparent en track+parent */ + /* deze berekent alleen de directe relatie met de parent en track */ + /* GEEN TIMEOFFS */ + + /* geen ipo! (ivm dloc en realtime-ipos) */ + ipo= ob->ipo; + ob->ipo= NULL; + + if(ob->parent) { + par= ob->parent; + + solve_parenting(ob, par, slowmat, 1); + + if(ob->partype & PARSLOW) { + + fac1= (float)(1.0/(1.0+ fabs(ob->sf))); + fac2= 1.0f-fac1; + fp1= ob->obmat[0]; + fp2= slowmat[0]; + for(a=0; a<16; a++, fp1++, fp2++) { + fp1[0]= fac1*fp1[0] + fac2*fp2[0]; + } + } + + } + else { + object_to_mat4(ob, ob->obmat); + } + + if(ob->track) + solve_tracking(ob, ob->track->obmat); + + solve_constraints(ob, TARGET_OBJECT, NULL, G.scene->r.cfra); + + /* LET OP!!! */ + ob->ipo= ipo; + +} +extern void Mat4BlendMat4(float out[][4], float dst[][4], float src[][4], float srcweight); + +void solve_constraints (Object *ob, short obtype, void *obdata, float ctime) +{ + bConstraint *con; + float tmat[4][4], focusmat[4][4], lastmat[4][4]; + int i, clear=1, tot=0; + float a; + float aquat[4], quat[4]; + float aloc[3], loc[3]; + float asize[3], size[3]; + float oldmat[4][4]; + float smat[3][3], rmat[3][3], mat[3][3]; + float enf; + + for (con = ob->constraints.first; con; con=con->next){ + /* Clear accumulators if necessary*/ + if (clear){ + clear=0; + a=0; + tot=0; + memset(aquat, 0, sizeof(float)*4); + memset(aloc, 0, sizeof(float)*3); + memset(asize, 0, sizeof(float)*3); + } + + /* Check this constraint only if it has some enforcement */ + // if (con->enforce > 0) + if (!(con->flag & CONSTRAINT_DISABLE)) + { + if (con->enforce==0) + enf = 0.001f; + enf = con->enforce; + + /* Get the targetmat */ + get_constraint_target(con, obtype, obdata, tmat, size, ctime); + + Mat4CpyMat4(focusmat, tmat); + + /* Extract the components & accumulate */ + Mat4ToQuat(focusmat, quat); + VECCOPY(loc, focusmat[3]); + + a+=enf; + tot++; + + for(i=0; i<3; i++){ + aquat[i+1]+=(quat[i+1]) * enf; + aloc[i]+=(loc[i]) * enf; + asize[i]+=(size[i]-1.0f) * enf; + } + aquat[0]+=(quat[0])*enf; + Mat4CpyMat4(lastmat, focusmat); + } + + /* If the next constraint is not the same type (or there isn't one), + * then evaluate the accumulator & request a clear */ + if ((!con->next)||(con->next && con->next->type!=con->type)) + { + clear=1; + Mat4CpyMat4(oldmat, ob->obmat); + + /* If we have several inputs, do a blend of them */ + if (tot){ + if (tot>1){ + if (a){ + for (i=0; i<3; i++){ + asize[i]=1.0f + (asize[i]/(a)); + aloc[i]=(aloc[i]/a); + } + + NormalQuat(aquat); + + QuatToMat3(aquat, rmat); + SizeToMat3(asize, smat); + Mat3MulMat3(mat, rmat, smat); + Mat4CpyMat3(focusmat, mat); + VECCOPY(focusmat[3], aloc); + + evaluate_constraint(con, ob, obtype, obdata, focusmat); + } + + } + /* If we only have one, blend with the current obmat */ + else{ + float solution[4][4]; + float delta[4][4]; + float imat[4][4]; + float identity[4][4]; + float worldmat[4][4]; + + if (con->type!=CONSTRAINT_TYPE_KINEMATIC){ + /* If we're not an IK constraint, solve the constraint then blend it to the previous one */ + evaluate_constraint(con, ob, obtype, obdata, lastmat); + + Mat4CpyMat4 (solution, ob->obmat); + + /* Interpolate the enforcement */ + Mat4Invert (imat, oldmat); + Mat4MulMat4 (delta, solution, imat); + + Mat4One(identity); + Mat4BlendMat4(delta, identity, delta, a); + Mat4MulMat4 (ob->obmat, delta, oldmat); + + } + else{ + /* Interpolate the target between the chain's unconstrained endpoint and the effector loc */ + if (obtype==TARGET_BONE){ + get_objectspace_bone_matrix(obdata, oldmat, 1, 1); + + Mat4MulMat4(worldmat, oldmat, ob->parent->obmat); + + Mat4BlendMat4(focusmat, worldmat, lastmat, a); + + evaluate_constraint(con, ob, obtype, obdata, focusmat); + } + } + } + } + } + } +} +void what_does_parent1(Object *par, int partype, int par1, int par2, int par3) +{ + + clear_workob(); + Mat4One(workob.parentinv); + workob.parent= par; + if(par) + workob.track= par->track; /* LET OP: NIET ECHT NETJES */ + workob.partype= partype; + workob.par1= par1; + workob.par2= par2; + workob.par3= par3; + + if (par){ + workob.constraints.first = par->constraints.first; + workob.constraints.last = par->constraints.last; + } + + where_is_object(&workob); +} + + +void what_does_parent(Object *ob) +{ + + clear_workob(); + Mat4One(workob.obmat); + Mat4One(workob.parentinv); + workob.parent= ob->parent; + workob.track= ob->track; + + workob.trackflag= ob->trackflag; + workob.upflag= ob->upflag; + + workob.partype= ob->partype; + workob.par1= ob->par1; + workob.par2= ob->par2; + workob.par3= ob->par3; + + workob.constraints.first = ob->constraints.first; + workob.constraints.last = ob->constraints.last; + + strcpy (workob.parsubstr, ob->parsubstr); + + where_is_object(&workob); +} + +BoundBox *unit_boundbox() +{ + BoundBox *bb; + + bb= MEM_mallocN(sizeof(BoundBox), "bb"); + + bb->vec[0][0]=bb->vec[1][0]=bb->vec[2][0]=bb->vec[3][0]= -1.0; + bb->vec[4][0]=bb->vec[5][0]=bb->vec[6][0]=bb->vec[7][0]= 1.0; + + bb->vec[0][1]=bb->vec[1][1]=bb->vec[4][1]=bb->vec[5][1]= -1.0; + bb->vec[2][1]=bb->vec[3][1]=bb->vec[6][1]=bb->vec[7][1]= 1.0; + + bb->vec[0][2]=bb->vec[3][2]=bb->vec[4][2]=bb->vec[7][2]= -1.0; + bb->vec[1][2]=bb->vec[2][2]=bb->vec[5][2]=bb->vec[6][2]= 1.0; + + return bb; +} + +void minmax_object(Object *ob, float *min, float *max) +{ + BoundBox bb; + Mesh *me; + Curve *cu; + float vec[3]; + int a; + + switch(ob->type) { + + case OB_CURVE: + case OB_FONT: + case OB_SURF: + cu= ob->data; + + if(cu->bb==0) tex_space_curve(cu); + bb= *(cu->bb); + + for(a=0; a<8; a++) { + Mat4MulVecfl(ob->obmat, bb.vec[a]); + DO_MINMAX(bb.vec[a], min, max); + } + break; + + case OB_MESH: + me= get_mesh(ob); + + if(me) { + if(me->bb==0) tex_space_mesh(me); + bb= *(me->bb); + + for(a=0; a<8; a++) { + Mat4MulVecfl(ob->obmat, bb.vec[a]); + DO_MINMAX(bb.vec[a], min, max); + } + } + if(min[0] < max[0] ) break; + + /* else here no break!!!, mesh can be zero sized */ + + default: + DO_MINMAX(ob->obmat[3], min, max); + + VECCOPY(vec, ob->obmat[3]); + VecAddf(vec, vec, ob->size); + DO_MINMAX(vec, min, max); + + VECCOPY(vec, ob->obmat[3]); + VecSubf(vec, vec, ob->size); + DO_MINMAX(vec, min, max); + break; + } +} + + diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c new file mode 100644 index 00000000000..991b4a8c840 --- /dev/null +++ b/source/blender/blenkernel/intern/packedFile.c @@ -0,0 +1,638 @@ +/** + * blenkernel/packedFile.c - (cleaned up mar-01 nzc) + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <stdio.h> +#include <fcntl.h> +#include <sys/stat.h> +#ifndef WIN32 +#include <unistd.h> +#else +#include <io.h> +#endif +#include <string.h> +#include "MEM_guardedalloc.h" + +#include "DNA_image_types.h" +#include "DNA_sound_types.h" +#include "DNA_vfont_types.h" +#include "DNA_packedFile_types.h" + + +#include "BLI_blenlib.h" + +#include "BKE_utildefines.h" +#include "BKE_bad_level_calls.h" + +#include "BKE_global.h" +#include "BKE_main.h" + +#include "BKE_screen.h" + +#include "BKE_sound.h" +//#include "sound.h" + +#include "BKE_image.h" +#include "BKE_font.h" +#include "BKE_packedFile.h" + +int seekPackedFile(PackedFile * pf, int offset, int whence) +{ + int oldseek = -1, seek = 0; + + if (pf) { + oldseek = pf->seek; + switch(whence) { + case SEEK_CUR: + seek = oldseek + offset; + break; + case SEEK_END: + seek = pf->size + offset; + break; + case SEEK_SET: + seek = offset; + break; + default: + oldseek = -1; + } + if (seek < 0) { + seek = 0; + } else if (seek > pf->size) { + seek = pf->size; + } + pf->seek = seek; + } + + return(oldseek); +} + +void rewindPackedFile(PackedFile * pf) +{ + seekPackedFile(pf, 0, SEEK_SET); +} + +int readPackedFile(PackedFile * pf, void * data, int size) +{ + if ((pf != NULL) && (size >= 0) && (data != NULL)) { + if (size + pf->seek > pf->size) { + size = pf->size - pf->seek; + } + + if (size > 0) { + memcpy(data, ((char *) pf->data) + pf->seek, size); + } else { + size = 0; + } + + pf->seek += size; + } else { + size = -1; + } + + return(size); +} + +int countPackedFiles() +{ + int count = 0; + Image *ima; + VFont *vf; + bSample *sample; + + // let's check if there are packed files... + ima = G.main->image.first; + while (ima) { + if (ima->packedfile) { + count++; + } + ima= ima->id.next; + } + + vf = G.main->vfont.first; + while (vf) { + if (vf->packedfile) { + count++; + } + vf = vf->id.next; + } + + sample = samples->first; + while (sample) { + if (sample->packedfile) { + count++; + } + sample = sample->id.next; + } + + return(count); +} + +void freePackedFile(PackedFile * pf) +{ + if (pf) { + MEM_freeN(pf->data); + MEM_freeN(pf); + } else { + printf("freePackedFile: Trying to free a NULL pointer\n"); + } +} + +PackedFile * newPackedFileMemory(void *mem, int memlen) +{ + PackedFile * pf = MEM_callocN(sizeof(*pf), "PackedFile"); + pf->data = mem; + pf->size = memlen; + + return pf; +} + +PackedFile * newPackedFile(char * filename) +{ + PackedFile * pf = NULL; + int file, filelen; + char name[FILE_MAXDIR+FILE_MAXFILE]; + void * data; + + waitcursor(1); + + // convert relative filenames to absolute filenames + + strcpy(name, filename); + BLI_convertstringcode(name, G.sce, G.scene->r.cfra); + + // open the file + // and create a PackedFile structure + + file= open(name, O_BINARY|O_RDONLY); + if (file <= 0) { + // error("Can't open file: %s", name); + } else { + filelen = BLI_filesize(file); + + if (filelen == 0) { + // MEM_mallocN complains about MEM_mallocN(0, "bla"); + // we don't care.... + data = MEM_mallocN(1, "packFile"); + } else { + data = MEM_mallocN(filelen, "packFile"); + } + if (read(file, data, filelen) == filelen) { + pf = newPackedFileMemory(data, filelen); + } + + close(file); + } + + waitcursor(0); + + return (pf); +} + +void packAll() +{ + Image *ima; + VFont *vf; + bSample *sample; + + ima = G.main->image.first; + while (ima) { + if (ima->packedfile == NULL) { + ima->packedfile = newPackedFile(ima->name); + } + ima= ima->id.next; + } + + vf = G.main->vfont.first; + while (vf) { + if (vf->packedfile == NULL) { + vf->packedfile = newPackedFile(vf->name); + } + vf = vf->id.next; + } + + + sample = samples->first; + while (sample) { + if (sample->packedfile == NULL) { + sound_set_packedfile(sample, newPackedFile(sample->name)); + } + sample = sample->id.next; + } +} + + +/* + +// attempt to create a function that generates an unique filename +// this will work when all funtions in fileops.c understand relative filenames... + +char * find_new_name(char * name) +{ + char tempname[FILE_MAXDIR + FILE_MAXFILE]; + char * newname; + + if (fop_exists(name)) { + for (number = 1; number <= 999; number++) { + sprintf(tempname, "%s.%03d", name, number); + if (! fop_exists(tempname)) { + break; + } + } + } + + newname = mallocN(strlen(tempname) + 1, "find_new_name"); + strcpy(newname, tempname); + + return(newname); +} + +*/ + +int writePackedFile(char * filename, PackedFile *pf) +{ + int file, number, remove_tmp = FALSE; + int ret_value = RET_OK; + char name[FILE_MAXDIR + FILE_MAXFILE]; + char tempname[FILE_MAXDIR + FILE_MAXFILE]; +/* void * data; */ + + waitcursor(1); + + strcpy(name, filename); + BLI_convertstringcode(name, G.sce, G.scene->r.cfra); + + if (BLI_exists(name)) { + for (number = 1; number <= 999; number++) { + sprintf(tempname, "%s.%03d_", name, number); + if (! BLI_exists(tempname)) { + if (BLI_copy_fileops(name, tempname) == RET_OK) { + remove_tmp = TRUE; + } + break; + } + } + } + + // make sure the path to the file exists... + RE_make_existing_file(name); + + file = open(name, O_BINARY + O_WRONLY + O_CREAT + O_TRUNC, 0666); + if (file >= 0) { + if (write(file, pf->data, pf->size) != pf->size) { + error("Error writing file: %s", name); + ret_value = RET_ERROR; + } + close(file); + } else { + error("Error creating file: %s", name); + ret_value = RET_ERROR; + } + + if (remove_tmp) { + if (ret_value == RET_ERROR) { + if (BLI_rename(tempname, name) == RET_ERROR) { + error("Error restoring tempfile. Check files: '%s' '%s'", tempname, name); + } + } else { + if (BLI_delete(tempname, 0, 0) == RET_ERROR) { + error("Error deleting '%s' (ignored)"); + } + } + } + + waitcursor(0); + + return (ret_value); +} + +/* + +This function compares a packed file to a 'real' file. +It returns an integer indicating if: + +PF_EQUAL - the packed file and original file are identical +PF_DIFFERENT - the packed file and original file differ +PF_NOFILE - the original file doens't exist + +*/ + +int checkPackedFile(char * filename, PackedFile * pf) +{ + struct stat st; + int ret_val, i, len, file; + char buf[4096]; + char name[FILE_MAXDIR + FILE_MAXFILE]; + + strcpy(name, filename); + BLI_convertstringcode(name, G.sce, G.scene->r.cfra); + + if (stat(name, &st)) { + ret_val = PF_NOFILE; + } else if (st.st_size != pf->size) { + ret_val = PF_DIFFERS; + } else { + // we'll have to compare the two... + + file = open(name, O_BINARY | O_RDONLY); + if (file < 0) { + ret_val = PF_NOFILE; + } else { + ret_val = PF_EQUAL; + + for (i = 0; i < pf->size; i += sizeof(buf)) { + len = pf->size - i; + if (len > sizeof(buf)) { + len = sizeof(buf); + } + + if (read(file, buf, len) != len) { + // read error ... + ret_val = PF_DIFFERS; + break; + } else { + if (memcmp(buf, ((char *)pf->data) + i, len)) { + ret_val = PF_DIFFERS; + break; + } + } + } + } + } + + return(ret_val); +} + +/* + +unpackFile() looks at the existing files (abs_name, local_name) and a packed file. +If how == PF_ASK it offers the user a couple of options what to do with the packed file. + +It returns a char * to the existing file name / new file name or NULL when +there was an error or when the user desides to cancel the operation. + +*/ + +char * unpackFile(char * abs_name, char * local_name, PackedFile * pf, int how) +{ + char menu[6 * (FILE_MAXDIR + FILE_MAXFILE + 100)]; + char line[FILE_MAXDIR + FILE_MAXFILE + 100]; + char * newname = NULL, * temp = NULL; + + // char newabs[FILE_MAXDIR + FILE_MAXFILE]; + // char newlocal[FILE_MAXDIR + FILE_MAXFILE]; + + if (pf != NULL) { + if (how == PF_ASK) { + strcpy(menu, "UnPack file%t"); + + if (strcmp(abs_name, local_name)) { + switch (checkPackedFile(local_name, pf)) { + case PF_NOFILE: + sprintf(line, "|Create %s%%x%d", local_name, PF_WRITE_LOCAL); + strcat(menu, line); + break; + case PF_EQUAL: + sprintf(line, "|Use %s (identical)%%x%d", local_name, PF_USE_LOCAL); + strcat(menu, line); + break; + case PF_DIFFERS: + sprintf(line, "|Use %s (differs)%%x%d", local_name, PF_USE_LOCAL); + strcat(menu, line); + sprintf(line, "|Overwrite %s%%x%d", local_name, PF_WRITE_LOCAL); + strcat(menu, line); + break; + } + // sprintf(line, "|%%x%d", PF_INVALID); + // strcat(menu, line); + } + + switch (checkPackedFile(abs_name, pf)) { + case PF_NOFILE: + sprintf(line, "|Create %s%%x%d", abs_name, PF_WRITE_ORIGINAL); + strcat(menu, line); + break; + case PF_EQUAL: + sprintf(line, "|Use %s (identical)%%x%d", abs_name, PF_USE_ORIGINAL); + strcat(menu, line); + break; + case PF_DIFFERS: + sprintf(line, "|Use %s (differs)%%x%d", abs_name, PF_USE_ORIGINAL); + strcat(menu, line); + sprintf(line, "|Overwrite %s%%x%d", abs_name, PF_WRITE_ORIGINAL); + strcat(menu, line); + break; + } + + how = pupmenu(menu); + } + + switch (how) { + case -1: + case PF_KEEP: + break; + case PF_USE_LOCAL: + // if file exists use it + if (BLI_exists(local_name)) { + temp = local_name; + break; + } + // else fall through and create it + case PF_WRITE_LOCAL: + if (writePackedFile(local_name, pf) == RET_OK) { + temp = local_name; + } + break; + case PF_USE_ORIGINAL: + // if file exists use it + if (BLI_exists(abs_name)) { + temp = abs_name; + break; + } + // else fall through and create it + case PF_WRITE_ORIGINAL: + if (writePackedFile(abs_name, pf) == RET_OK) { + temp = abs_name; + } + break; + default: + printf("unpackFile: unknown return_value %d\n", how); + break; + } + + if (temp) { + newname = MEM_mallocN(strlen(temp) + 1, "unpack_file newname"); + strcpy(newname, temp); + } + } + + return (newname); +} + + +int unpackVFont(VFont * vfont, int how) +{ + char localname[FILE_MAXDIR + FILE_MAXFILE], fi[FILE_MAXFILE]; + char * newname; + int ret_value = RET_ERROR; + + if (vfont != NULL) { + strcpy(localname, vfont->name); + BLI_splitdirstring(localname, fi); + + sprintf(localname, "//fonts/%s", fi); + + newname = unpackFile(vfont->name, localname, vfont->packedfile, how); + if (newname != NULL) { + ret_value = RET_OK; + freePackedFile(vfont->packedfile); + vfont->packedfile = 0; + strcpy(vfont->name, newname); + MEM_freeN(newname); + } + } + + return (ret_value); +} + +/* +create_local_name() creates a relative (starting with //) name. +Because it is allowed to have /'s and \'s in blenderobject names +we have to remove these first. +*/ + + +void create_local_name(char *localname, char *prefix, char *filename) +{ + char tempname[FILE_MAXDIR + FILE_MAXFILE]; + int i, len; + + strcpy(tempname, filename); + len = strlen(tempname); + + for (i = 0; i < len ; i++) { + switch (tempname[i]) + { + case '/': + case '\\': + case ' ': + tempname[i] = '_'; + break; + } + } + + strcpy(localname, prefix); + strcat(localname, tempname); +} + + +int unpackSample(bSample *sample, int how) +{ + char localname[FILE_MAXDIR + FILE_MAXFILE]; + char * newname; + int ret_value = RET_ERROR; + PackedFile *pf; + + if (sample != NULL) { + create_local_name(localname, "//samples/", sample->id.name + 2); + + newname = unpackFile(sample->name, localname, sample->packedfile, how); + if (newname != NULL) { + strcpy(sample->name, newname); + MEM_freeN(newname); + + pf = sample->packedfile; + // because samples and sounds can point to the + // same packedfile we have to check them all + sound_set_packedfile(sample, NULL); + freePackedFile(pf); + + ret_value = RET_OK; + } + } + + return(ret_value); +} + +int unpackImage(Image * ima, int how) +{ + char localname[FILE_MAXDIR + FILE_MAXFILE]; + char * newname; + int ret_value = RET_ERROR; + + if (ima != NULL) { + create_local_name(localname, "//textures/", ima->id.name + 2); + + newname = unpackFile(ima->name, localname, ima->packedfile, how); + if (newname != NULL) { + ret_value = RET_OK; + freePackedFile(ima->packedfile); + ima->packedfile = 0; + strcpy(ima->name, newname); + MEM_freeN(newname); + free_image_buffers(ima); + } + } + + return(ret_value); +} + +void unpackAll(int how) +{ + Image *ima; + VFont *vf; + bSample *sample; + + ima = G.main->image.first; + while (ima) { + if (ima->packedfile) { + unpackImage(ima, how); + } + ima= ima->id.next; + } + + vf = G.main->vfont.first; + while (vf) { + if (vf->packedfile) { + unpackVFont(vf, how); + } + vf = vf->id.next; + } + + sample = samples->first; + while (sample) { + if (sample->packedfile) { + unpackSample(sample, how); + } + sample = sample->id.next; + } +} diff --git a/source/blender/blenkernel/intern/property.c b/source/blender/blenkernel/intern/property.c new file mode 100644 index 00000000000..d097dba0db0 --- /dev/null +++ b/source/blender/blenkernel/intern/property.c @@ -0,0 +1,269 @@ + +/* property.c june 2000 + * + * ton roosendaal + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifdef WIN32 +#include "BLI_winstuff.h" +#endif + +#include "MEM_guardedalloc.h" + +#include "DNA_property_types.h" +#include "DNA_object_types.h" +#include "DNA_listBase.h" + + +#include "BLI_blenlib.h" +#include "BKE_bad_level_calls.h" +#include "BKE_property.h" + +void free_property(bProperty *prop) +{ + + if(prop->poin && prop->poin != &prop->data) MEM_freeN(prop->poin); + MEM_freeN(prop); + +} + +void free_properties(ListBase *lb) +{ + bProperty *prop; + + while( (prop= lb->first) ) { + BLI_remlink(lb, prop); + free_property(prop); + } +} + +bProperty *copy_property(bProperty *prop) +{ + bProperty *propn; + + propn= MEM_dupallocN(prop); + if(prop->poin && prop->poin != &prop->data) { + propn->poin= MEM_dupallocN(prop->poin); + } + else propn->poin= &propn->data; + + return propn; +} + +void copy_properties(ListBase *lbn, ListBase *lbo) +{ + bProperty *prop, *propn; + + lbn->first= lbn->last= 0; + prop= lbo->first; + while(prop) { + propn= copy_property(prop); + BLI_addtail(lbn, propn); + prop= prop->next; + } + + +} + +void init_property(bProperty *prop) +{ + /* also use when property changes type */ + + if(prop->poin && prop->poin != &prop->data) MEM_freeN(prop->poin); + prop->poin= 0; + + prop->otype= prop->type; + prop->data= 0; + + switch(prop->type) { + case PROP_BOOL: + prop->poin= &prop->data; + break; + case PROP_INT: + prop->poin= &prop->data; + break; + case PROP_FLOAT: + prop->poin= &prop->data; + break; + case PROP_STRING: + prop->poin= MEM_callocN(MAX_PROPSTRING, "property string"); + break; + case PROP_TIME: + prop->poin= &prop->data; + break; + } +} + + +bProperty *new_property(int type) +{ + bProperty *prop; + + prop= MEM_callocN(sizeof(bProperty), "property"); + prop->type= type; + + init_property(prop); + + strcpy(prop->name, "prop"); + + return prop; +} + +bProperty *get_property(Object *ob, char *name) +{ + bProperty *prop; + + prop= ob->prop.first; + while(prop) { + if( strcmp(prop->name, name)==0 ) return prop; + prop= prop->next; + } + return NULL; +} + +/* negative: prop is smaller + * positive: prop is larger + */ +int compare_property(bProperty *prop, char *str) +{ +// extern int Gdfra; /* sector.c */ + float fvalue, ftest; + + switch(prop->type) { + case PROP_BOOL: + if(strcasecmp(str, "true")==0) { + if(prop->data==1) return 0; + else return 1; + } + else if(strcasecmp(str, "false")==0) { + if(prop->data==0) return 0; + else return 1; + } + /* no break, do prop_int too! */ + + case PROP_INT: + return prop->data - atoi(str); + + case PROP_FLOAT: + case PROP_TIME: + // WARNING: untested for PROP_TIME + // function isn't used currently + fvalue= *((float *)&prop->data); + ftest= (float)atof(str); + if( fvalue > ftest) return 1; + else if( fvalue < ftest) return -1; + return 0; + + case PROP_STRING: + return strcmp(prop->poin, str); + } + + return 0; +} + +void set_property(bProperty *prop, char *str) +{ +// extern int Gdfra; /* sector.c */ + + switch(prop->type) { + case PROP_BOOL: + if(strcasecmp(str, "true")==0) prop->data= 1; + else if(strcasecmp(str, "false")==0) prop->data= 0; + else prop->data= (atoi(str)!=0); + break; + case PROP_INT: + prop->data= atoi(str); + break; + case PROP_FLOAT: + case PROP_TIME: + *((float *)&prop->data)= (float)atof(str); + break; + case PROP_STRING: + strcpy(prop->poin, str); + break; + } + +} + +void add_property(bProperty *prop, char *str) +{ +// extern int Gdfra; /* sector.c */ + + switch(prop->type) { + case PROP_BOOL: + case PROP_INT: + prop->data+= atoi(str); + break; + case PROP_FLOAT: + case PROP_TIME: + *((float *)&prop->data)+= (float)atof(str); + break; + case PROP_STRING: + /* strcpy(prop->poin, str); */ + break; + } +} + +/* reads value of property, sets it in chars in str */ +void set_property_valstr(bProperty *prop, char *str) +{ +// extern int Gdfra; /* sector.c */ + + if(str == NULL) return; + + switch(prop->type) { + case PROP_BOOL: + case PROP_INT: + sprintf(str, "%d", prop->data); + break; + case PROP_FLOAT: + case PROP_TIME: + sprintf(str, "%f", *((float *)&prop->data)); + break; + case PROP_STRING: + BLI_strncpy(str, prop->poin, MAX_PROPSTRING); + break; + } +} + +void cp_property(bProperty *prop1, bProperty *prop2) +{ + char str[128]; + + set_property_valstr(prop2, str); + + set_property(prop1, str); +} diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c new file mode 100644 index 00000000000..a105b240942 --- /dev/null +++ b/source/blender/blenkernel/intern/sca.c @@ -0,0 +1,631 @@ +/** + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * these all are linked to objects (listbase) + * all data is 'direct data', not Blender lib data. + */ + +#include <stdio.h> +#include <string.h> +#include "MEM_guardedalloc.h" + +#include "nla.h" /* For __NLA: Important, do not remove */ +#include "DNA_text_types.h" +#include "DNA_controller_types.h" +#include "DNA_sensor_types.h" +#include "DNA_actuator_types.h" +#include "DNA_object_types.h" + +#include "BLI_blenlib.h" +#include "BKE_bad_level_calls.h" +#include "BKE_utildefines.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_blender.h" +#include "BKE_sca.h" + +void free_text_controllers(Text *txt) +{ + Object *ob; + bController *cont; + + ob= G.main->object.first; + while(ob) { + cont= ob->controllers.first; + while(cont) { + if(cont->type==CONT_PYTHON) { + bPythonCont *pc; + + pc= cont->data; + if(pc->text==txt) pc->text= NULL; + } + cont= cont->next; + } + ob= ob->id.next; + } +} + + +/* ******************* SENSORS ************************ */ + +void free_sensor(bSensor *sens) +{ + if(sens->links) MEM_freeN(sens->links); + if(sens->data) MEM_freeN(sens->data); + MEM_freeN(sens); + +} + +void free_sensors(ListBase *lb) +{ + bSensor *sens; + + while((sens= lb->first)) { + BLI_remlink(lb, sens); + free_sensor(sens); + } +} + +bSensor *copy_sensor(bSensor *sens) +{ + bSensor *sensn; + + sensn= MEM_dupallocN(sens); + sensn->flag |= SENS_NEW; + if(sens->data) { + sensn->data= MEM_dupallocN(sens->data); + } + + if(sens->links) sensn->links= MEM_dupallocN(sens->links); + + return sensn; +} + +void copy_sensors(ListBase *lbn, ListBase *lbo) +{ + bSensor *sens, *sensn; + + lbn->first= lbn->last= 0; + sens= lbo->first; + while(sens) { + sensn= copy_sensor(sens); + BLI_addtail(lbn, sensn); + sens= sens->next; + } +} + +void init_sensor(bSensor *sens) +{ + /* also use when sensor changes type */ + bNearSensor *ns; + bMouseSensor *ms; + + if(sens->data) MEM_freeN(sens->data); + sens->data= NULL; + sens->pulse = 0; + + switch(sens->type) { + case SENS_ALWAYS: + sens->pulse = 1; + break; + case SENS_TOUCH: + sens->data= MEM_callocN(sizeof(bTouchSensor), "touchsens"); + break; + case SENS_NEAR: + ns=sens->data= MEM_callocN(sizeof(bNearSensor), "nearsens"); + ns->dist= 1.0; + ns->resetdist= 2.0; + break; + case SENS_KEYBOARD: + sens->data= MEM_callocN(sizeof(bKeyboardSensor), "keysens"); + break; + case SENS_PROPERTY: + sens->data= MEM_callocN(sizeof(bPropertySensor), "propsens"); + break; + case SENS_MOUSE: + ms=sens->data= MEM_callocN(sizeof(bMouseSensor), "mousesens"); + ms->type= LEFTMOUSE; + break; + case SENS_COLLISION: + sens->data= MEM_callocN(sizeof(bCollisionSensor), "colsens"); + break; + case SENS_RADAR: + sens->data= MEM_callocN(sizeof(bRadarSensor), "radarsens"); + break; + case SENS_RANDOM: + sens->data= MEM_callocN(sizeof(bRandomSensor), "randomsens"); + break; + case SENS_RAY: + sens->data= MEM_callocN(sizeof(bRaySensor), "raysens"); + break; + case SENS_MESSAGE: + sens->data= MEM_callocN(sizeof(bMessageSensor), "messagesens"); + break; + default: + ; /* this is very severe... I cannot make any memory for this */ + /* logic brick... */ + } +} + +bSensor *new_sensor(int type) +{ + bSensor *sens; + + sens= MEM_callocN(sizeof(bSensor), "Sensor"); + sens->type= type; + sens->flag= SENS_SHOW; + + init_sensor(sens); + + strcpy(sens->name, "sensor"); + make_unique_prop_names(sens->name); + + return sens; +} + +/* ******************* CONTROLLERS ************************ */ + +void unlink_controller(bController *cont) +{ + bSensor *sens; + Object *ob; + int a, removed; + + /* check for controller pointers in sensors */ + ob= G.main->object.first; + while(ob) { + sens= ob->sensors.first; + while(sens) { + removed= 0; + for(a=0; a<sens->totlinks; a++) { + if(removed) (sens->links)[a-1] = (sens->links)[a]; + else if((sens->links)[a] == cont) removed= 1; + } + if(removed) { + sens->totlinks--; + + if(sens->totlinks==0) { + MEM_freeN(sens->links); + sens->links= NULL; + } + } + sens= sens->next; + } + ob= ob->id.next; + } +} + +void unlink_controllers(ListBase *lb) +{ + bController *cont; + + for (cont= lb->first; cont; cont= cont->next) + unlink_controller(cont); +} + +void free_controller(bController *cont) +{ + if(cont->links) MEM_freeN(cont->links); + + /* the controller itself */ + if(cont->data) MEM_freeN(cont->data); + MEM_freeN(cont); + +} + +void free_controllers(ListBase *lb) +{ + bController *cont; + + while((cont= lb->first)) { + BLI_remlink(lb, cont); + if(cont->slinks) MEM_freeN(cont->slinks); + free_controller(cont); + } +} + +bController *copy_controller(bController *cont) +{ + bController *contn; + + cont->mynew=contn= MEM_dupallocN(cont); + contn->flag |= CONT_NEW; + if(cont->data) { + contn->data= MEM_dupallocN(cont->data); + } + + if(cont->links) contn->links= MEM_dupallocN(cont->links); + contn->slinks= NULL; + contn->totslinks= 0; + + return contn; +} + +void copy_controllers(ListBase *lbn, ListBase *lbo) +{ + bController *cont, *contn; + + lbn->first= lbn->last= 0; + cont= lbo->first; + while(cont) { + contn= copy_controller(cont); + BLI_addtail(lbn, contn); + cont= cont->next; + } +} + +void init_controller(bController *cont) +{ + /* also use when controller changes type, leave actuators... */ + + if(cont->data) MEM_freeN(cont->data); + cont->data= 0; + + switch(cont->type) { + case CONT_EXPRESSION: + cont->data= MEM_callocN(sizeof(bExpressionCont), "expcont"); + break; + case CONT_PYTHON: + cont->data= MEM_callocN(sizeof(bPythonCont), "pycont"); + break; + } +} + +bController *new_controller(int type) +{ + bController *cont; + + cont= MEM_callocN(sizeof(bController), "Controller"); + cont->type= type; + cont->flag= CONT_SHOW; + + init_controller(cont); + + strcpy(cont->name, "cont"); + make_unique_prop_names(cont->name); + + return cont; +} + +/* ******************* ACTUATORS ************************ */ + +void unlink_actuator(bActuator *act) +{ + bController *cont; + Object *ob; + int a, removed; + + /* check for actuator pointers in controllers */ + ob= G.main->object.first; + while(ob) { + cont= ob->controllers.first; + while(cont) { + removed= 0; + for(a=0; a<cont->totlinks; a++) { + if(removed) (cont->links)[a-1] = (cont->links)[a]; + else if((cont->links)[a] == act) removed= 1; + } + if(removed) { + cont->totlinks--; + + if(cont->totlinks==0) { + MEM_freeN(cont->links); + cont->links= NULL; + } + } + cont= cont->next; + } + ob= ob->id.next; + } +} + +void unlink_actuators(ListBase *lb) +{ + bActuator *act; + + for (act= lb->first; act; act= act->next) + unlink_actuator(act); +} + +void free_actuator(bActuator *act) +{ + if(act->data) MEM_freeN(act->data); + MEM_freeN(act); +} + +void free_actuators(ListBase *lb) +{ + bActuator *act; + + while((act= lb->first)) { + BLI_remlink(lb, act); + free_actuator(act); + } +} + +bActuator *copy_actuator(bActuator *act) +{ + bActuator *actn; + + act->mynew=actn= MEM_dupallocN(act); + actn->flag |= ACT_NEW; + if(act->data) { + actn->data= MEM_dupallocN(act->data); + } + + return actn; +} + +void copy_actuators(ListBase *lbn, ListBase *lbo) +{ + bActuator *act, *actn; + + lbn->first= lbn->last= 0; + act= lbo->first; + while(act) { + actn= copy_actuator(act); + BLI_addtail(lbn, actn); + act= act->next; + } +} + +void init_actuator(bActuator *act) +{ + /* also use when actuator changes type */ + bObjectActuator *oa; + + if(act->data) MEM_freeN(act->data); + act->data= 0; + + switch(act->type) { +#ifdef __NLA + case ACT_ACTION: + act->data= MEM_callocN(sizeof(bActionActuator), "actionact"); + break; +#endif + case ACT_SOUND: + act->data= MEM_callocN(sizeof(bSoundActuator), "soundact"); + break; + case ACT_CD: + act->data= MEM_callocN(sizeof(bCDActuator), "cdact"); + break; + case ACT_OBJECT: + act->data= MEM_callocN(sizeof(bObjectActuator), "objectact"); + oa= act->data; + oa->flag= 15; + break; + case ACT_IPO: + act->data= MEM_callocN(sizeof(bIpoActuator), "ipoact"); + break; + case ACT_PROPERTY: + act->data= MEM_callocN(sizeof(bPropertyActuator), "propact"); + break; + case ACT_CAMERA: + act->data= MEM_callocN(sizeof(bCameraActuator), "camact"); + break; + case ACT_EDIT_OBJECT: + act->data= MEM_callocN(sizeof(bEditObjectActuator), "editobact"); + break; + case ACT_CONSTRAINT: + act->data= MEM_callocN(sizeof(bConstraintActuator), "cons act"); + break; + case ACT_SCENE: + act->data= MEM_callocN(sizeof(bSceneActuator), "scene act"); + break; + case ACT_GROUP: + act->data= MEM_callocN(sizeof(bGroupActuator), "group act"); + break; + case ACT_RANDOM: + act->data= MEM_callocN(sizeof(bRandomActuator), "random act"); + break; + case ACT_MESSAGE: + act->data= MEM_callocN(sizeof(bMessageActuator), "message act"); + break; + case ACT_GAME: + act->data= MEM_callocN(sizeof(bGameActuator), "game act"); + break; + case ACT_VISIBILITY: + act->data= MEM_callocN(sizeof(bVisibilityActuator), "visibility act"); + break; + default: + ; /* this is very severe... I cannot make any memory for this */ + /* logic brick... */ + } +} + +bActuator *new_actuator(int type) +{ + bActuator *act; + + act= MEM_callocN(sizeof(bActuator), "Actuator"); + act->type= type; + act->flag= ACT_SHOW; + + init_actuator(act); + + strcpy(act->name, "act"); + make_unique_prop_names(act->name); + + return act; +} + +/* ******************** GENERAL ******************* */ + +void clear_sca_new_poins_ob(Object *ob) +{ + bSensor *sens; + bController *cont; + bActuator *act; + + sens= ob->sensors.first; + while(sens) { + sens->flag &= ~SENS_NEW; + sens= sens->next; + } + cont= ob->controllers.first; + while(cont) { + cont->mynew= NULL; + cont->flag &= ~CONT_NEW; + cont= cont->next; + } + act= ob->actuators.first; + while(act) { + act->mynew= NULL; + act->flag &= ~ACT_NEW; + act= act->next; + } +} + +void clear_sca_new_poins() +{ + Object *ob; + + ob= G.main->object.first; + while(ob) { + clear_sca_new_poins_ob(ob); + ob= ob->id.next; + } +} + +void set_sca_new_poins_ob(Object *ob) +{ + bSensor *sens; + bController *cont; + bActuator *act; + int a; + + sens= ob->sensors.first; + while(sens) { + if(sens->flag & SENS_NEW) { + for(a=0; a<sens->totlinks; a++) { + if(sens->links[a] && sens->links[a]->mynew) + sens->links[a]= sens->links[a]->mynew; + } + } + sens= sens->next; + } + + cont= ob->controllers.first; + while(cont) { + if(cont->flag & CONT_NEW) { + for(a=0; a<cont->totlinks; a++) { + if( cont->links[a] && cont->links[a]->mynew) + cont->links[a]= cont->links[a]->mynew; + } + } + cont= cont->next; + } + + + act= ob->actuators.first; + while(act) { + if(act->flag & ACT_NEW) { + if(act->type==ACT_EDIT_OBJECT) { + bEditObjectActuator *eoa= act->data; + ID_NEW(eoa->ob); + } + else if(act->type==ACT_SCENE) { + bSceneActuator *sca= act->data; + ID_NEW(sca->camera); + } + else if(act->type==ACT_CAMERA) { + bCameraActuator *ca= act->data; + ID_NEW(ca->ob); + } + else if(act->type==ACT_SCENE) { + bSceneActuator *sca= act->data; + ID_NEW(sca->camera); + } + } + act= act->next; + } +} + + +void set_sca_new_poins() +{ + Object *ob; + + ob= G.main->object.first; + while(ob) { + set_sca_new_poins_ob(ob); + ob= ob->id.next; + } +} + +void sca_remove_ob_poin(Object *obt, Object *ob) +{ + bSensor *sens; + bMessageSensor *ms; + bActuator *act; + bCameraActuator *ca; + bSceneActuator *sa; + bEditObjectActuator *eoa; + bPropertyActuator *pa; + bMessageActuator *ma; + + sens= obt->sensors.first; + while(sens) { + switch(sens->type) { + case SENS_MESSAGE: + ms= sens->data; + if(ms->fromObject==ob) ms->fromObject= NULL; + } + sens= sens->next; + } + + act= obt->actuators.first; + while(act) { + switch(act->type) { + case ACT_CAMERA: + ca= act->data; + if(ca->ob==ob) ca->ob= NULL; + break; + case ACT_PROPERTY: + pa= act->data; + if(pa->ob==ob) pa->ob= NULL; + break; + case ACT_SCENE: + sa= act->data; + if(sa->camera==ob) sa->camera= NULL; + break; + case ACT_EDIT_OBJECT: + eoa= act->data; + if(eoa->ob==ob) eoa->ob= NULL; + break; + case ACT_MESSAGE: + ma= act->data; + if(ma->toObject==ob) ma->toObject= NULL; + break; + + } + act= act->next; + } +} diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c new file mode 100644 index 00000000000..d1da1d4d1b6 --- /dev/null +++ b/source/blender/blenkernel/intern/scene.c @@ -0,0 +1,536 @@ + +/* scene.c MIXED MODEL + * + * jan 95 + * + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <stdio.h> + +#ifndef WIN32 +#include <unistd.h> +#else +#include "BLI_winstuff.h" +#include <io.h> +#endif +#include "MEM_guardedalloc.h" + +#include "nla.h" /* for __NLA : IMPORTANT Do not delete me yet! */ +#ifdef __NLA /* for __NLA : IMPORTANT Do not delete me yet! */ +#include "DNA_armature_types.h" /* for __NLA : IMPORTANT Do not delete me yet! */ +#include "BKE_armature.h" /* for __NLA : IMPORTANT Do not delete me yet! */ +#include "BKE_action.h" /* for __NLA : IMPORTANT Do not delete me yet! */ +#endif /* for __NLA : IMPORTANT Do not delete me yet! */ + +#include "DNA_constraint_types.h" +#include "DNA_scene_types.h" +#include "DNA_object_types.h" +#include "DNA_scriptlink_types.h" +#include "DNA_meta_types.h" +#include "DNA_ika_types.h" +#include "DNA_lamp_types.h" +#include "DNA_material_types.h" +#include "DNA_mesh_types.h" +#include "DNA_group_types.h" +#include "DNA_curve_types.h" +#include "DNA_userdef_types.h" + +#include "BLI_blenlib.h" + +#include "BKE_bad_level_calls.h" +#include "BKE_utildefines.h" + +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_anim.h" + +#include "BKE_library.h" + +#include "BPY_extern.h" +#include "BKE_scene.h" +#include "BKE_world.h" +#include "BKE_ipo.h" +#include "BKE_ika.h" +#include "BKE_key.h" + +void free_avicodecdata(AviCodecData *acd) +{ + if (acd) { + if (acd->lpFormat){ + MEM_freeN(acd->lpFormat); + acd->lpFormat = NULL; + acd->cbFormat = 0; + } + if (acd->lpParms){ + MEM_freeN(acd->lpParms); + acd->lpParms = NULL; + acd->cbParms = 0; + } + } +} + +/* niet scene zelf vrijgeven */ +void free_scene(Scene *sce) +{ + Base *base; + + base= sce->base.first; + while(base) { + base->object->id.us--; + base= base->next; + } + /* pas op: niet objects vrijgeven! */ + + BLI_freelistN(&sce->base); + free_editing(sce->ed); + if(sce->radio) MEM_freeN(sce->radio); + if(sce->fcam) MEM_freeN(sce->fcam); + sce->radio= 0; + + BPY_free_scriptlink(&sce->scriptlink); + if (sce->r.avicodecdata) { + free_avicodecdata(sce->r.avicodecdata); + MEM_freeN(sce->r.avicodecdata); + sce->r.avicodecdata = NULL; + } +} + +Scene *add_scene(char *name) +{ + Scene *sce; + + sce= alloc_libblock(&G.main->scene, ID_SCE, name); + sce->lay= 1; + + sce->r.mode= R_GAMMA; + sce->r.cfra= 1; + sce->r.sfra= 1; + sce->r.efra= 250; + sce->r.xsch= 320; + sce->r.ysch= 256; + sce->r.xasp= 1; + sce->r.yasp= 1; + sce->r.xparts= 1; + sce->r.yparts= 1; + sce->r.size= 100; + sce->r.planes= 24; + sce->r.quality= 90; + sce->r.framapto= 100; + sce->r.images= 100; + sce->r.framelen= 1.0; + sce->r.frs_sec= 25; + + sce->r.xplay= 640; + sce->r.yplay= 480; + sce->r.freqplay= 60; + sce->r.depth= 32; + + sce->r.stereomode = 1; // no stereo + + strcpy(sce->r.backbuf, "//backbuf"); + strcpy(sce->r.pic, U.renderdir); + strcpy(sce->r.ftype, "//ftype"); + + BLI_init_rctf(&sce->r.safety, 0.1f, 0.9f, 0.1f, 0.9f); + sce->r.osa= 8; + + return sce; +} + +int object_in_scene(Object *ob, Scene *sce) +{ + Base *base; + + base= sce->base.first; + while(base) { + if(base->object == ob) return 1; + base= base->next; + } + return 0; +} + +void sort_baselist(Scene *sce) +{ + /* alles in volgorde van parent en track */ + ListBase tempbase, noparentbase, notyetbase; + Base *base, *test=NULL; + Object *par; + int doit, domore= 0, lastdomore=1; + + + /* volgorde gelijk houden als er niets veranderd is! */ + /* hier waren problemen met campos array's: volgorde camera's is van belang */ + + while(domore!=lastdomore) { + + lastdomore= domore; + domore= 0; + tempbase.first= tempbase.last= 0; + noparentbase.first= noparentbase.last= 0; + notyetbase.first= notyetbase.last= 0; + + while( (base= sce->base.first) ) { + BLI_remlink(&sce->base, base); + + par= 0; + if(base->object->type==OB_IKA) { + Ika *ika= base->object->data; + par= ika->parent; + } + + if(par || base->object->parent || base->object->track) { + + doit= 0; + if(base->object->parent) doit++; + if(base->object->track) doit++; + + /* Count constraints */ + { + bConstraint *con; + for (con = base->object->constraints.first; con; con=con->next){ + switch (con->type){ + case CONSTRAINT_TYPE_KINEMATIC: + { + bKinematicConstraint *data=con->data; + if (data->tar) doit++; + } + break; + case CONSTRAINT_TYPE_TRACKTO: + { + bTrackToConstraint *data=con->data; + if (data->tar) doit++; + } + break; + case CONSTRAINT_TYPE_NULL: + break; + case CONSTRAINT_TYPE_ROTLIKE: + { + bRotateLikeConstraint *data=con->data; + if (data->tar) doit++; + + } + break; + case CONSTRAINT_TYPE_LOCLIKE: + { + bLocateLikeConstraint *data=con->data; + if (data->tar) doit++; + } + break; + case CONSTRAINT_TYPE_ACTION: + { + bActionConstraint *data=con->data; + if (data->tar) doit++; + } + break; + default: + break; + } + } + } + + if(par) doit++; + + test= tempbase.first; + while(test) { + + if(test->object==base->object->parent) doit--; + if(test->object==base->object->track) doit--; + if(test->object==par) doit--; + + /* Decrement constraints */ + { + bConstraint *con; + for (con = base->object->constraints.first; con; con=con->next){ + switch (con->type){ + case CONSTRAINT_TYPE_KINEMATIC: + { + bKinematicConstraint *data=con->data; + if (test->object == data->tar && test->object!=base->object) doit--; + } + break; + case CONSTRAINT_TYPE_TRACKTO: + { + bTrackToConstraint *data=con->data; + if (test->object == data->tar && test->object!=base->object) doit--; + } + break; + case CONSTRAINT_TYPE_NULL: + break; + case CONSTRAINT_TYPE_ROTLIKE: + { + bRotateLikeConstraint *data=con->data; + if (test->object == data->tar && test->object!=base->object) doit--; + + } + break; + case CONSTRAINT_TYPE_LOCLIKE: + { + bLocateLikeConstraint *data=con->data; + if (test->object == data->tar && test->object!=base->object) doit--; + } + break; + case CONSTRAINT_TYPE_ACTION: + { + bActionConstraint *data=con->data; + if (test->object == data->tar && test->object!=base->object) doit--; + } + break; + default: + break; + } + } + } + + if(doit==0) break; + test= test->next; + } + + if(test) BLI_insertlink(&tempbase, test, base); + else { + BLI_addhead(&tempbase, base); + domore++; + } + + } + else BLI_addtail(&noparentbase, base); + + } + sce->base= noparentbase; + addlisttolist(&sce->base, &tempbase); + addlisttolist(&sce->base, ¬yetbase); + + } +} + + +void set_scene_bg(Scene *sce) +{ + Base *base; + Object *ob; + Group *group; + GroupObject *go; + int flag; + + G.scene= sce; + + /* objecten deselecteren (voor dataselect) */ + ob= G.main->object.first; + while(ob) { + ob->flag &= ~(SELECT|OB_FROMGROUP); + ob= ob->id.next; + } + + /* group flags again */ + group= G.main->group.first; + while(group) { + go= group->gobject.first; + while(go) { + if(go->ob) go->ob->flag |= OB_FROMGROUP; + go= go->next; + } + group= group->id.next; + } + + /* baselijst sorteren */ + sort_baselist(sce); + + /* layers en flags uit bases naar objecten kopieeren */ + base= G.scene->base.first; + while(base) { + + base->object->lay= base->lay; + + base->flag &= ~OB_FROMGROUP; + flag= base->object->flag & OB_FROMGROUP; + base->flag |= flag; + + base->object->ctime= -1234567.0; /* forceer ipo */ + base= base->next; + } + + do_all_ipos(); /* layers/materials */ + + BPY_do_all_scripts(SCRIPT_FRAMECHANGED); + do_all_keys(); +#ifdef __NLA + do_all_actions(); +#endif + do_all_ikas(); + + +} + +void set_scene_name(char *name) +{ + Scene *sce; + + for (sce= G.main->scene.first; sce; sce= sce->id.next) { + if (BLI_streq(name, sce->id.name+2)) { + set_scene_bg(sce); + return; + } + } + + error("Can't find scene: %s", name); +} + +/* used by metaballs + * doesnt return the original duplicated object, only dupli's + */ +int next_object(int val, Base **base, Object **ob) +{ + extern ListBase duplilist; + static Object *dupob; + static int fase; + int run_again=1; + + /* init */ + if(val==0) { + fase= F_START; + dupob= 0; + } + else { + + /* run_again is set when a duplilist has been ended */ + while(run_again) { + run_again= 0; + + + + /* de eerste base */ + if(fase==F_START) { + *base= G.scene->base.first; + if(*base) { + *ob= (*base)->object; + fase= F_SCENE; + } + else { + /* uitzondering: een lege scene */ + if(G.scene->set && G.scene->set->base.first) { + *base= G.scene->set->base.first; + *ob= (*base)->object; + fase= F_SET; + } + } + } + else { + if(*base && fase!=F_DUPLI) { + *base= (*base)->next; + if(*base) *ob= (*base)->object; + else { + if(fase==F_SCENE) { + /* de scene is klaar, we gaan door met de set */ + if(G.scene->set && G.scene->set->base.first) { + *base= G.scene->set->base.first; + *ob= (*base)->object; + fase= F_SET; + } + } + } + } + } + + if(*base == 0) fase= F_START; + else { + if(fase!=F_DUPLI) { + if( (*base)->object->transflag & OB_DUPLI) { + + make_duplilist(G.scene, (*base)->object); + dupob= duplilist.first; + + } + } + /* dupli's afhandelen */ + if(dupob) { + + *ob= dupob; + fase= F_DUPLI; + + dupob= dupob->id.next; + } + else if(fase==F_DUPLI) { + fase= F_SCENE; + free_duplilist(); + run_again= 1; + } + + } + } + } + + return fase; +} + +Object *scene_find_camera(Scene *sc) +{ + Base *base; + + for (base= sc->base.first; base; base= base->next) + if (base->object->type==OB_CAMERA) + return base->object; + + return NULL; +} + + +Base *scene_add_base(Scene *sce, Object *ob) +{ + Base *b= MEM_callocN(sizeof(*b), "scene_add_base"); + BLI_addhead(&sce->base, b); + + b->object= ob; + b->flag= ob->flag; + b->lay= ob->lay; + + return b; +} + +void scene_deselect_all(Scene *sce) +{ + Base *b; + + for (b= sce->base.first; b; b= b->next) { + b->flag&= ~SELECT; + b->object->flag= b->flag; + } +} + +void scene_select_base(Scene *sce, Base *selbase) +{ + scene_deselect_all(sce); + + selbase->flag |= SELECT; + selbase->object->flag= selbase->flag; + + sce->basact= selbase; +} diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c new file mode 100644 index 00000000000..1f04c20cc72 --- /dev/null +++ b/source/blender/blenkernel/intern/screen.c @@ -0,0 +1,53 @@ + +/* screen.c dec/jan 93/94 GRAPHICS + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <string.h> +#include <stdio.h> +#include <math.h> + +#include "DNA_screen_types.h" + +#include "BKE_bad_level_calls.h" + +#include "BLI_blenlib.h" + +/* don't free screen itself */ +void free_screen(bScreen *sc) +{ + unlink_screen(sc); + + BLI_freelistN(&sc->vertbase); + BLI_freelistN(&sc->edgebase); + BLI_freelistN(&sc->areabase); +} diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c new file mode 100644 index 00000000000..6f8c46bb877 --- /dev/null +++ b/source/blender/blenkernel/intern/sound.c @@ -0,0 +1,112 @@ +/** + * sound.c (mar-2001 nzc) + * + * $Id$ + */ + +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" + +#include "DNA_scene_types.h" +#include "DNA_sound_types.h" +#include "DNA_packedFile_types.h" + +#include "BKE_utildefines.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_sound.h" +#include "BKE_packedFile.h" + +ListBase _samples = {0,0}, *samples = &_samples; + +void sound_free_sound(bSound *sound) +{ + /* this crashes blender, PLEASE fix! */ + // still crashes :( + //if (sound) { + // sound_set_sample(sound, NULL); + //} + +} + +void sound_free_sample(bSample *sample) +{ + if (sample) { + if (sample->data != &sample->fakedata[0] && sample->data != NULL) { + MEM_freeN(sample->data); + sample->data = &sample->fakedata[0]; + } + + if (sample->packedfile) { + freePackedFile(sample->packedfile); //FIXME: crashes sometimes + sample->packedfile = NULL; + } + + if (sample->alindex != SAMPLE_INVALID) { +// AUD_free_sample(sample->snd_sample); + sample->alindex = SAMPLE_INVALID; + } + + sample->type = SAMPLE_INVALID; + } +} + + + +void sound_set_packedfile(bSample *sample, PackedFile *pf) +{ + bSound *sound; + + if (sample) { + sample->packedfile = pf; + sound = G.main->sound.first; + while (sound) { + if (sound->sample == sample) { + sound->newpackedfile = pf; + if (pf == NULL) { + strcpy(sound->name, sample->name); + } + } + sound = sound->id.next; + } + } +} + +PackedFile* sound_find_packedfile(bSound *sound) +{ + bSound *search; + PackedFile *pf = NULL; + char soundname[FILE_MAXDIR + FILE_MAXFILE], searchname[FILE_MAXDIR + FILE_MAXFILE]; + + // convert sound->name to abolute filename + strcpy(soundname, sound->name); + BLI_convertstringcode(soundname, G.sce, G.scene->r.cfra); + + search = G.main->sound.first; + while (search) { + if (search->sample && search->sample->packedfile) { + strcpy(searchname, search->sample->name); + BLI_convertstringcode(searchname, G.sce, G.scene->r.cfra); + + if (BLI_streq(searchname, soundname)) { + pf = search->sample->packedfile; + break; + } + } + + if (search->newpackedfile) { + strcpy(searchname, search->name); + BLI_convertstringcode(searchname, G.sce, G.scene->r.cfra); + if (BLI_streq(searchname, soundname)) { + pf = search->newpackedfile; + break; + } + } + search = search->id.next; + } + + return (pf); +} diff --git a/source/blender/blenkernel/intern/subsurf.c b/source/blender/blenkernel/intern/subsurf.c new file mode 100644 index 00000000000..3f747fb684f --- /dev/null +++ b/source/blender/blenkernel/intern/subsurf.c @@ -0,0 +1,890 @@ + +/* subsurf.c MIXED MODEL + * + * jun 2001 + * + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#ifdef WIN32 +#include "BLI_winstuff.h" +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <math.h> +#include "MEM_guardedalloc.h" + +#include "DNA_mesh_types.h" +#include "DNA_object_types.h" + +#include "BKE_bad_level_calls.h" +#include "BKE_global.h" +#include "BKE_mesh.h" +#include "BKE_subsurf.h" +#include "BKE_displist.h" + +#include "BLI_blenlib.h" +#include "BLI_editVert.h" +#include "BLI_arithb.h" +#include "BLI_linklist.h" +#include "BLI_memarena.h" + +/* + * TODO + * + * make uvco's && vcol's properly subdivided + * - requires moving uvco and vcol data to vertices + * (where it belongs?), or making sharedness explicit + * remove/integrate zsl functions + * clean up uvco && vcol stuff + * add option to update subsurf only after done transverting + * decouple display subdivlevel and render subdivlevel + * look into waves/particles with subsurfs + * groan... make it work with sticky? + * U check if storing tfaces (clut, tpage) in a displist is + * going to be a mem problem (for example, on duplicate) + * U write game blender convert routine + * U thorough rendering check + background + * + */ + +/****/ + +static float *Vec2Cpy(float *t, float *a) { + t[0]= a[0]; + t[1]= a[1]; + return t; +} +static float *Vec3Cpy(float *t, float *a) { + t[0]= a[0]; + t[1]= a[1]; + t[2]= a[2]; + return t; +} + +static float *Vec2CpyI(float *t, float x, float y) { + t[0]= x; + t[1]= y; + return t; +} +static float *Vec3CpyI(float *t, float x, float y, float z) { + t[0]= x; + t[1]= y; + t[2]= z; + return t; +} + +static float *Vec2AvgT(float *t, float *a, float *b) { + t[0]= (a[0]+b[0])*0.5f; + t[1]= (a[1]+b[1])*0.5f; + return t; +} +static float *Vec3AvgT(float *t, float *a, float *b) { + t[0]= (a[0]+b[0])*0.5f; + t[1]= (a[1]+b[1])*0.5f; + t[2]= (a[2]+b[2])*0.5f; + return t; +} + +static float *Vec3AddT(float *t, float *a, float *b) { + t[0]= a[0]+b[0]; + t[1]= a[1]+b[1]; + t[2]= a[2]+b[2]; + return t; +} +static float *Vec2Add(float *ta, float *b) { + ta[0]+= b[0]; + ta[1]+= b[1]; + ta[2]+= b[2]; + return ta; +} + +static float *Vec3MulNT(float *t, float *a, float n) { + t[0]= a[0]*n; + t[1]= a[1]*n; + t[2]= a[2]*n; + return t; +} + +static float *Vec3Add(float *ta, float *b) { + ta[0]+= b[0]; + ta[1]+= b[1]; + ta[2]+= b[2]; + return ta; +} + +static float *Vec3MulN(float *ta, float n) { + ta[0]*= n; + ta[1]*= n; + ta[2]*= n; + return ta; +} + +/****/ + +typedef struct _HyperVert HyperVert; +typedef struct _HyperEdge HyperEdge; +typedef struct _HyperFace HyperFace; +typedef struct _HyperMesh HyperMesh; + +struct _HyperVert { + HyperVert *next; + + float co[3]; + + HyperVert *nmv; + LinkNode *edges, *faces; +}; + +struct _HyperEdge { + HyperEdge *next; + + HyperVert *v[2]; + HyperVert *ep; + + LinkNode *faces; +}; + +struct _HyperFace { + HyperFace *next; + + int nverts; + HyperVert **verts; + HyperEdge **edges; + + HyperVert *mid; + + unsigned char (*vcol)[4]; + float (*uvco)[2]; + + /* for getting back tface, matnr, etc */ + union { + int ind; + EditVlak *ef; + } orig; +}; + +struct _HyperMesh { + HyperVert *verts; + HyperEdge *edges; + HyperFace *faces; + Mesh *orig_me; + short hasuvco, hasvcol; + + MemArena *arena; +}; + +/***/ + +static HyperEdge *hypervert_find_edge(HyperVert *v, HyperVert *to) { + LinkNode *l; + + for (l= v->edges; l; l= l->next) { + HyperEdge *e= l->link; + + if ((e->v[0]==v&&e->v[1]==to) || (e->v[1]==v&&e->v[0]==to)) + return e; + } + + return NULL; +} + +static int hyperedge_is_boundary(HyperEdge *e) { + /* len(e->faces) <= 1 */ + return (!e->faces || !e->faces->next); +} + +static int hypervert_is_boundary(HyperVert *v) { + LinkNode *l; + + for (l= v->edges; l; l= l->next) + if (hyperedge_is_boundary(l->link)) + return 1; + + return 0; +} + +static HyperVert *hyperedge_other_vert(HyperEdge *e, HyperVert *a) { + return (a==e->v[0])?e->v[1]:e->v[0]; +} + +static HyperVert *hypermesh_add_vert(HyperMesh *hme, float *co) { + HyperVert *hv= BLI_memarena_alloc(hme->arena, sizeof(*hv)); + + hv->nmv= NULL; + hv->edges= NULL; + hv->faces= NULL; + + Vec3Cpy(hv->co, co); + + hv->next= hme->verts; + hme->verts= hv; + + return hv; +} + +static HyperEdge *hypermesh_add_edge(HyperMesh *hme, HyperVert *v1, HyperVert *v2) { + HyperEdge *he= BLI_memarena_alloc(hme->arena, sizeof(*he)); + + BLI_linklist_prepend_arena(&v1->edges, he, hme->arena); + BLI_linklist_prepend_arena(&v2->edges, he, hme->arena); + + he->v[0]= v1; + he->v[1]= v2; + he->ep= NULL; + he->faces= NULL; + + he->next= hme->edges; + hme->edges= he; + + return he; +} + +static HyperFace *hypermesh_add_face(HyperMesh *hme, HyperVert **verts, int nverts) { + HyperFace *f= BLI_memarena_alloc(hme->arena, sizeof(*f)); + HyperVert *last; + int j; + + f->mid= NULL; + f->vcol= NULL; + f->uvco= NULL; + + f->nverts= nverts; + f->verts= BLI_memarena_alloc(hme->arena, sizeof(*f->verts)*f->nverts); + f->edges= BLI_memarena_alloc(hme->arena, sizeof(*f->edges)*f->nverts); + + last= verts[nverts-1]; + for (j=0; j<nverts; j++) { + HyperVert *v= verts[j]; + HyperEdge *e= hypervert_find_edge(v, last); + + if (!e) + e= hypermesh_add_edge(hme, v, last); + + f->verts[j]= v; + f->edges[j]= e; + + BLI_linklist_prepend_arena(&v->faces, f, hme->arena); + BLI_linklist_prepend_arena(&e->faces, f, hme->arena); + + last= v; + } + + f->next= hme->faces; + hme->faces= f; + + return f; +} + +static HyperMesh *hypermesh_new(void) { + HyperMesh *hme= MEM_mallocN(sizeof(*hme), "hme"); + + hme->verts= NULL; + hme->edges= NULL; + hme->faces= NULL; + hme->orig_me= NULL; + hme->hasuvco= hme->hasvcol= 0; + hme->arena= BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE); + + return hme; +} + +static HyperMesh *hypermesh_from_mesh(Mesh *me, DispList *dlverts) { + HyperMesh *hme= hypermesh_new(); + HyperVert **vert_tbl; + MFace *mface= me->mface; + int i, j; + + hme->orig_me= me; + if (me->tface) + hme->hasvcol= hme->hasuvco= 1; + else if (me->mcol) + hme->hasvcol= 1; + + vert_tbl= MEM_mallocN(sizeof(*vert_tbl)*me->totvert, "vert_tbl"); + + for (i= 0; i<me->totvert; i++) { + if (dlverts) + vert_tbl[i]= hypermesh_add_vert(hme, &dlverts->verts[i*3]); + else + vert_tbl[i]= hypermesh_add_vert(hme, me->mvert[i].co); + } + + for (i=0; i<me->totface; i++) { + MFace *mf= &mface[i]; + + if (mf->v3) { + int nverts= mf->v4?4:3; + HyperVert *verts[4]; + HyperFace *f; + + verts[0]= vert_tbl[mf->v1]; + verts[1]= vert_tbl[mf->v2]; + verts[2]= vert_tbl[mf->v3]; + if (nverts>3) + verts[3]= vert_tbl[mf->v4]; + + f= hypermesh_add_face(hme, verts, nverts); + f->orig.ind= i; + + if (hme->hasuvco) { + TFace *tf= &((TFace*) me->tface)[i]; + + f->uvco= BLI_memarena_alloc(hme->arena, sizeof(*f->uvco)*nverts); + for (j=0; j<nverts; j++) + Vec2Cpy(f->uvco[j], tf->uv[j]); + + f->vcol= BLI_memarena_alloc(hme->arena, sizeof(*f->vcol)*nverts); + for (j=0; j<nverts; j++) + *((unsigned int*) f->vcol[j])= tf->col[j]; + } else if (hme->hasvcol) { + MCol *mcol= &me->mcol[i*4]; + + f->vcol= BLI_memarena_alloc(hme->arena, sizeof(*f->vcol)*nverts); + for (j=0; j<nverts; j++) + *((unsigned int*) f->vcol[j])= *((unsigned int*) &mcol[j]); + } + } else { + hypermesh_add_edge(hme, vert_tbl[mf->v1], vert_tbl[mf->v2]); + } + } + + MEM_freeN(vert_tbl); + + return hme; +} + +static HyperMesh *hypermesh_from_editmesh(EditVert *everts, EditEdge *eedges, EditVlak *efaces) { + HyperMesh *hme= hypermesh_new(); + EditVert *ev, *prevev; + EditEdge *ee; + EditVlak *ef; + + /* hack, tuck the new hypervert pointer into + * the ev->prev link so we can find it easy, + * then restore real prev links later. + */ + for (ev= everts; ev; ev= ev->next) + ev->prev= (EditVert*) hypermesh_add_vert(hme, ev->co); + + for (ee= eedges; ee; ee= ee->next) + hypermesh_add_edge(hme, (HyperVert*) ee->v1->prev, (HyperVert*) ee->v2->prev); + + for (ef= efaces; ef; ef= ef->next) { + int nverts= ef->v4?4:3; + HyperVert *verts[4]; + HyperFace *f; + + verts[0]= (HyperVert*) ef->v1->prev; + verts[1]= (HyperVert*) ef->v2->prev; + verts[2]= (HyperVert*) ef->v3->prev; + if (nverts>3) + verts[3]= (HyperVert*) ef->v4->prev; + + f= hypermesh_add_face(hme, verts, nverts); + f->orig.ef= ef; + } + + /* see hack above, restore the prev links */ + for (prevev= NULL, ev= everts; ev; prevev= ev, ev= ev->next) + ev->prev= prevev; + + return hme; +} + +static void VColAvgT(unsigned char *t, unsigned char *a, unsigned char *b) { + t[0]= (a[0]+b[0])>>1; + t[1]= (a[1]+b[1])>>1; + t[2]= (a[2]+b[2])>>1; + t[3]= (a[3]+b[3])>>1; +} + +static void hypermesh_subdivide(HyperMesh *me, HyperMesh *nme) { + HyperVert *v; + HyperEdge *e; + HyperFace *f; + LinkNode *link; + float co[3]; + int j, k, count; + + for (f= me->faces; f; f= f->next) { + Vec3CpyI(co, 0.0, 0.0, 0.0); + for (j=0; j<f->nverts; j++) + Vec3Add(co, f->verts[j]->co); + Vec3MulN(co, (float)(1.0/f->nverts)); + + f->mid= hypermesh_add_vert(nme, co); + } + + for (e= me->edges; e; e= e->next) { + if (hyperedge_is_boundary(e)) { + Vec3AvgT(co, e->v[0]->co, e->v[1]->co); + } else { + Vec3AddT(co, e->v[0]->co, e->v[1]->co); + for (count=2, link= e->faces; link; count++, link= link->next) { + f= (HyperFace *) link->link; + Vec3Add(co, f->mid->co); + } + Vec3MulN(co, (float)(1.0/count)); + } + + e->ep= hypermesh_add_vert(nme, co); + } + + for (v= me->verts; v; v= v->next) { + float q[3], r[3], s[3]; + + if (hypervert_is_boundary(v)) { + Vec3CpyI(r, 0.0, 0.0, 0.0); + + for (count= 0, link= v->edges; link; link= link->next) { + if (hyperedge_is_boundary(link->link)) { + HyperVert *ov= hyperedge_other_vert(link->link, v); + + Vec3Add(r, ov->co); + count++; + } + } + + /* I believe CC give the factors as + 3/2k and 1/4k, but that doesn't make + sense (to me) as they don't sum to unity... + It's rarely important. + */ + Vec3MulNT(s, v->co, 0.75f); + Vec3Add(s, Vec3MulN(r, (float)(1.0/(4.0*count)))); + } else { + Vec3Cpy(q, Vec3Cpy(r, Vec3CpyI(s, 0.0f, 0.0f, 0.0f))); + + for (count=0, link= v->faces; link; count++, link= link->next) { + f= (HyperFace *) link->link; + Vec3Add(q, f->mid->co); + } + Vec3MulN(q, (float)(1.0/count)); + + for (count=0, link= v->edges; link; count++, link= link->next) { + e= (HyperEdge *) link->link; + Vec3Add(r, hyperedge_other_vert(e, v)->co); + } + Vec3MulN(r, (float)(1.0/count)); + + Vec3MulNT(s, v->co, (float)(count-2)); + + Vec3Add(s, q); + Vec3Add(s, r); + Vec3MulN(s, (float)(1.0/count)); + } + + v->nmv= hypermesh_add_vert(nme, s); + } + + for (e= me->edges; e; e= e->next) { + hypermesh_add_edge(nme, e->v[0]->nmv, e->ep); + hypermesh_add_edge(nme, e->v[1]->nmv, e->ep); + } + + for (f= me->faces; f; f= f->next) { + int last= f->nverts-1; + unsigned char vcol_mid[4]; + unsigned char vcol_edge[4][4]; + float uvco_mid[2]; + float uvco_edge[4][4]; + + if (me->hasvcol) { + int t[4]= {0, 0, 0, 0}; + for (j=0; j<f->nverts; j++) { + t[0]+= f->vcol[j][0]; + t[1]+= f->vcol[j][1]; + t[2]+= f->vcol[j][2]; + t[3]+= f->vcol[j][3]; + } + vcol_mid[0]= t[0]/f->nverts; + vcol_mid[1]= t[1]/f->nverts; + vcol_mid[2]= t[2]/f->nverts; + vcol_mid[3]= t[3]/f->nverts; + + for (j=0; j<f->nverts; last= j, j++) + VColAvgT(vcol_edge[j], f->vcol[last], f->vcol[j]); + last= f->nverts-1; + } + if (me->hasuvco) { + Vec2CpyI(uvco_mid, 0.0, 0.0); + for (j=0; j<f->nverts; j++) + Vec2Add(uvco_mid, f->uvco[j]); + Vec3MulN(uvco_mid, (float)(1.0/f->nverts)); + + for (j=0; j<f->nverts; last= j, j++) + Vec2AvgT(uvco_edge[j], f->uvco[last], f->uvco[j]); + last= f->nverts-1; + } + + for (j=0; j<f->nverts; last=j, j++) { + HyperVert *nv[4]; + HyperFace *nf; + + nv[0]= f->verts[last]->nmv; + nv[1]= f->edges[j]->ep; + nv[2]= f->mid; + nv[3]= f->edges[last]->ep; + + nf= hypermesh_add_face(nme, nv, 4); + nf->orig= f->orig; + + if (me->hasvcol) { + nf->vcol= BLI_memarena_alloc(nme->arena, sizeof(*nf->vcol)*4); + + for (k=0; k<4; k++) { + nf->vcol[0][k]= f->vcol[last][k]; + nf->vcol[1][k]= vcol_edge[j][k]; + nf->vcol[2][k]= vcol_mid[k]; + nf->vcol[3][k]= vcol_edge[last][k]; + } + } + if (me->hasuvco) { + nf->uvco= BLI_memarena_alloc(nme->arena, sizeof(*nf->uvco)*4); + + Vec2Cpy(nf->uvco[0], f->uvco[last]); + Vec2Cpy(nf->uvco[1], uvco_edge[j]); + Vec2Cpy(nf->uvco[2], uvco_mid); + Vec2Cpy(nf->uvco[3], uvco_edge[last]); + } + } + } +} + +static void hypermesh_free(HyperMesh *me) { + BLI_memarena_free(me->arena); + + MEM_freeN(me); +} + +/*****/ + +static void add_mvert_normals_from_mfaces(MVert *mverts, int nmverts, MFaceInt *mfaces, int nmfaces) { + float (*tnorms)[3]= MEM_callocN(nmverts*sizeof(*tnorms), "tnorms"); + int i; + + for (i=0; i<nmfaces; i++) { + MFaceInt *mf= &mfaces[i]; + float f_no[3]; + + if (!mf->v3) + continue; + + if (mf->v4) + CalcNormFloat4(mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co, mverts[mf->v4].co, f_no); + else + CalcNormFloat(mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co, f_no); + + Vec3Add(tnorms[mf->v1], f_no); + Vec3Add(tnorms[mf->v2], f_no); + Vec3Add(tnorms[mf->v3], f_no); + if (mf->v4) + Vec3Add(tnorms[mf->v4], f_no); + } + for (i=0; i<nmverts; i++) { + MVert *mv= &mverts[i]; + float *no= tnorms[i]; + + Normalise(no); + mv->no[0]= (short)(no[0]*32767.0); + mv->no[1]= (short)(no[1]*32767.0); + mv->no[2]= (short)(no[2]*32767.0); + } + + MEM_freeN(tnorms); +} + +static int hypermesh_get_nverts(HyperMesh *hme) { + HyperVert *v; + int count= 0; + + for (v= hme->verts; v; v= v->next) + count++; + + return count; +} + +static int hypermesh_get_nfaces(HyperMesh *hme) { + HyperFace *f; + int count= 0; + + for (f= hme->faces; f; f= f->next) + count++; + + return count; +} + +static int hypermesh_get_nlines(HyperMesh *hme) { + HyperEdge *e; + int n= 0; + + for (e= hme->edges; e; e= e->next) + if (!e->faces) + n++; + + return n; +} + +static int editface_is_hidden(EditVlak *ef) { + return (ef->v1->h || ef->v2->h || ef->v3->h || (ef->v4 && ef->v4->h)); +} + +static int hypermesh_get_nhidden(HyperMesh *hme) { + int count= 0; + + /* hme->orig_me==NULL if we are working on an editmesh */ + if (!hme->orig_me) { + HyperFace *f; + + for (f= hme->faces; f; f= f->next) + if (editface_is_hidden(f->orig.ef)) + count++; + } + + return count; +} + +static DispList *hypermesh_to_displist(HyperMesh *hme) { + int nverts= hypermesh_get_nverts(hme); + int nfaces= hypermesh_get_nfaces(hme) + hypermesh_get_nlines(hme) - hypermesh_get_nhidden(hme); + DispList *dl= MEM_callocN(sizeof(*dl), "dl"); + DispListMesh *dlm= MEM_callocN(sizeof(*dlm), "dlmesh"); + HyperFace *f; + HyperVert *v; + HyperEdge *e; + TFace *tfaces; + MFace *mfaces; + MFaceInt *mf; + int i, j; + + /* hme->orig_me==NULL if we are working on an editmesh */ + if (hme->orig_me) { + tfaces= hme->orig_me->tface; + mfaces= hme->orig_me->mface; + } else { + tfaces= NULL; + mfaces= NULL; + } + + dl->type= DL_MESH; + dl->mesh= dlm; + + dlm->totvert= nverts; + dlm->totface= nfaces; + dlm->mvert= MEM_mallocN(dlm->totvert*sizeof(*dlm->mvert), "dlm->mvert"); + dlm->mface= MEM_mallocN(dlm->totface*sizeof(*dlm->mface), "dlm->mface"); + + if (hme->hasuvco) + dlm->tface= MEM_callocN(dlm->totface*sizeof(*dlm->tface), "dlm->tface"); + else if (hme->hasvcol) + dlm->mcol= MEM_mallocN(dlm->totface*4*sizeof(*dlm->mcol), "dlm->mcol"); + + for (i=0, v= hme->verts; i<nverts; i++, v= v->next) { + MVert *mv= &dlm->mvert[i]; + Vec3Cpy(mv->co, v->co); + v->nmv= (void*) i; + } + + mf= dlm->mface; + for (i=0, f= hme->faces; f; i++, f= f->next) { + int voff= (((int) f->verts[3]->nmv)==0)?1:0; + + if (!hme->orig_me && editface_is_hidden(f->orig.ef)) + continue; + + /* compensate for blender's [braindead] way of encoding + * nverts by face vertices, if necessary. + */ + + mf->v1= (int) f->verts[(0+voff)%4]->nmv; + mf->v2= (int) f->verts[(1+voff)%4]->nmv; + mf->v3= (int) f->verts[(2+voff)%4]->nmv; + mf->v4= (int) f->verts[(3+voff)%4]->nmv; + + if (hme->orig_me) { + MFace *origmf= &mfaces[f->orig.ind]; + + mf->mat_nr= origmf->mat_nr; + mf->flag= origmf->flag; + mf->puno= 0; + mf->edcode= ME_V1V2|ME_V2V3|ME_V3V4|ME_V4V1; + } else { + EditVlak *origef= f->orig.ef; + + mf->mat_nr= origef->mat_nr; + mf->flag= origef->flag; + mf->puno= 0; + mf->edcode= ME_V1V2|ME_V2V3|ME_V3V4|ME_V4V1; + } + + if (hme->hasuvco) { + TFace *origtf, *tf= &dlm->tface[i]; + + if (hme->orig_me) + origtf= &tfaces[f->orig.ind]; + else + origtf= f->orig.ef->tface; + + for (j=0; j<4; j++) { + Vec2Cpy(tf->uv[j], f->uvco[(j+voff)%4]); + tf->col[j]= *((unsigned int*) f->vcol[(j+voff)%4]); + } + + tf->tpage= origtf->tpage; + tf->flag= origtf->flag; + tf->transp= origtf->transp; + tf->mode= origtf->mode; + tf->tile= origtf->tile; + } else if (hme->hasvcol) { + MCol *mcolbase= &dlm->mcol[i*4]; + + for (j=0; j<4; j++) + *((unsigned int*) &mcolbase[j])= *((unsigned int*) f->vcol[(j+voff)%4]); + } + + mf++; + } + + for (e= hme->edges; e; e= e->next) { + if (!e->faces) { + mf->v1= (int) e->v[0]->nmv; + mf->v2= (int) e->v[1]->nmv; + mf->v3= 0; + mf->v4= 0; + + mf->mat_nr= 0; + mf->flag= 0; + mf->puno= 0; + mf->edcode= ME_V1V2; + + mf++; + } + } + + add_mvert_normals_from_mfaces(dlm->mvert, dlm->totvert, dlm->mface, dlm->totface); + + return dl; +} + +static DispList *subsurf_subdivide_to_displist(HyperMesh *hme, short subdiv) { + DispList *dl; + int i; + + for (i= 0; i<subdiv; i++) { + HyperMesh *tmp= hypermesh_new(); + tmp->hasvcol= hme->hasvcol; + tmp->hasuvco= hme->hasuvco; + tmp->orig_me= hme->orig_me; + + hypermesh_subdivide(hme, tmp); + hypermesh_free(hme); + + hme= tmp; + } + + dl= hypermesh_to_displist(hme); + hypermesh_free(hme); + + return dl; +} + +void subsurf_make_editmesh(Object *ob) { + if (G.eded.first) { + Mesh *me= ob->data; + HyperMesh *hme= hypermesh_from_editmesh(G.edve.first, G.eded.first, G.edvl.first); + + free_displist_by_type(&me->disp, DL_MESH); + BLI_addtail(&me->disp, subsurf_subdivide_to_displist(hme, me->subdiv)); + } +} + +void subsurf_make_mesh(Object *ob, short subdiv) { + Mesh *me= ob->data; + + if (me->totface) { + HyperMesh *hme= hypermesh_from_mesh(me, find_displist(&ob->disp, DL_VERTS)); + + free_displist_by_type(&me->disp, DL_MESH); + BLI_addtail(&me->disp, subsurf_subdivide_to_displist(hme, subdiv)); + } +} + +void subsurf_to_mesh(Object *oldob, Mesh *me) { + Mesh *oldme= oldob->data; + + if (oldme->totface) { + HyperMesh *hme= hypermesh_from_mesh(oldme, NULL); + DispList *dl= subsurf_subdivide_to_displist(hme, oldme->subdiv); + DispListMesh *dlm= dl->mesh; + MFace *mfaces; + int i; + + if (dlm->totvert>65000) + error("Too many vertices"); + else { + me->totface= dlm->totface; + me->totvert= dlm->totvert; + + me->mvert= MEM_dupallocN(dlm->mvert); + me->mface= mfaces= MEM_mallocN(sizeof(*mfaces)*me->totface, "me->mface"); + me->tface= MEM_dupallocN(dlm->tface); + me->mcol= MEM_dupallocN(dlm->mcol); + + for (i=0; i<me->totface; i++) { + MFace *mf= &mfaces[i]; + MFaceInt *oldmf= &dlm->mface[i]; + + mf->v1= oldmf->v1; + mf->v2= oldmf->v2; + mf->v3= oldmf->v3; + mf->v4= oldmf->v4; + mf->flag= oldmf->flag; + mf->mat_nr= oldmf->mat_nr; + mf->puno= 0; + mf->edcode= ME_V1V2|ME_V2V3|ME_V3V4|ME_V4V1; + } + } + + free_disp_elem(dl); + } +} + +DispList* subsurf_mesh_to_displist(Mesh *me, DispList *dl, short subdiv) +{ + HyperMesh *hme; + + hme= hypermesh_from_mesh(me, dl); + + return subsurf_subdivide_to_displist(hme, subdiv); +} diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c new file mode 100644 index 00000000000..7f1c6f4935b --- /dev/null +++ b/source/blender/blenkernel/intern/text.c @@ -0,0 +1,1986 @@ +/** + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <ctype.h> /* isprint() */ +#include <string.h> /* strstr */ + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" + +#include "DNA_text_types.h" + +#include "BKE_bad_level_calls.h" +#include "BKE_utildefines.h" +#include "BKE_text.h" +#include "BKE_library.h" +#include "BKE_global.h" +#include "BKE_main.h" + +#include "BPY_extern.h" // Blender Python library + +/***************/ /* + +How Texts should work +-- +A text should relate to a file as follows - +(Text *)->name should be the place where the + file will or has been saved. + +(Text *)->flags has the following bits + TXT_ISDIRTY - should always be set if the file in mem. differs from + the file on disk, or if there is no file on disk. + TXT_ISTMP - should always be set if the (Text *)->name file has not + been written before, and attempts to save should result + in "Save over?" + TXT_ISMEM - should always be set if the Text has not been mapped to + a file, in which case (Text *)->name may be NULL or garbage. + TXT_ISEXT - should always be set if the Text is not to be written into + the .blend + TXT_ISSCRIPT - should be set if the user has designated the text + as a script. + +->>> see also: /makesdna/DNA_text_types.h + +Display +-- +The st->top determines at what line the top of the text is displayed. +If the user moves the cursor the st containing that cursor should +be popped ... other st's retain their own top location. + +*/ /***************/ + + +/****************/ /* + Undo + +Undo/Redo works by storing +events in a queue, and a pointer +to the current position in the +queue... + +Events are stored using an +arbitrary op-code system +to keep track of +a) the two cursors (normal and selected) +b) input (visible and control (ie backspace)) + +input data is stored as its +ASCII value, the opcodes are +then selected to not conflict. + +opcodes with data in between are +written at the beginning and end +of the data to allow undo and redo +to simply check the code at the current +undo position + +*/ /***************/ + +/***/ + +static void txt_pop_first(Text *text); +static void txt_pop_last(Text *text); +static void txt_undo_add_op(Text *text, int op); +static void txt_undo_add_block(Text *text, int op, char *buf); +static void txt_delete_line(Text *text, TextLine *line); + +/***/ + +static char *txt_cut_buffer= NULL; +static unsigned char undoing; + +/* allow to switch off undoing externally */ +void txt_set_undostate(int u) +{ + undoing = u; +} + +int txt_get_undostate(void) +{ + return undoing; +} + +void free_text(Text *text) +{ + TextLine *tmp; + + for (tmp= text->lines.first; tmp; tmp= tmp->next) + MEM_freeN(tmp->line); + + BLI_freelistN(&text->lines); + + if(text->name) MEM_freeN(text->name); + MEM_freeN(text->undo_buf); +} + +Text *add_empty_text(void) +{ + Text *ta; + TextLine *tmp; + + ta= alloc_libblock(&G.main->text, ID_TXT, "Text"); + ta->id.us= 1; + + ta->name= NULL; + + ta->undo_pos= -1; + ta->undo_len= TXT_INIT_UNDO; + ta->undo_buf= MEM_mallocN(ta->undo_len, "undo buf"); + + ta->nlines=1; + ta->flags= TXT_ISDIRTY | TXT_ISTMP | TXT_ISMEM; + + ta->lines.first= ta->lines.last= NULL; + + tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline"); + tmp->line= (char*) MEM_mallocN(1, "textline_string"); + + tmp->line[0]=0; + tmp->len= 0; + + tmp->next= NULL; + tmp->prev= NULL; + + BLI_addhead(&ta->lines, tmp); + + ta->curl= ta->lines.first; + ta->curc= 0; + ta->sell= ta->lines.first; + ta->selc= 0; + + return ta; +} + +// this function removes any control characters from +// a textline + +static void cleanup_textline(TextLine * tl) +{ + int i; + + for (i = 0; i < tl->len; i++ ) { + if (tl->line[i] < ' ' && tl->line[i] != '\t') { + memmove(tl->line + i, tl->line + i + 1, tl->len - i); + tl->len--; + i--; + } + } +} + +int reopen_text(Text *text) +{ + FILE *fp; + int i, llen, len; + unsigned char *buffer; + TextLine *tmp; + char sdir[FILE_MAXDIR]; + char sfile[FILE_MAXFILE]; + + if (!text || !text->name) return 0; + + BLI_split_dirfile(text->name, sdir, sfile); + + fp= fopen(text->name, "r"); + if(fp==NULL) return 0; + + /* free memory: */ + + for (tmp= text->lines.first; tmp; tmp= tmp->next) + MEM_freeN(tmp->line); + + BLI_freelistN(&text->lines); + + text->lines.first= text->lines.last= NULL; + text->curl= text->sell= NULL; + + /* clear undo buffer */ + MEM_freeN(text->undo_buf); + text->undo_pos= -1; + text->undo_len= TXT_INIT_UNDO; + text->undo_buf= MEM_mallocN(text->undo_len, "undo buf"); + + text->flags= TXT_ISDIRTY | TXT_ISTMP; + + fseek(fp, 0L, SEEK_END); + len= ftell(fp); + fseek(fp, 0L, SEEK_SET); + + text->undo_pos= -1; + + buffer= MEM_mallocN(len, "text_buffer"); + // under windows fread can return less then len bytes because + // of CR stripping + len = fread(buffer, 1, len, fp); + + fclose(fp); + + text->nlines=0; + i=0; + llen=0; + for(i=0; i<len; i++) { + if (buffer[i]=='\n') { + tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline"); + tmp->line= (char*) MEM_mallocN(llen+1, "textline_string"); + + if(llen) memcpy(tmp->line, &buffer[i-llen], llen); + tmp->line[llen]=0; + tmp->len= llen; + + cleanup_textline(tmp); + + BLI_addtail(&text->lines, tmp); + text->nlines++; + + llen=0; + continue; + } + llen++; + } + + if (llen!=0 || text->nlines==0) { + tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline"); + tmp->line= (char*) MEM_mallocN(llen+1, "textline_string"); + + if(llen) memcpy(tmp->line, &buffer[i-llen], llen); + + tmp->line[llen]=0; + tmp->len= llen; + + cleanup_textline(tmp); + + BLI_addtail(&text->lines, tmp); + text->nlines++; + } + + text->curl= text->sell= text->lines.first; + text->curc= text->selc= 0; + + MEM_freeN(buffer); + return 1; +} + +Text *add_text(char *file) +{ + FILE *fp; + int i, llen, len; + unsigned char *buffer; + TextLine *tmp; + Text *ta; + char sdir[FILE_MAXDIR]; + char sfile[FILE_MAXFILE]; + + BLI_split_dirfile(file, sdir, sfile); + + fp= fopen(file, "r"); + if(fp==NULL) return NULL; + + ta= alloc_libblock(&G.main->text, ID_TXT, sfile); + ta->id.us= 1; + + ta->lines.first= ta->lines.last= NULL; + ta->curl= ta->sell= NULL; + +/* ta->flags= TXT_ISTMP | TXT_ISEXT; */ + ta->flags= TXT_ISTMP; + + fseek(fp, 0L, SEEK_END); + len= ftell(fp); + fseek(fp, 0L, SEEK_SET); + + ta->name= MEM_mallocN(strlen(file)+1, "text_name"); + strcpy(ta->name, file); + + ta->undo_pos= -1; + ta->undo_len= TXT_INIT_UNDO; + ta->undo_buf= MEM_mallocN(ta->undo_len, "undo buf"); + + buffer= MEM_mallocN(len, "text_buffer"); + // under windows fread can return less then len bytes because + // of CR stripping + len = fread(buffer, 1, len, fp); + + fclose(fp); + + ta->nlines=0; + i=0; + llen=0; + for(i=0; i<len; i++) { + if (buffer[i]=='\n') { + tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline"); + tmp->line= (char*) MEM_mallocN(llen+1, "textline_string"); + + if(llen) memcpy(tmp->line, &buffer[i-llen], llen); + tmp->line[llen]=0; + tmp->len= llen; + + cleanup_textline(tmp); + + BLI_addtail(&ta->lines, tmp); + ta->nlines++; + + llen=0; + continue; + } + llen++; + } + + if (llen!=0 || ta->nlines==0) { + tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline"); + tmp->line= (char*) MEM_mallocN(llen+1, "textline_string"); + + if(llen) memcpy(tmp->line, &buffer[i-llen], llen); + + tmp->line[llen]=0; + tmp->len= llen; + + cleanup_textline(tmp); + + BLI_addtail(&ta->lines, tmp); + ta->nlines++; + } + + ta->curl= ta->sell= ta->lines.first; + ta->curc= ta->selc= 0; + + MEM_freeN(buffer); + + return ta; +} + +Text *copy_text(Text *ta) +{ + Text *tan; + TextLine *line, *tmp; + + tan= copy_libblock(ta); + + tan->name= MEM_mallocN(strlen(ta->name)+1, "text_name"); + strcpy(tan->name, ta->name); + + tan->flags = ta->flags | TXT_ISDIRTY | TXT_ISTMP; + + tan->lines.first= tan->lines.last= NULL; + tan->curl= tan->sell= NULL; + + tan->nlines= ta->nlines; + + line= ta->lines.first; + /* Walk down, reconstructing */ + while (line) { + tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline"); + tmp->line= MEM_mallocN(line->len+1, "textline_string"); + strcpy(tmp->line, line->line); + + tmp->len= line->len; + + BLI_addtail(&tan->lines, tmp); + + line= line->next; + } + + tan->curl= tan->sell= tan->lines.first; + tan->curc= tan->selc= 0; + + return tan; +} + +/*****************************/ +/* Editing utility functions */ +/*****************************/ + +static void make_new_line (TextLine *line, char *newline) +{ + MEM_freeN(line->line); + + line->line= newline; + line->len= strlen(newline); +} + +static TextLine *txt_new_line(char *str) +{ + TextLine *tmp; + + if(!str) str= ""; + + tmp= (TextLine *) MEM_mallocN(sizeof(TextLine), "textline"); + tmp->line= MEM_mallocN(strlen(str)+1, "textline_string"); + strcpy(tmp->line, str); + + tmp->len= strlen(str); + tmp->next= tmp->prev= NULL; + + return tmp; +} + +static TextLine *txt_new_linen(char *str, int n) +{ + TextLine *tmp; + + if(!str) str= ""; + + tmp= (TextLine *) MEM_mallocN(sizeof(TextLine), "textline"); + tmp->line= MEM_mallocN(n+1, "textline_string"); + BLI_strncpy(tmp->line, str, n+1); + + tmp->len= strlen(tmp->line); + tmp->next= tmp->prev= NULL; + + return tmp; +} + +void txt_clean_text (Text *text) +{ + TextLine **top, **bot; + + if (!text) return; + + if (!text->lines.first) { + if (text->lines.last) text->lines.first= text->lines.last; + else text->lines.first= text->lines.last= txt_new_line(NULL); + } + + if (!text->lines.last) text->lines.last= text->lines.first; + + top= (TextLine **) &text->lines.first; + bot= (TextLine **) &text->lines.last; + + while ((*top)->prev) *top= (*top)->prev; + while ((*bot)->next) *bot= (*bot)->next; + + if(!text->curl) { + if(text->sell) text->curl= text->sell; + else text->curl= text->lines.first; + text->curc= 0; + } + + if(!text->sell) { + text->sell= text->curl; + text->selc= 0; + } +} + +int txt_get_span (TextLine *from, TextLine *to) +{ + int ret=0; + TextLine *tmp= from; + + if (!to || !from) return 0; + if (from==to) return 0; + + /* Look forwards */ + while (tmp) { + if (tmp == to) return ret; + ret++; + tmp= tmp->next; + } + + /* Look backwards */ + if (!tmp) { + tmp= from; + ret=0; + while(tmp) { + if (tmp == to) break; + ret--; + tmp= tmp->prev; + } + if(!tmp) ret=0; + } + + return ret; +} + +static int txt_illegal_char (char c) +{ + if (isprint(c) || c=='\t') return 0; + + return 1; +} + +static void txt_make_dirty (Text *text) +{ + text->flags |= TXT_ISDIRTY; + if (text->compiled) BPY_free_compiled_text(text); +} + +/****************************/ +/* Cursor utility functions */ +/****************************/ + +static void txt_curs_cur (Text *text, TextLine ***linep, int **charp) +{ + *linep= &text->curl; *charp= &text->curc; +} + +static void txt_curs_sel (Text *text, TextLine ***linep, int **charp) +{ + *linep= &text->sell; *charp= &text->selc; +} + +static void txt_curs_first (Text *text, TextLine **linep, int *charp) +{ + if (text->curl==text->sell) { + *linep= text->curl; + if (text->curc<text->selc) *charp= text->curc; + else *charp= text->selc; + } else if (txt_get_span(text->lines.first, text->curl)<txt_get_span(text->lines.first, text->sell)) { + *linep= text->curl; + *charp= text->curc; + } else { + *linep= text->sell; + *charp= text->selc; + } +} + +/****************************/ +/* Cursor movement functions */ +/****************************/ + +void txt_move_up(Text *text, short sel) +{ + TextLine **linep; + int *charp, old; + + if (!text) return; + if(sel) txt_curs_sel(text, &linep, &charp); + else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); } + if (!*linep) return; + old= *charp; + + if((*linep)->prev) { + *linep= (*linep)->prev; + if (*charp > (*linep)->len) { + *charp= (*linep)->len; + if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, (*linep)->next), old, txt_get_span(text->lines.first, *linep), (unsigned short) *charp); + } else { + if(!undoing) txt_undo_add_op(text, sel?UNDO_SUP:UNDO_CUP); + } + } else { + *charp= 0; + if(!undoing) txt_undo_add_op(text, sel?UNDO_SUP:UNDO_CUP); + } + + if(!sel) txt_pop_sel(text); +} + +void txt_move_down(Text *text, short sel) +{ + TextLine **linep; + int *charp, old; + + if (!text) return; + if(sel) txt_curs_sel(text, &linep, &charp); + else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); } + if (!*linep) return; + old= *charp; + + if((*linep)->next) { + *linep= (*linep)->next; + if (*charp > (*linep)->len) { + *charp= (*linep)->len; + if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, (*linep)->prev), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); + } else + if(!undoing) txt_undo_add_op(text, sel?UNDO_SDOWN:UNDO_CDOWN); + } else { + *charp= (*linep)->len; + if(!undoing) txt_undo_add_op(text, sel?UNDO_SDOWN:UNDO_CDOWN); + } + + if(!sel) txt_pop_sel(text); +} + +void txt_move_left(Text *text, short sel) +{ + TextLine **linep; + int *charp, oundoing= undoing; + + if (!text) return; + if(sel) txt_curs_sel(text, &linep, &charp); + else { txt_pop_first(text); txt_curs_cur(text, &linep, &charp); } + if (!*linep) return; + + undoing= 1; + if (*charp== 0) { + if ((*linep)->prev) { + txt_move_up(text, sel); + *charp= (*linep)->len; + } + } else { + (*charp)--; + } + undoing= oundoing; + if(!undoing) txt_undo_add_op(text, sel?UNDO_SLEFT:UNDO_CLEFT); + + if(!sel) txt_pop_sel(text); +} + +void txt_move_right(Text *text, short sel) +{ + TextLine **linep; + int *charp, oundoing= undoing; + + if (!text) return; + if(sel) txt_curs_sel(text, &linep, &charp); + else { txt_pop_last(text); txt_curs_cur(text, &linep, &charp); } + if (!*linep) return; + + undoing= 1; + if (*charp== (*linep)->len) { + if ((*linep)->next) { + txt_move_down(text, sel); + *charp= 0; + } + } else { + (*charp)++; + } + undoing= oundoing; + if(!undoing) txt_undo_add_op(text, sel?UNDO_SRIGHT:UNDO_CRIGHT); + + if(!sel) txt_pop_sel(text); +} + +void txt_move_bol (Text *text, short sel) +{ + TextLine **linep; + int *charp, old; + + if (!text) return; + if(sel) txt_curs_sel(text, &linep, &charp); + else txt_curs_cur(text, &linep, &charp); + if (!*linep) return; + old= *charp; + + *charp= 0; + + if(!sel) txt_pop_sel(text); + if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); +} + +void txt_move_eol (Text *text, short sel) +{ + TextLine **linep; + int *charp, old; + + if (!text) return; + if(sel) txt_curs_sel(text, &linep, &charp); + else txt_curs_cur(text, &linep, &charp); + if (!*linep) return; + old= *charp; + + *charp= (*linep)->len; + + if(!sel) txt_pop_sel(text); + if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); +} + +void txt_move_bof (Text *text, short sel) +{ + TextLine **linep; + int *charp, old; + + if (!text) return; + if(sel) txt_curs_sel(text, &linep, &charp); + else txt_curs_cur(text, &linep, &charp); + if (!*linep) return; + old= *charp; + + *linep= text->lines.first; + *charp= 0; + + if(!sel) txt_pop_sel(text); + if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); +} + +void txt_move_eof (Text *text, short sel) +{ + TextLine **linep; + int *charp, old; + + if (!text) return; + if(sel) txt_curs_sel(text, &linep, &charp); + else txt_curs_cur(text, &linep, &charp); + if (!*linep) return; + old= *charp; + + *linep= text->lines.last; + *charp= (*linep)->len; + + if(!sel) txt_pop_sel(text); + if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, *linep), old, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); +} + +void txt_move_toline (Text *text, unsigned int line, short sel) +{ + TextLine **linep, *oldl; + int *charp, oldc; + unsigned int i; + + if (!text) return; + if(sel) txt_curs_sel(text, &linep, &charp); + else txt_curs_cur(text, &linep, &charp); + if (!*linep) return; + oldc= *charp; + oldl= *linep; + + *linep= text->lines.first; + for (i=0; i<line; i++) { + if ((*linep)->next) *linep= (*linep)->next; + else break; + } + *charp= 0; + + if(!sel) txt_pop_sel(text); + if(!undoing) txt_undo_add_toop(text, sel?UNDO_STO:UNDO_CTO, txt_get_span(text->lines.first, oldl), oldc, txt_get_span(text->lines.first, *linep), (unsigned short)*charp); +} + +/****************************/ +/* Text selection functions */ +/****************************/ + +static void txt_curs_swap (Text *text) +{ + TextLine *tmpl; + int tmpc; + + tmpl= text->curl; + text->curl= text->sell; + text->sell= tmpl; + + tmpc= text->curc; + text->curc= text->selc; + text->selc= tmpc; + + if(!undoing) txt_undo_add_op(text, UNDO_SWAP); +} + +static void txt_pop_first (Text *text) +{ + + if (txt_get_span(text->curl, text->sell)<0 || + (text->curl==text->sell && text->curc>text->selc)) { + txt_curs_swap(text); + } + + if(!undoing) txt_undo_add_toop(text, UNDO_STO, + txt_get_span(text->lines.first, text->sell), + text->selc, + txt_get_span(text->lines.first, text->curl), + text->curc); + + txt_pop_sel(text); +} + +static void txt_pop_last (Text *text) +{ + if (txt_get_span(text->curl, text->sell)>0 || + (text->curl==text->sell && text->curc<text->selc)) { + txt_curs_swap(text); + } + + if(!undoing) txt_undo_add_toop(text, UNDO_STO, + txt_get_span(text->lines.first, text->sell), + text->selc, + txt_get_span(text->lines.first, text->curl), + text->curc); + + txt_pop_sel(text); +} + +/* never used: CVS 1.19 */ +/* static void txt_pop_selr (Text *text) */ + +void txt_pop_sel (Text *text) +{ + text->sell= text->curl; + text->selc= text->curc; +} + +void txt_order_cursors(Text *text) +{ + if (!text) return; + if (!text->curl) return; + if (!text->sell) return; + + /* Flip so text->curl is before text->sell */ + if (txt_get_span(text->curl, text->sell)<0 || + (text->curl==text->sell && text->curc>text->selc)) + txt_curs_swap(text); +} + +int txt_has_sel(Text *text) +{ + return ((text->curl!=text->sell) || (text->curc!=text->selc)); +} + +static void txt_delete_sel (Text *text) +{ + TextLine *tmpl; + char *buf; + + if (!text) return; + if (!text->curl) return; + if (!text->sell) return; + + if (!txt_has_sel(text)) return; + + txt_order_cursors(text); + + if(!undoing) { + buf= txt_sel_to_buf(text); + txt_undo_add_block(text, UNDO_DBLOCK, buf); + MEM_freeN(buf); + } + + buf= MEM_mallocN(text->curc+(text->sell->len - text->selc)+1, "textline_string"); + + strncpy(buf, text->curl->line, text->curc); + strcpy(buf+text->curc, text->sell->line + text->selc); + buf[text->curc+(text->sell->len - text->selc)]=0; + + make_new_line(text->curl, buf); + + tmpl= text->sell; + while (tmpl != text->curl) { + tmpl= tmpl->prev; + if (!tmpl) break; + + txt_delete_line(text, tmpl->next); + } + + text->sell= text->curl; + text->selc= text->curc; +} + +void txt_sel_all (Text *text) +{ + if (!text) return; + + text->curl= text->lines.first; + text->curc= 0; + + text->sell= text->lines.last; + text->selc= text->sell->len; +} + +void txt_sel_line (Text *text) +{ + if (!text) return; + if (!text->curl) return; + + text->curc= 0; + text->sell= text->curl; + text->selc= text->sell->len; +} + +/***************************/ +/* Cut and paste functions */ +/***************************/ + +void txt_print_cutbuffer (void) +{ + printf ("Cut buffer\n--\n%s\n--\n", txt_cut_buffer); +} + +char *txt_to_buf (Text *text) +{ + int length; + TextLine *tmp, *linef, *linel; + int charf, charl; + char *buf; + + if (!text) return NULL; + if (!text->curl) return NULL; + if (!text->sell) return NULL; + + linef= text->lines.first; + charf= 0; + + linel= text->lines.last; + charl= linel->len; + + if (linef == text->lines.last) { + length= charl-charf; + + buf= MEM_mallocN(length+2, "text buffer"); + + BLI_strncpy(buf, linef->line + charf, length+1); + buf[length]=0; + } else { + length= linef->len - charf; + length+= charl; + length+= 2; /* For the 2 '\n' */ + + tmp= linef->next; + while (tmp && tmp!= linel) { + length+= tmp->len+1; + tmp= tmp->next; + } + + buf= MEM_mallocN(length+1, "cut buffer"); + + strncpy(buf, linef->line + charf, linef->len-charf); + length= linef->len - charf; + + buf[length++]='\n'; + + tmp= linef->next; + while (tmp && tmp!=linel) { + strncpy(buf+length, tmp->line, tmp->len); + length+= tmp->len; + + buf[length++]='\n'; + + tmp= tmp->next; + } + strncpy(buf+length, linel->line, charl); + length+= charl; + + /* python compiler wants an empty end line */ + buf[length++]='\n'; + buf[length]=0; + } + + return buf; +} + +int txt_find_string(Text *text, char *findstr) +{ + TextLine *tl, *startl; + char *s= NULL; + + if (!text || !text->curl || !text->sell) return 0; + + txt_order_cursors(text); + + tl= startl= text->sell; + + s= strstr(&tl->line[text->selc], findstr); + while (!s) { + tl= tl->next; + if (!tl) + tl= text->lines.first; + + s= strstr(tl->line, findstr); + if (tl==startl) + break; + } + + if (s) { + text->curl= text->sell= tl; + text->curc= (int) (s-tl->line); + text->selc= text->curc + strlen(findstr); + + return 1; + } else + return 0; +} + +void txt_cut_sel (Text *text) +{ + txt_copy_sel(text); + + txt_delete_sel(text); +} + +char *txt_sel_to_buf (Text *text) +{ + char *buf; + int length=0; + TextLine *tmp, *linef, *linel; + int charf, charl; + + if (!text) return NULL; + if (!text->curl) return NULL; + if (!text->sell) return NULL; + + if (text->curl==text->sell) { + linef= linel= text->curl; + + if (text->curc < text->selc) { + charf= text->curc; + charl= text->selc; + } else{ + charf= text->selc; + charl= text->curc; + } + } else if (txt_get_span(text->curl, text->sell)<0) { + linef= text->sell; + linel= text->curl; + + charf= text->selc; + charl= text->curc; + } else { + linef= text->curl; + linel= text->sell; + + charf= text->curc; + charl= text->selc; + } + + if (linef == linel) { + length= charl-charf; + + buf= MEM_mallocN(length+1, "sel buffer"); + + BLI_strncpy(buf, linef->line + charf, length+1); + } else { + length+= linef->len - charf; + length+= charl; + length++; /* For the '\n' */ + + tmp= linef->next; + while (tmp && tmp!= linel) { + length+= tmp->len+1; + tmp= tmp->next; + } + + buf= MEM_mallocN(length+1, "sel buffer"); + + strncpy(buf, linef->line+ charf, linef->len-charf); + length= linef->len-charf; + + buf[length++]='\n'; + + tmp= linef->next; + while (tmp && tmp!=linel) { + strncpy(buf+length, tmp->line, tmp->len); + length+= tmp->len; + + buf[length++]='\n'; + + tmp= tmp->next; + } + strncpy(buf+length, linel->line, charl); + length+= charl; + + buf[length]=0; + } + + return buf; +} + +void txt_copy_sel (Text *text) +{ + int length=0; + TextLine *tmp, *linef, *linel; + int charf, charl; + + if (!text) return; + if (!text->curl) return; + if (!text->sell) return; + + if (!txt_has_sel(text)) return; + + if (txt_cut_buffer) MEM_freeN(txt_cut_buffer); + txt_cut_buffer= NULL; + + if (text->curl==text->sell) { + linef= linel= text->curl; + + if (text->curc < text->selc) { + charf= text->curc; + charl= text->selc; + } else{ + charf= text->selc; + charl= text->curc; + } + } else if (txt_get_span(text->curl, text->sell)<0) { + linef= text->sell; + linel= text->curl; + + charf= text->selc; + charl= text->curc; + } else { + linef= text->curl; + linel= text->sell; + + charf= text->curc; + charl= text->selc; + } + + if (linef == linel) { + length= charl-charf; + + txt_cut_buffer= MEM_mallocN(length+1, "cut buffera"); + + BLI_strncpy(txt_cut_buffer, linef->line + charf, length+1); + } else { + length+= linef->len - charf; + length+= charl; + length++; /* For the '\n' */ + + tmp= linef->next; + while (tmp && tmp!= linel) { + length+= tmp->len+1; + tmp= tmp->next; + } + + txt_cut_buffer= MEM_mallocN(length+1, "cut bufferb"); + + strncpy(txt_cut_buffer, linef->line+ charf, linef->len-charf); + length= linef->len-charf; + + txt_cut_buffer[length++]='\n'; + + tmp= linef->next; + while (tmp && tmp!=linel) { + strncpy(txt_cut_buffer+length, tmp->line, tmp->len); + length+= tmp->len; + + txt_cut_buffer[length++]='\n'; + + tmp= tmp->next; + } + strncpy(txt_cut_buffer+length, linel->line, charl); + length+= charl; + + txt_cut_buffer[length]=0; + } +} + +void txt_insert_buf(Text *text, char *in_buffer) +{ + int i=0, l=0, j, u, len; + TextLine *add; + + if (!text) return; + if (!in_buffer) return; + + txt_delete_sel(text); + + if(!undoing) txt_undo_add_block (text, UNDO_IBLOCK, in_buffer); + + u= undoing; + undoing= 1; + + /* Read the first line (or as close as possible */ + while (in_buffer[i] && in_buffer[i]!='\n') { + txt_add_char(text, in_buffer[i]); + i++; + } + + if (in_buffer[i]=='\n') txt_split_curline(text); + else { undoing = u; return; } + i++; + + /* Read as many full lines as we can */ + len= strlen(in_buffer); + + while (i<len) { + l=0; + + while (in_buffer[i] && in_buffer[i]!='\n') { + i++; l++; + } + + if(in_buffer[i]=='\n') { + add= txt_new_linen(in_buffer +(i-l), l); + BLI_insertlinkbefore(&text->lines, text->curl, add); + i++; + } else { + for (j= i-l; j<i && j<(int)strlen(in_buffer); j++) { + txt_add_char(text, in_buffer[j]); + } + break; + } + } + + undoing= u; +} + +void txt_free_cut_buffer(void) +{ + if (txt_cut_buffer) MEM_freeN(txt_cut_buffer); +} + +void txt_paste(Text *text) +{ + txt_insert_buf(text, txt_cut_buffer); +} + +/******************/ +/* Undo functions */ +/******************/ + +#define MAX_UNDO_TEST(x) \ + while (text->undo_pos+x >= text->undo_len) { \ + if(text->undo_len*2 > TXT_MAX_UNDO) { \ + error("Undo limit reached, buffer cleared\n"); \ + MEM_freeN(text->undo_buf); \ + text->undo_len= TXT_INIT_UNDO; \ + text->undo_buf= MEM_mallocN(text->undo_len, "undo buf"); \ + text->undo_pos=-1; \ + return; \ + } else { \ + void *tmp= text->undo_buf; \ + text->undo_buf= MEM_callocN(text->undo_len*2, "undo buf"); \ + memcpy(text->undo_buf, tmp, text->undo_len); \ + text->undo_len*=2; \ + MEM_freeN(tmp); \ + } \ + } + +static void dump_buffer(Text *text) { + int i= 0; + + while (i++<text->undo_pos) printf("%d: %d %c\n", i, text->undo_buf[i], text->undo_buf[i]); +} + +void txt_print_undo(Text *text) +{ + int i= 0; + int op; + char *ops; + int linep, charp; + + dump_buffer(text); + + printf ("---< Undo Buffer >---\n"); + + printf ("UndoPosition is %d\n", text->undo_pos); + + while (i<=text->undo_pos) { + op= text->undo_buf[i]; + + if (op==UNDO_CLEFT) { + ops= "Cursor left"; + } else if (op==UNDO_CRIGHT) { + ops= "Cursor right"; + } else if (op==UNDO_CUP) { + ops= "Cursor up"; + } else if (op==UNDO_CDOWN) { + ops= "Cursor down"; + } else if (op==UNDO_SLEFT) { + ops= "Selection left"; + } else if (op==UNDO_SRIGHT) { + ops= "Selection right"; + } else if (op==UNDO_SUP) { + ops= "Selection up"; + } else if (op==UNDO_SDOWN) { + ops= "Selection down"; + } else if (op==UNDO_STO) { + ops= "Selection "; + } else if (op==UNDO_CTO) { + ops= "Cursor "; + } else if (op==UNDO_INSERT) { + ops= "Insert"; + } else if (op==UNDO_BS) { + ops= "Backspace"; + } else if (op==UNDO_DEL) { + ops= "Delete"; + } else if (op==UNDO_SWAP) { + ops= "Cursor swap"; + } else if (op==UNDO_DBLOCK) { + ops= "Delete text block"; + } else if (op==UNDO_IBLOCK) { + ops= "Insert text block"; + } else { + ops= "Unknown"; + } + + printf ("Op (%o) at %d = %s", op, i, ops); + if (op==UNDO_INSERT || op==UNDO_BS || op==UNDO_DEL) { + i++; + printf (" - Char is %c", text->undo_buf[i]); + i++; + } else if (op==UNDO_STO || op==UNDO_CTO) { + i++; + + charp= text->undo_buf[i]; i++; + charp= charp+(text->undo_buf[i]<<8); i++; + + linep= text->undo_buf[i]; i++; + linep= linep+(text->undo_buf[i]<<8); i++; + linep= linep+(text->undo_buf[i]<<16); i++; + linep= linep+(text->undo_buf[i]<<24); i++; + + printf ("to <%d, %d> ", linep, charp); + + charp= text->undo_buf[i]; i++; + charp= charp+(text->undo_buf[i]<<8); i++; + + linep= text->undo_buf[i]; i++; + linep= linep+(text->undo_buf[i]<<8); i++; + linep= linep+(text->undo_buf[i]<<16); i++; + linep= linep+(text->undo_buf[i]<<24); i++; + + printf ("from <%d, %d>", linep, charp); + } else if (op==UNDO_DBLOCK || op==UNDO_IBLOCK) { + i++; + + linep= text->undo_buf[i]; i++; + linep= linep+(text->undo_buf[i]<<8); i++; + linep= linep+(text->undo_buf[i]<<16); i++; + linep= linep+(text->undo_buf[i]<<24); i++; + + printf (" (length %d) <", linep); + + while (linep>0) { + putchar(text->undo_buf[i]); + linep--; i++; + } + + linep= text->undo_buf[i]; i++; + linep= linep+(text->undo_buf[i]<<8); i++; + linep= linep+(text->undo_buf[i]<<16); i++; + linep= linep+(text->undo_buf[i]<<24); i++; + printf ("> (%d)", linep); + } + + printf (" %d\n", i); + i++; + } +} + +static void txt_undo_add_op(Text *text, int op) +{ + MAX_UNDO_TEST(2); + + text->undo_pos++; + text->undo_buf[text->undo_pos]= op; + text->undo_buf[text->undo_pos+1]= 0; +} + +static void txt_undo_add_block(Text *text, int op, char *buf) +{ + unsigned int length; + + length= strlen(buf); + + MAX_UNDO_TEST(length+11); + + text->undo_pos++; + text->undo_buf[text->undo_pos]= op; + + text->undo_pos++; + text->undo_buf[text->undo_pos]= (length)&0xff; + text->undo_pos++; + text->undo_buf[text->undo_pos]= (length>>8)&0xff; + text->undo_pos++; + text->undo_buf[text->undo_pos]= (length>>16)&0xff; + text->undo_pos++; + text->undo_buf[text->undo_pos]= (length>>24)&0xff; + + text->undo_pos++; + strncpy(text->undo_buf+text->undo_pos, buf, length); + text->undo_pos+=length; + + text->undo_buf[text->undo_pos]= (length)&0xff; + text->undo_pos++; + text->undo_buf[text->undo_pos]= (length>>8)&0xff; + text->undo_pos++; + text->undo_buf[text->undo_pos]= (length>>16)&0xff; + text->undo_pos++; + text->undo_buf[text->undo_pos]= (length>>24)&0xff; + + text->undo_pos++; + text->undo_buf[text->undo_pos]= op; + + text->undo_buf[text->undo_pos+1]= 0; +} + +void txt_undo_add_toop(Text *text, int op, unsigned int froml, unsigned short fromc, unsigned int tol, unsigned short toc) +{ + MAX_UNDO_TEST(15); + + if (froml==tol && fromc==toc) return; + + text->undo_pos++; + text->undo_buf[text->undo_pos]= op; + + text->undo_pos++; + text->undo_buf[text->undo_pos]= (fromc)&0xff; + text->undo_pos++; + text->undo_buf[text->undo_pos]= (fromc>>8)&0xff; + + text->undo_pos++; + text->undo_buf[text->undo_pos]= (froml)&0xff; + text->undo_pos++; + text->undo_buf[text->undo_pos]= (froml>>8)&0xff; + text->undo_pos++; + text->undo_buf[text->undo_pos]= (froml>>16)&0xff; + text->undo_pos++; + text->undo_buf[text->undo_pos]= (froml>>24)&0xff; + + text->undo_pos++; + text->undo_buf[text->undo_pos]= (toc)&0xff; + text->undo_pos++; + text->undo_buf[text->undo_pos]= (toc>>8)&0xff; + + text->undo_pos++; + text->undo_buf[text->undo_pos]= (tol)&0xff; + text->undo_pos++; + text->undo_buf[text->undo_pos]= (tol>>8)&0xff; + text->undo_pos++; + text->undo_buf[text->undo_pos]= (tol>>16)&0xff; + text->undo_pos++; + text->undo_buf[text->undo_pos]= (tol>>24)&0xff; + + text->undo_pos++; + text->undo_buf[text->undo_pos]= op; + + text->undo_buf[text->undo_pos+1]= 0; +} + +static void txt_undo_add_charop(Text *text, int op, char c) +{ + MAX_UNDO_TEST(4); + + text->undo_pos++; + text->undo_buf[text->undo_pos]= op; + text->undo_pos++; + text->undo_buf[text->undo_pos]= c; + text->undo_pos++; + text->undo_buf[text->undo_pos]= op; + text->undo_buf[text->undo_pos+1]= 0; +} + +void txt_do_undo(Text *text) +{ + int op= text->undo_buf[text->undo_pos], i; + unsigned int linep; + unsigned short charp; + TextLine *holdl; + int holdc, holdln; + char *buf; + + if (text->undo_pos<0) { + return; + } + + text->undo_pos--; + + undoing= 1; + + switch(op) { + case UNDO_CLEFT: + txt_move_right(text, 0); + break; + + case UNDO_CRIGHT: + txt_move_left(text, 0); + break; + + case UNDO_CUP: + txt_move_down(text, 0); + break; + + case UNDO_CDOWN: + txt_move_up(text, 0); + break; + + case UNDO_SLEFT: + txt_move_right(text, 1); + break; + + case UNDO_SRIGHT: + txt_move_left(text, 1); + break; + + case UNDO_SUP: + txt_move_down(text, 1); + break; + + case UNDO_SDOWN: + txt_move_up(text, 1); + break; + + case UNDO_CTO: + case UNDO_STO: + text->undo_pos--; + text->undo_pos--; + text->undo_pos--; + text->undo_pos--; + + text->undo_pos--; + text->undo_pos--; + + linep= text->undo_buf[text->undo_pos]; text->undo_pos--; + linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; + linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; + linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; + + charp= text->undo_buf[text->undo_pos]; text->undo_pos--; + charp= (charp<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; + + if (op==UNDO_CTO) { + txt_move_toline(text, linep, 0); + text->curc= charp; + txt_pop_sel(text); + } else { + txt_move_toline(text, linep, 1); + text->selc= charp; + } + + text->undo_pos--; + break; + + case UNDO_INSERT: + txt_backspace_char(text); + text->undo_pos--; + text->undo_pos--; + break; + + case UNDO_BS: + txt_add_char(text, text->undo_buf[text->undo_pos]); + text->undo_pos--; + text->undo_pos--; + break; + + case UNDO_DEL: + txt_add_char(text, text->undo_buf[text->undo_pos]); + txt_move_left(text, 0); + text->undo_pos--; + text->undo_pos--; + break; + + case UNDO_SWAP: + txt_curs_swap(text); + txt_do_undo(text); /* swaps should appear transparent */ + break; + + case UNDO_DBLOCK: + linep= text->undo_buf[text->undo_pos]; text->undo_pos--; + linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; + linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; + linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; + + buf= MEM_mallocN(linep+1, "dblock buffer"); + for (i=0; i < (int)linep; i++){ + buf[(linep-1)-i]= text->undo_buf[text->undo_pos]; + text->undo_pos--; + } + buf[i]= 0; + + txt_curs_first(text, &holdl, &holdc); + holdln= txt_get_span(text->lines.first, holdl); + + txt_insert_buf(text, buf); + MEM_freeN(buf); + + text->curl= text->lines.first; + while (holdln>0) { + if(text->curl->next) + text->curl= text->curl->next; + + holdln--; + } + text->curc= holdc; + + linep= text->undo_buf[text->undo_pos]; text->undo_pos--; + linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; + linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; + linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; + + text->undo_pos--; + + break; + + case UNDO_IBLOCK: + linep= text->undo_buf[text->undo_pos]; text->undo_pos--; + linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; + linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; + linep= (linep<<8)+text->undo_buf[text->undo_pos]; text->undo_pos--; + + txt_delete_sel(text); + while (linep>0) { + txt_backspace_char(text); + text->undo_pos--; + linep--; + } + + text->undo_pos--; + text->undo_pos--; + text->undo_pos--; + text->undo_pos--; + + text->undo_pos--; + + break; + + default: + error("Undo buffer error - resetting"); + text->undo_pos= -1; + + break; + } + + undoing= 0; +} + +void txt_do_redo(Text *text) +{ + char op; + unsigned int linep; + unsigned short charp; + char *buf; + + text->undo_pos++; + op= text->undo_buf[text->undo_pos]; + + if (!op) { + text->undo_pos--; + return; + } + + undoing= 1; + + switch(op) { + case UNDO_CLEFT: + txt_move_left(text, 0); + break; + + case UNDO_CRIGHT: + txt_move_right(text, 0); + break; + + case UNDO_CUP: + txt_move_up(text, 0); + break; + + case UNDO_CDOWN: + txt_move_down(text, 0); + break; + + case UNDO_SLEFT: + txt_move_left(text, 1); + break; + + case UNDO_SRIGHT: + txt_move_right(text, 1); + break; + + case UNDO_SUP: + txt_move_up(text, 1); + break; + + case UNDO_SDOWN: + txt_move_down(text, 1); + break; + + case UNDO_INSERT: + text->undo_pos++; + txt_add_char(text, text->undo_buf[text->undo_pos]); + text->undo_pos++; + break; + + case UNDO_BS: + text->undo_pos++; + txt_backspace_char(text); + text->undo_pos++; + break; + + case UNDO_DEL: + text->undo_pos++; + txt_delete_char(text); + text->undo_pos++; + break; + + case UNDO_SWAP: + txt_curs_swap(text); + txt_do_undo(text); /* swaps should appear transparent a*/ + break; + + case UNDO_CTO: + case UNDO_STO: + text->undo_pos++; + text->undo_pos++; + + text->undo_pos++; + text->undo_pos++; + text->undo_pos++; + text->undo_pos++; + + text->undo_pos++; + + charp= text->undo_buf[text->undo_pos]; + text->undo_pos++; + charp= charp+(text->undo_buf[text->undo_pos]<<8); + + text->undo_pos++; + linep= text->undo_buf[text->undo_pos]; text->undo_pos++; + linep= linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++; + linep= linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++; + linep= linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++; + + if (op==UNDO_CTO) { + txt_move_toline(text, linep, 0); + text->curc= charp; + txt_pop_sel(text); + } else { + txt_move_toline(text, linep, 1); + text->selc= charp; + } + + break; + + case UNDO_DBLOCK: + text->undo_pos++; + linep= text->undo_buf[text->undo_pos]; text->undo_pos++; + linep= linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++; + linep= linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++; + linep= linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++; + + txt_delete_sel(text); + text->undo_pos+=linep; + + text->undo_pos++; + text->undo_pos++; + text->undo_pos++; + text->undo_pos++; + + break; + + case UNDO_IBLOCK: + text->undo_pos++; + linep= text->undo_buf[text->undo_pos]; text->undo_pos++; + linep= linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++; + linep= linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++; + linep= linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++; + + buf= MEM_mallocN(linep+1, "iblock buffer"); + memcpy (buf, &text->undo_buf[text->undo_pos], linep); + text->undo_pos+= linep; + buf[linep]= 0; + + txt_insert_buf(text, buf); + MEM_freeN(buf); + + linep= text->undo_buf[text->undo_pos]; text->undo_pos++; + linep= linep+(text->undo_buf[text->undo_pos]<<8); text->undo_pos++; + linep= linep+(text->undo_buf[text->undo_pos]<<16); text->undo_pos++; + linep= linep+(text->undo_buf[text->undo_pos]<<24); text->undo_pos++; + + break; + + default: + error("Undo buffer error - resetting"); + text->undo_pos= -1; + + break; + } + + undoing= 0; +} + +/**************************/ +/* Line editing functions */ +/**************************/ + +void txt_split_curline (Text *text) { + TextLine *ins; + char *left, *right; + + if (!text) return; + if (!text->curl) return; + + txt_delete_sel(text); + + /* Make the two half strings */ + + left= MEM_mallocN(text->curc+1, "textline_string"); + if (text->curc) memcpy(left, text->curl->line, text->curc); + left[text->curc]=0; + + right= MEM_mallocN(text->curl->len - text->curc+1, "textline_string"); + if (text->curl->len - text->curc) memcpy(right, text->curl->line+text->curc, text->curl->len-text->curc); + right[text->curl->len - text->curc]=0; + + MEM_freeN(text->curl->line); + + /* Make the new TextLine */ + + ins= MEM_mallocN(sizeof(TextLine), "textline"); + ins->line= left; + ins->len= text->curc; + + text->curl->line= right; + text->curl->len= text->curl->len - text->curc; + + BLI_insertlinkbefore(&text->lines, text->curl, ins); + + text->curc=0; + + txt_make_dirty(text); + txt_clean_text(text); + + txt_pop_sel(text); + if(!undoing) txt_undo_add_charop(text, UNDO_INSERT, '\n'); +} + +static void txt_delete_line (Text *text, TextLine *line) +{ + if (!text) return; + if (!text->curl) return; + + BLI_remlink (&text->lines, line); + + if (line->line) MEM_freeN(line->line); + MEM_freeN(line); + + txt_make_dirty(text); + txt_clean_text(text); +} + +static void txt_combine_lines (Text *text, TextLine *linea, TextLine *lineb) +{ + char *tmp; + + if (!text) return; + + if(!linea || !lineb) return; + + tmp= MEM_mallocN(linea->len+lineb->len+1, "textline_string"); + + strcpy(tmp, linea->line); + strcat(tmp, lineb->line); + + make_new_line(linea, tmp); + + txt_delete_line(text, lineb); + + txt_make_dirty(text); + txt_clean_text(text); +} + +void txt_delete_char (Text *text) +{ + char c='\n'; + + if (!text) return; + if (!text->curl) return; + + if (txt_has_sel(text)) { + txt_delete_sel(text); + return; + } + + if (text->curc== text->curl->len) { /* Appending two lines */ + if (text->curl->next) { + txt_combine_lines(text, text->curl, text->curl->next); + txt_pop_sel(text); + } + } else { /* Just deleting a char */ + int i= text->curc; + + c= text->curl->line[i]; + while(i< text->curl->len) { + text->curl->line[i]= text->curl->line[i+1]; + i++; + } + text->curl->len--; + + txt_pop_sel(text); + } + + txt_make_dirty(text); + txt_clean_text(text); + + if(!undoing) txt_undo_add_charop(text, UNDO_DEL, c); +} + +void txt_backspace_char (Text *text) { + char c='\n'; + + if (!text) return; + if (!text->curl) return; + + if (txt_has_sel(text)) { + txt_delete_sel(text); + return; + } + + if (text->curc==0) { /* Appending two lines */ + if (text->curl->prev) { + text->curl= text->curl->prev; + text->curc= text->curl->len; + + txt_combine_lines(text, text->curl, text->curl->next); + txt_pop_sel(text); + } + } else { /* Just backspacing a char */ + int i= text->curc-1; + + c= text->curl->line[i]; + while(i< text->curl->len) { + text->curl->line[i]= text->curl->line[i+1]; + i++; + } + text->curl->len--; + text->curc--; + + txt_pop_sel(text); + } + + txt_make_dirty(text); + txt_clean_text(text); + + if(!undoing) txt_undo_add_charop(text, UNDO_BS, c); +} + +int txt_add_char (Text *text, char add) { + int len; + char *tmp; + + if (!text) return 0; + if (!text->curl) return 0; + + if (add=='\n') { + txt_split_curline(text); + return 1; + } + + if(txt_illegal_char(add)) return 0; + + txt_delete_sel(text); + + tmp= MEM_mallocN(text->curl->len+2, "textline_string"); + + if(text->curc) memcpy(tmp, text->curl->line, text->curc); + tmp[text->curc]= add; + + len= text->curl->len - text->curc; + if(len>0) memcpy(tmp+text->curc+1, text->curl->line+text->curc, len); + tmp[text->curl->len+1]=0; + + make_new_line(text->curl, tmp); + + text->curc++; + + txt_pop_sel(text); + + txt_make_dirty(text); + txt_clean_text(text); + + if(!undoing) txt_undo_add_charop(text, UNDO_INSERT, add); + return 1; +} diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c new file mode 100644 index 00000000000..eed8a39d6ce --- /dev/null +++ b/source/blender/blenkernel/intern/texture.c @@ -0,0 +1,2320 @@ +/** + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +#ifdef WIN32 +#include "BLI_winstuff.h" +#endif + +#include "MEM_guardedalloc.h" + +#include "PIL_dynlib.h" + +#include "MTC_matrixops.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "BLI_rand.h" + +#include "DNA_texture_types.h" +#include "DNA_key_types.h" +#include "DNA_mesh_types.h" +#include "DNA_object_types.h" +#include "DNA_lamp_types.h" +#include "DNA_material_types.h" +#include "DNA_image_types.h" + +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" + +#include "BKE_osa_types.h" +#include "BKE_plugin_types.h" + +#include "BKE_bad_level_calls.h" +#include "BKE_utildefines.h" + +#include "BKE_global.h" +#include "BKE_main.h" + +#include "BKE_library.h" +#include "BKE_image.h" +#include "BKE_texture.h" +#include "BKE_key.h" +#include "BKE_ipo.h" + + +/* These vars form the texture channel */ +float Tin, Tr, Tg, Tb, Ta, Txtra; +extern int Talpha; + + +/* ------------------------------------------------------------------------- */ + +/* Alle support voor plugin textures: */ +int test_dlerr(const char *name, const char *symbol) +{ + char *err; + + err= PIL_dynlib_get_error_as_string(NULL); + if(err) { + printf("var1: %s, var2: %s, var3: %s\n", name, symbol, err); + return 1; + } + + return 0; +} + +/* ------------------------------------------------------------------------- */ + +void open_plugin_tex(PluginTex *pit) +{ + int (*version)(void); + + /* init all the happy variables */ + pit->doit= 0; + pit->pname= 0; + pit->stnames= 0; + pit->varstr= 0; + pit->result= 0; + pit->cfra= 0; + pit->version= 0; + + /* clear the error list */ + PIL_dynlib_get_error_as_string(NULL); + + /* no PIL_dynlib_close! multiple opened plugins... */ + /* if(pit->handle) PIL_dynlib_close(pit->handle); */ + /* pit->handle= 0; */ + + /* open the needed object */ + pit->handle= PIL_dynlib_open(pit->name); + if(test_dlerr(pit->name, pit->name)) return; + + if (pit->handle != 0) { + /* find the address of the version function */ + version= (int (*)(void)) PIL_dynlib_find_symbol(pit->handle, "plugin_tex_getversion"); + if (test_dlerr(pit->name, "plugin_tex_getversion")) return; + + if (version != 0) { + pit->version= version(); + if (pit->version==2 || pit->version==3) { + int (*info_func)(PluginInfo *); + PluginInfo *info= (PluginInfo*) MEM_mallocN(sizeof(PluginInfo), "plugin_info"); + + info_func= (int (*)(PluginInfo *))PIL_dynlib_find_symbol(pit->handle, "plugin_getinfo"); + if (!test_dlerr(pit->name, "plugin_getinfo")) { + + info_func(info); + + pit->doit= (int(*)(void)) info->tex_doit; + pit->callback= (void(*)(unsigned short)) info->callback; + pit->stypes= info->stypes; + pit->vars= info->nvars; + pit->pname= info->name; + pit->stnames= info->snames; + pit->varstr= info->varstr; + pit->result= info->result; + pit->cfra= info->cfra; + if (info->init) info->init(); + } + MEM_freeN(info); + } else { + printf ("Plugin returned unrecognized version number\n"); + return; + } + } + } +} + +/* ------------------------------------------------------------------------- */ + +PluginTex *add_plugin_tex(char *str) +{ + PluginTex *pit; + VarStruct *varstr; + int a; + + pit= MEM_callocN(sizeof(PluginTex), "plugintex"); + + strcpy(pit->name, str); + open_plugin_tex(pit); + + if(pit->doit==0) { + if(pit->handle==0) error("no plugin: %s", str); + else error("in plugin: %s", str); + MEM_freeN(pit); + return NULL; + } + + varstr= pit->varstr; + for(a=0; a<pit->vars; a++, varstr++) { + if( (varstr->type & FLO)==FLO) + pit->data[a]= varstr->def; + else if( (varstr->type & INT)==INT) + *((int *)(pit->data+a))= (int) varstr->def; + } + + return pit; +} + +/* ------------------------------------------------------------------------- */ + +void free_plugin_tex(PluginTex *pit) +{ + if(pit==0) return; + + /* geen PIL_dynlib_close: dezelfde plugin kan meerdere keren geopend zijn: 1 handle */ + MEM_freeN(pit); +} + +/* ****************** COLORBAND ******************* */ + +ColorBand *add_colorband() +{ + ColorBand *coba; + int a; + + coba= MEM_callocN( sizeof(ColorBand), "colorband"); + + coba->data[0].r= 0.0; + coba->data[0].g= 0.0; + coba->data[0].b= 0.0; + coba->data[0].a= 0.0; + coba->data[0].pos= 0.0; + + coba->data[1].r= 0.0; + coba->data[1].g= 1.0; + coba->data[1].b= 1.0; + coba->data[1].a= 1.0; + coba->data[1].pos= 1.0; + + for(a=2; a<MAXCOLORBAND; a++) { + coba->data[a].r= 0.5; + coba->data[a].g= 0.5; + coba->data[a].b= 0.5; + coba->data[a].a= 1.0; + coba->data[a].pos= 0.5; + } + + coba->tot= 2; + + return coba; +} + +/* ------------------------------------------------------------------------- */ + +int do_colorband(ColorBand *coba) +{ + CBData *cbd1, *cbd2, *cbd0, *cbd3; + float fac, mfac, t[4]; + int a; + + if(coba->tot==0) return 0; + Talpha= 1; + + cbd1= coba->data; + + if(Tin <= cbd1->pos) { /* helemaal links */ + Tr= cbd1->r; + Tg= cbd1->g; + Tb= cbd1->b; + Ta= cbd1->a; + } + else { + /* we zoeken de eerste pos > Tin */ + + for(a=0; a<coba->tot; a++, cbd1++) if(cbd1->pos >= Tin) break; + + if(a==coba->tot) { /* helemaal rechts */ + cbd1--; + Tr= cbd1->r; + Tg= cbd1->g; + Tb= cbd1->b; + Ta= cbd1->a; + } + else { + cbd2= cbd1-1; + fac= (Tin-cbd1->pos)/(cbd2->pos-cbd1->pos); + + if(coba->ipotype==2) { + /* ipo van r naar l: 3 2 1 0 */ + + if(a>=coba->tot-1) cbd0= cbd1; + else cbd0= cbd1+1; + if(a<2) cbd3= cbd2; + else cbd3= cbd2-1; + + set_four_ipo(fac, t, KEY_BSPLINE); + + Tr= t[3]*cbd3->r +t[2]*cbd2->r +t[1]*cbd1->r +t[0]*cbd0->r; + Tg= t[3]*cbd3->g +t[2]*cbd2->g +t[1]*cbd1->g +t[0]*cbd0->g; + Tb= t[3]*cbd3->b +t[2]*cbd2->b +t[1]*cbd1->b +t[0]*cbd0->b; + Ta= t[3]*cbd3->a +t[2]*cbd2->a +t[1]*cbd1->a +t[0]*cbd0->a; + CLAMP(Tr, 0.0, 1.0); + CLAMP(Tg, 0.0, 1.0); + CLAMP(Tb, 0.0, 1.0); + CLAMP(Ta, 0.0, 1.0); + } + else { + + if(coba->ipotype==1) { /* EASE */ + mfac= fac*fac; + fac= 3.0f*mfac-2.0f*mfac*fac; + } + mfac= 1.0f-fac; + + Tr= mfac*cbd1->r + fac*cbd2->r; + Tg= mfac*cbd1->g + fac*cbd2->g; + Tb= mfac*cbd1->b + fac*cbd2->b; + Ta= mfac*cbd1->a + fac*cbd2->a; + } + } + } + return 1; /* OK */ +} + +/* ******************* TEX ************************ */ + +void free_texture(Tex *tex) +{ + free_plugin_tex(tex->plugin); + if(tex->coba) MEM_freeN(tex->coba); + if(tex->env) RE_free_envmap(tex->env); +} + +/* ------------------------------------------------------------------------- */ + +void default_tex(Tex *tex) +{ + tex->stype= 0; + tex->imaflag= TEX_INTERPOL+TEX_MIPMAP; + tex->extend= TEX_REPEAT; + tex->cropxmin= tex->cropymin= 0.0; + tex->cropxmax= tex->cropymax= 1.0; + tex->xrepeat= tex->yrepeat= 1; + tex->fie_ima= 2; + tex->sfra= 1; + tex->frames= 0; + tex->offset= 0; + tex->noisesize= 0.25; + tex->noisedepth= 2; + tex->turbul= 5.0; + tex->bright= 1.0; + tex->contrast= tex->filtersize= 1.0; + tex->rfac= 1.0; + tex->gfac= 1.0; + tex->bfac= 1.0; + +} + +/* ------------------------------------------------------------------------- */ + +Tex *add_texture(char *name) +{ + Tex *tex; + + tex= alloc_libblock(&G.main->tex, ID_TE, name); + + default_tex(tex); + + return tex; +} + +/* ------------------------------------------------------------------------- */ + +void default_mtex(MTex *mtex) +{ + mtex->texco= TEXCO_ORCO; + mtex->mapto= MAP_COL; + mtex->object= 0; + mtex->projx= PROJ_X; + mtex->projy= PROJ_Y; + mtex->projz= PROJ_Z; + mtex->mapping= MTEX_FLAT; + mtex->ofs[0]= 0.0; + mtex->ofs[1]= 0.0; + mtex->ofs[2]= 0.0; + mtex->size[0]= 1.0; + mtex->size[1]= 1.0; + mtex->size[2]= 1.0; + mtex->tex= 0; + mtex->texflag= 0; + mtex->colormodel= 0; + mtex->r= 1.0; + mtex->g= 0.0; + mtex->b= 1.0; + mtex->k= 1.0; + mtex->def_var= 1.0; + mtex->blendtype= MTEX_BLEND; + mtex->colfac= 1.0; + mtex->norfac= 0.5; + mtex->varfac= 1.0; +} + + +/* ------------------------------------------------------------------------- */ + +MTex *add_mtex() +{ + MTex *mtex; + + mtex= MEM_callocN(sizeof(MTex), "add_mtex"); + + default_mtex(mtex); + + return mtex; +} + +/* ------------------------------------------------------------------------- */ + +Tex *copy_texture(Tex *tex) +{ + Tex *texn; + + texn= copy_libblock(tex); + if(texn->type==TEX_IMAGE) id_us_plus((ID *)texn->ima); + else texn->ima= 0; + + if(texn->plugin) { + texn->plugin= MEM_dupallocN(texn->plugin); + open_plugin_tex(texn->plugin); + } + + if(texn->coba) texn->coba= MEM_dupallocN(texn->coba); + if(texn->env) texn->env= RE_copy_envmap(texn->env); + + return texn; +} + +/* ------------------------------------------------------------------------- */ + +void make_local_texture(Tex *tex) +{ + Tex *texn; + Material *ma; + World *wrld; + Lamp *la; + int a, local=0, lib=0; + + /* - zijn er alleen lib users: niet doen + * - zijn er alleen locale users: flag zetten + * - mixed: copy + */ + + if(tex->id.lib==0) return; + + /* speciaal geval: ima altijd meteen lokaal */ + if(tex->ima) { + tex->ima->id.lib= 0; + tex->ima->id.flag= LIB_LOCAL; + new_id(0, (ID *)tex->ima, 0); + } + + if(tex->id.us==1) { + tex->id.lib= 0; + tex->id.flag= LIB_LOCAL; + new_id(0, (ID *)tex, 0); + + return; + } + + ma= G.main->mat.first; + while(ma) { + for(a=0; a<8; a++) { + if(ma->mtex[a] && ma->mtex[a]->tex==tex) { + if(ma->id.lib) lib= 1; + else local= 1; + } + } + ma= ma->id.next; + } + la= G.main->lamp.first; + while(la) { + for(a=0; a<8; a++) { + if(la->mtex[a] && la->mtex[a]->tex==tex) { + if(la->id.lib) lib= 1; + else local= 1; + } + } + la= la->id.next; + } + wrld= G.main->world.first; + while(wrld) { + for(a=0; a<8; a++) { + if(wrld->mtex[a] && wrld->mtex[a]->tex==tex) { + if(wrld->id.lib) lib= 1; + else local= 1; + } + } + wrld= wrld->id.next; + } + + if(local && lib==0) { + tex->id.lib= 0; + tex->id.flag= LIB_LOCAL; + new_id(0, (ID *)tex, 0); + } + else if(local && lib) { + texn= copy_texture(tex); + texn->id.us= 0; + + ma= G.main->mat.first; + while(ma) { + for(a=0; a<8; a++) { + if(ma->mtex[a] && ma->mtex[a]->tex==tex) { + if(ma->id.lib==0) { + ma->mtex[a]->tex= texn; + texn->id.us++; + tex->id.us--; + } + } + } + ma= ma->id.next; + } + la= G.main->lamp.first; + while(la) { + for(a=0; a<8; a++) { + if(la->mtex[a] && la->mtex[a]->tex==tex) { + if(la->id.lib==0) { + la->mtex[a]->tex= texn; + texn->id.us++; + tex->id.us--; + } + } + } + la= la->id.next; + } + wrld= G.main->world.first; + while(wrld) { + for(a=0; a<8; a++) { + if(wrld->mtex[a] && wrld->mtex[a]->tex==tex) { + if(wrld->id.lib==0) { + wrld->mtex[a]->tex= texn; + texn->id.us++; + tex->id.us--; + } + } + } + wrld= wrld->id.next; + } + + } +} + +/* ------------------------------------------------------------------------- */ + +void autotexname(Tex *tex) +{ +/* extern char texstr[15][8]; *//* buttons.c, already in bad lev calls*/ + Image *ima; + char di[FILE_MAXDIR], fi[FILE_MAXFILE]; + + if(tex) { + if(tex->type==TEX_IMAGE) { + ima= tex->ima; + if(ima) { + strcpy(di, ima->name); + BLI_splitdirstring(di, fi); + strcpy(di, "I."); + strcat(di, fi); + new_id(&G.main->tex, (ID *)tex, di); + } + else new_id(&G.main->tex, (ID *)tex, texstr[tex->type]); + } + else if(tex->type==TEX_PLUGIN && tex->plugin) new_id(&G.main->tex, (ID *)tex, tex->plugin->pname); + else new_id(&G.main->tex, (ID *)tex, texstr[tex->type]); + } +} + +/* ------------------------------------------------------------------------- */ + +void init_render_texture(Tex *tex) +{ + Image *ima; + int imanr; + unsigned short numlen; + char name[256], head[FILE_MAXFILE], tail[FILE_MAXFILE]; + + /* is also used as signal */ + tex->nor= 0; + + /* imap testen */ + if(tex->frames && tex->ima && tex->ima->name) { /* frames */ + strcpy(name, tex->ima->name); + + imanr= calcimanr(G.scene->r.cfra, tex); + + if(tex->imaflag & TEX_ANIM5) { + if(tex->ima->lastframe != imanr) { + if(tex->ima->ibuf) IMB_freeImBuf(tex->ima->ibuf); + tex->ima->ibuf= 0; + tex->ima->lastframe= imanr; + } + } + else { + /* voor patch field-ima rendering */ + tex->ima->lastframe= imanr; + + BLI_stringdec(name, head, tail, &numlen); + BLI_stringenc(name, head, tail, numlen, imanr); + + ima= add_image(name); + + if(ima) { + ima->flag |= IMA_FROMANIM; + + if(tex->ima) tex->ima->id.us--; + tex->ima= ima; + + ima->ok= 1; + } + } + } + if(tex->imaflag & (TEX_ANTIALI+TEX_ANTISCALE)) { + if(tex->ima && tex->ima->lastquality<R.osa) { + if(tex->ima->ibuf) IMB_freeImBuf(tex->ima->ibuf); + tex->ima->ibuf= 0; + } + } + + if(tex->type==TEX_PLUGIN) { + if(tex->plugin && tex->plugin->doit) { + if(tex->plugin->cfra) { + *(tex->plugin->cfra)= frame_to_float(G.scene->r.cfra); + } + } + } + else if(tex->type==TEX_ENVMAP) { + /* just in case */ + tex->imaflag= TEX_INTERPOL | TEX_MIPMAP; + tex->extend= TEX_CLIP; + + if(tex->env) { + /* temporal solution: layer 21 is to indicate an anvmap object */ + tex->env->notlay |= (1<<20); + if(tex->env->object) tex->env->object->lay |= (1<<20); + + if(R.flag & R_RENDERING) { + if(tex->env->stype==ENV_ANIM) RE_free_envmapdata(tex->env); + } + } + } +} + +/* ------------------------------------------------------------------------- */ + +void init_render_textures() +{ + Tex *tex; + + tex= G.main->tex.first; + while(tex) { + if(tex->id.us) init_render_texture(tex); + tex= tex->id.next; + } + + free_unused_animimages(); +} + +/* ------------------------------------------------------------------------- */ + +void end_render_texture(Tex *tex) +{ + + +} + +/* ------------------------------------------------------------------------- */ + +void end_render_textures() +{ + Tex *tex; + + tex= G.main->tex.first; + while(tex) { + if(tex->id.us) end_render_texture(tex); + tex= tex->id.next; + } + +} + + +/* ************************** */ + +int clouds(Tex *tex, float *texvec) +{ + float (*turbfunc)(float, float, float, float, int); + + if(tex->noisetype==TEX_NOISESOFT) turbfunc= BLI_turbulence; + else turbfunc= BLI_turbulence1; + + Tin= turbfunc(tex->noisesize, texvec[0], texvec[1], texvec[2], tex->noisedepth); + + if(tex->stype==1) { + + Tr= Tin; + Tg= turbfunc(tex->noisesize, texvec[1], texvec[0], texvec[2], tex->noisedepth); + + Tb= turbfunc(tex->noisesize,texvec[1],texvec[2],texvec[0], tex->noisedepth); + + BRICONRGB; + Ta= 1.0; + + return 1; + } + + BRICON; + + if(tex->flag & TEX_COLORBAND) return do_colorband(tex->coba); + + return 0; +} + +/* ------------------------------------------------------------------------- */ + +int blend(Tex *tex, float *texvec) +{ + float x, y, t; + + if(tex->flag & TEX_FLIPBLEND) { + x= texvec[1]; + y= texvec[0]; + } + else { + x= texvec[0]; + y= texvec[1]; + } + + if(tex->stype==0) { /* lin */ + Tin= (1.0+x)/2.0; + } + else if(tex->stype==1) { /* quad */ + Tin= (1.0+x)/2.0; + if(Tin<0.0) Tin= 0.0; + else Tin*= Tin; + } + else if(tex->stype==2) { /* ease */ + Tin= (1.0+x)/2.0; + if(Tin<=.0) Tin= 0.0; + else if(Tin>=1.0) Tin= 1.0; + else { + t= Tin*Tin; + Tin= (3.0*t-2.0*t*Tin); + } + } + else if(tex->stype==3) { /* diag */ + Tin= (2.0+x+y)/4.0; + } + else { /* sphere */ + Tin= 1.0-sqrt(x*x+ y*y+texvec[2]*texvec[2]); + if(Tin<0.0) Tin= 0.0; + if(tex->stype==5) Tin*= Tin; /* halo */ + } + + BRICON; + if(tex->flag & TEX_COLORBAND) return do_colorband(tex->coba); + + return 0; +} + +/* ------------------------------------------------------------------------- */ + +int wood(Tex *tex, float *texvec) +{ + float (*noisefunc)(float, float, float, float); + + if(tex->noisetype==TEX_NOISESOFT) noisefunc= BLI_hnoise; + else noisefunc= BLI_hnoisep; + + + if(tex->stype==0) { + Tin= 0.5+0.5*sin( (texvec[0]+texvec[1]+texvec[2])*10.0 ); + } + else if(tex->stype==1) { + Tin= 0.5+0.5*sin( sqrt(texvec[0]*texvec[0]+texvec[1]*texvec[1]+texvec[2]*texvec[2])*20.0 ); + } + else if(tex->stype==2) { + Tin= noisefunc(tex->noisesize, texvec[0], texvec[1], texvec[2]); + Tin= 0.5+ 0.5*sin(tex->turbul*Tin+(texvec[0]+texvec[1]+texvec[2])*10.0); + } + else if(tex->stype==3) { + Tin= noisefunc(tex->noisesize, texvec[0], texvec[1], texvec[2]); + Tin= 0.5+ 0.5*sin(tex->turbul*Tin+(sqrt(texvec[0]*texvec[0]+texvec[1]*texvec[1]+texvec[2]*texvec[2]))*20.0); + } + + + BRICON; + if(tex->flag & TEX_COLORBAND) return do_colorband(tex->coba); + + return 0; +} + +/* ------------------------------------------------------------------------- */ + +int marble(Tex *tex, float *texvec) +{ + float n; + float (*turbfunc)(float, float, float, float, int); + + if(tex->noisetype==TEX_NOISESOFT) turbfunc= BLI_turbulence; + else turbfunc= BLI_turbulence1; + + n= 5.0*(texvec[0]+texvec[1]+texvec[2]); + + Tin = 0.5+0.5*sin(n+tex->turbul*turbfunc(tex->noisesize, texvec[0],texvec[1],texvec[2], tex->noisedepth)); + + switch (tex->stype) { + case 1: + Tin= sqrt(Tin); + break; + case 2: + Tin= sqrt(Tin); + Tin= sqrt(Tin); + break; + } + + BRICON; + if(tex->flag & TEX_COLORBAND) return do_colorband(tex->coba); + + return 0; +} + +/* ------------------------------------------------------------------------- */ + +int magic(Tex *tex, float *texvec) +{ + float x, y, z, turb=1.0; + int n; + + n= tex->noisedepth; + turb= tex->turbul/5.0; + + x= sin( ( texvec[0]+texvec[1]+texvec[2])*5.0 ); + y= cos( (-texvec[0]+texvec[1]-texvec[2])*5.0 ); + z= -cos( (-texvec[0]-texvec[1]+texvec[2])*5.0 ); + if(n>0) { + x*= turb; + y*= turb; + z*= turb; + y= -cos(x-y+z); + y*= turb; + if(n>1) { + x= cos(x-y-z); + x*= turb; + if(n>2) { + z= sin(-x-y-z); + z*= turb; + if(n>3) { + x= -cos(-x+y-z); + x*= turb; + if(n>4) { + y= -sin(-x+y+z); + y*= turb; + if(n>5) { + y= -cos(-x+y+z); + y*= turb; + if(n>6) { + x= cos(x+y+z); + x*= turb; + if(n>7) { + z= sin(x+y-z); + z*= turb; + if(n>8) { + x= -cos(-x-y+z); + x*= turb; + if(n>9) { + y= -sin(x-y+z); + y*= turb; + } + } + } + } + } + } + } + } + } + } + + if(turb!=0.0) { + turb*= 2.0; + x/= turb; + y/= turb; + z/= turb; + } + Tr= 0.5-x; + Tg= 0.5-y; + Tb= 0.5-z; + + BRICONRGB; + Ta= 1.0; + + return 1; +} + +/* ------------------------------------------------------------------------- */ + +int stucci(Tex *tex, float *texvec) +{ + float b2, vec[3]; + float ofs; + float (*noisefunc)(float, float, float, float); + + if(tex->nor == NULL) return 0; + + if(tex->noisetype==TEX_NOISESOFT) noisefunc= BLI_hnoise; + else noisefunc= BLI_hnoisep; + + ofs= tex->turbul/200.0; + + b2= noisefunc(tex->noisesize, texvec[0], texvec[1], texvec[2]); + if(tex->stype) ofs*=(b2*b2); + vec[0]= b2-noisefunc(tex->noisesize, texvec[0]+ofs, texvec[1], texvec[2]); + vec[1]= b2-noisefunc(tex->noisesize, texvec[0], texvec[1]+ofs, texvec[2]); + vec[2]= b2-noisefunc(tex->noisesize, texvec[0], texvec[1], texvec[2]+ofs); + + if(tex->stype==1) { + tex->nor[0]= vec[0]; + tex->nor[1]= vec[1]; + tex->nor[2]= vec[2]; + } + else { + tex->nor[0]= -vec[0]; + tex->nor[1]= -vec[1]; + tex->nor[2]= -vec[2]; + } + + return 2; +} + +/* ------------------------------------------------------------------------- */ + +int texnoise(Tex *tex) +{ + float div=3.0; + int val, ran, loop; + + ran= BLI_rand(); + val= (ran & 3); + + loop= tex->noisedepth; + while(loop--) { + ran= (ran>>2); + val*= (ran & 3); + div*= 3.0; + } + + Tin= ((float)val)/div;; + + BRICON; + if(tex->flag & TEX_COLORBAND) return do_colorband(tex->coba); + + return 0; +} + +/* ------------------------------------------------------------------------- */ + +int plugintex(Tex *tex, float *texvec, float *dxt, float *dyt) +{ + PluginTex *pit; + int rgbnor=0; + + Tin= 0.0; + + pit= tex->plugin; + if(pit && pit->doit) { + VECCOPY(pit->result+5, R.vn); + + if(R.osatex) rgbnor= ((TexDoit)pit->doit)(tex->stype, pit->data, texvec, dxt, dyt); + else rgbnor= ((TexDoit)pit->doit)(tex->stype, pit->data, texvec, 0, 0); + + Tin= pit->result[0]; + + if(rgbnor & TEX_NOR) { + if(tex->nor) { + VECCOPY(tex->nor, pit->result+5); + } + } + + if(rgbnor & TEX_RGB) { + Tr= pit->result[1]; + Tg= pit->result[2]; + Tb= pit->result[3]; + Ta= pit->result[4]; + + BRICONRGB; + } + + BRICON; + if(tex->flag & TEX_COLORBAND) rgbnor |= do_colorband(tex->coba); + } + + return rgbnor; +} + +/* *************** PROJEKTIES ******************* */ + +void tubemap(float x, float y, float z, float *adr1, float *adr2) +{ + float len; + + *adr2 = (z + 1.0) / 2.0; + + len= sqrt(x*x+y*y); + if(len>0) { + *adr1 = (1.0 - (atan2(x/len,y/len) / M_PI)) / 2.0; + } +} + +/* ------------------------------------------------------------------------- */ + +void spheremap(float x, float y, float z, float *adr1, float *adr2) +{ + float len; + + len= sqrt(x*x+y*y+z*z); + if(len>0.0) { + + if(x==0.0 && y==0.0) *adr1= 0.0; /* anders domain error */ + else *adr1 = (1.0 - atan2(x,y)/M_PI )/2.0; + + z/=len; + *adr2 = 1.0- saacos(z)/M_PI; + } +} + +/* ------------------------------------------------------------------------- */ + +static int cubemap_glob(MTex *mtex, float x, float y, float z, float *adr1, float *adr2) +{ + float x1, y1, z1, nor[3]; + int ret; + + VECCOPY(nor, R.vn); + MTC_Mat4Mul3Vecfl(R.viewinv, nor); + + x1= fabs(nor[0]); + y1= fabs(nor[1]); + z1= fabs(nor[2]); + + if(z1>=x1 && z1>=y1) { + *adr1 = (x + 1.0) / 2.0; + *adr2 = (y + 1.0) / 2.0; + ret= 0; + } + else if(y1>=x1 && y1>=z1) { + *adr1 = (x + 1.0) / 2.0; + *adr2 = (z + 1.0) / 2.0; + ret= 1; + } + else { + *adr1 = (y + 1.0) / 2.0; + *adr2 = (z + 1.0) / 2.0; + ret= 2; + } + return ret; +} + +/* ------------------------------------------------------------------------- */ + +static int cubemap(MTex *mtex, float x, float y, float z, float *adr1, float *adr2) +{ + int proj[4], ret= 0; + + if(R.vlr && R.vlr->mface) { + int index; + /* the mtex->proj{xyz} have type char. maybe this should be wider? */ + /* casting to int ensures that the index type is right. */ + index = (int) mtex->projx; + proj[index]= ME_PROJXY; + + index = (int) mtex->projy; + proj[index]= ME_PROJXZ; + + index = (int) mtex->projz; + proj[index]= ME_PROJYZ; + + if(R.vlr->mface->puno & proj[1]) { + *adr1 = (x + 1.0) / 2.0; + *adr2 = (y + 1.0) / 2.0; + } + else if(R.vlr->mface->puno & proj[2]) { + *adr1 = (x + 1.0) / 2.0; + *adr2 = (z + 1.0) / 2.0; + ret= 1; + } + else { + *adr1 = (y + 1.0) / 2.0; + *adr2 = (z + 1.0) / 2.0; + ret= 2; + } + } else + return cubemap_glob(mtex, x, y, z, adr1, adr2); + + return ret; +} + +/* ------------------------------------------------------------------------- */ + +static int cubemap_ob(MTex *mtex, float x, float y, float z, float *adr1, float *adr2) +{ + float x1, y1, z1, nor[3]; + int ret; + + VECCOPY(nor, R.vn); + if(mtex->object) MTC_Mat4Mul3Vecfl(mtex->object->imat, nor); + + x1= fabs(nor[0]); + y1= fabs(nor[1]); + z1= fabs(nor[2]); + + if(z1>=x1 && z1>=y1) { + *adr1 = (x + 1.0) / 2.0; + *adr2 = (y + 1.0) / 2.0; + ret= 0; + } + else if(y1>=x1 && y1>=z1) { + *adr1 = (x + 1.0) / 2.0; + *adr2 = (z + 1.0) / 2.0; + ret= 1; + } + else { + *adr1 = (y + 1.0) / 2.0; + *adr2 = (z + 1.0) / 2.0; + ret= 2; + } + return ret; +} + +/* ------------------------------------------------------------------------- */ + +void do_2d_mapping(MTex *mtex, float *t, float *dxt, float *dyt) +{ + Tex *tex; + float fx, fy, fac1, area[8]; + int ok, proj, areaflag= 0, wrap; + + wrap= mtex->mapping; + tex= mtex->tex; + + if(R.osa==0) { + + if(wrap==MTEX_FLAT) { + fx = (t[0] + 1.0) / 2.0; + fy = (t[1] + 1.0) / 2.0; + } + else if(wrap==MTEX_TUBE) tubemap(t[0], t[1], t[2], &fx, &fy); + else if(wrap==MTEX_SPHERE) spheremap(t[0], t[1], t[2], &fx, &fy); + else { + if(mtex->texco==TEXCO_OBJECT) cubemap_ob(mtex, t[0], t[1], t[2], &fx, &fy); + else if(mtex->texco==TEXCO_GLOB) cubemap_glob(mtex, t[0], t[1], t[2], &fx, &fy); + else cubemap(mtex, t[0], t[1], t[2], &fx, &fy); + } + + /* repeat */ + if(tex->xrepeat>1) { + fx *= tex->xrepeat; + if(fx>1.0) fx -= (int)(fx); + else if(fx<0.0) fx+= 1-(int)(fx); + } + if(tex->yrepeat>1) { + fy *= tex->yrepeat; + if(fy>1.0) fy -= (int)(fy); + else if(fy<0.0) fy+= 1-(int)(fy); + } + + /* crop */ + if(tex->cropxmin!=0.0 || tex->cropxmax!=1.0) { + fac1= tex->cropxmax - tex->cropxmin; + fx= tex->cropxmin+ fx*fac1; + } + if(tex->cropymin!=0.0 || tex->cropymax!=1.0) { + fac1= tex->cropymax - tex->cropymin; + fy= tex->cropymin+ fy*fac1; + } + + t[0]= fx; + t[1]= fy; + } + else { + + if(wrap==MTEX_FLAT) { + fx= (t[0] + 1.0) / 2.0; + fy= (t[1] + 1.0) / 2.0; + dxt[0]/= 2.0; + dxt[1]/= 2.0; + dyt[0]/= 2.0; + dyt[1]/= 2.0; + } + else if ELEM(wrap, MTEX_TUBE, MTEX_SPHERE) { + /* uitzondering: de naad achter (y<0.0) */ + ok= 1; + if(t[1]<=0.0) { + fx= t[0]+dxt[0]; + fy= t[0]+dyt[0]; + if(fx>=0.0 && fy>=0.0 && t[0]>=0.0); + else if(fx<=0.0 && fy<=0.0 && t[0]<=0.0); + else ok= 0; + } + if(ok) { + if(wrap==MTEX_TUBE) { + tubemap(t[0], t[1], t[2], area, area+1); + tubemap(t[0]+dxt[0], t[1]+dxt[1], t[2]+dxt[2], area+2, area+3); + tubemap(t[0]+dyt[0], t[1]+dyt[1], t[2]+dyt[2], area+4, area+5); + } + else { + spheremap(t[0], t[1], t[2],area,area+1); + spheremap(t[0]+dxt[0], t[1]+dxt[1], t[2]+dxt[2], area+2, area+3); + spheremap(t[0]+dyt[0], t[1]+dyt[1], t[2]+dyt[2], area+4, area+5); + } + areaflag= 1; + } + else { + if(wrap==MTEX_TUBE) tubemap(t[0], t[1], t[2], &fx, &fy); + else spheremap(t[0], t[1], t[2], &fx, &fy); + dxt[0]/= 2.0; + dxt[1]/= 2.0; + dyt[0]/= 2.0; + dyt[1]/= 2.0; + } + } + else { + + if(mtex->texco==TEXCO_OBJECT) proj = cubemap_ob(mtex, t[0], t[1], t[2], &fx, &fy); + else if (mtex->texco==TEXCO_GLOB) proj = cubemap_glob(mtex, t[0], t[1], t[2], &fx, &fy); + else proj = cubemap(mtex, t[0], t[1], t[2], &fx, &fy); + + if(proj==1) { + dxt[1]= dxt[2]; + dyt[1]= dyt[2]; + } + else if(proj==2) { + dxt[0]= dxt[1]; + dyt[0]= dyt[1]; + dxt[1]= dxt[2]; + dyt[1]= dyt[2]; + } + dxt[0]/= 2.0; + dxt[1]/= 2.0; + dyt[0]/= 2.0; + dyt[1]/= 2.0; + } + + /* als area dan dxt[] en dyt[] opnieuw berekenen */ + if(areaflag) { + fx= area[0]; + fy= area[1]; + dxt[0]= area[2]-fx; + dxt[1]= area[3]-fy; + dyt[0]= area[4]-fx; + dyt[1]= area[5]-fy; + } + + /* repeat */ + if(tex->xrepeat>1) { + fx *= tex->xrepeat; + dxt[0]*= tex->xrepeat; + dyt[0]*= tex->xrepeat; + if(fx>1.0) fx -= (int)(fx); + else if(fx<0.0) fx+= 1-(int)(fx); + } + if(tex->yrepeat>1) { + fy *= tex->yrepeat; + dxt[1]*= tex->yrepeat; + dyt[1]*= tex->yrepeat; + if(fy>1.0) fy -= (int)(fy); + else if(fy<0.0) fy+= 1-(int)(fy); + } + + /* crop */ + if(tex->cropxmin!=0.0 || tex->cropxmax!=1.0) { + fac1= tex->cropxmax - tex->cropxmin; + fx= tex->cropxmin+ fx*fac1; + dxt[0]*= fac1; + dyt[0]*= fac1; + } + if(tex->cropymin!=0.0 || tex->cropymax!=1.0) { + fac1= tex->cropymax - tex->cropymin; + fy= tex->cropymin+ fy*fac1; + dxt[1]*= fac1; + dyt[1]*= fac1; + } + + t[0]= fx; + t[1]= fy; + + } +} + + +/* ************************************** */ + +int multitex(Tex *tex, float *texvec, float *dxt, float *dyt) +{ + + + switch(tex->type) { + + case 0: + Tin= 0.0; + return 0; + case TEX_CLOUDS: + return clouds(tex, texvec); + case TEX_WOOD: + return wood(tex, texvec); + case TEX_MARBLE: + return marble(tex, texvec); + case TEX_MAGIC: + return magic(tex, texvec); + case TEX_BLEND: + return blend(tex, texvec); + case TEX_STUCCI: + Tin= 0.0; + return stucci(tex, texvec); + case TEX_NOISE: + return texnoise(tex); + case TEX_IMAGE: + if(R.osatex) return imagewraposa(tex, texvec, dxt, dyt); + else return imagewrap(tex, texvec); + break; + case TEX_PLUGIN: + return plugintex(tex, texvec, dxt, dyt); + break; + case TEX_ENVMAP: + return RE_envmaptex(tex, texvec, dxt, dyt); + break; + } + return 0; +} + +/* ------------------------------------------------------------------------- */ + +void do_material_tex() +{ + Object *ob; + Material *mat_col, *mat_colspec, *mat_colmir, *mat_ref; + Material *mat_spec, *mat_har, *mat_emit, *mat_alpha; + MTex *mtex; + Tex *tex; + float *co = NULL, *dx = NULL, *dy = NULL, fact, + facm, factt, facmm, facmul = 0.0, stencilTin=1.0; + float texvec[3], dxt[3], dyt[3], tempvec[3], norvec[3]; + int tex_nr, rgbnor= 0; + + /* hier flag testen of er wel tex is */ + + mat_col=mat_colspec=mat_colmir=mat_ref=mat_spec=mat_har=mat_emit=mat_alpha= R.mat; + + tex_nr= 0; + if(R.mat->septex) tex_nr= R.mat->texact; + + for(; tex_nr<8; tex_nr++) { + if(R.mat->mtex[tex_nr]) { + mtex= R.mat->mtex[tex_nr]; + + tex= mtex->tex; + if(tex==0) continue; + + /* welke coords */ + if(mtex->texco==TEXCO_ORCO) { + co= R.lo; dx= O.dxlo; dy= O.dylo; + } + else if(mtex->texco==TEXCO_STICKY) { + co= R.sticky; dx= O.dxsticky; dy= O.dysticky; + } + else if(mtex->texco==TEXCO_OBJECT) { + ob= mtex->object; + if(ob) { + co= tempvec; + dx= dxt; + dy= dyt; + VECCOPY(tempvec, R.co); + MTC_Mat4MulVecfl(ob->imat, tempvec); + if(R.osatex) { + VECCOPY(dxt, O.dxco); + VECCOPY(dyt, O.dyco); + MTC_Mat4Mul3Vecfl(ob->imat, dxt); + MTC_Mat4Mul3Vecfl(ob->imat, dyt); + } + } + else { + /* als object niet bestaat geen orco's gebruiken (zijn niet geinitialiseerd */ + co= R.co; + dx= O.dxco; dy= O.dyco; + } + } + else if(mtex->texco==TEXCO_REFL) { + co= R.ref; dx= O.dxref; dy= O.dyref; + } + else if(mtex->texco==TEXCO_NORM) { + co= R.orn; dx= O.dxno; dy= O.dyno; + } + else if(mtex->texco==TEXCO_GLOB) { + co= R.gl; dx= O.dxco; dy= O.dyco; + } + else if(mtex->texco==TEXCO_UV) { + co= R.uv; dx= O.dxuv; dy= O.dyuv; + } + else if(mtex->texco==TEXCO_WINDOW) { + co= R.winco; dx= O.dxwin; dy= O.dywin; + } + + /* de pointer defines if bumping happens */ + if(mtex->mapto & MAP_NORM) { + tex->nor= norvec; + norvec[0]= norvec[1]= norvec[2]= 0.0; + } + else tex->nor= 0; + + if(tex->type==TEX_IMAGE) { + + /* nieuw: eerst coords verwisselen, dan map, dan trans/scale */ + + /* placement */ + if(mtex->projx) texvec[0]= co[mtex->projx-1]; + else texvec[0]= 0.0; + if(mtex->projy) texvec[1]= co[mtex->projy-1]; + else texvec[1]= 0.0; + if(mtex->projz) texvec[2]= co[mtex->projz-1]; + else texvec[2]= 0.0; + + if(R.osatex) { + + if(mtex->projx) { + dxt[0]= dx[mtex->projx-1]; + dyt[0]= dy[mtex->projx-1]; + } + else dxt[0]= 0.0; + if(mtex->projy) { + dxt[1]= dx[mtex->projy-1]; + dyt[1]= dy[mtex->projy-1]; + } + else dxt[1]= 0.0; + if(mtex->projx) { + dxt[2]= dx[mtex->projz-1]; + dyt[2]= dy[mtex->projz-1]; + } + else dxt[2]= 0.0; + } + + do_2d_mapping(mtex, texvec, dxt, dyt); + + /* translate en scale */ + texvec[0]= mtex->size[0]*(texvec[0]-0.5) +mtex->ofs[0]+0.5; + texvec[1]= mtex->size[1]*(texvec[1]-0.5) +mtex->ofs[1]+0.5; + if(R.osatex) { + dxt[0]= mtex->size[0]*dxt[0]; + dxt[1]= mtex->size[1]*dxt[1]; + dyt[0]= mtex->size[0]*dyt[0]; + dyt[1]= mtex->size[1]*dyt[1]; + } + } + else { + + /* placement */ + if(mtex->projx) texvec[0]= mtex->size[0]*(co[mtex->projx-1]+mtex->ofs[0]); + else texvec[0]= mtex->size[0]*(mtex->ofs[0]); + + if(mtex->projy) texvec[1]= mtex->size[1]*(co[mtex->projy-1]+mtex->ofs[1]); + else texvec[1]= mtex->size[1]*(mtex->ofs[1]); + + if(mtex->projz) texvec[2]= mtex->size[2]*(co[mtex->projz-1]+mtex->ofs[2]); + else texvec[2]= mtex->size[2]*(mtex->ofs[2]); + + if(R.osatex) { + if(mtex->projx) { + dxt[0]= mtex->size[0]*dx[mtex->projx-1]; + dyt[0]= mtex->size[0]*dy[mtex->projx-1]; + } + else dxt[0]= 0.0; + if(mtex->projy) { + dxt[1]= mtex->size[1]*dx[mtex->projy-1]; + dyt[1]= mtex->size[1]*dy[mtex->projy-1]; + } + else dxt[1]= 0.0; + if(mtex->projx) { + dxt[2]= mtex->size[2]*dx[mtex->projz-1]; + dyt[2]= mtex->size[2]*dy[mtex->projz-1]; + } + else dxt[2]= 0.0; + } + } + + rgbnor= multitex(tex, texvec, dxt, dyt); + + /* texture output */ + + if( (rgbnor & TEX_RGB) && (mtex->texflag & MTEX_RGBTOINT)) { + Tin= (0.35*Tr+0.45*Tg+0.2*Tb); + rgbnor-= 1; + } + if(mtex->texflag & MTEX_NEGATIVE) { + if(rgbnor & TEX_RGB) { + Tr= 1.0-Tr; + Tg= 1.0-Tg; + Tb= 1.0-Tb; + } + Tin= 1.0-Tin; + } + if(mtex->texflag & MTEX_STENCIL) { + if(rgbnor & TEX_RGB) { + fact= Ta; + Ta*= stencilTin; + stencilTin*= fact; + } + else { + fact= Tin; + Tin*= stencilTin; + stencilTin*= fact; + } + } + else { + if(rgbnor & TEX_RGB) Ta*= stencilTin; + else Tin*= stencilTin; + } + + if(tex->nor && (rgbnor & TEX_NOR)==0) { + /* make our own normal */ + if(rgbnor & TEX_RGB) { + tex->nor[0]= Tr; + tex->nor[1]= Tg; + tex->nor[2]= Tb; + } + else { + float co= 0.5*cos(Tin-0.5); + float si= 0.5*sin(Tin-0.5); + float f1, f2; + + f1= R.vn[0]; + f2= R.vn[1]; + tex->nor[0]= f1*co+f2*si; + tex->nor[1]= f2*co-f1*si; + f1= R.vn[1]; + f2= R.vn[2]; + tex->nor[1]= f1*co+f2*si; + tex->nor[2]= f2*co-f1*si; + } + } + + + /* mapping */ + if(mtex->mapto & (MAP_COL+MAP_COLSPEC+MAP_COLMIR)) { + + if((rgbnor & TEX_RGB)==0) { + Tr= mtex->r; + Tg= mtex->g; + Tb= mtex->b; + } + else if(mtex->mapto & MAP_ALPHA) { + if(mtex->texflag & MTEX_ALPHAMIX) Tin= Ta; + else Tin= stencilTin; + } + else Tin= Ta; + + fact= Tin*mtex->colfac; + facm= 1.0-fact; + if(mtex->blendtype==MTEX_MUL) facm= 1.0-mtex->colfac; + if(mtex->blendtype==MTEX_SUB) fact= -fact; + + if(mtex->mapto & MAP_COL) { + if(mtex->blendtype==MTEX_BLEND) { + R.matren->r= (fact*Tr + facm*mat_col->r); + R.matren->g= (fact*Tg + facm*mat_col->g); + R.matren->b= (fact*Tb + facm*mat_col->b); + } + else if(mtex->blendtype==MTEX_MUL) { + R.matren->r= (facm+fact*Tr)*mat_col->r; + R.matren->g= (facm+fact*Tg)*mat_col->g; + R.matren->b= (facm+fact*Tb)*mat_col->b; + } + else { + R.matren->r= (fact*Tr + mat_col->r); + R.matren->g= (fact*Tg + mat_col->g); + R.matren->b= (fact*Tb + mat_col->b); + } + mat_col= R.matren; + } + if(mtex->mapto & MAP_COLSPEC) { + if(mtex->blendtype==MTEX_BLEND) { + R.matren->specr= (fact*Tr + facm*mat_colspec->specr); + R.matren->specg= (fact*Tg + facm*mat_colspec->specg); + R.matren->specb= (fact*Tb + facm*mat_colspec->specb); + } + else if(mtex->blendtype==MTEX_MUL) { + R.matren->specr= (facm+fact*Tr)*mat_colspec->specr; + R.matren->specg= (facm+fact*Tg)*mat_colspec->specg; + R.matren->specb= (facm+fact*Tb)*mat_colspec->specb; + } + else { + R.matren->specr= (fact*Tr + mat_colspec->specr); + R.matren->specg= (fact*Tg + mat_colspec->specg); + R.matren->specb= (fact*Tb + mat_colspec->specb); + } + mat_colspec= R.matren; + } + if(mtex->mapto & MAP_COLMIR) { + if(mtex->blendtype==MTEX_BLEND) { + R.refcol[0]= fact + facm*R.refcol[0]; + + R.refcol[1]= fact*Tr + facm*R.refcol[1]; + R.refcol[2]= fact*Tg + facm*R.refcol[2]; + R.refcol[3]= fact*Tb + facm*R.refcol[3]; + } + else if(mtex->blendtype==MTEX_MUL) { + R.matren->mirr= (facm+fact*Tr)*mat_colmir->mirr; + R.matren->mirg= (facm+fact*Tg)*mat_colmir->mirg; + R.matren->mirb= (facm+fact*Tb)*mat_colmir->mirb; + } + else { + R.matren->mirr= (fact*Tr + mat_colmir->mirr); + R.matren->mirg= (fact*Tg + mat_colmir->mirg); + R.matren->mirb= (fact*Tb + mat_colmir->mirb); + } + mat_colmir= R.matren; + } + } + if( (mtex->mapto & MAP_NORM) ) { + if(tex->nor) { + + if(mtex->maptoneg & MAP_NORM) tex->norfac= -mtex->norfac; + else tex->norfac= mtex->norfac; + + R.vn[0]+= tex->norfac*tex->nor[0]; + R.vn[1]+= tex->norfac*tex->nor[1]; + R.vn[2]+= tex->norfac*tex->nor[2]; + + Normalise(R.vn); + + /* hierdoor wordt de bump aan de volgende texture doorgegeven */ + R.orn[0]= R.vn[0]; + R.orn[1]= -R.vn[1]; + R.orn[2]= R.vn[2]; + + /* reflection vector */ + RE_calc_R_ref(); + } + } + + if(mtex->mapto & MAP_VARS) { + if(rgbnor & TEX_RGB) { + if(Talpha) Tin= Ta; + else Tin= (0.35*Tr+0.45*Tg+0.2*Tb); + } + + fact= Tin*mtex->varfac; + facm= 1.0-fact; + if(mtex->blendtype==MTEX_MUL) facmul= 1.0-mtex->varfac; + if(mtex->blendtype==MTEX_SUB) fact= -fact; + + if(mtex->mapto & MAP_REF) { + if(mtex->maptoneg & MAP_REF) {factt= facm; facmm= fact;} + else {factt= fact; facmm= facm;} + + if(mtex->blendtype==MTEX_BLEND) + R.matren->ref= factt*mtex->def_var+ facmm*mat_ref->ref; + else if(mtex->blendtype==MTEX_MUL) + R.matren->ref= (facmul+factt)*mat_ref->ref; + else { + R.matren->ref= factt+mat_ref->ref; + if(R.matren->ref<0.0) R.matren->ref= 0.0; + } + mat_ref= R.matren; + } + if(mtex->mapto & MAP_SPEC) { + if(mtex->maptoneg & MAP_SPEC) {factt= facm; facmm= fact;} + else {factt= fact; facmm= facm;} + + if(mtex->blendtype==MTEX_BLEND) + R.matren->spec= factt*mtex->def_var+ facmm*mat_spec->spec; + else if(mtex->blendtype==MTEX_MUL) + R.matren->spec= (facmul+factt)*mat_spec->spec; + else { + R.matren->spec= factt+mat_spec->spec; + if(R.matren->spec<0.0) R.matren->spec= 0.0; + } + mat_spec= R.matren; + } + if(mtex->mapto & MAP_EMIT) { + if(mtex->maptoneg & MAP_EMIT) {factt= facm; facmm= fact;} + else {factt= fact; facmm= facm;} + + if(mtex->blendtype==MTEX_BLEND) + R.matren->emit= factt*mtex->def_var+ facmm*mat_emit->emit; + else if(mtex->blendtype==MTEX_MUL) + R.matren->emit= (facmul+factt)*mat_emit->emit; + else { + R.matren->emit= factt+mat_emit->emit; + if(R.matren->emit<0.0) R.matren->emit= 0.0; + } + mat_emit= R.matren; + } + if(mtex->mapto & MAP_ALPHA) { + if(mtex->maptoneg & MAP_ALPHA) {factt= facm; facmm= fact;} + else {factt= fact; facmm= facm;} + + if(mtex->blendtype==MTEX_BLEND) + R.matren->alpha= factt*mtex->def_var+ facmm*mat_alpha->alpha; + else if(mtex->blendtype==MTEX_MUL) + R.matren->alpha= (facmul+factt)*mat_alpha->alpha; + else { + R.matren->alpha= factt+mat_alpha->alpha; + if(R.matren->alpha<0.0) R.matren->alpha= 0.0; + else if(R.matren->alpha>1.0) R.matren->alpha= 1.0; + } + mat_alpha= R.matren; + } + if(mtex->mapto & MAP_HAR) { + if(mtex->maptoneg & MAP_HAR) {factt= facm; facmm= fact;} + else {factt= fact; facmm= facm;} + + if(mtex->blendtype==MTEX_BLEND) { + R.matren->har= 128.0*factt*mtex->def_var+ facmm*mat_har->har; + } else if(mtex->blendtype==MTEX_MUL) { + R.matren->har= (facmul+factt)*mat_har->har; + } else { + R.matren->har= 128.0*factt+mat_har->har; + if(R.matren->har<1) R.matren->har= 1; + } + mat_har= R.matren; + } + } + } + + if(R.mat->septex) break; + } +} + +/* ------------------------------------------------------------------------- */ + +void do_halo_tex(HaloRen *har, float xn, float yn, float *colf) +{ + MTex *mtex; + float texvec[3], dxt[3], dyt[3], fact, facm, dx; + int rgb; + + mtex= har->mat->mtex[0]; + if(mtex->tex==0) return; + /* no normal mapping */ + mtex->tex->nor= 0; + + texvec[0]= xn/har->rad; + texvec[1]= yn/har->rad; + texvec[2]= 0.0; + + R.osatex= (har->mat->texco & TEXCO_OSA); + + /* placement */ + if(mtex->projx) texvec[0]= mtex->size[0]*(texvec[mtex->projx-1]+mtex->ofs[0]); + else texvec[0]= mtex->size[0]*(mtex->ofs[0]); + + if(mtex->projy) texvec[1]= mtex->size[1]*(texvec[mtex->projy-1]+mtex->ofs[1]); + else texvec[1]= mtex->size[1]*(mtex->ofs[1]); + + if(mtex->projz) texvec[2]= mtex->size[2]*(texvec[mtex->projz-1]+mtex->ofs[2]); + else texvec[2]= mtex->size[2]*(mtex->ofs[2]); + + if(R.osatex) { + + dx= 1.0/har->rad; + + if(mtex->projx) { + dxt[0]= mtex->size[0]*dx; + dyt[0]= mtex->size[0]*dx; + } + else dxt[0]= 0.0; + if(mtex->projy) { + dxt[1]= mtex->size[1]*dx; + dyt[1]= mtex->size[1]*dx; + } + else dxt[1]= 0.0; + if(mtex->projz) { + dxt[2]= 0.0; + dyt[2]= 0.0; + } + else dxt[2]= 0.0; + + } + + + if(mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, dxt, dyt); + + rgb= multitex(mtex->tex, texvec, dxt, dyt); + + /* texture uitgang */ + if(rgb && (mtex->texflag & MTEX_RGBTOINT)) { + Tin= (0.35*Tr+0.45*Tg+0.2*Tb); + rgb= 0; + } + if(mtex->texflag & MTEX_NEGATIVE) { + if(rgb) { + Tr= 1.0-Tr; + Tg= 1.0-Tg; + Tb= 1.0-Tb; + } + else Tin= 1.0-Tin; + } + + /* mapping */ + if(mtex->mapto & MAP_COL) { + + if(rgb==0) { + Tr= mtex->r; + Tg= mtex->g; + Tb= mtex->b; + } + else if(mtex->mapto & MAP_ALPHA) { + if(mtex->texflag & MTEX_ALPHAMIX) Tin= Ta; + else Tin= 1.0; + } + else Tin= Ta; + + fact= Tin*mtex->colfac; + facm= 1.0-fact; + + if(mtex->blendtype==MTEX_MUL) { + facm= 1.0-mtex->colfac; + } + else fact*= 256; + + if(mtex->blendtype==MTEX_SUB) fact= -fact; + + if(mtex->blendtype==MTEX_BLEND) { + colf[0]= (fact*Tr + facm*har->r); + colf[1]= (fact*Tg + facm*har->g); + colf[2]= (fact*Tb + facm*har->b); + } + else if(mtex->blendtype==MTEX_MUL) { + colf[0]= (facm+fact*Tr)*har->r; + colf[1]= (facm+fact*Tg)*har->g; + colf[2]= (facm+fact*Tb)*har->b; + } + else { + colf[0]= (fact*Tr + har->r); + colf[1]= (fact*Tg + har->g); + colf[2]= (fact*Tb + har->b); + + CLAMP(colf[0], 0.0, 1.0); + CLAMP(colf[1], 0.0, 1.0); + CLAMP(colf[2], 0.0, 1.0); + } + } + if(mtex->mapto & MAP_ALPHA) { + if(rgb) { + if(Talpha) Tin= Ta; + else Tin= (0.35*Tr+0.45*Tg+0.2*Tb); + } + + colf[3]*= Tin; + } + + R.osatex= 0; +} + +/* ------------------------------------------------------------------------- */ + +void do_sky_tex() +{ + World *wrld_hor, *wrld_zen; + MTex *mtex; + float *co, fact, facm, factt, facmm, facmul = 0.0, stencilTin=1.0; + float tempvec[3], texvec[3], dxt[3], dyt[3]; + int tex_nr, rgb= 0, ok; + + + /* hier flag testen of er wel tex is */ + + wrld_hor= wrld_zen= G.scene->world; + + /* The 6 here is rather arbitrary, it seems. */ + for(tex_nr=0; tex_nr<6; tex_nr++) { + if(R.wrld.mtex[tex_nr]) { + mtex= R.wrld.mtex[tex_nr]; + + if(mtex->tex==0) continue; + /* if(mtex->mapto==0) continue; */ + + /* welke coords */ + co= R.lo; + + /* Grab the mapping settings for this texture */ + if(mtex->texco==TEXCO_OBJECT) { + Object *ob= mtex->object; + if(ob) { + VECCOPY(tempvec, R.lo); + MTC_Mat4MulVecfl(ob->imat, tempvec); + co= tempvec; + } + } + + /* placement */ + if(mtex->projx) texvec[0]= mtex->size[0]*(co[mtex->projx-1]+mtex->ofs[0]); + else texvec[0]= mtex->size[0]*(mtex->ofs[0]); + + if(mtex->projy) texvec[1]= mtex->size[1]*(co[mtex->projy-1]+mtex->ofs[1]); + else texvec[1]= mtex->size[1]*(mtex->ofs[1]); + + if(mtex->projz) texvec[2]= mtex->size[2]*(co[mtex->projz-1]+mtex->ofs[2]); + else texvec[2]= mtex->size[2]*(mtex->ofs[2]); + + /* texture */ + if(mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, dxt, dyt); + + rgb= multitex(mtex->tex, texvec, dxt, dyt); + + /* texture uitgang */ + if(rgb && (mtex->texflag & MTEX_RGBTOINT)) { + Tin= (0.35*Tr+0.45*Tg+0.2*Tb); + rgb= 0; + } + if(mtex->texflag & MTEX_NEGATIVE) { + if(rgb) { + Tr= 1.0-Tr; + Tg= 1.0-Tg; + Tb= 1.0-Tb; + } + else Tin= 1.0-Tin; + } + if(mtex->texflag & MTEX_STENCIL) { + if(rgb) { + + } + else { + fact= Tin; + Tin*= stencilTin; + stencilTin*= fact; + } + } + else { + if(rgb) ; + else Tin*= stencilTin; + } + + /* colour mapping */ + if(mtex->mapto & (WOMAP_HORIZ+WOMAP_ZENUP+WOMAP_ZENDOWN)) { + + if(rgb==0) { + Tr= mtex->r; + Tg= mtex->g; + Tb= mtex->b; + } + else Tin= 1.0; + + fact= Tin*mtex->colfac; + facm= 1.0-fact; + if(mtex->blendtype==MTEX_MUL) facm= 1.0-mtex->colfac; + if(mtex->blendtype==MTEX_SUB) fact= -fact; + + if(mtex->mapto & WOMAP_HORIZ) { + if(mtex->blendtype==MTEX_BLEND) { + R.wrld.horr= (fact*Tr + facm*wrld_hor->horr); + R.wrld.horg= (fact*Tg + facm*wrld_hor->horg); + R.wrld.horb= (fact*Tb + facm*wrld_hor->horb); + } + else if(mtex->blendtype==MTEX_MUL) { + R.wrld.horr= (facm+fact*Tr)*wrld_hor->horr; + R.wrld.horg= (facm+fact*Tg)*wrld_hor->horg; + R.wrld.horb= (facm+fact*Tb)*wrld_hor->horb; + } + else { + R.wrld.horr= (fact*Tr + wrld_hor->horr); + R.wrld.horg= (fact*Tg + wrld_hor->horg); + R.wrld.horb= (fact*Tb + wrld_hor->horb); + } + wrld_hor= &R.wrld; + } + if(mtex->mapto & (WOMAP_ZENUP+WOMAP_ZENDOWN)) { + ok= 0; + if(R.wrld.skytype & WO_SKYREAL) { + if((R.wrld.skytype & WO_ZENUP)) { + if(mtex->mapto & WOMAP_ZENUP) ok= 1; + } + else if(mtex->mapto & WOMAP_ZENDOWN) ok= 1; + } + else ok= 1; + + if(ok) { + + if(mtex->blendtype==MTEX_BLEND) { + R.wrld.zenr= (fact*Tr + facm*wrld_zen->zenr); + R.wrld.zeng= (fact*Tg + facm*wrld_zen->zeng); + R.wrld.zenb= (fact*Tb + facm*wrld_zen->zenb); + } + else if(mtex->blendtype==MTEX_MUL) { + R.wrld.zenr= (facm+fact*Tr)*wrld_zen->zenr; + R.wrld.zeng= (facm+fact*Tg)*wrld_zen->zeng; + R.wrld.zenb= (facm+fact*Tb)*wrld_zen->zenb; + } + else { + R.wrld.zenr= (fact*Tr + wrld_zen->zenr); + R.wrld.zeng= (fact*Tg + wrld_zen->zeng); + R.wrld.zenb= (fact*Tb + wrld_zen->zenb); + } + wrld_zen= &R.wrld; + } + else { + /* anders blijft zenRGB hangen */ + R.wrld.zenr= wrld_zen->zenr; + R.wrld.zeng= wrld_zen->zeng; + R.wrld.zenb= wrld_zen->zenb; + } + } + } + if(mtex->mapto & WOMAP_BLEND) { + if(rgb) Tin= (0.35*Tr+0.45*Tg+0.2*Tb); + + fact= Tin*mtex->varfac; + facm= 1.0-fact; + if(mtex->blendtype==MTEX_MUL) facmul= 1.0-mtex->varfac; + if(mtex->blendtype==MTEX_SUB) fact= -fact; + + factt= fact; facmm= facm; + + if(mtex->blendtype==MTEX_BLEND) + R.inprz= factt*mtex->def_var+ facmm*R.inprz; + else if(mtex->blendtype==MTEX_MUL) + R.inprz= (facmul+factt)*R.inprz; + else { + R.inprz= factt+R.inprz; + } + } + } + } +} + +/* ------------------------------------------------------------------------- */ +/* explicit lampren stuff should be factored out! or rather, the + texturing stuff might need to go...*/ +void do_lamp_tex(LampRen *la, float *lavec) +{ + Object *ob; + LampRen *la_col; + MTex *mtex; + Tex *tex; + float *co = NULL, *dx = NULL, *dy = NULL, fact, facm, stencilTin=1.0; + float texvec[3], dxt[3], dyt[3], tempvec[3]; + int tex_nr, rgb= 0; + + /* hier flag testen of er wel tex is */ + + la_col= la->org; + + tex_nr= 0; + + for(; tex_nr<6; tex_nr++) { + + if(la->mtex[tex_nr]) { + mtex= la->mtex[tex_nr]; + + tex= mtex->tex; + if(tex==0) continue; + + /* welke coords */ + if(mtex->texco==TEXCO_OBJECT) { + ob= mtex->object; + if(ob) { + co= tempvec; + dx= dxt; + dy= dyt; + VECCOPY(tempvec, R.co); + MTC_Mat4MulVecfl(ob->imat, tempvec); + if(R.osatex) { + VECCOPY(dxt, O.dxco); + VECCOPY(dyt, O.dyco); + MTC_Mat4Mul3Vecfl(ob->imat, dxt); + MTC_Mat4Mul3Vecfl(ob->imat, dyt); + } + } + else { + co= R.co; + dx= O.dxco; dy= O.dyco; + } + } + else if(mtex->texco==TEXCO_GLOB) { + co= R.gl; dx= O.dxco; dy= O.dyco; + VECCOPY(R.gl, R.co); + MTC_Mat4MulVecfl(R.viewinv, R.gl); + } + else if(mtex->texco==TEXCO_VIEW) { + + VECCOPY(tempvec, lavec); + MTC_Mat3MulVecfl(la->imat, tempvec); + + tempvec[0]*= la->spottexfac; + tempvec[1]*= la->spottexfac; + co= tempvec; + + dx= dxt; dy= dyt; + if(R.osatex) { + VECCOPY(dxt, O.dxlv); + VECCOPY(dyt, O.dylv); + /* need some matrix conversion here? la->imat is a [3][3] matrix!!! **/ + MTC_Mat3MulVecfl(la->imat, dxt); + MTC_Mat3MulVecfl(la->imat, dyt); + + VecMulf(dxt, la->spottexfac); + VecMulf(dyt, la->spottexfac); + } + } + + + /* placement */ + if(mtex->projx) texvec[0]= mtex->size[0]*(co[mtex->projx-1]+mtex->ofs[0]); + else texvec[0]= mtex->size[0]*(mtex->ofs[0]); + + if(mtex->projy) texvec[1]= mtex->size[1]*(co[mtex->projy-1]+mtex->ofs[1]); + else texvec[1]= mtex->size[1]*(mtex->ofs[1]); + + if(mtex->projz) texvec[2]= mtex->size[2]*(co[mtex->projz-1]+mtex->ofs[2]); + else texvec[2]= mtex->size[2]*(mtex->ofs[2]); + + if(R.osatex) { + if(mtex->projx) { + dxt[0]= mtex->size[0]*dx[mtex->projx-1]; + dyt[0]= mtex->size[0]*dy[mtex->projx-1]; + } + else dxt[0]= 0.0; + if(mtex->projy) { + dxt[1]= mtex->size[1]*dx[mtex->projy-1]; + dyt[1]= mtex->size[1]*dy[mtex->projy-1]; + } + else dxt[1]= 0.0; + if(mtex->projx) { + dxt[2]= mtex->size[2]*dx[mtex->projz-1]; + dyt[2]= mtex->size[2]*dy[mtex->projz-1]; + } + else dxt[2]= 0.0; + } + + /* texture */ + if(tex->type==TEX_IMAGE) { + do_2d_mapping(mtex, texvec, dxt, dyt); + + if(mtex->mapto & MAP_NORM) { + /* de pointer bepaalt of er gebumpt wordt */ + tex->nor= R.vn; + if(mtex->maptoneg & MAP_NORM) tex->norfac= -mtex->norfac; + else tex->norfac= mtex->norfac; + } + else tex->nor= 0; + } + + rgb= multitex(tex, texvec, dxt, dyt); + + + + /* texture uitgang */ + if(rgb && (mtex->texflag & MTEX_RGBTOINT)) { + Tin= (0.35*Tr+0.45*Tg+0.2*Tb); + rgb= 0; + } + if(mtex->texflag & MTEX_NEGATIVE) { + if(rgb) { + Tr= 1.0-Tr; + Tg= 1.0-Tg; + Tb= 1.0-Tb; + } + else Tin= 1.0-Tin; + } + if(mtex->texflag & MTEX_STENCIL) { + if(rgb) { + fact= Ta; + Ta*= stencilTin; + stencilTin*= fact; + } + else { + fact= Tin; + Tin*= stencilTin; + stencilTin*= fact; + } + } + else { + if(rgb) Ta*= stencilTin; + else Tin*= stencilTin; + } + + /* mapping */ + if(mtex->mapto & LAMAP_COL) { + + if(rgb==0) { + Tr= mtex->r; + Tg= mtex->g; + Tb= mtex->b; + } + else if(mtex->mapto & MAP_ALPHA) { + if(mtex->texflag & MTEX_ALPHAMIX) Tin= Ta; + else Tin= stencilTin; + } + else Tin= Ta; + + Tr*= la->energy; + Tg*= la->energy; + Tb*= la->energy; + + fact= Tin*mtex->colfac; + facm= 1.0-fact; + if(mtex->blendtype==MTEX_MUL) facm= 1.0-mtex->colfac; + if(mtex->blendtype==MTEX_SUB) fact= -fact; + + if(mtex->blendtype==MTEX_BLEND) { + la->r= (fact*Tr + facm*la_col->r); + la->g= (fact*Tg + facm*la_col->g); + la->b= (fact*Tb + facm*la_col->b); + } + else if(mtex->blendtype==MTEX_MUL) { + la->r= (facm+fact*Tr)*la_col->r; + la->g= (facm+fact*Tg)*la_col->g; + la->b= (facm+fact*Tb)*la_col->b; + } + else { + la->r= (fact*Tr + la_col->r); + la->g= (fact*Tg + la_col->g); + la->b= (fact*Tb + la_col->b); + } + la_col= la; /* Is it just me or is this a useless statement? */ + } + + } + } +} + +/* ------------------------------------------------------------------------- */ + +void externtex(MTex *mtex, float *vec) +{ + Tex *tex; + float dxt[3], dyt[3], texvec[3]; + int rgb; + + tex= mtex->tex; + if(tex==0) return; + + R.osatex= 0; + R.vlr= 0; + + /* placement */ + if(mtex->projx) texvec[0]= mtex->size[0]*(vec[mtex->projx-1]+mtex->ofs[0]); + else texvec[0]= mtex->size[0]*(mtex->ofs[0]); + + if(mtex->projy) texvec[1]= mtex->size[1]*(vec[mtex->projy-1]+mtex->ofs[1]); + else texvec[1]= mtex->size[1]*(mtex->ofs[1]); + + if(mtex->projz) texvec[2]= mtex->size[2]*(vec[mtex->projz-1]+mtex->ofs[2]); + else texvec[2]= mtex->size[2]*(mtex->ofs[2]); + + /* texture */ + if(tex->type==TEX_IMAGE) { + do_2d_mapping(mtex, texvec, dxt, dyt); + + if(mtex->mapto & MAP_NORM) { + /* de pointer bepaalt of er gebumpt wordt */ + tex->nor= R.vn; + if(mtex->maptoneg & MAP_NORM) tex->norfac= -mtex->norfac; + else tex->norfac= mtex->norfac; + } + else tex->nor= 0; + } + + rgb= multitex(tex, texvec, dxt, dyt); + if(rgb) { + Tin= (0.35*Tr+0.45*Tg+0.2*Tb); + } + else { + Tr= mtex->r; + Tg= mtex->g; + Tb= mtex->b; + } +} + +/* ------------------------------------------------------------------------- */ + +void externtexcol(MTex *mtex, float *orco, char *col) +{ + int temp; + float b1; + + if(mtex->tex==0) return; + + externtex(mtex, orco); + + b1= 1.0-Tin; + + temp= 255*(Tin*Tr)+b1*col[0]; + if(temp>255) col[0]= 255; else col[0]= temp; + temp= 255*(Tin*Tg)+b1*col[1]; + if(temp>255) col[1]= 255; else col[1]= temp; + temp= 255*(Tin*Tb)+b1*col[2]; + if(temp>255) col[2]= 255; else col[2]= temp; + +} + +/* ------------------------------------------------------------------------- */ + +void render_realtime_texture() +{ + static Tex tex; + static int firsttime= 1; + float texvec[2], dx[2], dy[2]; + + if(firsttime) { + default_tex(&tex); + tex.type= TEX_IMAGE; + firsttime= 0; + } + + tex.ima = R.vlr->tface->tpage; + if(tex.ima) { + + texvec[0]= 0.5+0.5*R.uv[0]; + texvec[1]= 0.5+0.5*R.uv[1]; + if(R.osatex) { + dx[0]= 0.5*O.dxuv[0]; + dx[1]= 0.5*O.dxuv[1]; + dy[0]= 0.5*O.dyuv[0]; + dy[1]= 0.5*O.dyuv[1]; + } + + if(R.osatex) imagewraposa(&tex, texvec, dx, dy); + else imagewrap(&tex, texvec); + + R.vcol[0]*= Tr; + R.vcol[1]*= Tg; + R.vcol[2]*= Tb; + } + + +} + +/* eof */ diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c new file mode 100644 index 00000000000..d0f3ba4cb1a --- /dev/null +++ b/source/blender/blenkernel/intern/world.c @@ -0,0 +1,201 @@ + +/* world.c MIX MODEL + * + * april 95 + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + */ + +#include <string.h> +#include <math.h> +#include "MEM_guardedalloc.h" + +#include "DNA_world_types.h" +#include "DNA_texture_types.h" +#include "DNA_scriptlink_types.h" +#include "DNA_scene_types.h" +#include "DNA_object_types.h" +#include "DNA_camera_types.h" + + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" + +#include "BKE_bad_level_calls.h" +#include "BKE_utildefines.h" + +#include "BKE_library.h" +#include "BKE_world.h" +#include "BKE_global.h" +#include "BPY_extern.h" +#include "BKE_main.h" + + +void free_world(World *wrld) +{ + MTex *mtex; + int a; + + BPY_free_scriptlink(&wrld->scriptlink); + + for(a=0; a<8; a++) { + mtex= wrld->mtex[a]; + if(mtex && mtex->tex) mtex->tex->id.us--; + if(mtex) MEM_freeN(mtex); + } + wrld->ipo= 0; +} + + +World *add_world(char *name) +{ + World *wrld; + + wrld= alloc_libblock(&G.main->world, ID_WO, name); + + wrld->horb= 0.6f; + wrld->skytype= WO_SKYBLEND; + wrld->exposure= 1.0f; + wrld->stardist= 15.0f; + wrld->starsize= 2.0f; + wrld->gravity= 9.8f; + + return wrld; +} + +World *copy_world(World *wrld) +{ + World *wrldn; + int a; + + wrldn= copy_libblock(wrld); + + for(a=0; a<8; a++) { + if(wrld->mtex[a]) { + wrldn->mtex[a]= MEM_mallocN(sizeof(MTex), "copymaterial"); + memcpy(wrldn->mtex[a], wrld->mtex[a], sizeof(MTex)); + id_us_plus((ID *)wrldn->mtex[a]->tex); + } + } + + BPY_copy_scriptlink(&wrld->scriptlink); + + id_us_plus((ID *)wrldn->ipo); + + return wrldn; +} + +void make_local_world(World *wrld) +{ + Scene *sce; + World *wrldn; + int local=0, lib=0; + + /* - zijn er alleen lib users: niet doen + * - zijn er alleen locale users: flag zetten + * - mixed: copy + */ + + if(wrld->id.lib==0) return; + if(wrld->id.us==1) { + wrld->id.lib= 0; + wrld->id.flag= LIB_LOCAL; + new_id(0, (ID *)wrld, 0); + return; + } + + sce= G.main->scene.first; + while(sce) { + if(sce->world==wrld) { + if(sce->id.lib) lib= 1; + else local= 1; + } + sce= sce->id.next; + } + + if(local && lib==0) { + wrld->id.lib= 0; + wrld->id.flag= LIB_LOCAL; + new_id(0, (ID *)wrld, 0); + } + else if(local && lib) { + wrldn= copy_world(wrld); + wrldn->id.us= 0; + + sce= G.main->scene.first; + while(sce) { + if(sce->world==wrld) { + if(sce->id.lib==0) { + sce->world= wrldn; + wrldn->id.us++; + wrld->id.us--; + } + } + sce= sce->id.next; + } + } +} + + +void init_render_world() +{ + int a; + char *cp; + + if(G.scene->world) { + R.wrld= *(G.scene->world); + + cp= (char *)&R.wrld.fastcol; + + cp[0]= 255.0*R.wrld.horr; + cp[1]= 255.0*R.wrld.horg; + cp[2]= 255.0*R.wrld.horb; + cp[3]= 1; + + VECCOPY(R.grvec, R.viewmat[2]); + Normalise(R.grvec); + Mat3CpyMat4(R.imat, R.viewinv); + + for(a=0; a<6; a++) if(R.wrld.mtex[a] && R.wrld.mtex[a]->tex) R.wrld.skytype |= WO_SKYTEX; + + if(G.scene->camera && G.scene->camera->type==OB_CAMERA) { + Camera *cam= G.scene->camera->data; + if(cam->type==CAM_ORTHO) { + /* dit is maar ongeveer */ + R.wrld.miststa+= (float)fabs(R.viewmat[3][2]); + } + } + } + else { + memset(&R.wrld, 0, sizeof(World)); + R.wrld.exposure= 1.0; + } +} diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c new file mode 100644 index 00000000000..109553c816e --- /dev/null +++ b/source/blender/blenkernel/intern/writeavi.c @@ -0,0 +1,147 @@ +/** + * Functions for writing avi-format files. + * + * $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. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * + */ + +#include <string.h> + +#ifdef WIN32 +#include "BLI_winstuff.h" +#endif + +#include "MEM_guardedalloc.h" +#include "BLI_blenlib.h" + +#include "AVI_avi.h" + +#include "BKE_bad_level_calls.h" +#include "BKE_global.h" + +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" + +static AviMovie *avi=NULL; +static int sframe; + +void makeavistring (char *string) +{ + char txt[64]; + + if (string==0) return; + + strcpy(string, G.scene->r.pic); + BLI_convertstringcode(string, G.sce, G.scene->r.cfra); + + RE_make_existing_file(string); + + if (strcasecmp(string + strlen(string) - 4, ".avi")) { + sprintf(txt, "%04d_%04d.avi", (G.scene->r.sfra) , (G.scene->r.efra) ); + strcat(string, txt); + } +} + +void start_avi(void) +{ + int x, y; + char name[256]; + AviFormat format; + int quality, framerate; + + makeavistring(name); + + sframe = (G.scene->r.sfra); + x = R.rectx; + y = R.recty; + + quality= R.r.quality; + framerate= R.r.frs_sec; + + avi = MEM_mallocN (sizeof(AviMovie), "avimovie"); + + if (R.r.imtype != AVI_FORMAT_MJPEG) format = AVI_FORMAT_AVI_RGB; + else format = AVI_FORMAT_MJPEG; + + if (AVI_open_compress (name, avi, 1, format) != AVI_ERROR_NONE) { + error("open movie"); + MEM_freeN (avi); + avi = NULL; + return; + } + + AVI_set_compress_option (avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_WIDTH, &x); + AVI_set_compress_option (avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_HEIGHT, &y); + AVI_set_compress_option (avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_QUALITY, &quality); + AVI_set_compress_option (avi, AVI_OPTION_TYPE_MAIN, 0, AVI_OPTION_FRAMERATE, &framerate); + + avi->interlace= 0; + avi->odd_fields= 0; +/* avi->interlace= R.r.mode & R_FIELDS; */ +/* avi->odd_fields= (R.r.mode & R_ODDFIELD)?1:0; */ + + printf("Created avi: %s\n", name); +} + +void append_avi(int frame) +{ + unsigned int *rt1, *rt2, *temp; + int y; + + if (avi == NULL) { + G.afbreek = 1; + return; + } + + /* note that libavi free's the buffer... stupid interface - zr */ + temp = MEM_mallocN(R.rectx*R.recty*4, "append_avi buf"); + + rt1= temp; + rt2= R.rectot + (R.recty-1)*R.rectx; + for (y=0; y < R.recty; y++, rt1+= R.rectx, rt2-= R.rectx) { + memcpy (rt1, rt2, R.rectx*4); + } + + IMB_convert_rgba_to_abgr(R.rectx*R.recty, temp); + + AVI_write_frame (avi, (frame-sframe), AVI_FORMAT_RGB32, + temp, R.rectx*R.recty*4); + printf ("added frame %3d (frame %3d in avi): ", frame, frame-sframe); +} + +void end_avi(void) +{ + if (avi == NULL) return; + + AVI_close_compress (avi); + MEM_freeN (avi); + avi= NULL; +} |