mirror of
https://github.com/glest/glest-source.git
synced 2025-09-02 04:22:32 +02:00
- added glexemel to svn and CMake builds
- updated the G3D import script to properly bring in animations into Blender!
This commit is contained in:
@@ -130,9 +130,15 @@ ENDIF()
|
|||||||
|
|
||||||
ADD_SUBDIRECTORY( source/shared_lib )
|
ADD_SUBDIRECTORY( source/shared_lib )
|
||||||
ADD_SUBDIRECTORY( source/glest_game )
|
ADD_SUBDIRECTORY( source/glest_game )
|
||||||
ADD_SUBDIRECTORY( source/glest_map_editor )
|
#if(wxWidgets_FOUND)
|
||||||
ADD_SUBDIRECTORY( source/g3d_viewer )
|
ADD_SUBDIRECTORY( source/glest_map_editor )
|
||||||
ADD_SUBDIRECTORY( source/configurator )
|
ADD_SUBDIRECTORY( source/g3d_viewer )
|
||||||
|
ADD_SUBDIRECTORY( source/configurator )
|
||||||
|
#else()
|
||||||
|
# MESSAGE(STATUS "WARNING... the following game tools will NOT be built since we cannot find wxWidgets on this machine")
|
||||||
|
# MESSAGE(STATUS "map editor, g3d viewer, configurator")
|
||||||
|
#endif()
|
||||||
|
ADD_SUBDIRECTORY( source/tools/glexemel )
|
||||||
|
|
||||||
IF(APPLE)
|
IF(APPLE)
|
||||||
include(mk/macosx/CMakeLists.txt)
|
include(mk/macosx/CMakeLists.txt)
|
||||||
|
13
source/tools/glexemel/CMakeLists.txt
Normal file
13
source/tools/glexemel/CMakeLists.txt
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# glexemel
|
||||||
|
|
||||||
|
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/source/tools/glexemel)
|
||||||
|
add_executable(g2xml g2xml.c g3dv4.h)
|
||||||
|
|
||||||
|
find_package(LibXml2)
|
||||||
|
IF(LIBXML2_FOUND)
|
||||||
|
include_directories(${LIBXML2_INCLUDE_DIR})
|
||||||
|
add_executable(xml2g xml2g.c g3dv4.h)
|
||||||
|
target_link_libraries(xml2g ${LIBXML2_LIBRARIES})
|
||||||
|
ELSE()
|
||||||
|
MESSAGE(STATUS "WARNING... xml2g will NOT be built since we cannot find libXml2 on this machine")
|
||||||
|
ENDIF()
|
340
source/tools/glexemel/COPYING
Normal file
340
source/tools/glexemel/COPYING
Normal file
@@ -0,0 +1,340 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||||
|
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Library General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Library General
|
||||||
|
Public License instead of this License.
|
11
source/tools/glexemel/INSTALL
Normal file
11
source/tools/glexemel/INSTALL
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
Sorry - no autotools support (yet!).
|
||||||
|
|
||||||
|
You will need:
|
||||||
|
1) GNU Make (or an equivalent).
|
||||||
|
2) An ANSI C compiler (eg: gcc).
|
||||||
|
3) libxml2 (http://xmlsoft.org) - the XML parser for GNOME.
|
||||||
|
|
||||||
|
Just copy Makefile.linux to Makefile:
|
||||||
|
$ cp Makefile.linux Makefile
|
||||||
|
Then edit Makefile to suit your needs (it's *very* simple).
|
||||||
|
|
30
source/tools/glexemel/Makefile.linux
Normal file
30
source/tools/glexemel/Makefile.linux
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# You need to edit this Makefile for your specific platform
|
||||||
|
|
||||||
|
# CC is the name of your C compiler
|
||||||
|
CC=gcc
|
||||||
|
# CFLAGS are the flags that you want to pass to the C compiler
|
||||||
|
CFLAGS=-Wall -ansi -pedantic
|
||||||
|
# IDIRS specify the include directories to use
|
||||||
|
IDIRS=-I/usr/include/libxml2
|
||||||
|
# LIBS specify the libraries (libxml2)
|
||||||
|
LIBS=-lxml2
|
||||||
|
# INSTALLDIR specifies the directory to which the binaries should be installed
|
||||||
|
INSTALLDIR=/usr/local/bin
|
||||||
|
# CP specifies the copy command for the system
|
||||||
|
CP=cp
|
||||||
|
|
||||||
|
all: g2xml xml2g
|
||||||
|
|
||||||
|
g2xml:
|
||||||
|
${CC} ${CFLAGS} ${IDIRS} g2xml.c -o g2xml ${LIBS}
|
||||||
|
|
||||||
|
xml2g:
|
||||||
|
${CC} ${CFLAGS} ${IDIRS} xml2g.c -o xml2g ${LIBS}
|
||||||
|
|
||||||
|
install:
|
||||||
|
${CP} g2xml ${INSTALLDIR}/.
|
||||||
|
${CP} xml2g ${INSTALLDIR}/.
|
||||||
|
${CP} g3d.dtd ${INSTALLDIR}/.
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f g2xml xml2g
|
13
source/tools/glexemel/README
Normal file
13
source/tools/glexemel/README
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
=== GLEXEMEL ===
|
||||||
|
An XML format for the G3D file format used by the game Glest:
|
||||||
|
http://www.glest.org
|
||||||
|
|
||||||
|
This XML format allows for exporters to create XML file descriptions that
|
||||||
|
can then be converted to binary.
|
||||||
|
|
||||||
|
Note: This package is not yet part of Glest, although it is offered for
|
||||||
|
inclusion should the developers wish.
|
||||||
|
|
||||||
|
Copyright (C) Jonathan Merritt 2005.
|
||||||
|
This package may be distributed under the terms of the GNU General Public
|
||||||
|
License (see the file COPYING for more details).
|
362
source/tools/glexemel/g2xml.c
Normal file
362
source/tools/glexemel/g2xml.c
Normal file
@@ -0,0 +1,362 @@
|
|||||||
|
/**
|
||||||
|
* File: g2xml.c
|
||||||
|
* Written: Jonathan Merritt <jmerritt@warpax.com>
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Converts G3D format files into an XML representation.
|
||||||
|
*
|
||||||
|
* Copyright (C) Jonathan Merritt 2005.
|
||||||
|
* This file may be distributed under the terms of the GNU General Public
|
||||||
|
* License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "g3dv4.h"
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE 1
|
||||||
|
#endif
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forward function declarations.
|
||||||
|
*/
|
||||||
|
int g3d2xml(FILE *infile, FILE *outfile);
|
||||||
|
void usage(char *execname);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Program entry point.
|
||||||
|
*
|
||||||
|
* @param argc: Number of arguments passed to the program.
|
||||||
|
* @param argv: Array of string arguments.
|
||||||
|
*
|
||||||
|
* @returns: EXIT_SUCCESS or EXIT_FAILURE depending upon success or failure
|
||||||
|
* of the conversion to XML.
|
||||||
|
*/
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *infilename, *outfilename;
|
||||||
|
FILE *infile, *outfile;
|
||||||
|
int successFlag;
|
||||||
|
|
||||||
|
/* parse command line arguments */
|
||||||
|
if (argc != 3)
|
||||||
|
{
|
||||||
|
usage(argv[0]);
|
||||||
|
return (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
infilename = argv[1];
|
||||||
|
outfilename = argv[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* attempt to open the input and output files */
|
||||||
|
infile = fopen(infilename, "rb");
|
||||||
|
if (infile == NULL)
|
||||||
|
{
|
||||||
|
printf("Could not open file \"%s\" for binary reading.\n",
|
||||||
|
infilename);
|
||||||
|
return (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
outfile = fopen(outfilename, "w");
|
||||||
|
if (outfile == NULL)
|
||||||
|
{
|
||||||
|
printf("Could not open file \"%s\" for writing.\n",
|
||||||
|
outfilename);
|
||||||
|
fclose(infile);
|
||||||
|
return (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* perform the XML conversion */
|
||||||
|
successFlag = g3d2xml(infile, outfile);
|
||||||
|
|
||||||
|
/* close the two files */
|
||||||
|
fclose(infile);
|
||||||
|
fclose(outfile);
|
||||||
|
|
||||||
|
/* return a success or failure flag */
|
||||||
|
if (successFlag)
|
||||||
|
return (EXIT_SUCCESS);
|
||||||
|
else
|
||||||
|
return (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints a "Usage:" string for the program.
|
||||||
|
*
|
||||||
|
* @param execname: Executable name of the program.
|
||||||
|
*/
|
||||||
|
void usage(char *execname)
|
||||||
|
{
|
||||||
|
printf("Usage:\n");
|
||||||
|
printf(" %s infile.g3d outfile.xml\n", execname);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the conversion from the G3D file format to XML.
|
||||||
|
*
|
||||||
|
* @param infile: G3D binary file, opened as "rb", for input.
|
||||||
|
* @param outfile: Text file, opened as "w", for XML output.
|
||||||
|
*
|
||||||
|
* @returns: TRUE if conversion to XML was successful, and FALSE otherwise.
|
||||||
|
*/
|
||||||
|
int g3d2xml(FILE *infile, FILE *outfile)
|
||||||
|
{
|
||||||
|
struct FileHeader fileHeader;
|
||||||
|
struct ModelHeader modelHeader;
|
||||||
|
struct MeshHeader meshHeader;
|
||||||
|
size_t nBytes;
|
||||||
|
uint8 textureName[NAMESIZE];
|
||||||
|
float32 *fdata;
|
||||||
|
uint32 *idata;
|
||||||
|
int ii, jj, kk;
|
||||||
|
|
||||||
|
/* read in the FileHeader */
|
||||||
|
nBytes = sizeof(struct FileHeader);
|
||||||
|
if (fread(&fileHeader, nBytes, 1, infile) != 1)
|
||||||
|
{
|
||||||
|
printf("Could not read file header!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (strncmp((char*)fileHeader.id, "G3D", 3) != 0)
|
||||||
|
{
|
||||||
|
printf("Expected \"G3D\" id was not found!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (fileHeader.version != 4)
|
||||||
|
{
|
||||||
|
printf("Version 4 expected, but version %d found!\n",
|
||||||
|
fileHeader.version);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
fprintf(outfile, "<?xml version=\"1.0\" encoding=\"ASCII\" ?>\n");
|
||||||
|
fprintf(outfile, "<!DOCTYPE G3D SYSTEM \"g3d.dtd\">\n");
|
||||||
|
fprintf(outfile, "<!--\n");
|
||||||
|
fprintf(outfile, "\tThis file is an XML encoding of a G3D binary\n");
|
||||||
|
fprintf(outfile, "\tfile. The XML format is by Jonathan Merritt\n");
|
||||||
|
fprintf(outfile, "\t(not yet accepted as part of Glest!).\n");
|
||||||
|
fprintf(outfile, "-->\n");
|
||||||
|
fprintf(outfile, "<G3D version=\"%d\">\n", fileHeader.version);
|
||||||
|
|
||||||
|
/* read in the ModelHeader */
|
||||||
|
nBytes = sizeof(struct ModelHeader);
|
||||||
|
if (fread(&modelHeader, nBytes, 1, infile) != 1)
|
||||||
|
{
|
||||||
|
printf("Could not read model header!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (modelHeader.type != mtMorphMesh)
|
||||||
|
{
|
||||||
|
printf("Unrecognized mesh type!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read in the meshes */
|
||||||
|
for (ii = 0; ii < modelHeader.meshCount; ii++)
|
||||||
|
{
|
||||||
|
/* read in the MeshHeader */
|
||||||
|
nBytes = sizeof(struct MeshHeader);
|
||||||
|
if (fread(&meshHeader, nBytes, 1, infile) != 1)
|
||||||
|
{
|
||||||
|
printf("Could not read mesh header!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write out XML mesh header */
|
||||||
|
fprintf(outfile, "\t<Mesh name=\"%s\" ", meshHeader.name);
|
||||||
|
fprintf(outfile, "frameCount=\"%d\" ", meshHeader.frameCount);
|
||||||
|
fprintf(outfile, "vertexCount=\"%d\" ",
|
||||||
|
meshHeader.vertexCount);
|
||||||
|
fprintf(outfile, "indexCount=\"%d\" ", meshHeader.indexCount);
|
||||||
|
fprintf(outfile, "specularPower=\"%f\" ",
|
||||||
|
meshHeader.specularPower);
|
||||||
|
fprintf(outfile, "opacity=\"%f\" ", meshHeader.opacity);
|
||||||
|
if (meshHeader.properties & (0x1 << mpfTwoSided))
|
||||||
|
fprintf(outfile, "twoSided=\"true\" ");
|
||||||
|
else
|
||||||
|
fprintf(outfile, "twoSided=\"false\" ");
|
||||||
|
if (meshHeader.properties & (0x1 << mpfCustomColor))
|
||||||
|
fprintf(outfile, "customColor=\"true\" ");
|
||||||
|
else
|
||||||
|
fprintf(outfile, "customColor=\"false\" ");
|
||||||
|
if (meshHeader.textures)
|
||||||
|
fprintf(outfile, "diffuseTexture=\"true\"");
|
||||||
|
else
|
||||||
|
fprintf(outfile, "diffuseTexture=\"false\"");
|
||||||
|
fprintf(outfile, ">\n");
|
||||||
|
|
||||||
|
/* write out diffuse and specular colors */
|
||||||
|
fprintf(outfile, "\t\t<Diffuse>\n");
|
||||||
|
fprintf(outfile, "\t\t\t<Color r=\"%f\" g=\"%f\" b=\"%f\"/>\n",
|
||||||
|
meshHeader.diffuseColor[0],
|
||||||
|
meshHeader.diffuseColor[1],
|
||||||
|
meshHeader.diffuseColor[2]);
|
||||||
|
fprintf(outfile, "\t\t</Diffuse>\n");
|
||||||
|
fprintf(outfile, "\t\t<Specular>\n");
|
||||||
|
fprintf(outfile, "\t\t\t<Color r=\"%f\" g=\"%f\" b=\"%f\"/>\n",
|
||||||
|
meshHeader.specularColor[0],
|
||||||
|
meshHeader.specularColor[1],
|
||||||
|
meshHeader.specularColor[2]);
|
||||||
|
fprintf(outfile, "\t\t</Specular>\n");
|
||||||
|
|
||||||
|
/* read / write the texture name if present */
|
||||||
|
if (meshHeader.textures)
|
||||||
|
{
|
||||||
|
nBytes = sizeof(textureName);
|
||||||
|
if (fread(&textureName, nBytes, 1, infile) != 1)
|
||||||
|
{
|
||||||
|
printf("Could not read texture name!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
fprintf(outfile, "\t\t<Texture name=\"%s\"/>\n",
|
||||||
|
textureName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read / write each set of vertex data */
|
||||||
|
for (jj=0; jj < meshHeader.frameCount; jj++)
|
||||||
|
{
|
||||||
|
nBytes = sizeof(float32)*meshHeader.vertexCount*3;
|
||||||
|
fdata = malloc(nBytes);
|
||||||
|
if (fdata == NULL)
|
||||||
|
{
|
||||||
|
printf("Could not allocate buffer!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (fread(fdata, nBytes, 1, infile) != 1)
|
||||||
|
{
|
||||||
|
printf("Could not read vertex data!\n");
|
||||||
|
free(fdata);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
fprintf(outfile, "\t\t<Vertices frame=\"%d\">\n",
|
||||||
|
jj);
|
||||||
|
for (kk=0; kk < meshHeader.vertexCount; kk++)
|
||||||
|
{
|
||||||
|
fprintf(outfile, "\t\t\t<Vertex ");
|
||||||
|
/*fprintf(outfile, "i=\"%d\" ",
|
||||||
|
kk);*/
|
||||||
|
fprintf(outfile, "x=\"%f\" ",
|
||||||
|
fdata[3*kk]);
|
||||||
|
fprintf(outfile, "y=\"%f\" ",
|
||||||
|
fdata[3*kk+1]);
|
||||||
|
fprintf(outfile, "z=\"%f\"/>\n",
|
||||||
|
fdata[3*kk+2]);
|
||||||
|
}
|
||||||
|
fprintf(outfile, "\t\t</Vertices>\n");
|
||||||
|
free(fdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read / write each set of normal data */
|
||||||
|
for (jj=0; jj < meshHeader.frameCount; jj++)
|
||||||
|
{
|
||||||
|
nBytes = sizeof(float32)*meshHeader.vertexCount*3;
|
||||||
|
fdata = malloc(nBytes);
|
||||||
|
if (fdata == NULL)
|
||||||
|
{
|
||||||
|
printf("Could not allocate buffer!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (fread(fdata, nBytes, 1, infile) != 1)
|
||||||
|
{
|
||||||
|
printf("Could not read normal data!\n");
|
||||||
|
free(fdata);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
fprintf(outfile, "\t\t<Normals frame=\"%d\">\n",
|
||||||
|
jj);
|
||||||
|
for (kk=0; kk < meshHeader.vertexCount; kk++)
|
||||||
|
{
|
||||||
|
fprintf(outfile, "\t\t\t<Normal ");
|
||||||
|
/*fprintf(outfile, "i=\"%d\" ",
|
||||||
|
kk);*/
|
||||||
|
fprintf(outfile, "x=\"%f\" ",
|
||||||
|
fdata[3*kk]);
|
||||||
|
fprintf(outfile, "y=\"%f\" ",
|
||||||
|
fdata[3*kk+1]);
|
||||||
|
fprintf(outfile, "z=\"%f\"/>\n",
|
||||||
|
fdata[3*kk+2]);
|
||||||
|
}
|
||||||
|
fprintf(outfile, "\t\t</Normals>\n");
|
||||||
|
free(fdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read / write texture coordinates */
|
||||||
|
if (meshHeader.textures)
|
||||||
|
{
|
||||||
|
nBytes = sizeof(float32)*meshHeader.vertexCount*2;
|
||||||
|
fdata = malloc(nBytes);
|
||||||
|
if (fdata == NULL)
|
||||||
|
{
|
||||||
|
printf("Could not allocate buffer!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (fread(fdata, nBytes, 1, infile) != 1)
|
||||||
|
{
|
||||||
|
printf("Could not read texture coords!\n");
|
||||||
|
free(fdata);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
fprintf(outfile, "\t\t<TexCoords>\n");
|
||||||
|
for (kk=0; kk < meshHeader.vertexCount; kk++)
|
||||||
|
{
|
||||||
|
fprintf(outfile, "\t\t\t<ST ");
|
||||||
|
/*fprintf(outfile, "i=\"%d\" ",
|
||||||
|
kk);*/
|
||||||
|
fprintf(outfile, "s=\"%f\" ",
|
||||||
|
fdata[2*kk]);
|
||||||
|
fprintf(outfile, "t=\"%f\"/>\n",
|
||||||
|
fdata[2*kk+1]);
|
||||||
|
}
|
||||||
|
fprintf(outfile, "\t\t</TexCoords>\n");
|
||||||
|
free(fdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read / write face indices */
|
||||||
|
nBytes = sizeof(uint32)*meshHeader.indexCount;
|
||||||
|
idata = malloc(nBytes);
|
||||||
|
if (idata == NULL)
|
||||||
|
{
|
||||||
|
printf("Could not allocate buffer!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (fread(idata, nBytes, 1, infile) != 1)
|
||||||
|
{
|
||||||
|
printf("Could not read indexes!\n");
|
||||||
|
free(idata);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
fprintf(outfile, "\t\t<Indices>\n");
|
||||||
|
for (kk=0; kk < meshHeader.indexCount; kk++)
|
||||||
|
{
|
||||||
|
fprintf(outfile, "\t\t\t<Ix i=\"%d\"/>\n",
|
||||||
|
idata[kk]);
|
||||||
|
}
|
||||||
|
fprintf(outfile, "\t\t</Indices>\n");
|
||||||
|
free(idata);
|
||||||
|
|
||||||
|
fprintf(outfile, "\t</Mesh>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(outfile, "</G3D>\n");
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
66
source/tools/glexemel/g3d.dtd
Normal file
66
source/tools/glexemel/g3d.dtd
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
<?xml version="1.0" encoding="ASCII" ?>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
A DTD for describing an XML representation of G3D version 4 files.
|
||||||
|
|
||||||
|
Created by Jonathan Merritt <jmerritt@warpax.com>
|
||||||
|
Copyright (C) Jonathan Merritt 2005.
|
||||||
|
|
||||||
|
This DTD may be distributed under the terms of the GNU General Public
|
||||||
|
License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!ELEMENT G3D (Mesh+)>
|
||||||
|
<!ATTLIST G3D version CDATA #REQUIRED>
|
||||||
|
|
||||||
|
<!ELEMENT Mesh
|
||||||
|
(Diffuse,Specular,Texture?,Vertices+,Normals+,TexCoords?,Indices)>
|
||||||
|
<!ATTLIST Mesh name CDATA #REQUIRED>
|
||||||
|
<!ATTLIST Mesh frameCount CDATA #REQUIRED>
|
||||||
|
<!ATTLIST Mesh vertexCount CDATA #REQUIRED>
|
||||||
|
<!ATTLIST Mesh indexCount CDATA #REQUIRED>
|
||||||
|
<!ATTLIST Mesh specularPower CDATA #REQUIRED>
|
||||||
|
<!ATTLIST Mesh opacity CDATA #REQUIRED>
|
||||||
|
<!ATTLIST Mesh twoSided (true|false) #REQUIRED>
|
||||||
|
<!ATTLIST Mesh customColor (true|false) #REQUIRED>
|
||||||
|
<!ATTLIST Mesh diffuseTexture (true|false) #REQUIRED>
|
||||||
|
|
||||||
|
<!ELEMENT Diffuse (Color)>
|
||||||
|
|
||||||
|
<!ELEMENT Specular (Color)>
|
||||||
|
|
||||||
|
<!ELEMENT Color EMPTY>
|
||||||
|
<!ATTLIST Color r CDATA #REQUIRED>
|
||||||
|
<!ATTLIST Color g CDATA #REQUIRED>
|
||||||
|
<!ATTLIST Color b CDATA #REQUIRED>
|
||||||
|
|
||||||
|
<!ELEMENT Texture EMPTY>
|
||||||
|
<!ATTLIST Texture name CDATA #REQUIRED>
|
||||||
|
|
||||||
|
<!ELEMENT Vertices (Vertex+)>
|
||||||
|
<!ATTLIST Vertices frame CDATA #IMPLIED>
|
||||||
|
|
||||||
|
<!ELEMENT Vertex EMPTY>
|
||||||
|
<!ATTLIST Vertex x CDATA #REQUIRED>
|
||||||
|
<!ATTLIST Vertex y CDATA #REQUIRED>
|
||||||
|
<!ATTLIST Vertex z CDATA #REQUIRED>
|
||||||
|
|
||||||
|
<!ELEMENT Normals (Normal+)>
|
||||||
|
<!ATTLIST Normals frame CDATA #IMPLIED>
|
||||||
|
|
||||||
|
<!ELEMENT Normal EMPTY>
|
||||||
|
<!ATTLIST Normal x CDATA #REQUIRED>
|
||||||
|
<!ATTLIST Normal y CDATA #REQUIRED>
|
||||||
|
<!ATTLIST Normal z CDATA #REQUIRED>
|
||||||
|
|
||||||
|
<!ELEMENT TexCoords (ST+)>
|
||||||
|
|
||||||
|
<!ELEMENT ST EMPTY>
|
||||||
|
<!ATTLIST ST s CDATA #REQUIRED>
|
||||||
|
<!ATTLIST ST t CDATA #REQUIRED>
|
||||||
|
|
||||||
|
<!ELEMENT Indices (Ix+)>
|
||||||
|
|
||||||
|
<!ELEMENT Ix EMPTY>
|
||||||
|
<!ATTLIST Ix i CDATA #REQUIRED>
|
||||||
|
|
BIN
source/tools/glexemel/g3d_logo.png
Executable file
BIN
source/tools/glexemel/g3d_logo.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 59 KiB |
507
source/tools/glexemel/g3d_support.py
Normal file
507
source/tools/glexemel/g3d_support.py
Normal file
@@ -0,0 +1,507 @@
|
|||||||
|
#!BPY
|
||||||
|
"""
|
||||||
|
Name: 'G3D Fileformat Im/Exporter'
|
||||||
|
Blender: 237
|
||||||
|
Group: 'Wizards'
|
||||||
|
Tooltip: 'Imports and Exports the Glest fileformat V3/V4 (.g3d)'
|
||||||
|
"""
|
||||||
|
###########################################################################
|
||||||
|
# Glest Model / Texture / UV / Animation Importer and Exporter
|
||||||
|
# for the Game Glest that u can find http://www.glest.org
|
||||||
|
# copyright 2005 By Andreas Becker (seltsamuel@yahoo.de)
|
||||||
|
#
|
||||||
|
# Updated Jan 2011 by Mark Vejvoda (SoftCoder) to properly import animations
|
||||||
|
# from G3D into Blender
|
||||||
|
#
|
||||||
|
# Started Date: 07 June 2005 Put Public 20 June 2005
|
||||||
|
# Ver: 0.01 Beta Exporter ripped off because work in Progress
|
||||||
|
# Distributed under the GNU PUBLIC LICENSE for www.megaglest.org and glest.org
|
||||||
|
###########################################################################
|
||||||
|
#NOTE:
|
||||||
|
# Copy this Script AND g3d_logo.png into .Blender\scripts
|
||||||
|
# directory then start inside blender Scripts window
|
||||||
|
# "Update Menus" after that this Script here is accesible
|
||||||
|
# as 'Wizards' G3d Fileformat Im/Exporter
|
||||||
|
#ToDo:
|
||||||
|
#Exporter Bughunt he will be rejoined next release
|
||||||
|
#Maybe Integrate UV Painter to Generate UVMaps from Blender Material and procedural Textures
|
||||||
|
#will be nice to paint wireframe too, so that one can easyly load into Paintprogram and see where to paint
|
||||||
|
#(Already possible through Blender functions so at the end of the list :-) )
|
||||||
|
###########################################################################
|
||||||
|
"""
|
||||||
|
Here an explanation of the V4 Format found at www.glest.org
|
||||||
|
================================
|
||||||
|
1. DATA TYPES
|
||||||
|
================================
|
||||||
|
G3D files use the following data types:
|
||||||
|
uint8: 8 bit unsigned integer
|
||||||
|
uint16: 16 bit unsigned integer
|
||||||
|
uint32: 32 bit unsigned integer
|
||||||
|
float32: 32 bit floating point
|
||||||
|
================================
|
||||||
|
2. OVERALL STRUCTURE
|
||||||
|
================================
|
||||||
|
- File header
|
||||||
|
- Model header
|
||||||
|
- Mesh header
|
||||||
|
- Texture names
|
||||||
|
- Mesh data
|
||||||
|
================================
|
||||||
|
2. FILE HEADER
|
||||||
|
================================
|
||||||
|
Code:
|
||||||
|
struct FileHeader{
|
||||||
|
uint8 id[3];
|
||||||
|
uint8 version;
|
||||||
|
};
|
||||||
|
This header is shared among all the versions of G3D, it identifies this file as a G3D model and provides information of the version.
|
||||||
|
id: must be "G3D"
|
||||||
|
version: must be 4, in binary (not '4')
|
||||||
|
================================
|
||||||
|
3. MODEL HEADER
|
||||||
|
================================
|
||||||
|
Code:
|
||||||
|
struct ModelHeader{
|
||||||
|
uint16 meshCount;
|
||||||
|
uint8 type;
|
||||||
|
};
|
||||||
|
meshCount: number of meshes in this model
|
||||||
|
type: must be 0
|
||||||
|
================================
|
||||||
|
4. MESH HEADER
|
||||||
|
================================
|
||||||
|
There is a mesh header for each mesh, there must be "meshCount" headers in a file but they are not consecutive, texture names and mesh data are stored in between.
|
||||||
|
Code:
|
||||||
|
struct MeshHeader{
|
||||||
|
uint8 name[64];
|
||||||
|
uint32 frameCount;
|
||||||
|
uint32 vertexCount;
|
||||||
|
uint32 indexCount;
|
||||||
|
float32 diffuseColor[3];
|
||||||
|
float32 specularColor[3];
|
||||||
|
float32 specularPower;
|
||||||
|
float32 opacity;
|
||||||
|
uint32 properties;
|
||||||
|
uint32 textures;
|
||||||
|
};
|
||||||
|
name: name of the mesh
|
||||||
|
frameCount: number of keyframes in this mesh
|
||||||
|
vertexCount: number of vertices in each frame
|
||||||
|
indexCount: number of indices in this mesh (the number of triangles is indexCount/3)
|
||||||
|
diffuseColor: RGB diffuse color
|
||||||
|
specularColor: RGB specular color (currently unused)
|
||||||
|
specularPower: specular power (currently unused)
|
||||||
|
properties: property flags
|
||||||
|
Code:
|
||||||
|
enum MeshPropertyFlag{
|
||||||
|
mpfTwoSided= 1,
|
||||||
|
mpfCustomColor= 2,
|
||||||
|
};
|
||||||
|
mpfTwoSided: meshes in this mesh are rendered by both sides, if this flag is not present only "counter clockwise" faces are rendered
|
||||||
|
mpfCustomColor: alpha in this model is replaced by a custom color, usually the player color
|
||||||
|
textures: texture flags, only 0x1 is currently used, indicating that there is a diffuse texture in this mesh.
|
||||||
|
================================
|
||||||
|
4. TEXTURE NAMES
|
||||||
|
================================
|
||||||
|
A list of uint8[64] texture name values. One for each texture in the mesh. If there are no textures in the mesh no texture names are present. In practice since Glest only uses 1 texture for each mesh the number of texture names should be 0 or 1.
|
||||||
|
================================
|
||||||
|
5. MESH DATA
|
||||||
|
================================
|
||||||
|
After each mesh header and texture names the mesh data is placed.
|
||||||
|
vertices: frameCount * vertexCount * 3, float32 values representing the x, y, z vertex coords for all frames
|
||||||
|
normals: frameCount * vertexCount * 3, float32 values representing the x, y, z normal coords for all frames
|
||||||
|
texture coords: vertexCount * 2, float32 values representing the s, t tex coords for all frames (only present if the mesh has 1 texture at least)
|
||||||
|
indices: indexCount, uint32 values representing the indices
|
||||||
|
"""
|
||||||
|
###########################################################################
|
||||||
|
# Importing Structures needed (must later verify if i need them really all)
|
||||||
|
###########################################################################
|
||||||
|
import Blender
|
||||||
|
from Blender import NMesh, Object, Scene
|
||||||
|
from Blender.BGL import *
|
||||||
|
from Blender.Draw import *
|
||||||
|
from Blender.Window import *
|
||||||
|
from Blender.Image import *
|
||||||
|
import sys, struct, string, types
|
||||||
|
from types import *
|
||||||
|
import os
|
||||||
|
from os import path
|
||||||
|
from os.path import dirname
|
||||||
|
###########################################################################
|
||||||
|
# Variables that are better Global to handle
|
||||||
|
###########################################################################
|
||||||
|
imported = [] #List of all imported Objects
|
||||||
|
toexport = [] #List of Objects to export (actually only meshes)
|
||||||
|
sceneID = None #Points to the active Blender Scene
|
||||||
|
|
||||||
|
###########################################################################
|
||||||
|
# Declaring Structures of G3D Format
|
||||||
|
###########################################################################
|
||||||
|
class G3DHeader: #Read first 4 Bytes of file should be G3D + Versionnumber
|
||||||
|
binary_format = "<3cB"
|
||||||
|
def __init__(self, fileID):
|
||||||
|
temp = fileID.read(struct.calcsize(self.binary_format))
|
||||||
|
data = struct.unpack(self.binary_format,temp)
|
||||||
|
self.id = "".join(data[0:3])
|
||||||
|
self.version = data[3]
|
||||||
|
|
||||||
|
class G3DModelHeaderv3: #Read Modelheader in V3 there is only the number of Meshes in file
|
||||||
|
binary_format = "<I"
|
||||||
|
def __init__(self, fileID):
|
||||||
|
temp = fileID.read(struct.calcsize(self.binary_format))
|
||||||
|
data = struct.unpack(self.binary_format,temp)
|
||||||
|
self.meshcount = data[0]
|
||||||
|
|
||||||
|
class G3DModelHeaderv4: #Read Modelheader: Number of Meshes and Meshtype (must be 0)
|
||||||
|
binary_format = "<HB"
|
||||||
|
def __init__(self, fileID):
|
||||||
|
temp = fileID.read(struct.calcsize(self.binary_format))
|
||||||
|
data = struct.unpack(self.binary_format,temp)
|
||||||
|
self.meshcount = data[0]
|
||||||
|
self.mtype = data[1]
|
||||||
|
|
||||||
|
class G3DMeshHeaderv3: #Read Meshheader
|
||||||
|
binary_format = "<7I64c"
|
||||||
|
def __init__(self,fileID):
|
||||||
|
temp = fileID.read(struct.calcsize(self.binary_format))
|
||||||
|
data = struct.unpack(self.binary_format,temp)
|
||||||
|
self.framecount = data[0] #Framecount = Number of Animationsteps
|
||||||
|
self.normalframecount= data[1] #Number of Normal Frames actualli equal to Framecount
|
||||||
|
self.texturecoordframecount= data[2]#Number of Frames of Texturecoordinates seems everytime to be 1
|
||||||
|
self.colorframecount= data[3] #Number of Frames of Colors seems everytime to be 1
|
||||||
|
self.vertexcount= data[4] #Number of Vertices in each Frame
|
||||||
|
self.indexcount= data[5] #Number of Indices in Mesh (Triangles = Indexcount/3)
|
||||||
|
self.properties= data[6] #Property flags
|
||||||
|
if self.properties & 1: #PropertyBit is Mesh Textured ?
|
||||||
|
self.hastexture = False
|
||||||
|
self.texturefilename = None
|
||||||
|
else:
|
||||||
|
self.texturefilename = "".join([x for x in data[7:-1] if x in string.printable])
|
||||||
|
self.hastexture = True
|
||||||
|
if self.properties & 2: #PropertyBit is Mesh TwoSided ?
|
||||||
|
self.istwosided = True
|
||||||
|
else:
|
||||||
|
self.istwosided = False
|
||||||
|
if self.properties & 4: #PropertyBit is Mesh Alpha Channel custom Color in Game ?
|
||||||
|
self.customalpha = True
|
||||||
|
else:
|
||||||
|
self.customalpha = False
|
||||||
|
|
||||||
|
class G3DMeshHeaderv4: #Read Meshheader
|
||||||
|
binary_format = "<64c3I8f2I"
|
||||||
|
texname_format = "<64c"
|
||||||
|
def __init__(self,fileID):
|
||||||
|
temp = fileID.read(struct.calcsize(self.binary_format))
|
||||||
|
data = struct.unpack(self.binary_format,temp)
|
||||||
|
self.meshname = "".join([x for x in data[0:64] if x in string.printable]) #Name of Mesh every Char is a String on his own
|
||||||
|
self.framecount = data[64] #Framecount = Number of Animationsteps
|
||||||
|
self.vertexcount = data[65] #Number of Vertices in each Frame
|
||||||
|
self.indexcount = data[66] #Number of Indices in Mesh (Triangles = Indexcount/3)
|
||||||
|
self.diffusecolor = data[67:70] #RGB diffuse color
|
||||||
|
self.specularcolor = data[70:73] #RGB specular color (unused)
|
||||||
|
self.specularpower = data[73] #Specular power (unused)
|
||||||
|
self.opacity = data[74] #Opacity
|
||||||
|
self.properties= data[75] #Property flags
|
||||||
|
self.textures = data[76] #Texture flag
|
||||||
|
if self.properties & 1: #PropertyBit is Mesh TwoSided ?
|
||||||
|
self.istwosided = True
|
||||||
|
else:
|
||||||
|
self.istwosided = False
|
||||||
|
if self.properties & 2: #PropertyBit is Mesh Alpha Channel custom Color in Game ?
|
||||||
|
self.customalpha = True
|
||||||
|
else:
|
||||||
|
self.customalpha = False
|
||||||
|
if self.textures & 1: #PropertyBit is Mesh Textured ?
|
||||||
|
temp = fileID.read(struct.calcsize(self.texname_format))
|
||||||
|
data = struct.unpack(self.texname_format,temp)
|
||||||
|
self.texturefilename = "".join([x for x in data[0:-1] if x in string.printable])
|
||||||
|
self.hastexture = True
|
||||||
|
else:
|
||||||
|
self.hastexture = False
|
||||||
|
self.texturefilename = None
|
||||||
|
|
||||||
|
class G3DMeshdataV3: #Calculate and read the Mesh Datapack
|
||||||
|
def __init__(self,fileID,header):
|
||||||
|
#Calculation of the Meshdatasize to load because its variable
|
||||||
|
#Animationframes * Vertices per Animation * 3 (Each Point are 3 Float X Y Z Coordinates)
|
||||||
|
vertex_format = "<%if" % int(header.framecount * header.vertexcount * 3)
|
||||||
|
#The same for Normals
|
||||||
|
normals_format = "<%if" % int(header.normalframecount * header.vertexcount * 3)
|
||||||
|
#Same here but Textures are 2D so only 2 Floats needed for Position inside Texture Bitmap
|
||||||
|
texturecoords_format = "<%if" % int(header.texturecoordframecount * header.vertexcount * 2)
|
||||||
|
#Colors in format RGBA
|
||||||
|
colors_format = "<%if" % int(header.colorframecount * 4)
|
||||||
|
#Indices
|
||||||
|
indices_format = "<%iI" % int(header.indexcount)
|
||||||
|
#Load the Meshdata as calculated above
|
||||||
|
self.vertices = struct.unpack(vertex_format,fileID.read(struct.calcsize(vertex_format)))
|
||||||
|
self.normals = struct.unpack(normals_format,fileID.read(struct.calcsize(normals_format)))
|
||||||
|
self.texturecoords = struct.unpack(texturecoords_format,fileID.read(struct.calcsize(texturecoords_format)))
|
||||||
|
self.colors = struct.unpack(colors_format,fileID.read(struct.calcsize(colors_format)))
|
||||||
|
self.indices = struct.unpack(indices_format ,fileID.read(struct.calcsize(indices_format)))
|
||||||
|
|
||||||
|
class G3DMeshdataV4: #Calculate and read the Mesh Datapack
|
||||||
|
def __init__(self,fileID,header):
|
||||||
|
#Calculation of the Meshdatasize to load because its variable
|
||||||
|
#Animationframes * Points (Vertex) per Animation * 3 (Each Point are 3 Float X Y Z Coordinates)
|
||||||
|
vertex_format = "<%if" % int(header.framecount * header.vertexcount * 3)
|
||||||
|
#The same for Normals
|
||||||
|
normals_format = "<%if" % int(header.framecount * header.vertexcount * 3)
|
||||||
|
#Same here but Textures are 2D so only 2 Floats needed for Position inside Texture Bitmap
|
||||||
|
texturecoords_format = "<%if" % int(header.vertexcount * 2)
|
||||||
|
#Indices
|
||||||
|
indices_format = "<%iI" % int(header.indexcount)
|
||||||
|
#Load the Meshdata as calculated above
|
||||||
|
self.vertices = struct.unpack(vertex_format,fileID.read(struct.calcsize(vertex_format)))
|
||||||
|
self.normals = struct.unpack(normals_format,fileID.read(struct.calcsize(normals_format)))
|
||||||
|
if header.hastexture:
|
||||||
|
self.texturecoords = struct.unpack(texturecoords_format,fileID.read(struct.calcsize(texturecoords_format)))
|
||||||
|
self.indices = struct.unpack(indices_format ,fileID.read(struct.calcsize(indices_format)))
|
||||||
|
|
||||||
|
def createMesh(filename,header,data): #Create a Mesh inside Blender
|
||||||
|
mesh = NMesh.New() #New Mesh
|
||||||
|
meshobj = Object.New("Mesh",header.meshname) #New Object for the new Mesh
|
||||||
|
meshobj.link(mesh) #Link the Mesh to the Object
|
||||||
|
sceneID.link (meshobj) #Link the Object to the actual Scene
|
||||||
|
uvcoords = []
|
||||||
|
if header.hastexture: #Load Texture when assigned
|
||||||
|
texturefile = dirname(filename)+os.sep+header.texturefilename
|
||||||
|
texture = Load(texturefile)
|
||||||
|
mesh.hasFaceUV(1) #Because has Texture must have UV Coordinates
|
||||||
|
mesh.hasVertexUV(1) #UV for each Vertex not only for Face
|
||||||
|
for x in xrange(0,len(data.texturecoords),2): #Prepare the UVs
|
||||||
|
uvcoords.append((data.texturecoords[x],data.texturecoords[x+1]))
|
||||||
|
else: #Has no Texture
|
||||||
|
texture = None
|
||||||
|
mesh.hasFaceUV(0)
|
||||||
|
if header.isv4:
|
||||||
|
mesh.col(int(255*header.diffusecolor[0]),int(255*header.diffusecolor[1]),int(255*header.diffusecolor[2]),int(255*header.opacity))
|
||||||
|
if header.istwosided:
|
||||||
|
mesh.setMode("TwoSided","AutoSmooth") #Added Autosmooth because i think it does no harm
|
||||||
|
else: #I wonder why TwoSided here takes no effect on Faces ??
|
||||||
|
mesh.setMode("AutoSmooth") #Same here
|
||||||
|
y=0
|
||||||
|
for x in xrange(0,header.vertexcount*3,3): #Get the Vertices and Normals into empty Mesh
|
||||||
|
vertex=NMesh.Vert() #and load UV coords when needed per Vertex
|
||||||
|
vertex.co[0] = data.vertices[x]
|
||||||
|
vertex.co[1] = data.vertices[x+1]
|
||||||
|
vertex.co[2] = data.vertices[x+2]
|
||||||
|
vertex.no[0] = data.normals[x]
|
||||||
|
vertex.no[1] = data.normals[x+1]
|
||||||
|
vertex.no[2] = data.normals[x+2]
|
||||||
|
if header.hastexture: ###Have to Check this per Vertex UV### may not be needed
|
||||||
|
vertex.uvco[0] = data.texturecoords[y] ###but seems to do no harm :-)###
|
||||||
|
vertex.uvco[1] = data.texturecoords[y+1]
|
||||||
|
mesh.verts.append(vertex)
|
||||||
|
y= y+2
|
||||||
|
for i in xrange(0,len(data.indices),3): #Build Faces into Mesh
|
||||||
|
face = NMesh.Face()
|
||||||
|
face.smooth = 1
|
||||||
|
face.v.append(mesh.verts[data.indices[i]])
|
||||||
|
face.v.append(mesh.verts[data.indices[i+1]])
|
||||||
|
face.v.append(mesh.verts[data.indices[i+2]])
|
||||||
|
if header.hastexture: #Put UV in Faces too and assign Texture when textured
|
||||||
|
face.uv.append(uvcoords[data.indices[i]])
|
||||||
|
face.uv.append(uvcoords[data.indices[i+1]])
|
||||||
|
face.uv.append(uvcoords[data.indices[i+2]])
|
||||||
|
face.image = texture
|
||||||
|
if header.istwosided: #Finaly found out how it works :-)
|
||||||
|
face.mode |= NMesh.FaceModes['TWOSIDE'] #Really Bad documented this works to set all modes
|
||||||
|
mesh.faces.append(face)
|
||||||
|
mesh.update() #Update changes to Mesh
|
||||||
|
objdata = meshobj.getData() #Access Data of the Meshobject only the Obj has Key/IPOData
|
||||||
|
imported.append(meshobj) #Add to Imported Objects
|
||||||
|
for x in xrange(header.framecount): #Put in Vertex Positions for Keyanimation
|
||||||
|
for i in xrange(0,header.vertexcount*3,3):
|
||||||
|
objdata.verts[i/3].co[0]= data.vertices[x*header.vertexcount*3 + i]
|
||||||
|
objdata.verts[i/3].co[1]= data.vertices[x*header.vertexcount*3 + i +1]
|
||||||
|
objdata.verts[i/3].co[2]= data.vertices[x*header.vertexcount*3 + i +2 ]
|
||||||
|
objdata.update()
|
||||||
|
mesh.insertKey(x+1,"absolute")
|
||||||
|
Blender.Set("curframe",x)
|
||||||
|
|
||||||
|
# Make the keys animate in the 3d view.
|
||||||
|
key = mesh.key
|
||||||
|
key.relative = False
|
||||||
|
|
||||||
|
# Add an IPO to teh Key
|
||||||
|
ipo = Blender.Ipo.New('Key', 'md2')
|
||||||
|
key.ipo = ipo
|
||||||
|
# Add a curve to the IPO
|
||||||
|
curve = ipo.addCurve('Basis')
|
||||||
|
|
||||||
|
# Add 2 points to cycle through the frames.
|
||||||
|
curve.append((1, 0))
|
||||||
|
curve.append((header.framecount, (header.framecount-1)/10.0))
|
||||||
|
curve.interpolation = Blender.IpoCurve.InterpTypes.LINEAR
|
||||||
|
|
||||||
|
return
|
||||||
|
###########################################################################
|
||||||
|
# Import
|
||||||
|
###########################################################################
|
||||||
|
def G3DLoader(filename): #Main Import Routine
|
||||||
|
global imported, sceneID
|
||||||
|
print "\nNow Importing File : " + filename
|
||||||
|
fileID = open(filename,"rb")
|
||||||
|
header = G3DHeader(fileID)
|
||||||
|
print "\nHeader ID : " + header.id
|
||||||
|
print "Version : " + str(header.version)
|
||||||
|
if header.id != "G3D":
|
||||||
|
print "This is Not a G3D Model File"
|
||||||
|
fileID.close
|
||||||
|
return
|
||||||
|
if header.version not in (3, 4):
|
||||||
|
print "The Version of this G3D File is not Supported"
|
||||||
|
fileID.close
|
||||||
|
return
|
||||||
|
in_editmode = Blender.Window.EditMode() #Must leave Editmode when active
|
||||||
|
if in_editmode: Blender.Window.EditMode(0)
|
||||||
|
sceneID=Scene.getCurrent() #Get active Scene
|
||||||
|
scenecontext=sceneID.getRenderingContext() #To Access the Start/Endframe its so hidden i searched till i got angry :-)
|
||||||
|
basename=str(Blender.sys.makename(filename,"",1)) #Generate the Base Filename without Path + extension
|
||||||
|
imported = []
|
||||||
|
maxframe=0
|
||||||
|
if header.version == 3:
|
||||||
|
modelheader = G3DModelHeaderv3(fileID)
|
||||||
|
print "Number of Meshes : " + str(modelheader.meshcount)
|
||||||
|
for x in xrange(modelheader.meshcount):
|
||||||
|
meshheader = G3DMeshHeaderv3(fileID)
|
||||||
|
meshheader.isv4 = False
|
||||||
|
print "\nMesh Number : " + str(x+1)
|
||||||
|
print "framecount : " + str(meshheader.framecount)
|
||||||
|
print "normalframecount : " + str(meshheader.normalframecount)
|
||||||
|
print "texturecoordframecount: " + str(meshheader.texturecoordframecount)
|
||||||
|
print "colorframecount : " + str(meshheader.colorframecount)
|
||||||
|
print "pointcount : " + str(meshheader.vertexcount)
|
||||||
|
print "indexcount : " + str(meshheader.indexcount)
|
||||||
|
print "texturename : " + str(meshheader.texturefilename)
|
||||||
|
print "hastexture : " + str(meshheader.hastexture)
|
||||||
|
print "istwosided : " + str(meshheader.istwosided)
|
||||||
|
print "customalpha : " + str(meshheader.customalpha)
|
||||||
|
meshheader.meshname = basename+str(x+1) #Generate Meshname because V3 has none
|
||||||
|
if meshheader.framecount > maxframe: maxframe = meshheader.framecount #Evaluate the maximal animationsteps
|
||||||
|
meshdata = G3DMeshdataV3(fileID,meshheader)
|
||||||
|
createMesh(filename,meshheader,meshdata)
|
||||||
|
fileID.close
|
||||||
|
print "Imported Objects: ",imported
|
||||||
|
scenecontext.startFrame(1) #Yeah finally found this Options :-)
|
||||||
|
scenecontext.endFrame(maxframe) #Set it correctly to the last Animationstep :-))))
|
||||||
|
Blender.Set("curframe",1) #Why the Heck are the above Options not here accessible ????
|
||||||
|
anchor = Object.New("Empty",basename) #Build an "empty" to Parent all meshes to it for easy handling
|
||||||
|
sceneID.link(anchor) #Link it to current Scene
|
||||||
|
anchor.makeParent(imported) #Make it Parent for all imported Meshes
|
||||||
|
anchor.sel = 1 #Select it
|
||||||
|
if in_editmode: Blender.Window.EditMode(1) # Be nice and restore Editmode when was active
|
||||||
|
return
|
||||||
|
if header.version == 4:
|
||||||
|
modelheader = G3DModelHeaderv4(fileID)
|
||||||
|
print "Number of Meshes : " + str(modelheader.meshcount)
|
||||||
|
for x in xrange(modelheader.meshcount):
|
||||||
|
meshheader = G3DMeshHeaderv4(fileID)
|
||||||
|
meshheader.isv4 = False
|
||||||
|
print "\nMesh Number : " + str(x+1)
|
||||||
|
print "meshname : " + str(meshheader.meshname)
|
||||||
|
print "framecount : " + str(meshheader.framecount)
|
||||||
|
print "vertexcount : " + str(meshheader.vertexcount)
|
||||||
|
print "indexcount : " + str(meshheader.indexcount)
|
||||||
|
print "diffusecolor : %1.6f %1.6f %1.6f" %meshheader.diffusecolor
|
||||||
|
print "specularcolor : %1.6f %1.6f %1.6f" %meshheader.specularcolor
|
||||||
|
print "specularpower : %1.6f" %meshheader.specularpower
|
||||||
|
print "opacity : %1.6f" %meshheader.opacity
|
||||||
|
print "properties : " + str(meshheader.properties)
|
||||||
|
print "textures : " + str(meshheader.textures)
|
||||||
|
print "texturename : " + str(meshheader.texturefilename)
|
||||||
|
if len(meshheader.meshname) ==0: #When no Meshname in File Generate one
|
||||||
|
meshheader.meshname = basename+str(x+1)
|
||||||
|
if meshheader.framecount > maxframe: maxframe = meshheader.framecount #Evaluate the maximal animationsteps
|
||||||
|
meshdata = G3DMeshdataV4(fileID,meshheader)
|
||||||
|
createMesh(filename,meshheader,meshdata)
|
||||||
|
fileID.close
|
||||||
|
scenecontext.startFrame(1) #Yeah finally found this Options :-)
|
||||||
|
scenecontext.endFrame(maxframe) #Set it correctly to the last Animationstep :-))))
|
||||||
|
Blender.Set("curframe",1) #Why the Heck are the above Options not here accessible ????
|
||||||
|
anchor = Object.New("Empty",basename) #Build an "empty" to Parent all meshes to it for easy handling
|
||||||
|
sceneID.link(anchor) #Link it to current Scene
|
||||||
|
anchor.makeParent(imported) #Make it Parent for all imported Meshes
|
||||||
|
anchor.sel = 1 #Select it
|
||||||
|
if in_editmode: Blender.Window.EditMode(1) # Be nice and restore Editmode when was active
|
||||||
|
print "Created a empty Object as 'Grip' where all imported Objects are parented to"
|
||||||
|
print "To move the complete Meshes only select this empty Object and move it"
|
||||||
|
print "All Done, have a good Day :-)\n\n"
|
||||||
|
return
|
||||||
|
###########################################################################
|
||||||
|
# Export (Ripped out its work in Progress will be added soon
|
||||||
|
###########################################################################
|
||||||
|
def G3DSaverV3(filename):
|
||||||
|
return
|
||||||
|
|
||||||
|
def G3DSaverV4(filename):
|
||||||
|
return
|
||||||
|
###########################################################################
|
||||||
|
# Complete GUI Part of The Wizard
|
||||||
|
###########################################################################
|
||||||
|
# Events that can occure by pressing the Buttons
|
||||||
|
EVENT_LOADG3D=2
|
||||||
|
EVENT_SAVEG3DV3=3
|
||||||
|
EVENT_SAVEG3DV4=4
|
||||||
|
EVENT_EXIT=100
|
||||||
|
###########################################################################
|
||||||
|
# GUI eventhandler
|
||||||
|
###########################################################################
|
||||||
|
def event(evt, val):
|
||||||
|
if evt == Blender.Draw.ESCKEY and not val: Blender.Draw.Exit()
|
||||||
|
def button_event(evt):
|
||||||
|
global EVENT_LOAD_G3D,EVENT_SAVE_G3DV3,EVENT_SAVE_G3DV4,EVENT_EXIT
|
||||||
|
if evt == EVENT_EXIT: Exit()
|
||||||
|
if evt == EVENT_LOADG3D:
|
||||||
|
defaultname = os.sep + ".g3d"
|
||||||
|
#I use this defaultnames only for development to have short ways to models
|
||||||
|
#if u want make a path to your models here and comment the above defaultname out.
|
||||||
|
#Be careful to not move the start of the Line because it matters in python
|
||||||
|
# defaultname="I:/glest/glest_game/techs/magitech/factions/magic/units/magic_armor/models/magic_armor_walking.g3d"
|
||||||
|
# defaultname="I:/glest/glest_game/techs/magitech/factions/.g3d"
|
||||||
|
# defaultname="I:/entwicklung/blenderexport/test/swordman_sample/swordman.g3d"
|
||||||
|
FileSelector(G3DLoader, "G3D to load", defaultname)
|
||||||
|
Blender.Redraw()
|
||||||
|
if evt==EVENT_SAVEG3DV3:
|
||||||
|
defaultname = Blender.sys.makename(Blender.Get("filename"),".g3d",1)
|
||||||
|
FileSelector(G3DSaverV3, "G3D V3 to save", defaultname)
|
||||||
|
if evt==EVENT_SAVEG3DV4:
|
||||||
|
defaultname = Blender.sys.makename(Blender.Get("filename"),".g3d",1)
|
||||||
|
FileSelector(G3DSaverV4, "G3D V4 to save", defaultname)
|
||||||
|
###########################################################################
|
||||||
|
# GUI Screenmask as a nice looking feature i Center the Mask
|
||||||
|
###########################################################################
|
||||||
|
def gui():
|
||||||
|
global EVENT_LOADG3D,EVENT_SAVEG3DV3,EVENT_SAVEG3DV4,EVENT_EXIT
|
||||||
|
xmiddle= GetScreenSize()[0] / 2 #calculate horizontal middle of the screen
|
||||||
|
#Clearing the Screen all here needs imported BGL + DRAW
|
||||||
|
glClearColor(0.0, 0.0, 0.0,1)
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT)
|
||||||
|
# logo
|
||||||
|
homedir = Blender.Get("homedir")
|
||||||
|
Logo = Load(homedir+ os.sep + "scripts" + os.sep + "g3d_logo.png") # Load Logo file
|
||||||
|
glEnable(GL_BLEND)
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
|
||||||
|
Image(Logo,(xmiddle-(Logo.getSize()[0]/2)),20)
|
||||||
|
glDisable(GL_BLEND)
|
||||||
|
#Title
|
||||||
|
tbuffer= "G3D Import Wizard supporting V3 / V4 models"
|
||||||
|
xpos = xmiddle - (GetStringWidth(tbuffer) /2)
|
||||||
|
glColor3f(1, 0, 0)
|
||||||
|
glRasterPos2d(xpos, 70)
|
||||||
|
Text(tbuffer)
|
||||||
|
tbuffer= "Please view any Errors / Info in the Blender Console"
|
||||||
|
xpos = xmiddle - (GetStringWidth(tbuffer) /2)
|
||||||
|
glColor3f(1, 1, 0)
|
||||||
|
glRasterPos2d(xpos, 55)
|
||||||
|
Text(tbuffer)
|
||||||
|
#Buttons
|
||||||
|
Button("Load G3D",EVENT_LOADG3D , xmiddle-140, 10, 100, 40)
|
||||||
|
#Button("Save G3D V3",EVENT_SAVEG3DV3 , xmiddle-100, 10, 100, 40)
|
||||||
|
#Button("Save G3D V4",EVENT_SAVEG3DV4 , xmiddle, 10, 100, 40)
|
||||||
|
Button("Exit",EVENT_EXIT , xmiddle+40, 10, 100, 40)
|
||||||
|
###########################################################################
|
||||||
|
# Registering GUI events (Activating GUI) THE END
|
||||||
|
###########################################################################
|
||||||
|
Register(gui, event, button_event)
|
535
source/tools/glexemel/g3d_xml_exporter.py
Normal file
535
source/tools/glexemel/g3d_xml_exporter.py
Normal file
@@ -0,0 +1,535 @@
|
|||||||
|
#!BPY
|
||||||
|
# coding: utf-8
|
||||||
|
"""
|
||||||
|
Name: 'G3D XML Exporter Ver:1.1'
|
||||||
|
Blender: 2.43
|
||||||
|
Group: 'Export'
|
||||||
|
Tooltip: 'Exports directly to G3D(if xml2g is installed next to this script) or XML (which can be converted to .g3d using xml2g)'
|
||||||
|
"""
|
||||||
|
###########################################################################
|
||||||
|
# Glest Model / Texture / Animation Exporter
|
||||||
|
# for the game Glest that you can find at http://www.glest.org
|
||||||
|
# copyright 2005-2006 By Vincent Gadoury
|
||||||
|
# Started Date: December 18 2005 Put Public Decembre 20 2005
|
||||||
|
# Ver: 1.0 (Jan 30 2009)
|
||||||
|
# Distributed under the GNU PUBLIC LICENSE
|
||||||
|
# Based on g3d_support.py by Andreas Becker
|
||||||
|
# and on glexemel by Jonathan Merritt
|
||||||
|
###########################################################################
|
||||||
|
# (I'm sorry for the poor quality of this text,
|
||||||
|
# I'm not a native English speaker)
|
||||||
|
#
|
||||||
|
#INSTALLATION :
|
||||||
|
# Copy this Script into your .blender\scripts directory.
|
||||||
|
# if you want direct .g3d support unpack all needed glexemel files to this directory too:
|
||||||
|
# LINUX:
|
||||||
|
# In case of linux its only: xml2g and g3d.dtd ( included is a binary for linux32 bit).
|
||||||
|
# The sourcecode can be found here:
|
||||||
|
# http://www.glest.org/files/contrib/tools/glexemel-0.1a.zip
|
||||||
|
# WINDOWS:
|
||||||
|
# If you are using windows, all files from the "bin" directory from the
|
||||||
|
# following zip files are needed:
|
||||||
|
# http://www.glest.org/files/contrib/tools/glexemel_win32_0.1a.zip
|
||||||
|
#
|
||||||
|
# In Blender, open a Script Window and in the menu choose "Update Menus"
|
||||||
|
# Export with File->Export->G3D XML Exporter
|
||||||
|
#
|
||||||
|
#PREPARE THE MODEL :
|
||||||
|
# Each of your meshes' faces must be a triangle (3 vertex)
|
||||||
|
# In Edit mode, you can press Space, edit>faces>Convert to Triangles
|
||||||
|
# Create and place all your meshes before texturing or animating.
|
||||||
|
# The X axe is the floor and the Y axe is the elevation. The center
|
||||||
|
# of the Blender's 3D space will be the center of you object, at the
|
||||||
|
# ground level. Before exporting your model, apply the transformations
|
||||||
|
# to each of your mesh (In the 3D space window's menu :
|
||||||
|
# Object->Clear/Apply->Apply ... )
|
||||||
|
# This will place the center of your mesh (the yellow or pink dot)
|
||||||
|
# at the center of the Blender 3D space.
|
||||||
|
#
|
||||||
|
# !!!!!!!!!!!!!!
|
||||||
|
# !!!new since 0.1.4: !!!
|
||||||
|
# If you have a non animating model, you have to set the start frame
|
||||||
|
# and the end frame to '1' in blenders 'timeline'-window. Otherwise a non
|
||||||
|
# animating animation will be exported, containing a lot of frames and your
|
||||||
|
# model gets really big.
|
||||||
|
# !!!!!!!!!!!!!!
|
||||||
|
#
|
||||||
|
# Before doing any texturing or animation, try to export your model and
|
||||||
|
# check your python console (the terminal which opens Blender) to see
|
||||||
|
# if there is a warning about the number of used faces in the summary.
|
||||||
|
# If there is, try to delete "false" faces (which use only 2 vertices)
|
||||||
|
# and transform all your faces in triangle.
|
||||||
|
#
|
||||||
|
#EXPORTING :
|
||||||
|
# You MUST select the meshes you want to export.
|
||||||
|
# Only meshes are exported among the selected objects.
|
||||||
|
#
|
||||||
|
# The diffuse color of the mesh will be it's (first) material's color.
|
||||||
|
# The opacity of the mesh will be it's material's alpha.
|
||||||
|
# Double sided property of the mesh is exported (see F9).
|
||||||
|
# If you want to use custom color in the texture, your mesh must be
|
||||||
|
# double sided. If you don't want custom color to be activated for the
|
||||||
|
# mesh, add a new boolean property to it (F4) named customColor and with
|
||||||
|
# the false value. Custom Color set if the alpha of the texture is
|
||||||
|
# replaced for the color of the player.
|
||||||
|
#
|
||||||
|
#TEXTURING :
|
||||||
|
# To use a texture for the mesh, you must add a texture at the FIRST
|
||||||
|
# position to the mesh's material. The texture type must be 'image'
|
||||||
|
# and you should insert the real image. In fact, only the filename
|
||||||
|
# of the image is used. After having mapped the image on the
|
||||||
|
# mesh with UV Face selection, you don't need anymore to "stick"
|
||||||
|
# the coordinates to the vertices.
|
||||||
|
# Your texture's format must be TGA, without compression and with the origin
|
||||||
|
# at the bottom left position. The side of the image must be a multiple
|
||||||
|
# of 2. In practice, you must use only one image for all your meshes.
|
||||||
|
#
|
||||||
|
#ANIMATING :
|
||||||
|
# You can export all animations made with blenders armature system.
|
||||||
|
# You have to set the start frame and the end frame in the 'timeline'-window
|
||||||
|
# to define the animation which will be exported.
|
||||||
|
# If you animate without using the armatures it will not work!!
|
||||||
|
#
|
||||||
|
# LINKS :
|
||||||
|
# Animating with armatures
|
||||||
|
# http://www.blender.org/documentation/htmlI/x1829.html
|
||||||
|
# Map an image on your mesh with UV Face selection :
|
||||||
|
# http://en.wikibooks.org/wiki/Blender_3D:_Noob_to_Pro/UV_Map_Basics
|
||||||
|
# http://download.blender.org/documentation/htmlI/ch11s05.html
|
||||||
|
#
|
||||||
|
#CONVERT TO .G3D
|
||||||
|
# The following is no longer needed if you copied g3d.dtd and xml2g(.exe) next
|
||||||
|
# to this script:
|
||||||
|
#
|
||||||
|
# Use the xml2g program of the glexemel tool at
|
||||||
|
# http://www.glest.org/files/contrib/tools/
|
||||||
|
# Syntax : ./xml2g ExportedFile.xml DesiredFile.g3d
|
||||||
|
#
|
||||||
|
# WARNING : The current version of this program don't seems to work...
|
||||||
|
# You'll have to add the lines (if they aren't there) :
|
||||||
|
# #pragma pack(push, 1)
|
||||||
|
# near of the beginning of the file "g3dv4.h" of glexemel and
|
||||||
|
# #pragma pack(pop)
|
||||||
|
# before the #endif
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#ChangeLog :
|
||||||
|
# 1.1: by Titus Tscharntke (titi)
|
||||||
|
# fixed bug in windows ( problems with file sparator char )
|
||||||
|
# 1.0: Big thanks go to Frank Tetzel (Yggdrasil) who finally made a
|
||||||
|
# direct export to .g3d possible. If you copy g3d.dtd and
|
||||||
|
# xml2g(.exe) next to this script it will export to .g3d.
|
||||||
|
# If not, it will export to .xml like before.
|
||||||
|
#
|
||||||
|
# 0.1.7 : by Titus Tscharntke (titi)
|
||||||
|
# removed non 7-bit ascii characters for newer versions of python
|
||||||
|
# 0.1.6 : by justWeedy(weedkiller)
|
||||||
|
# Basic colorsettings for maps are often unused but may cause
|
||||||
|
# models look "bright".
|
||||||
|
# There are Hardcoded defauld values to avoid this.
|
||||||
|
# Turn On/Off due the boolean <useHardCodedColor>
|
||||||
|
# 0.1.5 : by weedkiller
|
||||||
|
# You don't have to apply scale and rotation anymore
|
||||||
|
# 0.1.4 : by weedkiller and Titus Tscharntke ( www.titusgames.de )
|
||||||
|
# New implementation of the animation export ( including some usage changes!!! )
|
||||||
|
# Exporting animations is now possible with newer Blender versions ( tested with 2.43 )
|
||||||
|
#
|
||||||
|
# 0.1.3 : by Titus Tscharntke ( www.titusgames.de )
|
||||||
|
# Fixed a bug with getProperty() in blender 2.43
|
||||||
|
#
|
||||||
|
# 0.1.2 :
|
||||||
|
# Correcting an execution bug
|
||||||
|
# Adding the "frameCount" property for each object
|
||||||
|
# Using only the triangle faces for the index count
|
||||||
|
# (problems of linking between index and vertex may occur)
|
||||||
|
# Adding the summary display in the python console
|
||||||
|
# Adding a better documentation
|
||||||
|
# 0.1.1b :
|
||||||
|
# Adding a vertex duplication method to correct the vertex UV problem.
|
||||||
|
# Correcting NMVert.uvco misuse
|
||||||
|
#
|
||||||
|
#ToDo:
|
||||||
|
# More tests...
|
||||||
|
# More validations...
|
||||||
|
# Warn the user if there is something wrong, e.g. :
|
||||||
|
# - no mesh among the selected objects;
|
||||||
|
# - texture without uvco;
|
||||||
|
# - no material on a mesh.
|
||||||
|
# Test and correct the theoric linking problem if faces are ignored...
|
||||||
|
#
|
||||||
|
#Contributions :
|
||||||
|
# pseudonym404 : NMVert.uvco issue and solutions
|
||||||
|
#
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
import Blender
|
||||||
|
from Blender import NMesh
|
||||||
|
from Blender import sys as bsys
|
||||||
|
|
||||||
|
import subprocess, os
|
||||||
|
|
||||||
|
|
||||||
|
# part Hardcoded Color >>
|
||||||
|
HardCodedDiffuse=0.588235
|
||||||
|
HardCodedSpecular=0.900000
|
||||||
|
useHardCodedColor='true' #'false' if not wanted
|
||||||
|
# part Hardcoded Color <<
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
seenindex=set()
|
||||||
|
uvlist=[]
|
||||||
|
|
||||||
|
# This list will contain the associative "real" vertex of each duplicated vertex
|
||||||
|
# in ascendant order.
|
||||||
|
# The fisrt "vertex" of the list (newvertices[0]) has the index len(mesh.verts)
|
||||||
|
newvertices=[]
|
||||||
|
currentnewvertex=0
|
||||||
|
|
||||||
|
#This list will contain all the "new" faces' indices
|
||||||
|
newindices=[]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def icmp(x,y):
|
||||||
|
return cmp(x,y)
|
||||||
|
|
||||||
|
def notseenindex(index):
|
||||||
|
seen = index in seenindex
|
||||||
|
if not seen: seenindex.add(index)
|
||||||
|
return not seen
|
||||||
|
|
||||||
|
# this will return the properties data if it exists, else the given defaultvalue
|
||||||
|
def getPropertyIfExists(blenderobject,propertyName,defaultvalue):
|
||||||
|
propertiesList = blenderobject.getAllProperties()
|
||||||
|
lpropertiesList = range( 0 , len(propertiesList) )
|
||||||
|
for iprop in lpropertiesList:
|
||||||
|
objectProperty = propertiesList[iprop]
|
||||||
|
currentPropertyName=objectProperty.getName()
|
||||||
|
if currentPropertyName == propertyName:
|
||||||
|
return objectProperty.getData()
|
||||||
|
return defaultvalue
|
||||||
|
|
||||||
|
|
||||||
|
def write_obj(filepath):
|
||||||
|
out = file(filepath, 'w')
|
||||||
|
|
||||||
|
print("-----------------------------------------------")
|
||||||
|
|
||||||
|
#Header
|
||||||
|
out.write( '<?xml version="1.0" encoding="ASCII" ?>\n' )
|
||||||
|
out.write( '<!DOCTYPE G3D SYSTEM "g3d.dtd">\n' )
|
||||||
|
out.write( '<!-- \n' )
|
||||||
|
out.write( ' This file is an XML encoding of a G3D binary\n' )
|
||||||
|
out.write( ' file. The XML format is by Jonathan Merritt\n' )
|
||||||
|
out.write( ' (not yet accepted as part of Glest!).\n' )
|
||||||
|
out.write( ' The file was exported from Blender with the\n' )
|
||||||
|
out.write( ' G3D-XML Exporter script by Vincent Gadoury.\n' )
|
||||||
|
out.write( '-->\n' )
|
||||||
|
out.write( '<G3D version="4">\n' )
|
||||||
|
|
||||||
|
objects = Blender.Object.GetSelected()
|
||||||
|
|
||||||
|
print("Exporting %i selected objects to XML-G3D format..." %(len(objects)))
|
||||||
|
|
||||||
|
#FOR EACH MESH
|
||||||
|
lobjects = range( 0 , len(objects) )
|
||||||
|
for iobj in lobjects:
|
||||||
|
object = objects[iobj]
|
||||||
|
|
||||||
|
mesh = object.getData()
|
||||||
|
# Skip the object if it's not a mesh
|
||||||
|
if type(mesh) != Blender.Types.NMeshType :
|
||||||
|
continue
|
||||||
|
|
||||||
|
#Clear the lists
|
||||||
|
seenindex.clear()
|
||||||
|
uvlist[:]=[]
|
||||||
|
newvertices[:]=[]
|
||||||
|
newindices[:]=[]
|
||||||
|
|
||||||
|
currentnewvertex=(len(mesh.verts))
|
||||||
|
|
||||||
|
#Find some properties of the mesh
|
||||||
|
|
||||||
|
image = None
|
||||||
|
textureName = ''
|
||||||
|
diffuseTexture = 'false'
|
||||||
|
opacity = 1
|
||||||
|
diffuseColor = [ 1.0, 1.0, 1.0 ]
|
||||||
|
|
||||||
|
#Find if the mesh has a material and a texture
|
||||||
|
# (opacity, diffuseColor, diffuseTexture, textureName)
|
||||||
|
if len(mesh.materials) > 0:
|
||||||
|
material = mesh.materials[0]
|
||||||
|
|
||||||
|
opacity = material.alpha
|
||||||
|
diffuseColor[0] = material.rgbCol[0]
|
||||||
|
diffuseColor[1] = material.rgbCol[1]
|
||||||
|
diffuseColor[2] = material.rgbCol[2]
|
||||||
|
|
||||||
|
# part Hardcoded Color >>
|
||||||
|
if useHardCodedColor :
|
||||||
|
diffuseColor[0] = HardCodedDiffuse
|
||||||
|
diffuseColor[1] = HardCodedDiffuse
|
||||||
|
diffuseColor[2] = HardCodedDiffuse
|
||||||
|
# part Hardcoded Color <<
|
||||||
|
|
||||||
|
if material.getTextures()[0]:
|
||||||
|
image = material.getTextures()[0].tex.getImage()
|
||||||
|
if image:
|
||||||
|
textureName = image.getFilename()
|
||||||
|
textureName = textureName.split(os.path.normcase('/'))[-1] #get only the filename
|
||||||
|
diffuseTexture = 'true'
|
||||||
|
#End material and texture
|
||||||
|
|
||||||
|
#TwoSided
|
||||||
|
if mesh.mode & NMesh.Modes['TWOSIDED']:
|
||||||
|
twoSided='true'
|
||||||
|
else:
|
||||||
|
twoSided='false'
|
||||||
|
|
||||||
|
#CustomColor
|
||||||
|
customColor = 1
|
||||||
|
customColor = getPropertyIfExists(object,'customColor',customColor)
|
||||||
|
if customColor:
|
||||||
|
customColor = 'true'
|
||||||
|
else:
|
||||||
|
customColor = 'false'
|
||||||
|
|
||||||
|
#Real face count (only use triangle)
|
||||||
|
realFaceCount = 0
|
||||||
|
for face in mesh.faces:
|
||||||
|
if (len(face.v) == 3):
|
||||||
|
realFaceCount += 1
|
||||||
|
|
||||||
|
#Frames number
|
||||||
|
frameCount = 1
|
||||||
|
#frameCount = getPropertyIfExists(object,'frameCount',frameCount)
|
||||||
|
startFrame = Blender.Get('staframe')
|
||||||
|
endFrame = Blender.Get('endframe')
|
||||||
|
frameCount = endFrame-startFrame+1
|
||||||
|
|
||||||
|
# TRANSFERING FACE TEXTURE COORD. TO VERTEX TEXTURE COORD.
|
||||||
|
# and duplicating vertex associated to different uvco
|
||||||
|
|
||||||
|
if textureName == '': #THERE IS NO TEXTURE
|
||||||
|
#create the index list, don't care of newvertices
|
||||||
|
for face in mesh.faces:
|
||||||
|
faceindices = []
|
||||||
|
if (len(face.v) == 3):
|
||||||
|
for vert in face.v:
|
||||||
|
faceindices.append(vert.index)
|
||||||
|
newindices.append(faceindices[0:3])
|
||||||
|
|
||||||
|
else: # THERE IS A TEXTURE
|
||||||
|
|
||||||
|
uvlist[:] = [[0]*3 for i in range( len(mesh.verts) )]
|
||||||
|
|
||||||
|
for face in mesh.faces:
|
||||||
|
faceindices = []
|
||||||
|
if (len(face.v) == 3):
|
||||||
|
for i in range(len(face.uv)):
|
||||||
|
vindex = face.v[i].index
|
||||||
|
|
||||||
|
if notseenindex(vindex):
|
||||||
|
uvlist[vindex] = [vindex, face.uv[i][0], face.uv[i][1]]
|
||||||
|
|
||||||
|
elif uvlist[vindex][1] != face.uv[i][0] or \
|
||||||
|
uvlist[vindex][2] != face.uv[i][1]:
|
||||||
|
#debug: print("dif: [%f,%f] et [%f,%f]" %( uvlist[vindex][1], face.uv[i][0], uvlist[vindex][2], face.uv[i][1] ))
|
||||||
|
#Create a new "entry" for an existing vertex
|
||||||
|
newvertices.append(vindex)
|
||||||
|
uvlist.append([currentnewvertex, face.uv[i][0], face.uv[i][1]])
|
||||||
|
vindex = currentnewvertex
|
||||||
|
currentnewvertex += 1
|
||||||
|
|
||||||
|
faceindices.append(vindex)
|
||||||
|
newindices.append(faceindices[0:3])
|
||||||
|
|
||||||
|
#End texture and vertex copy
|
||||||
|
|
||||||
|
|
||||||
|
# ---- BEGINNING OF THE WRITING OF THE FILE ----
|
||||||
|
|
||||||
|
#MESH HEADER
|
||||||
|
out.write( '\n<Mesh \n' )
|
||||||
|
out.write( ' name="%s" \n' % (mesh.name) )
|
||||||
|
out.write( ' frameCount="%i" \n' % ( frameCount ) )
|
||||||
|
out.write( ' vertexCount="%i" \n' % (len(mesh.verts) + len(newvertices)) )
|
||||||
|
out.write( ' indexCount="%i" \n' % ( realFaceCount * 3 ) )
|
||||||
|
out.write( ' specularPower="9.999999" \n' )
|
||||||
|
out.write( ' opacity="%f" \n' % (opacity) )
|
||||||
|
out.write( ' twoSided="%s" \n' % ( twoSided ) )
|
||||||
|
out.write( ' customColor="%s" \n' % ( customColor ) )
|
||||||
|
out.write( ' diffuseTexture="%s" > \n' % ( diffuseTexture ) )
|
||||||
|
|
||||||
|
#DIFFUSE
|
||||||
|
out.write( ' <Diffuse>\n <Color r="%f" g="%f" b="%f" />\n </Diffuse>\n' % ( diffuseColor[0], diffuseColor[1], diffuseColor[2] ) )
|
||||||
|
|
||||||
|
#SPECULAR # part Hardcoded Color: THIS WAS ALREADY HARDCODED ...
|
||||||
|
out.write( ' <Specular><Color r="%f" g="%f" b="%f" /></Specular>\n' % (HardCodedSpecular, HardCodedSpecular, HardCodedSpecular) )
|
||||||
|
|
||||||
|
#TEXTURE
|
||||||
|
if textureName == '':
|
||||||
|
out.write( ' <!-- NO TEXTURE -->\n' )
|
||||||
|
else:
|
||||||
|
out.write( ' <Texture name="%s" />\n' % (textureName) )
|
||||||
|
|
||||||
|
#For each FRAME
|
||||||
|
|
||||||
|
#VERTICES
|
||||||
|
framelist={}
|
||||||
|
l = range( startFrame , startFrame+frameCount )
|
||||||
|
for frame in l:
|
||||||
|
# set the right frame
|
||||||
|
Blender.Set('curframe', frame)
|
||||||
|
curObject=object
|
||||||
|
curMatrix= curObject.getMatrix('worldspace')
|
||||||
|
|
||||||
|
fmesh = curObject.getData()
|
||||||
|
|
||||||
|
# after creation of new Object, Selection is no longer reliable (new obj. are selected, too), already corrected in code (see: curObject= ...)
|
||||||
|
defmesh=Blender.Mesh.New(curObject.name+'F'+str(frame))
|
||||||
|
defmesh.getFromObject(curObject.name)
|
||||||
|
|
||||||
|
framelist[frame]=defmesh
|
||||||
|
|
||||||
|
# just to avoid work
|
||||||
|
fmesh=defmesh
|
||||||
|
|
||||||
|
out.write( ' <Vertices frame="%i">\n' % ( frame-startFrame ) )
|
||||||
|
# "real" vertex
|
||||||
|
for vert in fmesh.verts:
|
||||||
|
vert.co= vert.co * curMatrix
|
||||||
|
out.write( ' <Vertex x="%f" y="%f" z="%f" />\n' % (vert.co.x,vert.co.y,vert.co.z) )
|
||||||
|
# "linked" new vertex
|
||||||
|
for ind in newvertices:
|
||||||
|
out.write( ' <Vertex x="%f" y="%f" z="%f" />\n' % \
|
||||||
|
(fmesh.verts[ind].co.x, fmesh.verts[ind].co.y, fmesh.verts[ind].co.z) )
|
||||||
|
out.write( ' </Vertices>\n' )
|
||||||
|
|
||||||
|
#NORMALS
|
||||||
|
l = range( startFrame , startFrame+frameCount )
|
||||||
|
for frame in l:
|
||||||
|
Blender.Set('curframe', frame)
|
||||||
|
|
||||||
|
# getting the created meshes
|
||||||
|
fmesh = framelist[frame] #.getData()
|
||||||
|
|
||||||
|
out.write( ' <Normals frame="%i">\n' % ( frame-startFrame ) )
|
||||||
|
# "real" vertex
|
||||||
|
for vert in fmesh.verts:
|
||||||
|
out.write( ' <Normal x="%f" y="%f" z="%f" />\n' % (vert.no.x, vert.no.y, vert.no.z) )
|
||||||
|
# "linked" new vertex
|
||||||
|
for ind in newvertices:
|
||||||
|
out.write( ' <Normal x="%f" y="%f" z="%f" />\n' % \
|
||||||
|
(fmesh.verts[ind].no.x, fmesh.verts[ind].no.y, fmesh.verts[ind].no.z) )
|
||||||
|
out.write( ' </Normals>\n' )
|
||||||
|
|
||||||
|
#End FRAMES
|
||||||
|
|
||||||
|
|
||||||
|
#TEXTURES COORDS
|
||||||
|
if textureName == '':
|
||||||
|
out.write( ' <!-- NO TEXTURE COORDS -->\n' )
|
||||||
|
else:
|
||||||
|
out.write( ' <TexCoords>\n' )
|
||||||
|
#write list
|
||||||
|
for uv in uvlist:
|
||||||
|
out.write( ' <ST s="%f" t="%f" />\n' % (uv[1], uv[2]) )
|
||||||
|
out.write( ' </TexCoords>\n' )
|
||||||
|
|
||||||
|
#INDICES
|
||||||
|
out.write( ' <Indices>\n' )
|
||||||
|
for face in newindices:
|
||||||
|
for vert in face:
|
||||||
|
out.write( ' <Ix i="%i" />\n' % (vert) )
|
||||||
|
# out.write('\n')
|
||||||
|
out.write( ' </Indices>\n' )
|
||||||
|
|
||||||
|
#END MESH
|
||||||
|
out.write( '</Mesh>\n' )
|
||||||
|
|
||||||
|
#Printing a summary of the mesh to the output
|
||||||
|
print("\nObject : %s" %(object.getName() ) )
|
||||||
|
print("Mesh : %s" %(mesh.name) )
|
||||||
|
print("%i frames" % ( frameCount ) )
|
||||||
|
print("%i vertices" % (len(mesh.verts) + len(newvertices)) )
|
||||||
|
print("%i exported faces (%i real faces)" % (realFaceCount, len(mesh.faces) ) )
|
||||||
|
if realFaceCount != len(mesh.faces) :
|
||||||
|
print("WARNING : some faces have been ignored (not triangle)\n" +
|
||||||
|
" Errors may occur with faces and indices linking..." )
|
||||||
|
Blender.Draw.PupMenu("export warning:%t|WARNING : some faces have been ignored (not triangle)|" +
|
||||||
|
" Errors may occur with faces and indices linking...")
|
||||||
|
print("%i indices" % (realFaceCount * 3) )
|
||||||
|
print("opacity : %f" % (opacity) )
|
||||||
|
print("two sided : %s" % (twoSided) )
|
||||||
|
print("custom color : %s" % (customColor) )
|
||||||
|
print("Use a diffuse texture : %s" % (diffuseTexture) )
|
||||||
|
if textureName != '':
|
||||||
|
print( " texture name : %s" % (textureName) )
|
||||||
|
print("diffuse color : %f,%f,%f" % ( diffuseColor[0], diffuseColor[1], diffuseColor[2] ) )
|
||||||
|
print("Number of new vertices to fit uv mapping : %i\n" % ( len(newvertices) ) )
|
||||||
|
|
||||||
|
#FOOTER
|
||||||
|
out.write( '</G3D>\n' )
|
||||||
|
|
||||||
|
out.close()
|
||||||
|
#END write_obj
|
||||||
|
|
||||||
|
# file selector based on ac3d_export.py by Willian P. Germano
|
||||||
|
# File Selector callback:
|
||||||
|
def fs_callback(filename):
|
||||||
|
global cmd, extension, scriptsdir
|
||||||
|
if not filename.endswith(extension): filename = '%s%s' % (filename, extension)
|
||||||
|
if bsys.exists(filename):
|
||||||
|
if Blender.Draw.PupMenu('OVERWRITE?%t|File exists') != 1:
|
||||||
|
return
|
||||||
|
if cmd:
|
||||||
|
tmp = bsys.join(scriptsdir, "tmp.xml")
|
||||||
|
write_obj(tmp)
|
||||||
|
|
||||||
|
print "running glexemel"
|
||||||
|
cmd = [cmd, tmp, filename]
|
||||||
|
print cmd
|
||||||
|
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
out = p.stdout.read()
|
||||||
|
err = p.stderr.read()
|
||||||
|
res = p.wait()
|
||||||
|
if res != 0 or err:
|
||||||
|
s = ''
|
||||||
|
if out:
|
||||||
|
s += out.replace('\n', '|')
|
||||||
|
if err:
|
||||||
|
s += err.replace('\n', '|')
|
||||||
|
Blender.Draw.PupMenu('glexemel error: see console%t|' + s)
|
||||||
|
print out
|
||||||
|
print err
|
||||||
|
print res
|
||||||
|
else:
|
||||||
|
write_obj(filename)
|
||||||
|
print "glexemel not found"
|
||||||
|
|
||||||
|
|
||||||
|
scriptsdir = Blender.Get('scriptsdir')
|
||||||
|
files = os.listdir(scriptsdir)
|
||||||
|
cmd = ''
|
||||||
|
extension=".xml"
|
||||||
|
for fname in files:
|
||||||
|
if fname.startswith("xml2g"):
|
||||||
|
cmd = bsys.join(scriptsdir, fname)
|
||||||
|
extension = ".g3d"
|
||||||
|
break
|
||||||
|
|
||||||
|
OBJS = Blender.Object.GetSelected()
|
||||||
|
if not OBJS:
|
||||||
|
Blender.Draw.PupMenu('ERROR: no objects selected')
|
||||||
|
else:
|
||||||
|
fname = bsys.makename(ext=extension)
|
||||||
|
Blender.Window.FileSelector(fs_callback, "Export XML-G3D", fname)
|
||||||
|
#Blender.Window.FileSelector(write_obj, "Export")
|
57
source/tools/glexemel/g3dv4.h
Normal file
57
source/tools/glexemel/g3dv4.h
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/**
|
||||||
|
* File: g3dv4.h
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Data types used by the G3D format.
|
||||||
|
*
|
||||||
|
* This file is copied from portions of the Glest project:
|
||||||
|
* http://www.glest.org
|
||||||
|
*
|
||||||
|
* This file may be distributed under the terms of the GNU General Public
|
||||||
|
* License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef G3DV4_HEADER
|
||||||
|
#define G3DV4_HEADER
|
||||||
|
// bug fix from wiki
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
|
typedef float float32;
|
||||||
|
typedef unsigned char uint8;
|
||||||
|
typedef unsigned short int uint16;
|
||||||
|
typedef unsigned int uint32;
|
||||||
|
|
||||||
|
#define NAMESIZE 64
|
||||||
|
|
||||||
|
struct FileHeader{
|
||||||
|
uint8 id[3];
|
||||||
|
uint8 version;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ModelHeader{
|
||||||
|
uint16 meshCount;
|
||||||
|
uint8 type;
|
||||||
|
};
|
||||||
|
enum ModelType{
|
||||||
|
mtMorphMesh
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MeshHeader{
|
||||||
|
uint8 name[NAMESIZE];
|
||||||
|
uint32 frameCount;
|
||||||
|
uint32 vertexCount;
|
||||||
|
uint32 indexCount;
|
||||||
|
float32 diffuseColor[3];
|
||||||
|
float32 specularColor[3];
|
||||||
|
float32 specularPower;
|
||||||
|
float32 opacity;
|
||||||
|
uint32 properties;
|
||||||
|
uint32 textures;
|
||||||
|
};
|
||||||
|
enum MeshPropertyFlag{
|
||||||
|
mpfTwoSided= 0,
|
||||||
|
mpfCustomColor= 1
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
#endif
|
670
source/tools/glexemel/xml2g.c
Normal file
670
source/tools/glexemel/xml2g.c
Normal file
@@ -0,0 +1,670 @@
|
|||||||
|
/**
|
||||||
|
* File: xml2g.c
|
||||||
|
* Written: Jonathan Merritt <jmerritt@warpax.com>
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Converts G3Dv4 XML files into the binary representation used in the game.
|
||||||
|
* Requirements:
|
||||||
|
* libxml2
|
||||||
|
*
|
||||||
|
* Copyright (C) Jonathan Merritt 2005.
|
||||||
|
* This file may be distributed under the terms of the GNU General Public
|
||||||
|
* License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <libxml/parser.h>
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
|
||||||
|
#include "g3dv4.h"
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE 1
|
||||||
|
#endif
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forward function declarations.
|
||||||
|
*/
|
||||||
|
int xml2g3d(xmlDocPtr doc, FILE *outfile);
|
||||||
|
void usage(char *execname);
|
||||||
|
unsigned int countChildren(xmlNode *n, xmlChar *name);
|
||||||
|
int processMesh(xmlNode *n, FILE *outfile);
|
||||||
|
int readColorChild(xmlNode *n, char *childName, float32 *color);
|
||||||
|
int processVertices(xmlNode *n, FILE *outfile, uint32 vertexCount);
|
||||||
|
int processNormals(xmlNode *n, FILE *outfile, uint32 vertexCount);
|
||||||
|
int processTexcoords(xmlNode *n, FILE *outfile, uint32 vertexCount);
|
||||||
|
int processIndices(xmlNode *n, FILE *outfile, uint32 indexCount);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Program entry point.
|
||||||
|
*
|
||||||
|
* @param argc: Number of arguments passed to the program.
|
||||||
|
* @param argv: Array of string arguments.
|
||||||
|
*
|
||||||
|
* @returns: EXIT_SUCCESS or EXIT_FAILURE depending upon success or failure
|
||||||
|
* of the conversion to XML.
|
||||||
|
*/
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *infilename, *outfilename;
|
||||||
|
FILE *outfile;
|
||||||
|
int successFlag;
|
||||||
|
xmlParserCtxtPtr ctxt;
|
||||||
|
xmlDocPtr doc;
|
||||||
|
|
||||||
|
/* parse command line arguments */
|
||||||
|
if (argc != 3)
|
||||||
|
{
|
||||||
|
usage(argv[0]);
|
||||||
|
return (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
infilename = argv[1];
|
||||||
|
outfilename = argv[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* attempt to parse the XML file */
|
||||||
|
LIBXML_TEST_VERSION
|
||||||
|
ctxt = xmlNewParserCtxt();
|
||||||
|
if (ctxt == NULL)
|
||||||
|
{
|
||||||
|
printf("Failed to allocate XML parser context!\n");
|
||||||
|
return (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
doc = xmlCtxtReadFile(ctxt, infilename, NULL, XML_PARSE_DTDVALID);
|
||||||
|
if (doc == NULL)
|
||||||
|
{
|
||||||
|
printf("Could not parse XML file \"%s\"!\n", infilename);
|
||||||
|
xmlFreeParserCtxt(ctxt);
|
||||||
|
return (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* attempt to open the output binary file */
|
||||||
|
outfile = fopen(outfilename, "wb");
|
||||||
|
if (outfile == NULL)
|
||||||
|
{
|
||||||
|
printf("Could not open file \"%s\" for writing!\n",
|
||||||
|
outfilename);
|
||||||
|
xmlFreeDoc(doc);
|
||||||
|
xmlFreeParserCtxt(ctxt);
|
||||||
|
xmlCleanupParser();
|
||||||
|
return (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* perform the conversion: XML -> binary */
|
||||||
|
successFlag = xml2g3d(doc, outfile);
|
||||||
|
|
||||||
|
/* close the files */
|
||||||
|
xmlFreeDoc(doc);
|
||||||
|
xmlFreeParserCtxt(ctxt);
|
||||||
|
xmlCleanupParser();
|
||||||
|
fclose(outfile);
|
||||||
|
|
||||||
|
/* return a success or failure flag */
|
||||||
|
if (successFlag)
|
||||||
|
return (EXIT_SUCCESS);
|
||||||
|
else
|
||||||
|
return (EXIT_FAILURE);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints a "Usage:" string for the program.
|
||||||
|
*
|
||||||
|
* @param execname: Executable name of the program.
|
||||||
|
*/
|
||||||
|
void usage(char *execname)
|
||||||
|
{
|
||||||
|
printf("Usage:\n");
|
||||||
|
printf(" %s infile.xml outfile.g3d\n", execname);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the conversion from the XML file format to the G3D binary format.
|
||||||
|
*
|
||||||
|
* @param doc: XML DOM document for input.
|
||||||
|
* @param outfile: Binary file, opened as "wb", for output.
|
||||||
|
*/
|
||||||
|
int xml2g3d(xmlDocPtr doc, FILE *outfile)
|
||||||
|
{
|
||||||
|
struct FileHeader fh;
|
||||||
|
struct ModelHeader mh;
|
||||||
|
xmlNode *root_element;
|
||||||
|
xmlNode *curNode;
|
||||||
|
xmlChar version[] = "version";
|
||||||
|
|
||||||
|
/* fetch the root element and check it */
|
||||||
|
root_element = xmlDocGetRootElement(doc);
|
||||||
|
assert(root_element->type == XML_ELEMENT_NODE);
|
||||||
|
if (strcmp((char*)root_element->name, "G3D") != 0)
|
||||||
|
{
|
||||||
|
printf("G3D document not found!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (strcmp((char*)xmlGetProp(root_element, version), "4") != 0)
|
||||||
|
{
|
||||||
|
printf("Only version 4 G3D documents can be handled!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write out the file header */
|
||||||
|
memset(&fh, 0, sizeof(struct FileHeader));
|
||||||
|
fh.id[0] = 'G'; fh.id[1] = '3'; fh.id[2] = 'D'; fh.version=4;
|
||||||
|
fwrite(&fh, sizeof(struct FileHeader), 1, outfile);
|
||||||
|
|
||||||
|
/* write out the model header */
|
||||||
|
memset(&mh, 0, sizeof(struct ModelHeader));
|
||||||
|
mh.meshCount = (uint16)countChildren(root_element, (xmlChar*)"Mesh");
|
||||||
|
mh.type = 0;
|
||||||
|
fwrite(&mh, sizeof(struct ModelHeader), 1, outfile);
|
||||||
|
|
||||||
|
/* process each mesh in the file */
|
||||||
|
curNode = root_element->children;
|
||||||
|
for (; curNode; curNode = curNode->next)
|
||||||
|
{
|
||||||
|
if (curNode->type == XML_ELEMENT_NODE)
|
||||||
|
{
|
||||||
|
if (strcmp((char*)curNode->name, "Mesh") == 0)
|
||||||
|
{
|
||||||
|
if (processMesh(curNode, outfile) == FALSE)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Counts the number of child nodes with the specified name.
|
||||||
|
*
|
||||||
|
* @param n: Node to count the children from.
|
||||||
|
* @param name: Name of the child nodes to count.
|
||||||
|
*
|
||||||
|
* @return: The number of child nodes.
|
||||||
|
*/
|
||||||
|
unsigned int countChildren(xmlNode *n, xmlChar *name)
|
||||||
|
{
|
||||||
|
unsigned int count = 0;
|
||||||
|
xmlNode *curNode = NULL;
|
||||||
|
|
||||||
|
for (curNode = n->children; curNode; curNode = curNode->next)
|
||||||
|
{
|
||||||
|
if (curNode->type == XML_ELEMENT_NODE)
|
||||||
|
{
|
||||||
|
if (strcmp((char*)curNode->name, (char*)name) == 0)
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes all <Mesh> elements from the XML file.
|
||||||
|
*
|
||||||
|
* @param n: <Mesh> element
|
||||||
|
* @param outfile: Binary file, opened as "wb", for output.
|
||||||
|
*
|
||||||
|
* @return: TRUE if successful, FALSE otherwise.
|
||||||
|
*/
|
||||||
|
int processMesh(xmlNode *n, FILE *outfile)
|
||||||
|
{
|
||||||
|
xmlChar name[] = "name";
|
||||||
|
xmlChar frameCount[] = "frameCount";
|
||||||
|
xmlChar vertexCount[] = "vertexCount";
|
||||||
|
xmlChar indexCount[] = "indexCount";
|
||||||
|
xmlChar specularPower[] = "specularPower";
|
||||||
|
xmlChar opacity[] = "opacity";
|
||||||
|
xmlChar twoSided[] = "twoSided";
|
||||||
|
xmlChar customColor[] = "customColor";
|
||||||
|
xmlChar diffuseTexture[] = "diffuseTexture";
|
||||||
|
|
||||||
|
float32 color[3];
|
||||||
|
|
||||||
|
struct MeshHeader mh;
|
||||||
|
uint8 texname[NAMESIZE];
|
||||||
|
|
||||||
|
int foundFlag = FALSE;
|
||||||
|
xmlNode *texn = NULL;
|
||||||
|
xmlNode *curNode = NULL;
|
||||||
|
|
||||||
|
/* make sure we're dealing with a <Mesh> element */
|
||||||
|
assert(strcmp((char*)n->name, "Mesh") == 0);
|
||||||
|
|
||||||
|
/* populate the MeshHeader structure appropriately */
|
||||||
|
memset(&mh, 0, sizeof(struct MeshHeader));
|
||||||
|
strncpy((char*)mh.name, (char*)xmlGetProp(n, name), NAMESIZE);
|
||||||
|
mh.frameCount = (uint32)atoi((char*)xmlGetProp(n, frameCount));
|
||||||
|
mh.vertexCount = (uint32)atoi((char*)xmlGetProp(n, vertexCount));
|
||||||
|
mh.indexCount = (uint32)atoi((char*)xmlGetProp(n, indexCount));
|
||||||
|
if (readColorChild(n, "Diffuse", color) == FALSE)
|
||||||
|
return FALSE;
|
||||||
|
mh.diffuseColor[0] = color[0];
|
||||||
|
mh.diffuseColor[1] = color[1];
|
||||||
|
mh.diffuseColor[2] = color[2];
|
||||||
|
if (readColorChild(n, "Specular", color) == FALSE)
|
||||||
|
return FALSE;
|
||||||
|
mh.specularColor[0] = color[0];
|
||||||
|
mh.specularColor[1] = color[1];
|
||||||
|
mh.specularColor[2] = color[2];
|
||||||
|
mh.specularPower = (float32)atof((char*)xmlGetProp(n, specularPower));
|
||||||
|
mh.opacity = (float32)atof((char*)xmlGetProp(n, opacity));
|
||||||
|
mh.properties = 0;
|
||||||
|
if (strcmp((char*)xmlGetProp(n, twoSided), "true") == 0)
|
||||||
|
mh.properties += (0x1 << mpfTwoSided);
|
||||||
|
if (strcmp((char*)xmlGetProp(n, customColor), "true") == 0)
|
||||||
|
mh.properties += (0x1 << mpfCustomColor);
|
||||||
|
mh.textures = 0;
|
||||||
|
if (strcmp((char*)xmlGetProp(n, diffuseTexture), "true") == 0)
|
||||||
|
mh.textures = 1;
|
||||||
|
|
||||||
|
/* write the MeshHeader */
|
||||||
|
fwrite(&mh, sizeof(struct MeshHeader), 1, outfile);
|
||||||
|
|
||||||
|
/* if we have a texture, then also write its name */
|
||||||
|
foundFlag = FALSE;
|
||||||
|
if (mh.textures)
|
||||||
|
{
|
||||||
|
for (texn=n->children; texn; texn = texn->next)
|
||||||
|
{
|
||||||
|
if (texn->type == XML_ELEMENT_NODE)
|
||||||
|
{
|
||||||
|
if (strcmp((char*)texn->name, "Texture") == 0)
|
||||||
|
{
|
||||||
|
foundFlag = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (foundFlag == FALSE)
|
||||||
|
{
|
||||||
|
printf("Could not find <Texture> element!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
memset(texname, 0, NAMESIZE);
|
||||||
|
strncpy((char*)texname,
|
||||||
|
(char*)xmlGetProp(texn, (xmlChar*)"name"), NAMESIZE);
|
||||||
|
fwrite(texname, NAMESIZE, 1, outfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write out vertices */
|
||||||
|
foundFlag = FALSE;
|
||||||
|
for (curNode=n->children; curNode; curNode = curNode->next)
|
||||||
|
{
|
||||||
|
if (curNode->type == XML_ELEMENT_NODE)
|
||||||
|
{
|
||||||
|
if (strcmp((char*)curNode->name, "Vertices") == 0)
|
||||||
|
{
|
||||||
|
foundFlag = TRUE;
|
||||||
|
if (processVertices(curNode, outfile,
|
||||||
|
mh.vertexCount) == FALSE)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (foundFlag == FALSE)
|
||||||
|
{
|
||||||
|
printf("No <Vertices> found!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write out normals */
|
||||||
|
foundFlag = FALSE;
|
||||||
|
for (curNode=n->children; curNode; curNode = curNode->next)
|
||||||
|
{
|
||||||
|
if (curNode->type == XML_ELEMENT_NODE)
|
||||||
|
{
|
||||||
|
if (strcmp((char*)curNode->name, "Normals") == 0)
|
||||||
|
{
|
||||||
|
foundFlag = TRUE;
|
||||||
|
if (processNormals(curNode, outfile,
|
||||||
|
mh.vertexCount) == FALSE)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (foundFlag == FALSE)
|
||||||
|
{
|
||||||
|
printf("No <Normals> found!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write out texture coordinates */
|
||||||
|
if (mh.textures)
|
||||||
|
{
|
||||||
|
foundFlag = FALSE;
|
||||||
|
for (curNode=n->children; curNode; curNode = curNode->next)
|
||||||
|
{
|
||||||
|
if (curNode->type == XML_ELEMENT_NODE)
|
||||||
|
{
|
||||||
|
if (strcmp((char*)curNode->name, "TexCoords")
|
||||||
|
== 0)
|
||||||
|
{
|
||||||
|
foundFlag = TRUE;
|
||||||
|
if (processTexcoords(curNode,
|
||||||
|
outfile, mh.vertexCount) ==
|
||||||
|
FALSE)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (foundFlag == FALSE)
|
||||||
|
{
|
||||||
|
printf("No <TexCoords> found!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write out indices */
|
||||||
|
foundFlag = FALSE;
|
||||||
|
for (curNode=n->children; curNode; curNode = curNode->next)
|
||||||
|
{
|
||||||
|
if (curNode->type == XML_ELEMENT_NODE)
|
||||||
|
{
|
||||||
|
if (strcmp((char*)curNode->name, "Indices") == 0)
|
||||||
|
{
|
||||||
|
foundFlag = TRUE;
|
||||||
|
if (processIndices(curNode, outfile,
|
||||||
|
mh.indexCount) == FALSE)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (foundFlag == FALSE)
|
||||||
|
{
|
||||||
|
printf("No <Indices> found!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the <Color> child of a child of a node.
|
||||||
|
*
|
||||||
|
* For example:
|
||||||
|
* <Mesh>
|
||||||
|
* <Diffuse>
|
||||||
|
* <Color r="0.1" g="0.2" b="0.3"/>
|
||||||
|
* </Diffuse>
|
||||||
|
* </Mesh>
|
||||||
|
* If <Mesh> is passed in as n and childNode is the string "Diffuse", then
|
||||||
|
* the method will read the <Color> element from within the <Diffuse> element.
|
||||||
|
*
|
||||||
|
* @param n: Node from which the children should be read.
|
||||||
|
* @param childNode: Name of the child element that owns a <Color> element.
|
||||||
|
* @param color: float32[3] array to hold RGB color.
|
||||||
|
*
|
||||||
|
* @return TRUE if the method succeeds, FALSE otherwise.
|
||||||
|
*/
|
||||||
|
int readColorChild(xmlNode *n, char *childNode, float32 *color)
|
||||||
|
{
|
||||||
|
int foundFlag = FALSE;
|
||||||
|
double r,g,b;
|
||||||
|
xmlNode *curNode = NULL;
|
||||||
|
|
||||||
|
/* make sure that n is an element */
|
||||||
|
assert(n->type == XML_ELEMENT_NODE);
|
||||||
|
|
||||||
|
/* search for the first child node matching the given name */
|
||||||
|
for (curNode=n->children; curNode; curNode = curNode->next)
|
||||||
|
{
|
||||||
|
if (curNode->type == XML_ELEMENT_NODE)
|
||||||
|
{
|
||||||
|
if (strcmp((char*)curNode->name, (char*)childNode) == 0)
|
||||||
|
{
|
||||||
|
foundFlag = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (foundFlag == FALSE)
|
||||||
|
{
|
||||||
|
printf("Could not find child node \"%s\"!\n", childNode);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* search for a <Color> node child */
|
||||||
|
for (curNode=curNode->children; curNode; curNode = curNode->next)
|
||||||
|
{
|
||||||
|
if (curNode->type == XML_ELEMENT_NODE)
|
||||||
|
{
|
||||||
|
if (strcmp((char*)curNode->name, "Color") == 0)
|
||||||
|
{
|
||||||
|
r = atof((char*)xmlGetProp(curNode,
|
||||||
|
(xmlChar*)"r"));
|
||||||
|
g = atof((char*)xmlGetProp(curNode,
|
||||||
|
(xmlChar*)"g"));
|
||||||
|
b = atof((char*)xmlGetProp(curNode,
|
||||||
|
(xmlChar*)"b"));
|
||||||
|
color[0] = (float32)r;
|
||||||
|
color[1] = (float32)g;
|
||||||
|
color[2] = (float32)b;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("Could not find <Color> child of \"%s\"!\n", childNode);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes vertices into the binary file.
|
||||||
|
*
|
||||||
|
* @param n: <Vertices> element.
|
||||||
|
* @param outfile: Binary file, opened as "wb", for output.
|
||||||
|
* @param vertexCount: Expected number of vertices to process.
|
||||||
|
*
|
||||||
|
* @return: TRUE if the method succeeds, FALSE otherwise.
|
||||||
|
*/
|
||||||
|
int processVertices(xmlNode *n, FILE *outfile, uint32 vertexCount)
|
||||||
|
{
|
||||||
|
xmlNode *v;
|
||||||
|
uint32 counted_vertices = 0;
|
||||||
|
float32 p[3];
|
||||||
|
|
||||||
|
/* check we've been passed a <Vertices> element */
|
||||||
|
assert(n->type == XML_ELEMENT_NODE);
|
||||||
|
assert(strcmp((char*)n->name, "Vertices") == 0);
|
||||||
|
|
||||||
|
/* iterate over all <Vertex> children */
|
||||||
|
for (v=n->children; v; v=v->next)
|
||||||
|
{
|
||||||
|
if ((v->type == XML_ELEMENT_NODE) &&
|
||||||
|
(strcmp((char*)v->name, "Vertex") == 0))
|
||||||
|
{
|
||||||
|
counted_vertices++;
|
||||||
|
p[0] = (float32)atof((char*)xmlGetProp(v,
|
||||||
|
(xmlChar*)"x"));
|
||||||
|
p[1] = (float32)atof((char*)xmlGetProp(v,
|
||||||
|
(xmlChar*)"y"));
|
||||||
|
p[2] = (float32)atof((char*)xmlGetProp(v,
|
||||||
|
(xmlChar*)"z"));
|
||||||
|
fwrite(p, 3*sizeof(float32), 1, outfile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check that the correct number of vertices were processed */
|
||||||
|
if (counted_vertices != vertexCount)
|
||||||
|
{
|
||||||
|
printf("Found %d vertices, expected %d!\n",
|
||||||
|
counted_vertices, vertexCount);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes normals into the binary file.
|
||||||
|
*
|
||||||
|
* @param n: <Normals> element.
|
||||||
|
* @param outfile: Binary file, opened as "wb", for output.
|
||||||
|
* @param vertexCount: Expected number of normals to process.
|
||||||
|
*
|
||||||
|
* @return: TRUE if the method succeeds, FALSE otherwise.
|
||||||
|
*/
|
||||||
|
int processNormals(xmlNode *n, FILE *outfile, uint32 vertexCount)
|
||||||
|
{
|
||||||
|
xmlNode *v;
|
||||||
|
uint32 counted_normals = 0;
|
||||||
|
float32 p[3];
|
||||||
|
|
||||||
|
/* check we've been passed a <Normals> element */
|
||||||
|
assert(n->type == XML_ELEMENT_NODE);
|
||||||
|
assert(strcmp((char*)n->name, "Normals") == 0);
|
||||||
|
|
||||||
|
/* iterate over all <Normal> elements */
|
||||||
|
for (v=n->children; v; v=v->next)
|
||||||
|
{
|
||||||
|
if ((v->type == XML_ELEMENT_NODE) &&
|
||||||
|
(strcmp((char*)v->name, "Normal") == 0))
|
||||||
|
{
|
||||||
|
counted_normals++;
|
||||||
|
p[0] = (float32)atof((char*)xmlGetProp(v,
|
||||||
|
(xmlChar*)"x"));
|
||||||
|
p[1] = (float32)atof((char*)xmlGetProp(v,
|
||||||
|
(xmlChar*)"y"));
|
||||||
|
p[2] = (float32)atof((char*)xmlGetProp(v,
|
||||||
|
(xmlChar*)"z"));
|
||||||
|
fwrite(p, 3*sizeof(float32), 1, outfile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check that the correct number of normals were processed */
|
||||||
|
if (counted_normals != vertexCount)
|
||||||
|
{
|
||||||
|
printf("Found %d normals, expected %d!\n",
|
||||||
|
counted_normals, vertexCount);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes texture coordinates into the binary file.
|
||||||
|
*
|
||||||
|
* @param n: <TexCoords> element.
|
||||||
|
* @param outfile: Binary file, opened as "wb", for output.
|
||||||
|
* @param vertexCount: Expected number of vertices to process.
|
||||||
|
*
|
||||||
|
* @return: TRUE if the method succeeds, FALSE otherwise.
|
||||||
|
*/
|
||||||
|
int processTexcoords(xmlNode *n, FILE *outfile, uint32 vertexCount)
|
||||||
|
{
|
||||||
|
xmlNode *v;
|
||||||
|
uint32 counted_texco = 0;
|
||||||
|
float32 p[2];
|
||||||
|
|
||||||
|
/* check we've been passed a <TexCoords> element */
|
||||||
|
assert(n->type == XML_ELEMENT_NODE);
|
||||||
|
assert(strcmp((char*)n->name, "TexCoords") == 0);
|
||||||
|
|
||||||
|
/* iterate over all <ST> children */
|
||||||
|
for (v=n->children; v; v=v->next)
|
||||||
|
{
|
||||||
|
if ((v->type == XML_ELEMENT_NODE) &&
|
||||||
|
(strcmp((char*)v->name, "ST") == 0))
|
||||||
|
{
|
||||||
|
++counted_texco;
|
||||||
|
p[0] = (float32)atof((char*)xmlGetProp(v,
|
||||||
|
(xmlChar*)"s"));
|
||||||
|
p[1] = (float32)atof((char*)xmlGetProp(v,
|
||||||
|
(xmlChar*)"t"));
|
||||||
|
fwrite(p, 2*sizeof(float32), 1, outfile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check that the correct number of texco were processed */
|
||||||
|
if (counted_texco != vertexCount)
|
||||||
|
{
|
||||||
|
printf("Found %d texture coordinates, expected %d!\n",
|
||||||
|
counted_texco, vertexCount);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes indices into the binary file.
|
||||||
|
*
|
||||||
|
* @param n: <Indices> element.
|
||||||
|
* @param outfile: Binary file, opened as "wb", for output.
|
||||||
|
* @param indexCount: Expected number of indices to process.
|
||||||
|
*
|
||||||
|
* @return: TRUE if the method succeeds, FALSE otherwise.
|
||||||
|
*/
|
||||||
|
int processIndices(xmlNode *n, FILE *outfile, uint32 indexCount)
|
||||||
|
{
|
||||||
|
xmlNode *v;
|
||||||
|
uint32 counted_indices = 0;
|
||||||
|
uint32 index;
|
||||||
|
|
||||||
|
/* check we've been passed an <Indices> element */
|
||||||
|
assert(n->type == XML_ELEMENT_NODE);
|
||||||
|
assert(strcmp((char*)n->name, "Indices") == 0);
|
||||||
|
|
||||||
|
/* iterate over all <Ix> children */
|
||||||
|
for (v=n->children; v; v=v->next)
|
||||||
|
{
|
||||||
|
if ((v->type == XML_ELEMENT_NODE) &&
|
||||||
|
(strcmp((char*)v->name, "Ix") == 0))
|
||||||
|
{
|
||||||
|
++counted_indices;
|
||||||
|
index = (uint32)atoi((char*)xmlGetProp(v,
|
||||||
|
(xmlChar*)"i"));
|
||||||
|
fwrite(&index, 1*sizeof(uint32), 1, outfile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check that the correct number of indices were processed */
|
||||||
|
if (counted_indices != indexCount)
|
||||||
|
{
|
||||||
|
printf("Found %d indices, expected %d!\n",
|
||||||
|
counted_indices, indexCount);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
Reference in New Issue
Block a user