forked from bartvdbraak/blender
initial commit of the fluid simulator.
Ton reviewed and gave his blessing. Zr, can you have a look ? see : http://projects.blender.org/tracker/?func=detail&atid=127&aid=3039&group_id=9 for initial comments. N_T : the solver itself (elbeem) needs some works to get rid of warnings
This commit is contained in:
parent
9e3468bde2
commit
e2d577de9e
@ -35,7 +35,7 @@ SOURCEDIR = intern
|
||||
# include nan_subdirs.mk
|
||||
|
||||
ALLDIRS = string ghost guardedalloc bmfont moto container memutil
|
||||
ALLDIRS += decimation iksolver bsp SoundSystem opennl
|
||||
ALLDIRS += decimation iksolver bsp SoundSystem opennl elbeem
|
||||
|
||||
all::
|
||||
@for i in $(ALLDIRS); do \
|
||||
|
@ -9,6 +9,7 @@ SConscript(['SoundSystem/SConscript',
|
||||
'memutil/SConscript/',
|
||||
'decimation/SConscript',
|
||||
'iksolver/SConscript',
|
||||
'elbeem/SConscript',
|
||||
'opennl/SConscript'])
|
||||
|
||||
NEW_CSG='false'
|
||||
|
360
intern/elbeem/COPYING
Normal file
360
intern/elbeem/COPYING
Normal file
@ -0,0 +1,360 @@
|
||||
All code distributed as part of El'Bemm is covered by the following
|
||||
version of the GNU General Public License, expcept for excerpts of
|
||||
the trimesh2 package in src/isosurface.cpp (see COPYING_trimesh2
|
||||
for details).
|
||||
|
||||
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.
|
||||
|
||||
Copyright (c) 2003-2005 Nils Thuerey. All rights reserved.
|
||||
|
||||
|
||||
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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.
|
303
intern/elbeem/COPYING_trimesh2
Normal file
303
intern/elbeem/COPYING_trimesh2
Normal file
@ -0,0 +1,303 @@
|
||||
This distribution includes source to "miniball", "freeGLUT",
|
||||
and "GLUI", which are covered under their own licenses.
|
||||
|
||||
All other code distributed as part of trimesh2 is covered
|
||||
by the following license:
|
||||
|
||||
|
||||
Copyright (c) 2004 Szymon Rusinkiewicz.
|
||||
All rights reserved.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
|
||||
|
||||
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
|
58
intern/elbeem/Makefile
Normal file
58
intern/elbeem/Makefile
Normal file
@ -0,0 +1,58 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version. The Blender
|
||||
# Foundation also sells licenses for use in proprietary software under
|
||||
# the Blender License. See http://www.blender.org/BL/ for information
|
||||
# about this.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
# All rights reserved.
|
||||
#
|
||||
# The Original Code is: all of this file.
|
||||
#
|
||||
# Contributor(s): Hans Lambermont
|
||||
#
|
||||
# ***** END GPL/BL DUAL LICENSE BLOCK *****
|
||||
# elbeem main makefile.
|
||||
#
|
||||
|
||||
include nan_definitions.mk
|
||||
|
||||
unexport NAN_QUIET
|
||||
|
||||
LIBNAME = elbeem
|
||||
SOURCEDIR = intern/$(LIBNAME)
|
||||
DIR = $(OCGDIR)/$(SOURCEDIR)
|
||||
DIRS = intern
|
||||
#not ready yet TESTDIRS = test
|
||||
|
||||
include nan_subdirs.mk
|
||||
|
||||
install: all debug
|
||||
@[ -d $(NAN_ELBEEM) ] || mkdir $(NAN_ELBEEM)
|
||||
@[ -d $(NAN_ELBEEM)/include ] || mkdir $(NAN_ELBEEM)/include
|
||||
@[ -d $(NAN_ELBEEM)/lib ] || mkdir $(NAN_ELBEEM)/lib
|
||||
@[ -d $(NAN_ELBEEM)/lib/debug ] || mkdir $(NAN_ELBEEM)/lib/debug
|
||||
@../tools/cpifdiff.sh $(DIR)/libelbeem.a $(NAN_ELBEEM)/lib/
|
||||
@../tools/cpifdiff.sh $(DIR)/debug/libelbeem.a $(NAN_ELBEEM)/lib/debug/
|
||||
ifeq ($(OS),darwin)
|
||||
ranlib $(NAN_ELBEEM)/lib/libelbeem.a
|
||||
ranlib $(NAN_ELBEEM)/lib/debug/libelbeem.a
|
||||
endif
|
||||
@../tools/cpifdiff.sh extern/*.h $(NAN_ELBEEM)/include/
|
||||
|
56
intern/elbeem/SConscript
Normal file
56
intern/elbeem/SConscript
Normal file
@ -0,0 +1,56 @@
|
||||
#!/usr/bin/python
|
||||
Import ('library_env')
|
||||
Import('user_options_dict');
|
||||
|
||||
print "Including El'Beem Fluid Simulation..."
|
||||
elbeem_env = library_env.Copy();
|
||||
elbeem_env.Append(CXXFLAGS= ' -DNOGUI -DELBEEM_BLENDER=1 ');
|
||||
elbeem_env.Append(CCFLAGS= ' -DNOGUI -DELBEEM_BLENDER=1 ');
|
||||
#elbeem_env.Append(CPPPATH= '../src');
|
||||
#elbeem_env.Append(CCPATH= '../src');
|
||||
|
||||
elbeem_env.Append (CPPPATH = user_options_dict['PNG_INCLUDE'])
|
||||
elbeem_env.Append (CPPPATH = user_options_dict['Z_INCLUDE'])
|
||||
elbeem_env.Append (CPPPATH = user_options_dict['SDL_INCLUDE'])
|
||||
elbeem_env.Append (CCPATH = user_options_dict['PNG_INCLUDE'])
|
||||
elbeem_env.Append (CCPATH = user_options_dict['Z_INCLUDE'])
|
||||
elbeem_env.Append (CCPATH = user_options_dict['SDL_INCLUDE'])
|
||||
|
||||
#Export('elbeem_env');
|
||||
#SConscript(['src/SConscript'])
|
||||
|
||||
# main build----------------------------------------
|
||||
#Import('elbeem_env');
|
||||
#srcenv = elbeem_env.Copy();
|
||||
|
||||
Sources = [
|
||||
|
||||
"intern/cfgparser.cpp",
|
||||
"intern/cfglexer.cpp",
|
||||
|
||||
"intern/attributes.cpp",
|
||||
"intern/elbeem.cpp",
|
||||
"intern/factory_fsgr.cpp",
|
||||
"intern/isosurface.cpp",
|
||||
"intern/lbminterface.cpp",
|
||||
"intern/ntl_blenderdumper.cpp",
|
||||
"intern/ntl_bsptree.cpp",
|
||||
"intern/ntl_geometrybox.cpp",
|
||||
"intern/ntl_geometrymodel.cpp",
|
||||
"intern/ntl_geometryobject.cpp",
|
||||
"intern/ntl_geometrysphere.cpp",
|
||||
"intern/ntl_image.cpp",
|
||||
"intern/ntl_lightobject.cpp",
|
||||
"intern/ntl_ray.cpp",
|
||||
"intern/ntl_raytracer.cpp",
|
||||
"intern/ntl_scene.cpp",
|
||||
"intern/parametrizer.cpp",
|
||||
"intern/particletracer.cpp",
|
||||
"intern/simulation_object.cpp",
|
||||
"intern/utilities.cpp",
|
||||
"intern/blendercall.cpp"
|
||||
|
||||
]; # sources
|
||||
|
||||
elbeem_env.Library (target='#'+user_options_dict['BUILD_DIR']+'/lib/blender_elbeem', source=Sources)
|
||||
|
68
intern/elbeem/extern/LBM_fluidsim.h
vendored
Normal file
68
intern/elbeem/extern/LBM_fluidsim.h
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
/**
|
||||
* BKE_fluidsim.h
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version. The Blender
|
||||
* Foundation also sells licenses for use in proprietary software under
|
||||
* the Blender License. See http://www.blender.org/BL/ for information
|
||||
* about this.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) Blender Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
||||
*/
|
||||
#ifndef LBM_FLUIDSIM_H
|
||||
#define LBM_FLUIDSIM_H
|
||||
|
||||
struct Mesh;
|
||||
struct DerivedMesh;
|
||||
struct Object;
|
||||
struct fluidsimDerivedMesh;
|
||||
|
||||
extern double fluidsimViscosityPreset[6];
|
||||
extern char* fluidsimViscosityPresetString[6];
|
||||
|
||||
/* allocates and initializes fluidsim data */
|
||||
struct FluidsimSettings* fluidsimSettingsNew(struct Object *srcob);
|
||||
|
||||
/* frees internal data itself */
|
||||
void fluidsimSettingsFree(struct FluidsimSettings* sb);
|
||||
|
||||
/* export blender geometry to fluid solver */
|
||||
void fluidsimBake(struct Object* ob);
|
||||
|
||||
/* read & write bobj / bobj.gz files (e.g. for fluid sim surface meshes) */
|
||||
void writeBobjgz(char *filename, struct Object *ob);
|
||||
struct Mesh* readBobjgz(char *filename, struct Mesh *orgmesh);
|
||||
|
||||
/* create derived mesh for fluid sim objects */
|
||||
// WARNING - currently implemented in DerivedMesh.c!
|
||||
struct DerivedMesh *getFluidsimDerivedMesh(struct Object *srcob, int useRenderParams, float *extverts, float *nors);
|
||||
|
||||
/* run simulation with given config file */
|
||||
// WARNING - implemented in intern/elbeem/blendercall.cpp
|
||||
int performElbeemSimulation(char *cfgfilename);
|
||||
|
||||
#endif
|
||||
|
||||
|
48
intern/elbeem/intern/Makefile
Normal file
48
intern/elbeem/intern/Makefile
Normal file
@ -0,0 +1,48 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version. The Blender
|
||||
# Foundation also sells licenses for use in proprietary software under
|
||||
# the Blender License. See http://www.blender.org/BL/ for information
|
||||
# about this.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
# All rights reserved.
|
||||
#
|
||||
# The Original Code is: all of this file.
|
||||
#
|
||||
# Contributor(s): none yet.
|
||||
#
|
||||
# ***** END GPL/BL DUAL LICENSE BLOCK *****
|
||||
# elbeem intern Makefile
|
||||
#
|
||||
|
||||
LIBNAME = elbeem
|
||||
DIR = $(OCGDIR)/intern/$(LIBNAME)
|
||||
|
||||
include nan_compile.mk
|
||||
|
||||
unexport NAN_QUIET
|
||||
|
||||
CCFLAGS += $(LEVEL_2_CPP_WARNINGS)
|
||||
|
||||
CPPFLAGS += -DNOGUI -DELBEEM_BLENDER
|
||||
CPPFLAGS += -I.
|
||||
CPPFLAGS += -I../extern
|
||||
CPPFLAGS += $(NAN_SDLCFLAGS)
|
||||
CPPFLAGS += -I$(NAN_PNG)/include
|
||||
CPPFLAGS += -I$(NAN_PNG)/include/libpng
|
290
intern/elbeem/intern/arrays.h
Normal file
290
intern/elbeem/intern/arrays.h
Normal file
@ -0,0 +1,290 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* Array class definitions
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef ARRAYS_H
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* array handling "cutting off" access along the border */
|
||||
template<class T>
|
||||
class ArrayCutoffBc {
|
||||
public:
|
||||
//! constructor
|
||||
ArrayCutoffBc() :
|
||||
mpVal( NULL ), mElemSize( sizeof(T) ),
|
||||
mAllocSize(0),
|
||||
mSizex(0), mSizey(0), mSizez(0)
|
||||
{ };
|
||||
//! destructor
|
||||
virtual ~ArrayCutoffBc() {
|
||||
if((mpVal)&&(mAllocSize>0)) delete[] mpVal;
|
||||
mpVal = NULL;
|
||||
}
|
||||
|
||||
//! init sizes
|
||||
void initializeArray(int setx, int sety, int setz) {
|
||||
mSizex = setx;
|
||||
mSizey = sety;
|
||||
mSizez = setz;
|
||||
}
|
||||
|
||||
//! allocate a new array
|
||||
inline void allocate() {
|
||||
int size = mSizex*mSizey*mSizez;
|
||||
if(size == mAllocSize) return; // dont reallocate
|
||||
T* newval = new T[size];
|
||||
for(int i=0;i<size;i++) newval[i] = (T)(0.0);
|
||||
mpVal = (unsigned char *)newval;
|
||||
mAllocSize = size;
|
||||
};
|
||||
|
||||
//! set the scalar field pointer
|
||||
inline void setValuePointer(T *pnt, int elem) { mpVal = (unsigned char *)pnt; mElemSize = elem; };
|
||||
|
||||
//! internal array index calculator
|
||||
inline int arrayIndex(int x, int y, int z) {
|
||||
if(x<0) x=0;
|
||||
if(y<0) y=0;
|
||||
if(z<0) z=0;
|
||||
if(x>mSizex-1) x=mSizex-1;
|
||||
if(y>mSizey-1) y=mSizey-1;
|
||||
if(z>mSizez-1) z=mSizez-1;
|
||||
return z*mSizex*mSizey + y*mSizex + x;
|
||||
}
|
||||
//! phi access function
|
||||
inline T& getValue(int x, int y, int z) {
|
||||
unsigned char *bpnt = &mpVal[ arrayIndex(x,y,z)*mElemSize ];
|
||||
return *((T*)bpnt);
|
||||
//return mpPhi[ z*mSizex*mSizey + y*mSizex + x];
|
||||
}
|
||||
//! return relative offset in direction dir (x=0,y=1,z=2)
|
||||
inline T& getOffset(T *base,int off, int dir) {
|
||||
unsigned char *basep = (unsigned char *)base;
|
||||
int multiplier = 1;
|
||||
if(dir==1) multiplier=mSizex;
|
||||
if(dir==2) multiplier=mSizex*mSizey;
|
||||
// check boundary
|
||||
unsigned char *bpnt = (basep+ ((off*multiplier)*mElemSize) );
|
||||
if(bpnt<mpVal) bpnt = basep;
|
||||
if(bpnt>= (unsigned char *)&getValue(mSizex-1,mSizey-1,mSizez-1) ) bpnt = basep;
|
||||
return *((T*)bpnt);
|
||||
}
|
||||
|
||||
//! perform trilinear interpolation of array values
|
||||
inline T interpolateValueAt(LbmFloat x, LbmFloat y, LbmFloat z) {
|
||||
const LbmFloat gsx=1.0, gsy=1.0, gsz=1.0;
|
||||
int i= (int)x;
|
||||
int j= (int)y;
|
||||
int k= (int)z;
|
||||
|
||||
int in = i+1;
|
||||
int jn = j+1;
|
||||
int kn = k+1;
|
||||
if(in>=mSizex) in = mSizex-1;
|
||||
if(jn>=mSizey) jn = mSizey-1;
|
||||
if(kn>=mSizez) kn = mSizez-1;
|
||||
|
||||
LbmVec mStart(0.0); // TODO remove?
|
||||
LbmFloat x1 = mStart[0]+ (LbmFloat)(i)*gsx;
|
||||
LbmFloat x2 = mStart[0]+ (LbmFloat)(in)*gsx;
|
||||
LbmFloat y1 = mStart[1]+ (LbmFloat)(j)*gsy;
|
||||
LbmFloat y2 = mStart[1]+ (LbmFloat)(jn)*gsy;
|
||||
LbmFloat z1 = mStart[2]+ (LbmFloat)(k)*gsz;
|
||||
LbmFloat z2 = mStart[2]+ (LbmFloat)(kn)*gsz;
|
||||
|
||||
if(mSizez==1) {
|
||||
z1=0.0; z2=1.0;
|
||||
k = kn = 0;
|
||||
}
|
||||
|
||||
T v1, v2, v3, v4, v5, v6, v7, v8;
|
||||
v1 = getValue(i ,j ,k );
|
||||
v2 = getValue(in ,j ,k );
|
||||
v3 = getValue(i ,jn ,k );
|
||||
v4 = getValue(in ,jn ,k );
|
||||
v5 = getValue(i ,j ,kn );
|
||||
v6 = getValue(in ,j ,kn );
|
||||
v7 = getValue(i ,jn ,kn );
|
||||
v8 = getValue(in ,jn ,kn );
|
||||
|
||||
T val =
|
||||
( v1 *(x2-x)* (y2-y)* (z2-z) +
|
||||
v2 *(x-x1)* (y2-y)* (z2-z) +
|
||||
v3 *(x2-x)* (y-y1)* (z2-z) +
|
||||
v4 *(x-x1)* (y-y1)* (z2-z) +
|
||||
v5 *(x2-x)* (y2-y)* (z-z1) +
|
||||
v6 *(x-x1)* (y2-y)* (z-z1) +
|
||||
v7 *(x2-x)* (y-y1)* (z-z1) +
|
||||
v8 *(x-x1)* (y-y1)* (z-z1)
|
||||
) * (1.0/(gsx*gsy*gsz)) ;
|
||||
return val;
|
||||
}
|
||||
|
||||
//! get size of an element
|
||||
inline int getElementSize(){ return mElemSize; }
|
||||
//! get array sizes
|
||||
inline int getSizeX(){ return mSizex; }
|
||||
inline int getSizeY(){ return mSizey; }
|
||||
inline int getSizeZ(){ return mSizez; }
|
||||
//! get array pointer
|
||||
inline T* getPointer(){ return (T*)mpVal; }
|
||||
|
||||
//! testing, gnuplot dump (XY plane for k=Z/2)
|
||||
void dumpToFile(std::string filebase, int id, int nr) {
|
||||
std::ostringstream filename;
|
||||
filename << filebase << "_"<< id <<"_"<< nr <<".dump";
|
||||
std::ofstream outfile( filename.str().c_str() );
|
||||
for(int k=mSizez/2; k<=mSizez/2; k++) {
|
||||
for(int j=0; j<mSizey; j++) {
|
||||
for(int i=0; i<mSizex; i++) {
|
||||
outfile <<i<<" "<<j<<" " << getValue(i,j,k)<<" " <<std::endl;
|
||||
}
|
||||
outfile << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
//! testing, grid text dump (XY plane for k=Z/2)
|
||||
void dumpToGridFile(std::string filebase, int id, int nr) {
|
||||
std::ostringstream filename;
|
||||
filename << filebase << "_"<< id <<"_"<< nr <<".dump";
|
||||
std::ofstream outfile( filename.str().c_str() );
|
||||
for(int k=mSizez/2; k<=mSizez/2; k++) {
|
||||
for(int j=0; j<mSizey; j++) {
|
||||
for(int i=0; i<mSizex; i++) {
|
||||
outfile <<getValue(i,j,k)<<"\t";
|
||||
}
|
||||
outfile << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
//! pointer for the value field (unsigned char for adding element size)
|
||||
unsigned char *mpVal;
|
||||
//! element offset in array
|
||||
int mElemSize;
|
||||
//! store allocated size
|
||||
int mAllocSize;
|
||||
|
||||
//! Sizes of the scal array in each dimension
|
||||
int mSizex,mSizey,mSizez;
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
/* array handling "cutting off" access along the border */
|
||||
template<class T>
|
||||
class ArrayPlain {
|
||||
public:
|
||||
//! constructor
|
||||
ArrayPlain() :
|
||||
mpVal( NULL ), mElemSize( sizeof(T) ),
|
||||
mAllocSize(0),
|
||||
mSizex(0), mSizey(0), mSizez(0)
|
||||
{ };
|
||||
//! destructor
|
||||
virtual ~ArrayPlain() {
|
||||
if((mpVal)&&(mAllocSize>0)) delete[] mpVal;
|
||||
mpVal = NULL;
|
||||
}
|
||||
|
||||
//! init sizes
|
||||
void initializeArray(int setx, int sety, int setz) {
|
||||
mSizex = setx;
|
||||
mSizey = sety;
|
||||
mSizez = setz;
|
||||
}
|
||||
|
||||
//! allocate a new array
|
||||
inline void allocate() {
|
||||
int size = mSizex*mSizey*mSizez;
|
||||
if(size == mAllocSize) return; // dont reallocate
|
||||
T* newval = new T[size];
|
||||
for(int i=0;i<size;i++) newval[i] = (T)(0.0);
|
||||
mpVal = (unsigned char *)newval;
|
||||
mAllocSize = size;
|
||||
};
|
||||
|
||||
//! set the scalar field pointer
|
||||
inline void setValuePointer(T *pnt, int elem) { mpVal = (unsigned char *)pnt; mElemSize = elem; };
|
||||
|
||||
//! phi access function
|
||||
inline T& getValue(const int x, const int y, const int z) const {
|
||||
unsigned char *bpnt = &mpVal[ (z*mSizex*mSizey + y*mSizex + x)*mElemSize ];
|
||||
return *((T*)bpnt);
|
||||
}
|
||||
//! return relative offset in direction dir (x=0,y=1,z=2)
|
||||
inline T& getOffset(T *base,int off, int dir) {
|
||||
unsigned char *basep = (unsigned char *)base;
|
||||
int multiplier = 1;
|
||||
if(dir==1) multiplier=mSizex;
|
||||
if(dir==2) multiplier=mSizex*mSizey;
|
||||
// check boundary
|
||||
unsigned char *bpnt = (basep+ ((off*multiplier)*mElemSize) );
|
||||
if(bpnt<mpVal) bpnt = basep;
|
||||
if(bpnt>= (unsigned char *)&getValue(mSizex-1,mSizey-1,mSizez-1) ) bpnt = basep;
|
||||
return *((T*)bpnt);
|
||||
}
|
||||
|
||||
//! get size of an element
|
||||
inline int getElementSize(){ return mElemSize; }
|
||||
//! get array sizes
|
||||
inline int getSizeX(){ return mSizex; }
|
||||
inline int getSizeY(){ return mSizey; }
|
||||
inline int getSizeZ(){ return mSizez; }
|
||||
//! get array pointer
|
||||
inline T* getPointer(){ return (T*)mpVal; }
|
||||
|
||||
//! testing, gnuplot dump (XY plane for k=Z/2)
|
||||
void dumpToFile(std::string filebase, int id, int nr) {
|
||||
std::ostringstream filename;
|
||||
filename << filebase << "_"<< id <<"_"<< nr <<".dump";
|
||||
std::ofstream outfile( filename.str().c_str() );
|
||||
for(int k=mSizez/2; k<=mSizez/2; k++) {
|
||||
for(int j=0; j<mSizey; j++) {
|
||||
for(int i=0; i<mSizex; i++) {
|
||||
outfile <<i<<" "<<j<<" " << getValue(i,j,k)<<" " <<std::endl;
|
||||
}
|
||||
outfile << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
//! testing, grid text dump (XY plane for k=Z/2)
|
||||
void dumpToGridFile(std::string filebase, int id, int nr) {
|
||||
std::ostringstream filename;
|
||||
filename << filebase << "_"<< id <<"_"<< nr <<".dump";
|
||||
std::ofstream outfile( filename.str().c_str() );
|
||||
for(int k=mSizez/2; k<=mSizez/2; k++) {
|
||||
for(int j=0; j<mSizey; j++) {
|
||||
for(int i=0; i<mSizex; i++) {
|
||||
outfile <<getValue(i,j,k)<<"\t";
|
||||
}
|
||||
outfile << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
//! pointer for the value field (unsigned char for adding element size)
|
||||
unsigned char *mpVal;
|
||||
//! element offset in array
|
||||
int mElemSize;
|
||||
//! store allocated size
|
||||
int mAllocSize;
|
||||
|
||||
//! Sizes of the scal array in each dimension
|
||||
int mSizex,mSizey,mSizez;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define ARRAYS_H
|
||||
#endif
|
||||
|
358
intern/elbeem/intern/attributes.cpp
Normal file
358
intern/elbeem/intern/attributes.cpp
Normal file
@ -0,0 +1,358 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* configuration attribute storage class and attribute class
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "attributes.h"
|
||||
#include <sstream>
|
||||
|
||||
|
||||
//! output attribute values? on=1/off=0
|
||||
#define DEBUG_ATTRIBUTES 0
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* attribute conversion functions
|
||||
*****************************************************************************/
|
||||
|
||||
// get value as string
|
||||
string Attribute::getAsString()
|
||||
{
|
||||
if(mValue.size()!=1) {
|
||||
//errMsg("Attribute::getAsString", "Attribute \"" << mName << "\" used as string has invalid value '"<< getCompleteString() <<"' ");
|
||||
// for directories etc. , this might be valid! cutoff "..." first
|
||||
string comp = getCompleteString();
|
||||
if(comp.size()<2) return string("");
|
||||
return comp.substr(1, comp.size()-2);
|
||||
}
|
||||
return mValue[0];
|
||||
}
|
||||
|
||||
// get value as integer value
|
||||
int Attribute::getAsInt()
|
||||
{
|
||||
bool success = true;
|
||||
int ret = 0;
|
||||
if(mValue.size()!=1) success = false;
|
||||
else {
|
||||
const char *str = mValue[0].c_str();
|
||||
char *endptr;
|
||||
ret = strtol(str, &endptr, 10);
|
||||
if( (str==endptr) ||
|
||||
((str!=endptr) && (*endptr != '\0')) )success = false;
|
||||
}
|
||||
|
||||
if(!success) {
|
||||
errMsg("Attribute::getAsString", "Attribute \"" << mName << "\" used as int has invalid value '"<< getCompleteString() <<"' ");
|
||||
errMsg("Attribute::getAsString", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
|
||||
errMsg("Attribute::getAsString", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
|
||||
return 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// get value as integer value
|
||||
bool Attribute::getAsBool()
|
||||
{
|
||||
int val = getAsInt();
|
||||
if(val==0) return false;
|
||||
else return true;
|
||||
}
|
||||
|
||||
|
||||
// get value as double value
|
||||
double Attribute::getAsFloat()
|
||||
{
|
||||
bool success = true;
|
||||
double ret = 0.0;
|
||||
if(mValue.size()!=1) success = false;
|
||||
else {
|
||||
const char *str = mValue[0].c_str();
|
||||
char *endptr;
|
||||
ret = strtod(str, &endptr);
|
||||
if((str!=endptr) && (*endptr != '\0')) success = false;
|
||||
}
|
||||
|
||||
if(!success) {
|
||||
errMsg("Attribute::getAsFloat", "Attribute \"" << mName << "\" used as double has invalid value '"<< getCompleteString() <<"' ");
|
||||
errMsg("Attribute::getAsFloat", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
|
||||
errMsg("Attribute::getAsFloat", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
|
||||
return 0.0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// get value as 3d vector
|
||||
ntlVec3d Attribute::getAsVec3d()
|
||||
{
|
||||
bool success = true;
|
||||
ntlVec3d ret(0.0);
|
||||
if(mValue.size()==1) {
|
||||
const char *str = mValue[0].c_str();
|
||||
char *endptr;
|
||||
double rval = strtod(str, &endptr);
|
||||
if( (str==endptr) ||
|
||||
((str!=endptr) && (*endptr != '\0')) )success = false;
|
||||
if(success) ret = ntlVec3d( rval );
|
||||
} else if(mValue.size()==3) {
|
||||
char *endptr;
|
||||
const char *str = NULL;
|
||||
|
||||
str = mValue[0].c_str();
|
||||
double rval1 = strtod(str, &endptr);
|
||||
if( (str==endptr) ||
|
||||
((str!=endptr) && (*endptr != '\0')) )success = false;
|
||||
|
||||
str = mValue[1].c_str();
|
||||
double rval2 = strtod(str, &endptr);
|
||||
if( (str==endptr) ||
|
||||
((str!=endptr) && (*endptr != '\0')) )success = false;
|
||||
|
||||
str = mValue[2].c_str();
|
||||
double rval3 = strtod(str, &endptr);
|
||||
if( (str==endptr) ||
|
||||
((str!=endptr) && (*endptr != '\0')) )success = false;
|
||||
|
||||
if(success) ret = ntlVec3d( rval1, rval2, rval3 );
|
||||
} else {
|
||||
success = false;
|
||||
}
|
||||
|
||||
if(!success) {
|
||||
errMsg("Attribute::getAsVec3d", "Attribute \"" << mName << "\" used as Vec3d has invalid value '"<< getCompleteString() <<"' ");
|
||||
errMsg("Attribute::getAsVec3d", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
|
||||
errMsg("Attribute::getAsVec3d", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
|
||||
return ntlVec3d(0.0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// get value as 4x4 matrix
|
||||
ntlMat4Gfx Attribute::getAsMat4Gfx()
|
||||
{
|
||||
bool success = true;
|
||||
ntlMat4Gfx ret(0.0);
|
||||
char *endptr;
|
||||
const char *str = NULL;
|
||||
|
||||
if(mValue.size()==1) {
|
||||
const char *str = mValue[0].c_str();
|
||||
char *endptr;
|
||||
double rval = strtod(str, &endptr);
|
||||
if( (str==endptr) ||
|
||||
((str!=endptr) && (*endptr != '\0')) )success = false;
|
||||
if(success) {
|
||||
ret = ntlMat4Gfx( 0.0 );
|
||||
ret.value[0][0] = rval;
|
||||
ret.value[1][1] = rval;
|
||||
ret.value[2][2] = rval;
|
||||
ret.value[3][3] = 1.0;
|
||||
}
|
||||
} else if(mValue.size()==9) {
|
||||
// 3x3
|
||||
for(int i=0; i<3;i++) {
|
||||
for(int j=0; j<3;j++) {
|
||||
str = mValue[i*3+j].c_str();
|
||||
ret.value[i][j] = strtod(str, &endptr);
|
||||
if( (str==endptr) ||
|
||||
((str!=endptr) && (*endptr != '\0')) ) success = false;
|
||||
}
|
||||
}
|
||||
} else if(mValue.size()==16) {
|
||||
// 4x4
|
||||
for(int i=0; i<4;i++) {
|
||||
for(int j=0; j<4;j++) {
|
||||
str = mValue[i*4+j].c_str();
|
||||
ret.value[i][j] = strtod(str, &endptr);
|
||||
if( (str==endptr) ||
|
||||
((str!=endptr) && (*endptr != '\0')) ) success = false;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
success = false;
|
||||
}
|
||||
|
||||
if(!success) {
|
||||
errMsg("Attribute::getAsMat4Gfx", "Attribute \"" << mName << "\" used as Mat4x4 has invalid value '"<< getCompleteString() <<"' ");
|
||||
errMsg("Attribute::getAsMat4Gfx", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
|
||||
errMsg("Attribute::getAsMat4Gfx", "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" );
|
||||
return ntlMat4Gfx(0.0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// get the concatenated string of all value string
|
||||
string Attribute::getCompleteString()
|
||||
{
|
||||
string ret;
|
||||
for(size_t i=0;i<mValue.size();i++) {
|
||||
ret += mValue[i];
|
||||
if(i<mValue.size()-1) ret += " ";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* check if there were unknown params
|
||||
*****************************************************************************/
|
||||
bool AttributeList::checkUnusedParams()
|
||||
{
|
||||
bool found = false;
|
||||
for(map<string, Attribute*>::iterator i=mAttrs.begin();
|
||||
i != mAttrs.end(); i++) {
|
||||
if((*i).second) {
|
||||
if(!(*i).second->getUsed()) {
|
||||
errorOut("Attribute "<<mName<<" has unknown parameter '"<<(*i).first<<"' = '"<< mAttrs[(*i).first]->getAsString() <<"' ");
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
//! set all params to used, for invisible objects
|
||||
void AttributeList::setAllUsed() {
|
||||
for(map<string, Attribute*>::iterator i=mAttrs.begin();
|
||||
i != mAttrs.end(); i++) {
|
||||
if((*i).second) {
|
||||
(*i).second->setUsed(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Attribute list read functions
|
||||
*****************************************************************************/
|
||||
int AttributeList::readInt(string name, int defaultValue, string source,string target, bool needed) {
|
||||
if(!exists(name)) {
|
||||
if(needed) { errorOut("AttributeList::readInt error: Required attribute '"<<name<<"' for "<< source <<" not set! "); exit(1); }
|
||||
return defaultValue;
|
||||
}
|
||||
if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); }
|
||||
find(name)->setUsed(true);
|
||||
return find(name)->getAsInt();
|
||||
}
|
||||
bool AttributeList::readBool(string name, bool defaultValue, string source,string target, bool needed) {
|
||||
if(!exists(name)) {
|
||||
if(needed) { errorOut("AttributeList::readBool error: Required attribute '"<<name<<"' for "<< source <<" not set! "); exit(1); }
|
||||
return defaultValue;
|
||||
}
|
||||
if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); }
|
||||
find(name)->setUsed(true);
|
||||
return find(name)->getAsBool();
|
||||
}
|
||||
double AttributeList::readFloat(string name, double defaultValue, string source,string target, bool needed) {
|
||||
if(!exists(name)) {
|
||||
if(needed) { errorOut("AttributeList::readFloat error: Required attribute '"<<name<<"' for "<< source <<" not set! "); exit(1); }
|
||||
return defaultValue;
|
||||
}
|
||||
if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); }
|
||||
find(name)->setUsed(true);
|
||||
return find(name)->getAsFloat();
|
||||
}
|
||||
string AttributeList::readString(string name, string defaultValue, string source,string target, bool needed) {
|
||||
if(!exists(name)) {
|
||||
if(needed) { errorOut("AttributeList::readInt error: Required attribute '"<<name<<"' for "<< source <<" not set! "); exit(1); }
|
||||
return defaultValue;
|
||||
}
|
||||
if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); }
|
||||
find(name)->setUsed(true);
|
||||
return find(name)->getAsString();
|
||||
}
|
||||
ntlVec3d AttributeList::readVec3d(string name, ntlVec3d defaultValue, string source,string target, bool needed) {
|
||||
if(!exists(name)) {
|
||||
if(needed) { errorOut("AttributeList::readInt error: Required attribute '"<<name<<"' for "<< source <<" not set! "); exit(1); }
|
||||
return defaultValue;
|
||||
}
|
||||
if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); }
|
||||
find(name)->setUsed(true);
|
||||
return find(name)->getAsVec3d();
|
||||
}
|
||||
|
||||
ntlMat4Gfx AttributeList::readMat4Gfx(string name, ntlMat4Gfx defaultValue, string source,string target, bool needed) {
|
||||
if(!exists(name)) {
|
||||
if(needed) { errorOut("AttributeList::readInt error: Required attribute '"<<name<<"' for "<< source <<" not set! "); exit(1); }
|
||||
return defaultValue;
|
||||
}
|
||||
if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Var '"<< target <<"' set to '"<< find(name)->getCompleteString() <<"' as type int " , 3); }
|
||||
find(name)->setUsed(true);
|
||||
return find(name)->getAsMat4Gfx();
|
||||
}
|
||||
|
||||
// set that a parameter can be given, and will be ignored...
|
||||
bool AttributeList::ignoreParameter(string name, string source) {
|
||||
if(!exists(name)) return false;
|
||||
find(name)->setUsed(true);
|
||||
if(DEBUG_ATTRIBUTES==1) { debugOut( source << " Param '"<< name <<"' set but ignored... " , 3); }
|
||||
return true;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* destructor
|
||||
*****************************************************************************/
|
||||
AttributeList::~AttributeList() {
|
||||
for(map<string, Attribute*>::iterator i=mAttrs.begin();
|
||||
i != mAttrs.end(); i++) {
|
||||
if((*i).second) {
|
||||
delete (*i).second;
|
||||
(*i).second = NULL;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* debugging
|
||||
*****************************************************************************/
|
||||
|
||||
//! debug function, prints value
|
||||
void Attribute::print()
|
||||
{
|
||||
std::ostringstream ostr;
|
||||
ostr << " "<< mName <<"= ";
|
||||
for(size_t i=0;i<mValue.size();i++) {
|
||||
ostr <<"'"<< mValue[i]<<"' ";
|
||||
}
|
||||
ostr <<" (at line "<<mLine<<") "; //<< std::endl;
|
||||
debugOut( ostr.str(), 10);
|
||||
}
|
||||
|
||||
//! debug function, prints all attribs
|
||||
void AttributeList::print()
|
||||
{
|
||||
debugOut("Attribute "<<mName<<" values:", 10);
|
||||
for(map<string, Attribute*>::iterator i=mAttrs.begin();
|
||||
i != mAttrs.end(); i++) {
|
||||
if((*i).second) {
|
||||
(*i).second->print();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* import attributes from other attribute list
|
||||
*****************************************************************************/
|
||||
void AttributeList::import(AttributeList *oal)
|
||||
{
|
||||
for(map<string, Attribute*>::iterator i=oal->mAttrs.begin();
|
||||
i !=oal->mAttrs.end(); i++) {
|
||||
// FIXME - check freeing of copyied attributes
|
||||
if((*i).second) {
|
||||
Attribute *newAttr = new Attribute( *(*i).second );
|
||||
mAttrs[ (*i).first ] = newAttr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
143
intern/elbeem/intern/attributes.h
Normal file
143
intern/elbeem/intern/attributes.h
Normal file
@ -0,0 +1,143 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* configuration attribute storage class and attribute class
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#ifndef NTL_ATTRIBUTES_H
|
||||
|
||||
#include "utilities.h"
|
||||
#include "ntl_matrices.h"
|
||||
|
||||
|
||||
//! A single attribute
|
||||
class Attribute
|
||||
{
|
||||
public:
|
||||
//! Standard constructor
|
||||
Attribute(string mn, vector<string> &value, int setline) :
|
||||
mName(mn), mValue(value),
|
||||
mLine(setline), mUsed(false) { };
|
||||
//! Copy constructor
|
||||
Attribute(Attribute &a) :
|
||||
mName(a.mName), mValue(a.mValue),
|
||||
mLine(a.mLine), mUsed(false) { };
|
||||
//! Destructor
|
||||
~Attribute() { /* empty */ };
|
||||
|
||||
//! set used flag
|
||||
void setUsed(bool set){ mUsed = set; }
|
||||
//! get used flag
|
||||
bool getUsed() { return mUsed; }
|
||||
|
||||
//! get value as string
|
||||
string getAsString();
|
||||
|
||||
//! get value as integer value
|
||||
int getAsInt();
|
||||
|
||||
//! get value as boolean
|
||||
bool getAsBool();
|
||||
|
||||
//! get value as double value
|
||||
double getAsFloat();
|
||||
|
||||
//! get value as 3d vector
|
||||
ntlVec3d getAsVec3d();
|
||||
|
||||
//! get value as 4x4 matrix
|
||||
ntlMat4Gfx getAsMat4Gfx();
|
||||
|
||||
//! get the concatenated string of all value string
|
||||
string getCompleteString();
|
||||
|
||||
//! debug function, prints value
|
||||
void print();
|
||||
|
||||
protected:
|
||||
|
||||
/*! the attr name */
|
||||
string mName;
|
||||
|
||||
/*! the attr value */
|
||||
vector<string> mValue;
|
||||
|
||||
/*! line where the value was defined in the config file (for error messages) */
|
||||
int mLine;
|
||||
|
||||
/*! was this attribute used? */
|
||||
bool mUsed;
|
||||
};
|
||||
|
||||
|
||||
//! The list of configuration attributes
|
||||
class AttributeList
|
||||
{
|
||||
public:
|
||||
//! Standard constructor
|
||||
AttributeList(string name) :
|
||||
mName(name), mAttrs() { };
|
||||
//! Destructor , delete all contained attribs
|
||||
~AttributeList();
|
||||
|
||||
/*! add an attribute to this list */
|
||||
void addAttr(string name, vector<string> &value, int line) {
|
||||
if(exists(name)) delete mAttrs[name];
|
||||
mAttrs[name] = new Attribute(name,value,line);
|
||||
}
|
||||
|
||||
/*! check if an attribute is set */
|
||||
bool exists(string name) {
|
||||
if(mAttrs.find(name) == mAttrs.end()) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*! get an attribute */
|
||||
Attribute *find(string name) {
|
||||
if(mAttrs.find(name) == mAttrs.end()) {
|
||||
errorOut("AttributeList::find error: Invalid attribute '"<<name<<"' , not found..." );
|
||||
exit(1);
|
||||
}
|
||||
return mAttrs[name];
|
||||
}
|
||||
|
||||
//! set all params to used, for invisible objects
|
||||
void setAllUsed();
|
||||
//! check if there were unknown params
|
||||
bool checkUnusedParams();
|
||||
|
||||
//! import attributes from other attribute list
|
||||
void import(AttributeList *oal);
|
||||
|
||||
//! read attributes for object initialization
|
||||
int readInt(string name, int defaultValue, string source,string target, bool needed);
|
||||
bool readBool(string name, bool defaultValue, string source,string target, bool needed);
|
||||
double readFloat(string name, double defaultValue, string source,string target, bool needed);
|
||||
string readString(string name, string defaultValue, string source,string target, bool needed);
|
||||
ntlVec3d readVec3d(string name, ntlVec3d defaultValue, string source,string target, bool needed);
|
||||
ntlMat4Gfx readMat4Gfx(string name, ntlMat4Gfx defaultValue, string source,string target, bool needed);
|
||||
|
||||
//! set that a parameter can be given, and will be ignored...
|
||||
bool ignoreParameter(string name, string source);
|
||||
|
||||
//! debug function, prints all attribs
|
||||
void print();
|
||||
|
||||
protected:
|
||||
|
||||
/*! attribute name (form config file) */
|
||||
string mName;
|
||||
|
||||
/*! the global attribute storage */
|
||||
map<string, Attribute*> mAttrs;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#define NTL_ATTRIBUTES_H
|
||||
#endif
|
||||
|
28
intern/elbeem/intern/blendercall.cpp
Normal file
28
intern/elbeem/intern/blendercall.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* All code distributed as part of El'Beem is covered by the version 2 of the
|
||||
* GNU General Public License. See the file COPYING for details.
|
||||
* Copyright 2003-2005 Nils Thuerey
|
||||
*
|
||||
* Blender call interface
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "globals.h"
|
||||
#include "ntl_raytracer.h"
|
||||
#include "ntl_blenderdumper.h"
|
||||
|
||||
extern "C"
|
||||
int performElbeemSimulation(char *cfgfilename) {
|
||||
fprintf(GEN_userstream, "Running El'Beem from Blender with file '%s' ...\n",cfgfilename);
|
||||
// load given file in command line mode
|
||||
ntlBlenderDumper elbeem(cfgfilename, true);
|
||||
myTime_t timestart = getTime();
|
||||
elbeem.renderAnimation();
|
||||
myTime_t timeend = getTime();
|
||||
fprintf(GEN_userstream, "El'Beem simulation done, time: %f seconds.\n", ((timeend-timestart)/(double)1000.0) );
|
||||
return 1;
|
||||
};
|
||||
|
||||
|
2561
intern/elbeem/intern/cfglexer.cpp
Normal file
2561
intern/elbeem/intern/cfglexer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2348
intern/elbeem/intern/cfgparser.cpp
Normal file
2348
intern/elbeem/intern/cfgparser.cpp
Normal file
File diff suppressed because it is too large
Load Diff
259
intern/elbeem/intern/cfgparser.hpp
Normal file
259
intern/elbeem/intern/cfgparser.hpp
Normal file
@ -0,0 +1,259 @@
|
||||
/* A Bison parser, made by GNU Bison 1.875d. */
|
||||
|
||||
/* Skeleton parser for Yacc-like parsing with Bison,
|
||||
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
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, 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. */
|
||||
|
||||
/* As a special exception, when this file is copied by Bison into a
|
||||
Bison output file, you may use that output file without restriction.
|
||||
This special exception was added by the Free Software Foundation
|
||||
in version 1.24 of Bison. */
|
||||
|
||||
/* Tokens. */
|
||||
#ifndef YYTOKENTYPE
|
||||
# define YYTOKENTYPE
|
||||
/* Put the tokens into the symbol table, so that GDB and other debuggers
|
||||
know about them. */
|
||||
enum yytokentype {
|
||||
DT_INTEGER = 258,
|
||||
DT_FLOAT = 259,
|
||||
DT_STRING = 260,
|
||||
DT_ATTRNAME = 261,
|
||||
DT_ATTRVALUE = 262,
|
||||
KW_LBMSIM = 263,
|
||||
KW_COMPARELBM = 264,
|
||||
KW_ANIFRAMETIME = 265,
|
||||
KW_DEBUGMODE = 266,
|
||||
KW_P_RELAXTIME = 267,
|
||||
KW_P_REYNOLDS = 268,
|
||||
KW_P_VISCOSITY = 269,
|
||||
KW_P_SOUNDSPEED = 270,
|
||||
KW_P_DOMAINSIZE = 271,
|
||||
KW_P_FORCE = 272,
|
||||
KW_P_TIMELENGTH = 273,
|
||||
KW_P_STEPTIME = 274,
|
||||
KW_P_TIMEFACTOR = 275,
|
||||
KW_P_ANIFRAMETIME = 276,
|
||||
KW_P_ANISTART = 277,
|
||||
KW_P_SURFACETENSION = 278,
|
||||
KW_P_ACTIVATE = 279,
|
||||
KW_P_DEACTIVATE = 280,
|
||||
KW_P_DENSITY = 281,
|
||||
KW_P_CELLSIZE = 282,
|
||||
KW_P_GSTAR = 283,
|
||||
KW_PFSPATH = 284,
|
||||
KW_PARTLINELENGTH = 285,
|
||||
KW_PARTICLES = 286,
|
||||
KW_FRAMESPERSEC = 287,
|
||||
KW_RAYTRACING = 288,
|
||||
KW_PAROPEN = 289,
|
||||
KW_PARCLOSE = 290,
|
||||
KW_FILENAME = 291,
|
||||
KW_PMCAUSTICS = 292,
|
||||
KW_MAXRAYDEPTH = 293,
|
||||
KW_CAUSTICDIST = 294,
|
||||
KW_CAUSTICPHOT = 295,
|
||||
KW_SHADOWMAPBIAS = 296,
|
||||
KW_TREEMAXDEPTH = 297,
|
||||
KW_TREEMAXTRIANGLES = 298,
|
||||
KW_RESOLUTION = 299,
|
||||
KW_ANTIALIAS = 300,
|
||||
KW_EYEPOINT = 301,
|
||||
KW_ANISTART = 302,
|
||||
KW_ANIFRAMES = 303,
|
||||
KW_FRAMESKIP = 304,
|
||||
KW_LOOKAT = 305,
|
||||
KW_UPVEC = 306,
|
||||
KW_FOVY = 307,
|
||||
KW_ASPECT = 308,
|
||||
KW_AMBIENCE = 309,
|
||||
KW_BACKGROUND = 310,
|
||||
KW_DEBUGPIXEL = 311,
|
||||
KW_TESTMODE = 312,
|
||||
KW_OPENGLATTR = 313,
|
||||
KW_BLENDERATTR = 314,
|
||||
KW_ATTRIBUTE = 315,
|
||||
KW_OBJATTR = 316,
|
||||
KW_EQUALS = 317,
|
||||
KW_DEFINEATTR = 318,
|
||||
KW_ATTREND = 319,
|
||||
KW_GEOMETRY = 320,
|
||||
KW_TYPE = 321,
|
||||
KW_GEOTYPE_BOX = 322,
|
||||
KW_GEOTYPE_FLUID = 323,
|
||||
KW_GEOTYPE_OBJMODEL = 324,
|
||||
KW_GEOTYPE_SPHERE = 325,
|
||||
KW_CASTSHADOWS = 326,
|
||||
KW_RECEIVESHADOWS = 327,
|
||||
KW_VISIBLE = 328,
|
||||
KW_BOX_END = 329,
|
||||
KW_BOX_START = 330,
|
||||
KW_POLY = 331,
|
||||
KW_NUMVERTICES = 332,
|
||||
KW_VERTEX = 333,
|
||||
KW_NUMPOLYGONS = 334,
|
||||
KW_ISOSURF = 335,
|
||||
KW_FILEMODE = 336,
|
||||
KW_INVERT = 337,
|
||||
KW_MATERIAL = 338,
|
||||
KW_MATTYPE_PHONG = 339,
|
||||
KW_MATTYPE_BLINN = 340,
|
||||
KW_NAME = 341,
|
||||
KW_AMBIENT = 342,
|
||||
KW_DIFFUSE = 343,
|
||||
KW_SPECULAR = 344,
|
||||
KW_MIRROR = 345,
|
||||
KW_TRANSPARENCE = 346,
|
||||
KW_REFRACINDEX = 347,
|
||||
KW_TRANSADDITIVE = 348,
|
||||
KW_TRANSATTCOL = 349,
|
||||
KW_FRESNEL = 350,
|
||||
KW_LIGHT = 351,
|
||||
KW_ACTIVE = 352,
|
||||
KW_COLOUR = 353,
|
||||
KW_POSITION = 354,
|
||||
KW_LIGHT_OMNI = 355,
|
||||
KW_CAUSTICPHOTONS = 356,
|
||||
KW_CAUSTICSTRENGTH = 357,
|
||||
KW_SHADOWMAP = 358,
|
||||
KW_CAUSTICSMAP = 359
|
||||
};
|
||||
#endif
|
||||
#define DT_INTEGER 258
|
||||
#define DT_FLOAT 259
|
||||
#define DT_STRING 260
|
||||
#define DT_ATTRNAME 261
|
||||
#define DT_ATTRVALUE 262
|
||||
#define KW_LBMSIM 263
|
||||
#define KW_COMPARELBM 264
|
||||
#define KW_ANIFRAMETIME 265
|
||||
#define KW_DEBUGMODE 266
|
||||
#define KW_P_RELAXTIME 267
|
||||
#define KW_P_REYNOLDS 268
|
||||
#define KW_P_VISCOSITY 269
|
||||
#define KW_P_SOUNDSPEED 270
|
||||
#define KW_P_DOMAINSIZE 271
|
||||
#define KW_P_FORCE 272
|
||||
#define KW_P_TIMELENGTH 273
|
||||
#define KW_P_STEPTIME 274
|
||||
#define KW_P_TIMEFACTOR 275
|
||||
#define KW_P_ANIFRAMETIME 276
|
||||
#define KW_P_ANISTART 277
|
||||
#define KW_P_SURFACETENSION 278
|
||||
#define KW_P_ACTIVATE 279
|
||||
#define KW_P_DEACTIVATE 280
|
||||
#define KW_P_DENSITY 281
|
||||
#define KW_P_CELLSIZE 282
|
||||
#define KW_P_GSTAR 283
|
||||
#define KW_PFSPATH 284
|
||||
#define KW_PARTLINELENGTH 285
|
||||
#define KW_PARTICLES 286
|
||||
#define KW_FRAMESPERSEC 287
|
||||
#define KW_RAYTRACING 288
|
||||
#define KW_PAROPEN 289
|
||||
#define KW_PARCLOSE 290
|
||||
#define KW_FILENAME 291
|
||||
#define KW_PMCAUSTICS 292
|
||||
#define KW_MAXRAYDEPTH 293
|
||||
#define KW_CAUSTICDIST 294
|
||||
#define KW_CAUSTICPHOT 295
|
||||
#define KW_SHADOWMAPBIAS 296
|
||||
#define KW_TREEMAXDEPTH 297
|
||||
#define KW_TREEMAXTRIANGLES 298
|
||||
#define KW_RESOLUTION 299
|
||||
#define KW_ANTIALIAS 300
|
||||
#define KW_EYEPOINT 301
|
||||
#define KW_ANISTART 302
|
||||
#define KW_ANIFRAMES 303
|
||||
#define KW_FRAMESKIP 304
|
||||
#define KW_LOOKAT 305
|
||||
#define KW_UPVEC 306
|
||||
#define KW_FOVY 307
|
||||
#define KW_ASPECT 308
|
||||
#define KW_AMBIENCE 309
|
||||
#define KW_BACKGROUND 310
|
||||
#define KW_DEBUGPIXEL 311
|
||||
#define KW_TESTMODE 312
|
||||
#define KW_OPENGLATTR 313
|
||||
#define KW_BLENDERATTR 314
|
||||
#define KW_ATTRIBUTE 315
|
||||
#define KW_OBJATTR 316
|
||||
#define KW_EQUALS 317
|
||||
#define KW_DEFINEATTR 318
|
||||
#define KW_ATTREND 319
|
||||
#define KW_GEOMETRY 320
|
||||
#define KW_TYPE 321
|
||||
#define KW_GEOTYPE_BOX 322
|
||||
#define KW_GEOTYPE_FLUID 323
|
||||
#define KW_GEOTYPE_OBJMODEL 324
|
||||
#define KW_GEOTYPE_SPHERE 325
|
||||
#define KW_CASTSHADOWS 326
|
||||
#define KW_RECEIVESHADOWS 327
|
||||
#define KW_VISIBLE 328
|
||||
#define KW_BOX_END 329
|
||||
#define KW_BOX_START 330
|
||||
#define KW_POLY 331
|
||||
#define KW_NUMVERTICES 332
|
||||
#define KW_VERTEX 333
|
||||
#define KW_NUMPOLYGONS 334
|
||||
#define KW_ISOSURF 335
|
||||
#define KW_FILEMODE 336
|
||||
#define KW_INVERT 337
|
||||
#define KW_MATERIAL 338
|
||||
#define KW_MATTYPE_PHONG 339
|
||||
#define KW_MATTYPE_BLINN 340
|
||||
#define KW_NAME 341
|
||||
#define KW_AMBIENT 342
|
||||
#define KW_DIFFUSE 343
|
||||
#define KW_SPECULAR 344
|
||||
#define KW_MIRROR 345
|
||||
#define KW_TRANSPARENCE 346
|
||||
#define KW_REFRACINDEX 347
|
||||
#define KW_TRANSADDITIVE 348
|
||||
#define KW_TRANSATTCOL 349
|
||||
#define KW_FRESNEL 350
|
||||
#define KW_LIGHT 351
|
||||
#define KW_ACTIVE 352
|
||||
#define KW_COLOUR 353
|
||||
#define KW_POSITION 354
|
||||
#define KW_LIGHT_OMNI 355
|
||||
#define KW_CAUSTICPHOTONS 356
|
||||
#define KW_CAUSTICSTRENGTH 357
|
||||
#define KW_SHADOWMAP 358
|
||||
#define KW_CAUSTICSMAP 359
|
||||
|
||||
|
||||
|
||||
|
||||
#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
|
||||
#line 85 "src/cfgparser.yy"
|
||||
typedef union YYSTYPE {
|
||||
int intValue;
|
||||
float floatValue;
|
||||
char *charValue;
|
||||
} YYSTYPE;
|
||||
/* Line 1285 of yacc.c. */
|
||||
#line 251 "bld-std-gcc/src/cfgparser.hpp"
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
# define YYSTYPE_IS_DECLARED 1
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
#endif
|
||||
|
||||
extern YYSTYPE yy_lval;
|
||||
|
||||
|
||||
|
51
intern/elbeem/intern/elbeem.cpp
Normal file
51
intern/elbeem/intern/elbeem.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* All code distributed as part of El'Beem is covered by the version 2 of the
|
||||
* GNU General Public License. See the file COPYING for details.
|
||||
* Copyright 2003-2005 Nils Thuerey
|
||||
*
|
||||
* Main program functions
|
||||
*
|
||||
*/
|
||||
|
||||
//#include "globals.h"
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
// region of interest global vars
|
||||
// currently used by e.g. fsgr solver
|
||||
double guiRoiSX = 0.0;
|
||||
double guiRoiSY = 0.0;
|
||||
double guiRoiSZ = 0.0;
|
||||
double guiRoiEX = 1.0;
|
||||
double guiRoiEY = 1.0;
|
||||
double guiRoiEZ = 1.0;
|
||||
int guiRoiMaxLev=6, guiRoiMinLev=0;
|
||||
|
||||
//! global raytracer pointer (=world)
|
||||
class ntlRaytracer;
|
||||
ntlRaytracer *gpWorld = (ntlRaytracer*)0;
|
||||
|
||||
//! debug output switch
|
||||
bool myDebugOut = false;
|
||||
|
||||
//! global leave program variable
|
||||
bool gQuit = false;
|
||||
|
||||
//! start simulation?
|
||||
bool gThreadRunning = false;
|
||||
|
||||
/* usage message */
|
||||
char* usageString =
|
||||
"El'Beem - Lattice Boltzmann Free Surface Simulator\n\
|
||||
Command-line Options: \n\
|
||||
-b : .obj file dump mode for Blender\n\
|
||||
-c : Force command line mode for rendering \n\
|
||||
-d : Dump mode for ECR\n\
|
||||
-f <filename> : Specify fluid description file to use as <filename>\n\
|
||||
-h : Display this message \n\
|
||||
-o : single frame output to given file\n\
|
||||
\n ";
|
||||
|
||||
|
40
intern/elbeem/intern/factory_fsgr.cpp
Normal file
40
intern/elbeem/intern/factory_fsgr.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004,2005 Nils Thuerey
|
||||
*
|
||||
* Standard LBM Factory implementation
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "factory_lbm.h"
|
||||
|
||||
// compiler sanity check
|
||||
#ifndef LBMDIM
|
||||
#if LBMDIM!=2
|
||||
#if LBMDIM!=3
|
||||
print("Error - LBMDIM has to be defined (2/3)!");
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// disable sometimes to speed up compiling/2d tests
|
||||
#define DISABLE 0
|
||||
|
||||
#include "lbmdimensions.h"
|
||||
#include "lbmfsgrsolver.h"
|
||||
|
||||
//! lbm factory functions
|
||||
LbmSolverInterface* createSolverLbmFsgr() {
|
||||
#if DISABLE!=1
|
||||
#if LBMDIM==2
|
||||
return new LbmFsgrSolver< LbmBGK2D >();
|
||||
#endif // LBMDIM==2
|
||||
#if LBMDIM==3
|
||||
return new LbmFsgrSolver< LbmBGK3D >();
|
||||
#endif // LBMDIM==3
|
||||
#endif // DISABLE
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
18
intern/elbeem/intern/factory_lbm.h
Normal file
18
intern/elbeem/intern/factory_lbm.h
Normal file
@ -0,0 +1,18 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* 2D/3D LBM Factory header
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "lbminterface.h"
|
||||
|
||||
//! lbm factory functions
|
||||
LbmSolverInterface* createSolverLbmFsgr();
|
||||
#ifdef LBM_INCLUDE_TESTSOLVERS
|
||||
LbmSolverInterface* createSolverOld();
|
||||
#endif // LBM_INCLUDE_OLD
|
||||
|
||||
|
32
intern/elbeem/intern/globals.h
Normal file
32
intern/elbeem/intern/globals.h
Normal file
@ -0,0 +1,32 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* All code distributed as part of El'Beem is covered by the version 2 of the
|
||||
* GNU General Public License. See the file COPYING for details.
|
||||
* Copyright 2003-2005 Nils Thuerey
|
||||
*
|
||||
* Global variables (unavoidable at times...)
|
||||
* all defines in main.cpp
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
//! user interface variables
|
||||
|
||||
// global raytracer pointer (=world)
|
||||
class ntlRaytracer;
|
||||
extern ntlRaytracer *gpWorld;
|
||||
|
||||
// debug output switch
|
||||
extern bool myDebugOut;
|
||||
|
||||
// global leave program variable
|
||||
extern bool gQuit;
|
||||
|
||||
//! start simulation?
|
||||
extern bool gThreadRunning;
|
||||
|
||||
//! short manual
|
||||
extern char* usageString;
|
||||
|
1057
intern/elbeem/intern/isosurface.cpp
Normal file
1057
intern/elbeem/intern/isosurface.cpp
Normal file
File diff suppressed because it is too large
Load Diff
277
intern/elbeem/intern/isosurface.h
Normal file
277
intern/elbeem/intern/isosurface.h
Normal file
@ -0,0 +1,277 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* Marching Cubes "displayer"
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef ISOSURFACE_H
|
||||
|
||||
#include "ntl_geometryobject.h"
|
||||
#include "ntl_bsptree.h"
|
||||
//class LbmSolver3D;
|
||||
|
||||
|
||||
|
||||
/* access some 3d array */
|
||||
//#define ISOLEVEL_INDEX(ii,ij,ik) ((S::mSizex*S::mSizey*(ik))+(S::mSizex*(ij))+((ii)))
|
||||
#define ISOLEVEL_INDEX(ii,ij,ik) ((mSizex*mSizey*(ik))+(mSizex*(ij))+((ii)))
|
||||
|
||||
/* struct for a small cube in the scalar field */
|
||||
typedef struct {
|
||||
ntlVec3Gfx pos[8];
|
||||
double value[8];
|
||||
int i,j,k;
|
||||
} IsoLevelCube;
|
||||
|
||||
|
||||
typedef struct {
|
||||
ntlVec3Gfx v; // vertex
|
||||
ntlVec3Gfx n; // vertex normal
|
||||
} IsoLevelVertex;
|
||||
|
||||
//! class to triangulate a scalar field, e.g. for
|
||||
// the fluid surface, templated by scalar field access object
|
||||
//template<class S>
|
||||
class IsoSurface :
|
||||
public ntlGeometryObject //, public S
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
/*! Constructor */
|
||||
IsoSurface(double iso, double blend);
|
||||
/*! Destructor */
|
||||
~IsoSurface();
|
||||
|
||||
/*! Init ararys etc. */
|
||||
virtual void initializeIsosurface(int setx, int sety, int setz, ntlVec3Gfx extent);
|
||||
|
||||
/*! triangulate the scalar field given by pointer*/
|
||||
void triangulate( void );
|
||||
|
||||
protected:
|
||||
|
||||
/* variables ... */
|
||||
|
||||
//! size
|
||||
int mSizex, mSizey, mSizez;
|
||||
|
||||
//! data pointer
|
||||
float *mpData;
|
||||
|
||||
//! Level of the iso surface
|
||||
double mIsoValue;
|
||||
|
||||
//! blending distance for marching cubes
|
||||
double mBlendVal;
|
||||
|
||||
//! Store all the triangles vertices
|
||||
vector<IsoLevelVertex> mPoints;
|
||||
|
||||
//! Store indices of calculated points along the cubie edges
|
||||
int *mpEdgeVerticesX;
|
||||
int *mpEdgeVerticesY;
|
||||
int *mpEdgeVerticesZ;
|
||||
|
||||
|
||||
//! vector for all the triangles (stored as 3 indices)
|
||||
vector<unsigned int> mIndices;
|
||||
|
||||
//! start and end vectors for the triangulation region to create triangles in
|
||||
ntlVec3Gfx mStart, mEnd;
|
||||
|
||||
//! normalized domain extent from parametrizer/visualizer
|
||||
ntlVec3Gfx mDomainExtent;
|
||||
|
||||
//! initialized?
|
||||
bool mInitDone;
|
||||
|
||||
//! no. of refinement steps
|
||||
int mLoopSubdivs;
|
||||
//! amount of surface smoothing
|
||||
float mSmoothSurface;
|
||||
//! amount of normal smoothing
|
||||
float mSmoothNormals;
|
||||
|
||||
//! grid data
|
||||
vector<int> mAcrossEdge;
|
||||
vector< vector<int> > mAdjacentFaces;
|
||||
|
||||
vector<unsigned> flags;
|
||||
unsigned flag_curr;
|
||||
vector<ntlVec3Gfx> cornerareas;
|
||||
vector<float> pointareas;
|
||||
vector< vector<int> > neighbors;
|
||||
|
||||
public:
|
||||
// miscelleanous access functions
|
||||
|
||||
//! set geometry start (for renderer)
|
||||
void setStart(ntlVec3Gfx set) { mStart = set; };
|
||||
//! set geometry end (for renderer)
|
||||
void setEnd(ntlVec3Gfx set) { mEnd = set; };
|
||||
//! set iso level value for surface reconstruction
|
||||
inline void setIsolevel(double set) { mIsoValue = set; };
|
||||
//! set loop subdiv num
|
||||
inline void setLoopSubdivs(int set) { mLoopSubdivs = set; };
|
||||
inline void setSmoothSurface(float set) { mSmoothSurface = set; };
|
||||
inline void setSmoothNormals(float set) { mSmoothNormals = set; };
|
||||
|
||||
// geometry object functions
|
||||
virtual void getTriangles( vector<ntlTriangle> *triangles,
|
||||
vector<ntlVec3Gfx> *vertices,
|
||||
vector<ntlVec3Gfx> *normals, int objectId );
|
||||
|
||||
//! for easy GUI detection get start of axis aligned bounding box, return NULL of no BB
|
||||
virtual inline ntlVec3Gfx *getBBStart() { return &mStart; }
|
||||
virtual inline ntlVec3Gfx *getBBEnd() { return &mEnd; }
|
||||
|
||||
//! access data array
|
||||
inline float* getData(){ return mpData; }
|
||||
inline float* getData(int i, int j, int k){ return mpData + ISOLEVEL_INDEX(i,j,k); }
|
||||
inline float* lbmGetData(int i, int j, int k){ return mpData + ISOLEVEL_INDEX(i+1,j+1,k+1); }
|
||||
|
||||
//! OpenGL viz "interface"
|
||||
unsigned int getIsoVertexCount() {
|
||||
return mPoints.size();
|
||||
}
|
||||
unsigned int getIsoIndexCount() {
|
||||
return mIndices.size();
|
||||
}
|
||||
char* getIsoVertexArray() {
|
||||
return (char *) &(mPoints[0]);
|
||||
}
|
||||
unsigned int *getIsoIndexArray() {
|
||||
return &(mIndices[0]);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
//! computer normal
|
||||
inline ntlVec3Gfx getNormal(int i, int j,int k);
|
||||
|
||||
void subdivide();
|
||||
void smoothSurface(float val);
|
||||
void smoothNormals(float val);
|
||||
void diffuseVertexField(ntlVec3Gfx *field, const int pointerScale, int v, float invsigma2, ntlVec3Gfx &flt);
|
||||
};
|
||||
|
||||
|
||||
|
||||
class TriMesh {
|
||||
public:
|
||||
// Types
|
||||
struct Face {
|
||||
int v[3];
|
||||
|
||||
Face() {}
|
||||
Face(const int &v0, const int &v1, const int &v2)
|
||||
{ v[0] = v0; v[1] = v1; v[2] = v2; }
|
||||
Face(const int *v_)
|
||||
{ v[0] = v_[0]; v[1] = v_[1]; v[2] = v_[2]; }
|
||||
int &operator[] (int i) { return v[i]; }
|
||||
const int &operator[] (int i) const { return v[i]; }
|
||||
operator const int * () const { return &(v[0]); }
|
||||
operator const int * () { return &(v[0]); }
|
||||
operator int * () { return &(v[0]); }
|
||||
int indexof(int v_) const
|
||||
{
|
||||
return (v[0] == v_) ? 0 :
|
||||
(v[1] == v_) ? 1 :
|
||||
(v[2] == v_) ? 2 : -1;
|
||||
}
|
||||
};
|
||||
|
||||
struct BBox {
|
||||
ntlVec3Gfx min, max;
|
||||
ntlVec3Gfx center() const { return (min+max)*0.5f; }
|
||||
ntlVec3Gfx size() const { return max - min; }
|
||||
};
|
||||
|
||||
struct BSphere {
|
||||
ntlVec3Gfx center;
|
||||
float r;
|
||||
};
|
||||
|
||||
// Enums
|
||||
enum tstrip_rep { TSTRIP_LENGTH, TSTRIP_TERM };
|
||||
|
||||
// The basics: vertices and faces
|
||||
vector<ntlVec3Gfx> vertices;
|
||||
vector<Face> faces;
|
||||
|
||||
// Triangle strips
|
||||
vector<int> tstrips;
|
||||
|
||||
// Other per-vertex properties
|
||||
//vector<Color> colors;
|
||||
vector<float> confidences;
|
||||
vector<unsigned> flags;
|
||||
unsigned flag_curr;
|
||||
|
||||
// Computed per-vertex properties
|
||||
vector<ntlVec3Gfx> normals;
|
||||
vector<ntlVec3Gfx> pdir1, pdir2;
|
||||
vector<float> curv1, curv2;
|
||||
//vector< Vec<4,float> > dcurv;
|
||||
vector<ntlVec3Gfx> cornerareas;
|
||||
vector<float> pointareas;
|
||||
|
||||
// Bounding structures
|
||||
BBox bbox;
|
||||
BSphere bsphere;
|
||||
|
||||
// Connectivity structures:
|
||||
// For each vertex, all neighboring vertices
|
||||
vector< vector<int> > neighbors;
|
||||
// For each vertex, all neighboring faces
|
||||
vector< vector<int> > adjacentfaces;
|
||||
// For each face, the three faces attached to its edges
|
||||
// (for example, across_edge[3][2] is the number of the face
|
||||
// that's touching the edge opposite vertex 2 of face 3)
|
||||
vector<Face> across_edge;
|
||||
|
||||
// Compute all this stuff...
|
||||
void need_tstrips();
|
||||
void convert_strips(tstrip_rep rep);
|
||||
void need_faces();
|
||||
void need_normals();
|
||||
void need_pointareas();
|
||||
void need_curvatures();
|
||||
void need_dcurv();
|
||||
void need_bbox();
|
||||
void need_bsphere();
|
||||
void need_neighbors();
|
||||
void need_adjacentfaces();
|
||||
void need_across_edge();
|
||||
|
||||
// Input and output
|
||||
static TriMesh *read(const char *filename);
|
||||
void write(const char *filename);
|
||||
|
||||
// Statistics
|
||||
// XXX - Add stuff here
|
||||
float feature_size();
|
||||
|
||||
// Useful queries
|
||||
// XXX - Add stuff here
|
||||
bool is_bdy(int v)
|
||||
{
|
||||
if (neighbors.empty()) need_neighbors();
|
||||
if (adjacentfaces.empty()) need_adjacentfaces();
|
||||
return neighbors[v].size() != adjacentfaces[v].size();
|
||||
}
|
||||
|
||||
// Debugging printout, controllable by a "verbose"ness parameter
|
||||
static int verbose;
|
||||
static void set_verbose(int);
|
||||
static int dprintf(const char *format, ...);
|
||||
};
|
||||
|
||||
#define ISOSURFACE_H
|
||||
#endif
|
||||
|
||||
|
391
intern/elbeem/intern/lbmdimensions.h
Normal file
391
intern/elbeem/intern/lbmdimensions.h
Normal file
@ -0,0 +1,391 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* All code distributed as part of El'Beem is covered by the version 2 of the
|
||||
* GNU General Public License. See the file COPYING for details.
|
||||
* Copyright 2003-2005 Nils Thuerey
|
||||
*
|
||||
* Combined 2D/3D Lattice Boltzmann Solver auxiliary classes
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef LBMHEADER_H
|
||||
|
||||
/* LBM Files */
|
||||
#include "lbminterface.h"
|
||||
#include <sstream>
|
||||
|
||||
|
||||
//! shorten static const definitions
|
||||
#define STCON static const
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/*! class for solver templating - 3D implementation */
|
||||
//class LbmD3Q19 : public LbmSolverInterface {
|
||||
class LbmD3Q19 {
|
||||
|
||||
public:
|
||||
|
||||
// constructor, init interface
|
||||
LbmD3Q19() {};
|
||||
// virtual destructor
|
||||
virtual ~LbmD3Q19() {};
|
||||
//! id string of solver
|
||||
string getIdString() { return string("3D"); }
|
||||
|
||||
//! how many dimensions?
|
||||
STCON int cDimension;
|
||||
|
||||
// Wi factors for collide step
|
||||
STCON LbmFloat cCollenZero;
|
||||
STCON LbmFloat cCollenOne;
|
||||
STCON LbmFloat cCollenSqrtTwo;
|
||||
|
||||
//! threshold value for filled/emptied cells
|
||||
STCON LbmFloat cMagicNr2;
|
||||
STCON LbmFloat cMagicNr2Neg;
|
||||
STCON LbmFloat cMagicNr;
|
||||
STCON LbmFloat cMagicNrNeg;
|
||||
|
||||
//! size of a single set of distribution functions
|
||||
STCON int cDfNum;
|
||||
//! direction vector contain vecs for all spatial dirs, even if not used for LBM model
|
||||
STCON int cDirNum;
|
||||
|
||||
//! distribution functions directions
|
||||
typedef enum {
|
||||
cDirInv= -1,
|
||||
cDirC = 0,
|
||||
cDirN = 1,
|
||||
cDirS = 2,
|
||||
cDirE = 3,
|
||||
cDirW = 4,
|
||||
cDirT = 5,
|
||||
cDirB = 6,
|
||||
cDirNE = 7,
|
||||
cDirNW = 8,
|
||||
cDirSE = 9,
|
||||
cDirSW = 10,
|
||||
cDirNT = 11,
|
||||
cDirNB = 12,
|
||||
cDirST = 13,
|
||||
cDirSB = 14,
|
||||
cDirET = 15,
|
||||
cDirEB = 16,
|
||||
cDirWT = 17,
|
||||
cDirWB = 18
|
||||
} dfDir;
|
||||
|
||||
/* Vector Order 3D:
|
||||
* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
||||
* 0, 0, 0, 1,-1, 0, 0, 1,-1, 1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1,-1, 1,-1, 1,-1, 1,-1
|
||||
* 0, 1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1, 1,-1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1, 1,-1,-1
|
||||
* 0, 0, 0, 0, 0, 1,-1, 0, 0, 0, 0, 1,-1, 1,-1, 1,-1, 1,-1, 1, 1, 1, 1, -1,-1,-1,-1
|
||||
*/
|
||||
|
||||
/*! name of the dist. function
|
||||
only for nicer output */
|
||||
STCON char* dfString[ 19 ];
|
||||
|
||||
/*! index of normal dist func, not used so far?... */
|
||||
STCON dfDir dfNorm[ 19 ];
|
||||
|
||||
/*! index of inverse dist func, not fast, but useful... */
|
||||
STCON dfDir dfInv[ 19 ];
|
||||
|
||||
/*! index of x reflected dist func for free slip, not valid for all DFs... */
|
||||
STCON int dfRefX[ 19 ];
|
||||
/*! index of x reflected dist func for free slip, not valid for all DFs... */
|
||||
STCON int dfRefY[ 19 ];
|
||||
/*! index of x reflected dist func for free slip, not valid for all DFs... */
|
||||
STCON int dfRefZ[ 19 ];
|
||||
|
||||
/*! dist func vectors */
|
||||
STCON int dfVecX[ 27 ];
|
||||
STCON int dfVecY[ 27 ];
|
||||
STCON int dfVecZ[ 27 ];
|
||||
|
||||
/*! arrays as before with doubles */
|
||||
STCON LbmFloat dfDvecX[ 27 ];
|
||||
STCON LbmFloat dfDvecY[ 27 ];
|
||||
STCON LbmFloat dfDvecZ[ 27 ];
|
||||
|
||||
/*! principal directions */
|
||||
STCON int princDirX[ 2*3 ];
|
||||
STCON int princDirY[ 2*3 ];
|
||||
STCON int princDirZ[ 2*3 ];
|
||||
|
||||
/*! vector lengths */
|
||||
STCON LbmFloat dfLength[ 19 ];
|
||||
|
||||
/*! equilibrium distribution functions, precalculated = getCollideEq(i, 0,0,0,0) */
|
||||
static LbmFloat dfEquil[ 19 ];
|
||||
|
||||
/*! arrays for les model coefficients */
|
||||
static LbmFloat lesCoeffDiag[ (3-1)*(3-1) ][ 27 ];
|
||||
static LbmFloat lesCoeffOffdiag[ 3 ][ 27 ];
|
||||
|
||||
}; // LbmData3D
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
//! class for solver templating - 2D implementation
|
||||
//class LbmD2Q9 : public LbmSolverInterface {
|
||||
class LbmD2Q9 {
|
||||
|
||||
public:
|
||||
|
||||
// constructor, init interface
|
||||
LbmD2Q9() {};
|
||||
// virtual destructor
|
||||
virtual ~LbmD2Q9() {};
|
||||
//! id string of solver
|
||||
string getIdString() { return string("2D"); }
|
||||
|
||||
//! how many dimensions?
|
||||
STCON int cDimension;
|
||||
|
||||
//! Wi factors for collide step
|
||||
STCON LbmFloat cCollenZero;
|
||||
STCON LbmFloat cCollenOne;
|
||||
STCON LbmFloat cCollenSqrtTwo;
|
||||
|
||||
//! threshold value for filled/emptied cells
|
||||
STCON LbmFloat cMagicNr2;
|
||||
STCON LbmFloat cMagicNr2Neg;
|
||||
STCON LbmFloat cMagicNr;
|
||||
STCON LbmFloat cMagicNrNeg;
|
||||
|
||||
//! size of a single set of distribution functions
|
||||
STCON int cDfNum;
|
||||
STCON int cDirNum;
|
||||
|
||||
//! distribution functions directions
|
||||
typedef enum {
|
||||
cDirInv= -1,
|
||||
cDirC = 0,
|
||||
cDirN = 1,
|
||||
cDirS = 2,
|
||||
cDirE = 3,
|
||||
cDirW = 4,
|
||||
cDirNE = 5,
|
||||
cDirNW = 6,
|
||||
cDirSE = 7,
|
||||
cDirSW = 8
|
||||
} dfDir;
|
||||
|
||||
/* Vector Order 2D:
|
||||
* 0 1 2 3 4 5 6 7 8
|
||||
* 0, 0,0, 1,-1, 1,-1,1,-1
|
||||
* 0, 1,-1, 0,0, 1,1,-1,-1 */
|
||||
|
||||
/* name of the dist. function
|
||||
only for nicer output */
|
||||
STCON char* dfString[ 9 ];
|
||||
|
||||
/* index of normal dist func, not used so far?... */
|
||||
STCON dfDir dfNorm[ 9 ];
|
||||
|
||||
/* index of inverse dist func, not fast, but useful... */
|
||||
STCON dfDir dfInv[ 9 ];
|
||||
|
||||
/* index of x reflected dist func for free slip, not valid for all DFs... */
|
||||
STCON int dfRefX[ 9 ];
|
||||
/* index of x reflected dist func for free slip, not valid for all DFs... */
|
||||
STCON int dfRefY[ 9 ];
|
||||
/* index of x reflected dist func for free slip, not valid for all DFs... */
|
||||
STCON int dfRefZ[ 9 ];
|
||||
|
||||
/* dist func vectors */
|
||||
STCON int dfVecX[ 9 ];
|
||||
STCON int dfVecY[ 9 ];
|
||||
/* Z, 2D values are all 0! */
|
||||
STCON int dfVecZ[ 9 ];
|
||||
|
||||
/* arrays as before with doubles */
|
||||
STCON LbmFloat dfDvecX[ 9 ];
|
||||
STCON LbmFloat dfDvecY[ 9 ];
|
||||
/* Z, 2D values are all 0! */
|
||||
STCON LbmFloat dfDvecZ[ 9 ];
|
||||
|
||||
/*! principal directions */
|
||||
STCON int princDirX[ 2*2 ];
|
||||
STCON int princDirY[ 2*2 ];
|
||||
STCON int princDirZ[ 2*2 ];
|
||||
|
||||
/* vector lengths */
|
||||
STCON LbmFloat dfLength[ 9 ];
|
||||
|
||||
/* equilibrium distribution functions, precalculated = getCollideEq(i, 0,0,0,0) */
|
||||
static LbmFloat dfEquil[ 9 ];
|
||||
|
||||
/*! arrays for les model coefficients */
|
||||
static LbmFloat lesCoeffDiag[ (2-1)*(2-1) ][ 9 ];
|
||||
static LbmFloat lesCoeffOffdiag[ 2 ][ 9 ];
|
||||
|
||||
}; // LbmData3D
|
||||
|
||||
|
||||
|
||||
// not needed hereafter
|
||||
#undef STCON
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
//! class for solver templating - lbgk (srt) model implementation
|
||||
template<class DQ>
|
||||
class LbmModelLBGK : public DQ , public LbmSolverInterface {
|
||||
public:
|
||||
|
||||
/*! type for cells contents, needed for cell id interface */
|
||||
typedef DQ LbmCellContents;
|
||||
/*! type for cells */
|
||||
typedef LbmCellTemplate< LbmCellContents > LbmCell;
|
||||
|
||||
// constructor
|
||||
LbmModelLBGK() : DQ(), LbmSolverInterface() {};
|
||||
// virtual destructor
|
||||
virtual ~LbmModelLBGK() {};
|
||||
//! id string of solver
|
||||
std::string getIdString() { return DQ::getIdString() + std::string("lbgk]"); }
|
||||
|
||||
/*! calculate length of velocity vector */
|
||||
static inline LbmFloat getVelVecLen(int l, LbmFloat ux,LbmFloat uy,LbmFloat uz) {
|
||||
return ((ux)*DQ::dfDvecX[l]+(uy)*DQ::dfDvecY[l]+(uz)*DQ::dfDvecZ[l]);
|
||||
};
|
||||
|
||||
/*! calculate equilibrium DF for given values */
|
||||
static inline LbmFloat getCollideEq(int l, LbmFloat rho, LbmFloat ux, LbmFloat uy, LbmFloat uz) {
|
||||
LbmFloat tmp = getVelVecLen(l,ux,uy,uz);
|
||||
return( DQ::dfLength[l] *(
|
||||
+ rho - (3.0/2.0*(ux*ux + uy*uy + uz*uz))
|
||||
+ 3.0 *tmp
|
||||
+ 9.0/2.0 *(tmp*tmp) )
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
// input mux etc. as acceleration
|
||||
// outputs rho,ux,uy,uz
|
||||
/*inline void collideArrays_org(LbmFloat df[19],
|
||||
LbmFloat &outrho, // out only!
|
||||
// velocity modifiers (returns actual velocity!)
|
||||
LbmFloat &mux, LbmFloat &muy, LbmFloat &muz,
|
||||
LbmFloat omega
|
||||
) {
|
||||
LbmFloat rho=df[0];
|
||||
LbmFloat ux = mux;
|
||||
LbmFloat uy = muy;
|
||||
LbmFloat uz = muz;
|
||||
for(int l=1; l<DQ::cDfNum; l++) {
|
||||
rho += df[l];
|
||||
ux += (DQ::dfDvecX[l]*df[l]);
|
||||
uy += (DQ::dfDvecY[l]*df[l]);
|
||||
uz += (DQ::dfDvecZ[l]*df[l]);
|
||||
}
|
||||
for(int l=0; l<DQ::cDfNum; l++) {
|
||||
//LbmFloat tmp = (ux*DQ::dfDvecX[l]+uy*DQ::dfDvecY[l]+uz*DQ::dfDvecZ[l]);
|
||||
df[l] = (1.0-omega ) * df[l] + omega * ( getCollideEq(l,rho,ux,uy,uz) );
|
||||
}
|
||||
|
||||
mux = ux;
|
||||
muy = uy;
|
||||
muz = uz;
|
||||
outrho = rho;
|
||||
};*/
|
||||
|
||||
// LES functions
|
||||
inline LbmFloat getLesNoneqTensorCoeff(
|
||||
LbmFloat df[],
|
||||
LbmFloat feq[] ) {
|
||||
LbmFloat Qo = 0.0;
|
||||
for(int m=0; m< ((DQ::cDimension*DQ::cDimension)-DQ::cDimension)/2 ; m++) {
|
||||
LbmFloat qadd = 0.0;
|
||||
for(int l=1; l<DQ::cDfNum; l++) {
|
||||
if(DQ::lesCoeffOffdiag[m][l]==0.0) continue;
|
||||
qadd += DQ::lesCoeffOffdiag[m][l]*(df[l]-feq[l]);
|
||||
}
|
||||
Qo += (qadd*qadd);
|
||||
}
|
||||
Qo *= 2.0; // off diag twice
|
||||
for(int m=0; m<DQ::cDimension; m++) {
|
||||
LbmFloat qadd = 0.0;
|
||||
for(int l=1; l<DQ::cDfNum; l++) {
|
||||
if(DQ::lesCoeffDiag[m][l]==0.0) continue;
|
||||
qadd += DQ::lesCoeffDiag[m][l]*(df[l]-feq[l]);
|
||||
}
|
||||
Qo += (qadd*qadd);
|
||||
}
|
||||
Qo = sqrt(Qo);
|
||||
return Qo;
|
||||
}
|
||||
inline LbmFloat getLesOmega(LbmFloat omega, LbmFloat csmago, LbmFloat Qo) {
|
||||
const LbmFloat tau = 1.0/omega;
|
||||
const LbmFloat nu = (2.0*tau-1.0) * (1.0/6.0);
|
||||
const LbmFloat C = csmago;
|
||||
const LbmFloat Csqr = C*C;
|
||||
LbmFloat S = -nu + sqrt( nu*nu + 18.0*Csqr*Qo ) / (6.0*Csqr);
|
||||
return( 1.0/( 3.0*( nu+Csqr*S ) +0.5 ) );
|
||||
}
|
||||
|
||||
// "normal" collision
|
||||
inline void collideArrays(LbmFloat df[],
|
||||
LbmFloat &outrho, // out only!
|
||||
// velocity modifiers (returns actual velocity!)
|
||||
LbmFloat &mux, LbmFloat &muy, LbmFloat &muz,
|
||||
LbmFloat omega, LbmFloat csmago, LbmFloat *newOmegaRet = NULL
|
||||
) {
|
||||
LbmFloat rho=df[0];
|
||||
LbmFloat ux = mux;
|
||||
LbmFloat uy = muy;
|
||||
LbmFloat uz = muz;
|
||||
for(int l=1; l<DQ::cDfNum; l++) {
|
||||
rho += df[l];
|
||||
ux += (DQ::dfDvecX[l]*df[l]);
|
||||
uy += (DQ::dfDvecY[l]*df[l]);
|
||||
uz += (DQ::dfDvecZ[l]*df[l]);
|
||||
}
|
||||
LbmFloat feq[19];
|
||||
for(int l=0; l<DQ::cDfNum; l++) {
|
||||
feq[l] = getCollideEq(l,rho,ux,uy,uz);
|
||||
}
|
||||
|
||||
LbmFloat omegaNew;
|
||||
if(csmago>0.0) {
|
||||
LbmFloat Qo = getLesNoneqTensorCoeff(df,feq);
|
||||
omegaNew = getLesOmega(omega,csmago,Qo);
|
||||
} else {
|
||||
omegaNew = omega; // smago off...
|
||||
}
|
||||
if(newOmegaRet) *newOmegaRet=omegaNew; // return value for stats
|
||||
|
||||
for(int l=0; l<DQ::cDfNum; l++) {
|
||||
df[l] = (1.0-omegaNew ) * df[l] + omegaNew * feq[l];
|
||||
}
|
||||
|
||||
mux = ux;
|
||||
muy = uy;
|
||||
muz = uz;
|
||||
outrho = rho;
|
||||
};
|
||||
|
||||
}; // LBGK
|
||||
|
||||
#ifdef LBMMODEL_DEFINED
|
||||
// force compiler error!
|
||||
ERROR - Dont include several LBM models at once...
|
||||
#endif
|
||||
#define LBMMODEL_DEFINED 1
|
||||
|
||||
|
||||
typedef LbmModelLBGK< LbmD2Q9 > LbmBGK2D;
|
||||
typedef LbmModelLBGK< LbmD3Q19 > LbmBGK3D;
|
||||
|
||||
|
||||
#define LBMHEADER_H
|
||||
#endif
|
||||
|
||||
|
||||
|
6519
intern/elbeem/intern/lbmfsgrsolver.h
Normal file
6519
intern/elbeem/intern/lbmfsgrsolver.h
Normal file
File diff suppressed because it is too large
Load Diff
351
intern/elbeem/intern/lbmfunctions.h
Normal file
351
intern/elbeem/intern/lbmfunctions.h
Normal file
@ -0,0 +1,351 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* All code distributed as part of El'Beem is covered by the version 2 of the
|
||||
* GNU General Public License. See the file COPYING for details.
|
||||
* Copyright 2003-2005 Nils Thuerey
|
||||
*
|
||||
* Combined 2D/3D Lattice Boltzmann Solver templated helper functions
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef LBMFUNCTIONS_H
|
||||
|
||||
|
||||
#if LBM_USE_GUI==1
|
||||
#endif
|
||||
|
||||
|
||||
#if LBM_USE_GUI==1
|
||||
|
||||
//! display a single node
|
||||
template<typename D>
|
||||
void
|
||||
debugDisplayNode(fluidDispSettings *dispset, D *lbm, typename D::CellIdentifier cell ) {
|
||||
//debugOut(" DD: "<<cell->getAsString() , 10);
|
||||
ntlVec3Gfx org = lbm->getCellOrigin( cell );
|
||||
ntlVec3Gfx halfsize = lbm->getCellSize( cell );
|
||||
int set = lbm->getCellSet( cell );
|
||||
//debugOut(" DD: "<<cell->getAsString()<<" "<< (dispset->type) , 10);
|
||||
|
||||
bool showcell = true;
|
||||
int linewidth = 1;
|
||||
ntlColor col(0.5);
|
||||
LbmFloat cscale = dispset->scale;
|
||||
|
||||
switch(dispset->type) {
|
||||
case FLUIDDISPNothing: {
|
||||
showcell = false;
|
||||
} break;
|
||||
case FLUIDDISPCelltypes: {
|
||||
CellFlagType flag = lbm->getCellFlag(cell, set );
|
||||
cscale = 0.5;
|
||||
|
||||
if(flag& CFInvalid ) { if(!guiShowInvalid ) return; }
|
||||
if(flag& CFUnused ) { if(!guiShowInvalid ) return; }
|
||||
if(flag& CFEmpty ) { if(!guiShowEmpty ) return; }
|
||||
if(flag& CFInter ) { if(!guiShowInterface) return; }
|
||||
if(flag& CFNoDelete ) { if(!guiShowNoDelete ) return; }
|
||||
if(flag& CFBnd ) { if(!guiShowBnd ) return; }
|
||||
|
||||
// only dismiss one of these types
|
||||
if(flag& CFGrFromCoarse) { if(!guiShowCoarseInner ) return; } // inner not really interesting
|
||||
else
|
||||
if(flag& CFGrFromFine) { if(!guiShowCoarseBorder ) return; }
|
||||
else
|
||||
if(flag& CFFluid ) { if(!guiShowFluid ) return; }
|
||||
|
||||
|
||||
if(flag& CFNoDelete) { // TEST SOLVER debug, mark nodel cells
|
||||
glLineWidth( linewidth );
|
||||
ntlColor col(0.7,0.0,0.0);
|
||||
glColor3f( col[0], col[1], col[2]);
|
||||
ntlVec3Gfx s = org-(halfsize * 0.1);
|
||||
ntlVec3Gfx e = org+(halfsize * 0.1);
|
||||
drawCubeWire( s,e );
|
||||
}
|
||||
|
||||
/*if(flag& CFAccelerator) {
|
||||
cscale = 0.55;
|
||||
col = ntlColor(0,1,0);
|
||||
//showcell=false; // DEBUG
|
||||
} */
|
||||
if(flag& CFInvalid) {
|
||||
cscale = 0.50;
|
||||
col = ntlColor(0.0,0,0.0);
|
||||
//showcell=false; // DEBUG
|
||||
}
|
||||
/*else if(flag& CFSpeedSet) {
|
||||
cscale = 0.55;
|
||||
col = ntlColor(0.2,1,0.2);
|
||||
//showcell=false; // DEBUG
|
||||
}*/
|
||||
else if(flag& CFBnd) {
|
||||
cscale = 0.59;
|
||||
col = ntlColor(0.0);
|
||||
col = ntlColor(0.4); // DEBUG
|
||||
//if(lbm->getSizeZ()>2) { showcell=false; } // DEBUG, 3D no obstacles
|
||||
}
|
||||
|
||||
/*else if(flag& CFIfFluid) { // TEST SOLVER if inner fluid if
|
||||
cscale = 0.55;
|
||||
col = ntlColor(0,1,0);
|
||||
}
|
||||
else if(flag& CFIfEmpty) { // TEST SOLVER if outer empty if
|
||||
cscale = 0.55;
|
||||
col = ntlColor(0,0.5,0.5);
|
||||
}*/
|
||||
else if(flag& CFInter) {
|
||||
cscale = 0.55;
|
||||
col = ntlColor(0,1,1);
|
||||
|
||||
} else if(flag& CFGrFromCoarse) {
|
||||
// draw as - with marker
|
||||
ntlColor col2(0.0,1.0,0.3);
|
||||
glColor3f( col2[0], col2[1], col2[2]);
|
||||
ntlVec3Gfx s = org-(halfsize * 0.4);
|
||||
ntlVec3Gfx e = org+(halfsize * 0.4);
|
||||
drawCubeWire( s,e );
|
||||
cscale = 0.5;
|
||||
//col = ntlColor(0,0,1);
|
||||
showcell=false; // DEBUG
|
||||
}
|
||||
else if(flag& CFFluid) {
|
||||
cscale = 0.5;
|
||||
/*if(flag& CFCoarseInner) {
|
||||
col = ntlColor(0.3, 0.3, 1.0);
|
||||
} else */
|
||||
if(flag& CFGrToFine) {
|
||||
glLineWidth( linewidth );
|
||||
ntlColor col2(0.5,0.0,0.5);
|
||||
glColor3f( col2[0], col2[1], col2[2]);
|
||||
ntlVec3Gfx s = org-(halfsize * 0.31);
|
||||
ntlVec3Gfx e = org+(halfsize * 0.31);
|
||||
drawCubeWire( s,e );
|
||||
col = ntlColor(0,0,1);
|
||||
}
|
||||
if(flag& CFGrFromFine) {
|
||||
glLineWidth( linewidth );
|
||||
ntlColor col2(1.0,1.0,0.0);
|
||||
glColor3f( col2[0], col2[1], col2[2]);
|
||||
ntlVec3Gfx s = org-(halfsize * 0.56);
|
||||
ntlVec3Gfx e = org+(halfsize * 0.56);
|
||||
drawCubeWire( s,e );
|
||||
col = ntlColor(0,0,1);
|
||||
} else if(flag& CFGrFromCoarse) {
|
||||
// draw as fluid with marker
|
||||
ntlColor col2(0.0,1.0,0.3);
|
||||
glColor3f( col2[0], col2[1], col2[2]);
|
||||
ntlVec3Gfx s = org-(halfsize * 0.41);
|
||||
ntlVec3Gfx e = org+(halfsize * 0.41);
|
||||
drawCubeWire( s,e );
|
||||
col = ntlColor(0,0,1);
|
||||
} else {
|
||||
col = ntlColor(0,0,1);
|
||||
//showcell=false; // DEBUG
|
||||
}
|
||||
}
|
||||
else if(flag& CFEmpty) {
|
||||
showcell=false;
|
||||
}
|
||||
|
||||
// smaller for new lbmqt
|
||||
//cscale *= 0.5;
|
||||
|
||||
} break;
|
||||
case FLUIDDISPVelocities: {
|
||||
// dont use cube display
|
||||
LbmVec vel = lbm->getCellVelocity( cell, set );
|
||||
glBegin(GL_LINES);
|
||||
glColor3f( 0.0,0.0,0.0 );
|
||||
glVertex3f( org[0], org[1], org[2] );
|
||||
org += vec2G(vel * 10.0 * cscale);
|
||||
glColor3f( 1.0,1.0,1.0 );
|
||||
glVertex3f( org[0], org[1], org[2] );
|
||||
glEnd();
|
||||
showcell = false;
|
||||
} break;
|
||||
case FLUIDDISPCellfills: {
|
||||
CellFlagType flag = lbm->getCellFlag( cell,set );
|
||||
cscale = 0.5;
|
||||
|
||||
if(flag& CFFluid) {
|
||||
cscale = 0.75;
|
||||
col = ntlColor(0,0,0.5);
|
||||
}
|
||||
else if(flag& CFInter) {
|
||||
cscale = 0.75 * lbm->getCellMass(cell,set);
|
||||
col = ntlColor(0,1,1);
|
||||
}
|
||||
else {
|
||||
showcell=false;
|
||||
}
|
||||
|
||||
if( ABS(lbm->getCellMass(cell,set)) < 10.0 ) {
|
||||
cscale = 0.75 * lbm->getCellMass(cell,set);
|
||||
} else {
|
||||
showcell = false;
|
||||
}
|
||||
if(cscale>0.0) {
|
||||
col = ntlColor(0,1,1);
|
||||
} else {
|
||||
col = ntlColor(1,1,0);
|
||||
}
|
||||
// TODO
|
||||
} break;
|
||||
case FLUIDDISPDensity: {
|
||||
LbmFloat rho = lbm->getCellDensity(cell,set);
|
||||
cscale = rho*rho * 0.25;
|
||||
col = ntlColor( MIN(0.5+cscale,1.0) , MIN(0.0+cscale,1.0), MIN(0.0+cscale,1.0) );
|
||||
cscale *= 2.0;
|
||||
} break;
|
||||
case FLUIDDISPGrid: {
|
||||
cscale = 0.59;
|
||||
col = ntlColor(1.0);
|
||||
} break;
|
||||
default: {
|
||||
cscale = 0.5;
|
||||
col = ntlColor(1.0,0.0,0.0);
|
||||
} break;
|
||||
}
|
||||
|
||||
if(!showcell) return;
|
||||
glLineWidth( linewidth );
|
||||
glColor4f( col[0], col[1], col[2], 0.0);
|
||||
|
||||
ntlVec3Gfx s = org-(halfsize * cscale);
|
||||
ntlVec3Gfx e = org+(halfsize * cscale);
|
||||
//if(D::cDimension==2) {
|
||||
//s[2] = e[2] = (s[2]+e[2])*0.5;
|
||||
//}
|
||||
drawCubeWire( s,e );
|
||||
}
|
||||
|
||||
//! debug display function
|
||||
// D has to implement the CellIterator interface
|
||||
template<typename D>
|
||||
void
|
||||
lbmDebugDisplay(fluidDispSettings *dispset, D *lbm) {
|
||||
//je nach solver...?
|
||||
if(!dispset->on) return;
|
||||
glDisable( GL_LIGHTING ); // dont light lines
|
||||
|
||||
typename D::CellIdentifier cid = lbm->getFirstCell();
|
||||
for(; lbm->noEndCell( cid );
|
||||
lbm->advanceCell( cid ) ) {
|
||||
// display...
|
||||
#if (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
|
||||
::debugDisplayNode<>(dispset, lbm, cid );
|
||||
#else
|
||||
debugDisplayNode<D>(dispset, lbm, cid );
|
||||
#endif
|
||||
}
|
||||
delete cid;
|
||||
|
||||
glEnable( GL_LIGHTING ); // dont light lines
|
||||
}
|
||||
|
||||
//! debug display function
|
||||
// D has to implement the CellIterator interface
|
||||
template<typename D>
|
||||
void
|
||||
lbmMarkedCellDisplay(D *lbm) {
|
||||
fluidDispSettings dispset;
|
||||
// trick - display marked cells as grid displa -> white, big
|
||||
dispset.type = FLUIDDISPGrid;
|
||||
dispset.on = true;
|
||||
glDisable( GL_LIGHTING ); // dont light lines
|
||||
|
||||
typename D::CellIdentifier cid = lbm->markedGetFirstCell();
|
||||
for(; lbm->markedNoEndCell( cid );
|
||||
lbm->markedAdvanceCell( cid ) ) {
|
||||
// display... FIXME? this is a bit inconvenient...
|
||||
//MarkedCellIdentifier *mid = dynamic_cast<MarkedCellIdentifier *>( cid );
|
||||
#if (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
|
||||
//::debugDisplayNode<>(&dispset, lbm, mid->mpCell );
|
||||
::debugDisplayNode<>(&dispset, lbm, cid );
|
||||
#else
|
||||
//debugDisplayNode<D>(&dispset, lbm, mid->mpCell );
|
||||
debugDisplayNode<D>(&dispset, lbm, cid );
|
||||
#endif
|
||||
}
|
||||
delete cid;
|
||||
|
||||
glEnable( GL_LIGHTING ); // dont light lines
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//! display a single node
|
||||
template<typename D>
|
||||
void
|
||||
debugPrintNodeInfo(D *lbm, typename D::CellIdentifier cell, string printInfo,
|
||||
// force printing of one set? default = -1 = off
|
||||
int forceSet=-1) {
|
||||
bool printDF = false;
|
||||
bool printRho = false;
|
||||
bool printVel = false;
|
||||
bool printFlag = false;
|
||||
bool printGeom = false;
|
||||
bool printMass=false;
|
||||
bool printBothSets = false;
|
||||
|
||||
for(size_t i=0; i<printInfo.length()-0; i++) {
|
||||
char what = printInfo[i];
|
||||
switch(what) {
|
||||
case '+': // all on
|
||||
printDF = true; printRho = true; printVel = true; printFlag = true; printGeom = true; printMass = true;
|
||||
printBothSets = true; break;
|
||||
case '-': // all off
|
||||
printDF = false; printRho = false; printVel = false; printFlag = false; printGeom = false; printMass = false;
|
||||
printBothSets = false; break;
|
||||
case 'd': printDF = true; break;
|
||||
case 'r': printRho = true; break;
|
||||
case 'v': printVel = true; break;
|
||||
case 'f': printFlag = true; break;
|
||||
case 'g': printGeom = true; break;
|
||||
case 'm': printMass = true; break;
|
||||
case 's': printBothSets = true; break;
|
||||
default: errMsg("debugPrintNodeInfo","Invalid node info id "<<what); exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
ntlVec3Gfx org = lbm->getCellOrigin( cell );
|
||||
ntlVec3Gfx halfsize = lbm->getCellSize( cell );
|
||||
int set = lbm->getCellSet( cell );
|
||||
debMsgStd("debugPrintNodeInfo",DM_NOTIFY, "Printing cell info '"<<printInfo<<"' for node: "<<cell->getAsString()<<" from "<<lbm->getName()<<" currSet:"<<set , 1);
|
||||
if(printGeom) debMsgStd(" ",DM_MSG, "Org:"<<org<<" Halfsize:"<<halfsize<<" ", 1);
|
||||
|
||||
int setmax = 2;
|
||||
if(!printBothSets) setmax = 1;
|
||||
if(forceSet>=0) setmax = 1;
|
||||
|
||||
for(int s=0; s<setmax; s++) {
|
||||
int workset = set;
|
||||
if(s==1){ workset = (set^1); }
|
||||
if(forceSet>=0) workset = forceSet;
|
||||
debMsgStd(" ",DM_MSG, "Printing set:"<<workset<<" orgSet:"<<set, 1);
|
||||
|
||||
if(printDF) {
|
||||
for(int l=0; l<lbm->getDfNum(); l++) { // FIXME ??
|
||||
debMsgStd(" ",DM_MSG, " Df"<<l<<": "<<lbm->getCellDf(cell,workset,l), 1);
|
||||
}
|
||||
}
|
||||
if(printRho) {
|
||||
debMsgStd(" ",DM_MSG, " Rho: "<<lbm->getCellDensity(cell,workset), 1);
|
||||
}
|
||||
if(printVel) {
|
||||
debMsgStd(" ",DM_MSG, " Vel: "<<lbm->getCellVelocity(cell,workset), 1);
|
||||
}
|
||||
if(printFlag) {
|
||||
CellFlagType flag = lbm->getCellFlag(cell,workset);
|
||||
debMsgStd(" ",DM_MSG, " Flg: "<< flag<<" "<<convertFlags2String( flag ) <<" "<<convertCellFlagType2String( flag ), 1);
|
||||
}
|
||||
if(printMass) {
|
||||
debMsgStd(" ",DM_MSG, " Mss: "<<lbm->getCellMass(cell,workset), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define LBMFUNCTIONS_H
|
||||
#endif
|
||||
|
716
intern/elbeem/intern/lbminterface.cpp
Normal file
716
intern/elbeem/intern/lbminterface.cpp
Normal file
@ -0,0 +1,716 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* All code distributed as part of El'Beem is covered by the version 2 of the
|
||||
* GNU General Public License. See the file COPYING for details.
|
||||
* Copyright 2003-2005 Nils Thuerey
|
||||
*
|
||||
* Combined 2D/3D Lattice Boltzmann Interface Class
|
||||
* contains stuff to be statically compiled
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/* LBM Files */
|
||||
#include "lbmdimensions.h"
|
||||
#include "lbminterface.h"
|
||||
#include "lbmfunctions.h"
|
||||
#include "ntl_scene.h"
|
||||
#include "ntl_ray.h"
|
||||
#include "typeslbm.h"
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
//! common variables
|
||||
|
||||
/*****************************************************************************/
|
||||
/*! class for solver templating - 3D implementation D3Q19 */
|
||||
|
||||
//! how many dimensions?
|
||||
const int LbmD3Q19::cDimension = 3;
|
||||
|
||||
// Wi factors for collide step
|
||||
const LbmFloat LbmD3Q19::cCollenZero = (1.0/3.0);
|
||||
const LbmFloat LbmD3Q19::cCollenOne = (1.0/18.0);
|
||||
const LbmFloat LbmD3Q19::cCollenSqrtTwo = (1.0/36.0);
|
||||
|
||||
//! threshold value for filled/emptied cells
|
||||
const LbmFloat LbmD3Q19::cMagicNr2 = 1.0005;
|
||||
const LbmFloat LbmD3Q19::cMagicNr2Neg = -0.0005;
|
||||
const LbmFloat LbmD3Q19::cMagicNr = 1.010001;
|
||||
const LbmFloat LbmD3Q19::cMagicNrNeg = -0.010001;
|
||||
|
||||
//! size of a single set of distribution functions
|
||||
const int LbmD3Q19::cDfNum = 19;
|
||||
//! direction vector contain vecs for all spatial dirs, even if not used for LBM model
|
||||
const int LbmD3Q19::cDirNum = 27;
|
||||
|
||||
//const string LbmD3Q19::dfString[ cDfNum ] = {
|
||||
const char* LbmD3Q19::dfString[ cDfNum ] = {
|
||||
" C", " N"," S"," E"," W"," T"," B",
|
||||
"NE","NW","SE","SW",
|
||||
"NT","NB","ST","SB",
|
||||
"ET","EB","WT","WB"
|
||||
};
|
||||
|
||||
const LbmD3Q19::dfDir LbmD3Q19::dfNorm[ cDfNum ] = {
|
||||
cDirC, cDirN, cDirS, cDirE, cDirW, cDirT, cDirB,
|
||||
cDirNE, cDirNW, cDirSE, cDirSW,
|
||||
cDirNT, cDirNB, cDirST, cDirSB,
|
||||
cDirET, cDirEB, cDirWT, cDirWB
|
||||
};
|
||||
|
||||
const LbmD3Q19::dfDir LbmD3Q19::dfInv[ cDfNum ] = {
|
||||
cDirC, cDirS, cDirN, cDirW, cDirE, cDirB, cDirT,
|
||||
cDirSW, cDirSE, cDirNW, cDirNE,
|
||||
cDirSB, cDirST, cDirNB, cDirNT,
|
||||
cDirWB, cDirWT, cDirEB, cDirET
|
||||
};
|
||||
|
||||
const int LbmD3Q19::dfRefX[ cDfNum ] = {
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
cDirSE, cDirSW, cDirNE, cDirNW,
|
||||
0, 0, 0, 0,
|
||||
cDirEB, cDirET, cDirWB, cDirWT
|
||||
};
|
||||
|
||||
const int LbmD3Q19::dfRefY[ cDfNum ] = {
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
cDirNW, cDirNE, cDirSW, cDirSE,
|
||||
cDirNB, cDirNT, cDirSB, cDirST,
|
||||
0, 0, 0, 0
|
||||
};
|
||||
|
||||
const int LbmD3Q19::dfRefZ[ cDfNum ] = {
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
cDirST, cDirSB, cDirNT, cDirNB,
|
||||
cDirWT, cDirWB, cDirET, cDirEB
|
||||
};
|
||||
|
||||
// Vector Order 3D:
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
||||
// 0, 0, 0, 1,-1, 0, 0, 1,-1, 1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1,-1, 1,-1, 1,-1, 1,-1
|
||||
// 0, 1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1, 1,-1,-1, 0, 0, 0, 0, 1, 1,-1,-1, 1, 1,-1,-1
|
||||
// 0, 0, 0, 0, 0, 1,-1, 0, 0, 0, 0, 1,-1, 1,-1, 1,-1, 1,-1, 1, 1, 1, 1, -1,-1,-1,-1
|
||||
|
||||
const int LbmD3Q19::dfVecX[ cDirNum ] = {
|
||||
0, 0,0, 1,-1, 0,0,
|
||||
1,-1,1,-1,
|
||||
0,0,0,0,
|
||||
1,1,-1,-1,
|
||||
1,-1, 1,-1,
|
||||
1,-1, 1,-1,
|
||||
};
|
||||
const int LbmD3Q19::dfVecY[ cDirNum ] = {
|
||||
0, 1,-1, 0,0,0,0,
|
||||
1,1,-1,-1,
|
||||
1,1,-1,-1,
|
||||
0,0,0,0,
|
||||
1, 1,-1,-1,
|
||||
1, 1,-1,-1
|
||||
};
|
||||
const int LbmD3Q19::dfVecZ[ cDirNum ] = {
|
||||
0, 0,0,0,0,1,-1,
|
||||
0,0,0,0,
|
||||
1,-1,1,-1,
|
||||
1,-1,1,-1,
|
||||
1, 1, 1, 1,
|
||||
-1,-1,-1,-1
|
||||
};
|
||||
|
||||
const LbmFloat LbmD3Q19::dfDvecX[ cDirNum ] = {
|
||||
0, 0,0, 1,-1, 0,0,
|
||||
1,-1,1,-1,
|
||||
0,0,0,0,
|
||||
1,1,-1,-1,
|
||||
1,-1, 1,-1,
|
||||
1,-1, 1,-1
|
||||
};
|
||||
const LbmFloat LbmD3Q19::dfDvecY[ cDirNum ] = {
|
||||
0, 1,-1, 0,0,0,0,
|
||||
1,1,-1,-1,
|
||||
1,1,-1,-1,
|
||||
0,0,0,0,
|
||||
1, 1,-1,-1,
|
||||
1, 1,-1,-1
|
||||
};
|
||||
const LbmFloat LbmD3Q19::dfDvecZ[ cDirNum ] = {
|
||||
0, 0,0,0,0,1,-1,
|
||||
0,0,0,0,
|
||||
1,-1,1,-1,
|
||||
1,-1,1,-1,
|
||||
1, 1, 1, 1,
|
||||
-1,-1,-1,-1
|
||||
};
|
||||
|
||||
/* principal directions */
|
||||
const int LbmD3Q19::princDirX[ 2*LbmD3Q19::cDimension ] = {
|
||||
1,-1, 0,0, 0,0
|
||||
};
|
||||
const int LbmD3Q19::princDirY[ 2*LbmD3Q19::cDimension ] = {
|
||||
0,0, 1,-1, 0,0
|
||||
};
|
||||
const int LbmD3Q19::princDirZ[ 2*LbmD3Q19::cDimension ] = {
|
||||
0,0, 0,0, 1,-1
|
||||
};
|
||||
|
||||
/*! arrays for les model coefficients, inited in lbmsolver constructor */
|
||||
LbmFloat LbmD3Q19::lesCoeffDiag[ (cDimension-1)*(cDimension-1) ][ cDirNum ];
|
||||
LbmFloat LbmD3Q19::lesCoeffOffdiag[ cDimension ][ cDirNum ];
|
||||
|
||||
|
||||
const LbmFloat LbmD3Q19::dfLength[ cDfNum ]= {
|
||||
cCollenZero,
|
||||
cCollenOne, cCollenOne, cCollenOne,
|
||||
cCollenOne, cCollenOne, cCollenOne,
|
||||
cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo,
|
||||
cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo,
|
||||
cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo
|
||||
};
|
||||
|
||||
/* precalculated equilibrium dfs, inited in lbmsolver constructor */
|
||||
LbmFloat LbmD3Q19::dfEquil[ cDfNum ];
|
||||
|
||||
// D3Q19 end
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/*! class for solver templating - 2D implementation D2Q9 */
|
||||
|
||||
//! how many dimensions?
|
||||
const int LbmD2Q9::cDimension = 2;
|
||||
|
||||
//! Wi factors for collide step
|
||||
const LbmFloat LbmD2Q9::cCollenZero = (4.0/9.0);
|
||||
const LbmFloat LbmD2Q9::cCollenOne = (1.0/9.0);
|
||||
const LbmFloat LbmD2Q9::cCollenSqrtTwo = (1.0/36.0);
|
||||
|
||||
//! threshold value for filled/emptied cells
|
||||
const LbmFloat LbmD2Q9::cMagicNr2 = 1.0005;
|
||||
const LbmFloat LbmD2Q9::cMagicNr2Neg = -0.0005;
|
||||
const LbmFloat LbmD2Q9::cMagicNr = 1.010001;
|
||||
const LbmFloat LbmD2Q9::cMagicNrNeg = -0.010001;
|
||||
|
||||
//! size of a single set of distribution functions
|
||||
const int LbmD2Q9::cDfNum = 9;
|
||||
const int LbmD2Q9::cDirNum = 9;
|
||||
|
||||
//const string LbmD2Q9::dfString[ cDfNum ] = {
|
||||
const char* LbmD2Q9::dfString[ cDfNum ] = {
|
||||
" C",
|
||||
" N", " S", " E", " W",
|
||||
"NE", "NW", "SE","SW"
|
||||
};
|
||||
|
||||
const LbmD2Q9::dfDir LbmD2Q9::dfNorm[ cDfNum ] = {
|
||||
cDirC,
|
||||
cDirN, cDirS, cDirE, cDirW,
|
||||
cDirNE, cDirNW, cDirSE, cDirSW
|
||||
};
|
||||
|
||||
const LbmD2Q9::dfDir LbmD2Q9::dfInv[ cDfNum ] = {
|
||||
cDirC,
|
||||
cDirS, cDirN, cDirW, cDirE,
|
||||
cDirSW, cDirSE, cDirNW, cDirNE
|
||||
};
|
||||
|
||||
const int LbmD2Q9::dfRefX[ cDfNum ] = {
|
||||
0,
|
||||
0, 0, 0, 0,
|
||||
cDirSE, cDirSW, cDirNE, cDirNW
|
||||
};
|
||||
|
||||
const int LbmD2Q9::dfRefY[ cDfNum ] = {
|
||||
0,
|
||||
0, 0, 0, 0,
|
||||
cDirNW, cDirNE, cDirSW, cDirSE
|
||||
};
|
||||
|
||||
const int LbmD2Q9::dfRefZ[ cDfNum ] = {
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0
|
||||
};
|
||||
|
||||
// Vector Order 2D:
|
||||
// 0 1 2 3 4 5 6 7 8
|
||||
// 0, 0,0, 1,-1, 1,-1,1,-1
|
||||
// 0, 1,-1, 0,0, 1,1,-1,-1
|
||||
|
||||
const int LbmD2Q9::dfVecX[ cDirNum ] = {
|
||||
0,
|
||||
0,0, 1,-1,
|
||||
1,-1,1,-1
|
||||
};
|
||||
const int LbmD2Q9::dfVecY[ cDirNum ] = {
|
||||
0,
|
||||
1,-1, 0,0,
|
||||
1,1,-1,-1
|
||||
};
|
||||
const int LbmD2Q9::dfVecZ[ cDirNum ] = {
|
||||
0, 0,0,0,0, 0,0,0,0
|
||||
};
|
||||
|
||||
const LbmFloat LbmD2Q9::dfDvecX[ cDirNum ] = {
|
||||
0,
|
||||
0,0, 1,-1,
|
||||
1,-1,1,-1
|
||||
};
|
||||
const LbmFloat LbmD2Q9::dfDvecY[ cDirNum ] = {
|
||||
0,
|
||||
1,-1, 0,0,
|
||||
1,1,-1,-1
|
||||
};
|
||||
const LbmFloat LbmD2Q9::dfDvecZ[ cDirNum ] = {
|
||||
0, 0,0,0,0, 0,0,0,0
|
||||
};
|
||||
|
||||
const int LbmD2Q9::princDirX[ 2*LbmD2Q9::cDimension ] = {
|
||||
1,-1, 0,0
|
||||
};
|
||||
const int LbmD2Q9::princDirY[ 2*LbmD2Q9::cDimension ] = {
|
||||
0,0, 1,-1
|
||||
};
|
||||
const int LbmD2Q9::princDirZ[ 2*LbmD2Q9::cDimension ] = {
|
||||
0,0, 0,0
|
||||
};
|
||||
|
||||
|
||||
/*! arrays for les model coefficients, inited in lbmsolver constructor */
|
||||
LbmFloat LbmD2Q9::lesCoeffDiag[ (cDimension-1)*(cDimension-1) ][ cDirNum ];
|
||||
LbmFloat LbmD2Q9::lesCoeffOffdiag[ cDimension ][ cDirNum ];
|
||||
|
||||
|
||||
const LbmFloat LbmD2Q9::dfLength[ cDfNum ]= {
|
||||
cCollenZero,
|
||||
cCollenOne, cCollenOne, cCollenOne, cCollenOne,
|
||||
cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo, cCollenSqrtTwo
|
||||
};
|
||||
|
||||
/* precalculated equilibrium dfs, inited in lbmsolver constructor */
|
||||
LbmFloat LbmD2Q9::dfEquil[ cDfNum ];
|
||||
|
||||
// D2Q9 end
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Interface Constructor
|
||||
*****************************************************************************/
|
||||
LbmSolverInterface::LbmSolverInterface() :
|
||||
mPanic( false ),
|
||||
mSizex(10), mSizey(10), mSizez(10),
|
||||
mStepCnt( 0 ),
|
||||
mFixMass( 0.0 ),
|
||||
mOmega( 1.0 ),
|
||||
mGravity(0.0),
|
||||
mSurfaceTension( 0.0 ),
|
||||
mInitialMass (0.0),
|
||||
mBoundaryEast( (CellFlagType)(CFBnd) ),mBoundaryWest( (CellFlagType)(CFBnd) ),mBoundaryNorth( (CellFlagType)(CFBnd) ),
|
||||
mBoundarySouth( (CellFlagType)(CFBnd) ),mBoundaryTop( (CellFlagType)(CFBnd) ),mBoundaryBottom( (CellFlagType)(CFBnd) ),
|
||||
mInitDone( false ),
|
||||
mInitDensityGradient( false ),
|
||||
mpAttrs( NULL ), mpParam( NULL ),
|
||||
mNumParticlesLost(0), mNumInvalidDfs(0), mNumFilledCells(0), mNumEmptiedCells(0), mNumUsedCells(0), mMLSUPS(0),
|
||||
mDebugVelScale( 1.0 ), mNodeInfoString("+"),
|
||||
mRandom( 5123 ),
|
||||
mvGeoStart(-1.0), mvGeoEnd(1.0),
|
||||
mPerformGeoInit( false ),
|
||||
mName("lbm_default") ,
|
||||
mpIso( NULL ), mIsoValue(0.49999),
|
||||
mSilent(false) ,
|
||||
mGeoInitId( 0 ),
|
||||
mpGiTree( NULL ),
|
||||
mAccurateGeoinit(0),
|
||||
mpGiObjects( NULL ), mGiObjInside(), mpGlob( NULL )
|
||||
{
|
||||
#if ELBEEM_BLENDER==1
|
||||
mSilent = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************/
|
||||
/*! parse a boundary flag string */
|
||||
CellFlagType LbmSolverInterface::readBoundaryFlagInt(string name, int defaultValue, string source,string target, bool needed) {
|
||||
string val = mpAttrs->readString(name, "", source, target, needed);
|
||||
if(!strcmp(val.c_str(),"")) {
|
||||
// no value given...
|
||||
return CFEmpty;
|
||||
}
|
||||
if(!strcmp(val.c_str(),"bnd_no")) {
|
||||
return (CellFlagType)( CFBnd );
|
||||
}
|
||||
if(!strcmp(val.c_str(),"bnd_free")) {
|
||||
return (CellFlagType)( CFBnd );
|
||||
}
|
||||
if(!strcmp(val.c_str(),"fluid")) {
|
||||
/* might be used for some in/out flow cases */
|
||||
return (CellFlagType)( CFFluid );
|
||||
}
|
||||
errorOut("LbmStdSolver::readBoundaryFlagInt error: Invalid value '"<<val<<"' " );
|
||||
# if LBM_STRICT_DEBUG==1
|
||||
exit(1);
|
||||
# endif
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
/*! parse standard attributes */
|
||||
void LbmSolverInterface::parseStdAttrList() {
|
||||
if(!mpAttrs) {
|
||||
errorOut("LbmStdSolver::parseAttrList error: mpAttrs pointer not initialized!");
|
||||
exit(1); }
|
||||
|
||||
// st currently unused
|
||||
//mSurfaceTension = mpAttrs->readFloat("d_surfacetension", mSurfaceTension, "LbmStdSolver", "mSurfaceTension", false);
|
||||
mBoundaryEast = readBoundaryFlagInt("boundary_east", mBoundaryEast, "LbmStdSolver", "mBoundaryEast", false);
|
||||
mBoundaryWest = readBoundaryFlagInt("boundary_west", mBoundaryWest, "LbmStdSolver", "mBoundaryWest", false);
|
||||
mBoundaryNorth = readBoundaryFlagInt("boundary_north", mBoundaryNorth,"LbmStdSolver", "mBoundaryNorth", false);
|
||||
mBoundarySouth = readBoundaryFlagInt("boundary_south", mBoundarySouth,"LbmStdSolver", "mBoundarySouth", false);
|
||||
mBoundaryTop = readBoundaryFlagInt("boundary_top", mBoundaryTop,"LbmStdSolver", "mBoundaryTop", false);
|
||||
mBoundaryBottom= readBoundaryFlagInt("boundary_bottom", mBoundaryBottom,"LbmStdSolver", "mBoundaryBottom", false);
|
||||
|
||||
LbmVec sizeVec(mSizex,mSizey,mSizez);
|
||||
sizeVec = vec2L( mpAttrs->readVec3d("size", vec2P(sizeVec), "LbmStdSolver", "sizeVec", false) );
|
||||
mSizex = (int)sizeVec[0];
|
||||
mSizey = (int)sizeVec[1];
|
||||
mSizez = (int)sizeVec[2];
|
||||
mpParam->setSize(mSizex, mSizey, mSizez ); // param needs size in any case
|
||||
|
||||
mInitDensityGradient = mpAttrs->readBool("initdensitygradient", mInitDensityGradient,"LbmStdSolver", "mInitDensityGradient", false);
|
||||
mPerformGeoInit = mpAttrs->readBool("geoinit", mPerformGeoInit,"LbmStdSolver", "mPerformGeoInit", false);
|
||||
mGeoInitId = mpAttrs->readInt("geoinitid", mGeoInitId,"LbmStdSolver", "mGeoInitId", false);
|
||||
mIsoValue = mpAttrs->readFloat("isovalue", mIsoValue, "LbmOptSolver","mIsoValue", false );
|
||||
|
||||
mDebugVelScale = mpAttrs->readFloat("debugvelscale", mDebugVelScale,"LbmStdSolver", "mDebugVelScale", false);
|
||||
mNodeInfoString = mpAttrs->readString("nodeinfo", mNodeInfoString, "SimulationLbm","mNodeInfoString", false );
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************/
|
||||
/*! geometry initialization */
|
||||
/*******************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/*! init tree for certain geometry init */
|
||||
void LbmSolverInterface::initGeoTree(int id) {
|
||||
if(mpGlob == NULL) { errorOut("LbmSolverInterface::initGeoTree error: Requires globals!"); exit(1); }
|
||||
mGeoInitId = id;
|
||||
ntlScene *scene = mpGlob->getScene();
|
||||
mpGiObjects = scene->getObjects();
|
||||
mGiObjInside.resize( mpGiObjects->size() );
|
||||
mGiObjDistance.resize( mpGiObjects->size() );
|
||||
for(size_t i=0; i<mpGiObjects->size(); i++) {
|
||||
if((*mpGiObjects)[i]->getGeoInitIntersect()) mAccurateGeoinit=true;
|
||||
}
|
||||
debMsgStd("LbmSolverInterface::initGeoTree",DM_MSG,"Accurate geo init: "<<mAccurateGeoinit, 9)
|
||||
|
||||
if(mpGiTree != NULL) delete mpGiTree;
|
||||
char treeFlag = (1<<(mGeoInitId+4));
|
||||
mpGiTree = new ntlTree( 20, 4, // warning - fixed values for depth & maxtriangles here...
|
||||
scene, treeFlag );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*! destroy tree etc. when geometry init done */
|
||||
void LbmSolverInterface::freeGeoTree() {
|
||||
if(mpGiTree != NULL) {
|
||||
delete mpGiTree;
|
||||
mpGiTree = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/*! check for a certain flag type at position org */
|
||||
bool LbmSolverInterface::geoInitCheckPointInside(ntlVec3Gfx org, int flags, int &OId, gfxReal &distance) {
|
||||
// shift ve ctors to avoid rounding errors
|
||||
org += ntlVec3Gfx(0.0001);
|
||||
ntlVec3Gfx dir = ntlVec3Gfx(0.999999,0.0,0.0);
|
||||
OId = -1;
|
||||
ntlRay ray(org, dir, 0, 1.0, mpGlob);
|
||||
//int insCnt = 0;
|
||||
bool done = false;
|
||||
bool inside = false;
|
||||
//errMsg("III"," start org"<<org<<" dir"<<dir);
|
||||
//int insID = ray.getID();
|
||||
for(size_t i=0; i<mGiObjInside.size(); i++) { mGiObjInside[i] = 0; }
|
||||
// if not inside, return distance to first hit
|
||||
gfxReal firstHit=-1.0;
|
||||
|
||||
if(mAccurateGeoinit) {
|
||||
while(!done) {
|
||||
// find first inside intersection
|
||||
ntlTriangle *triIns = NULL;
|
||||
distance = -1.0;
|
||||
ntlVec3Gfx normal(0.0);
|
||||
mpGiTree->intersect(ray,distance,normal, triIns, flags, true);
|
||||
if(triIns) {
|
||||
ntlVec3Gfx norg = ray.getOrigin() + ray.getDirection()*distance;
|
||||
LbmFloat orientation = dot(normal, dir);
|
||||
OId = triIns->getObjectId();
|
||||
if(orientation<=0.0) {
|
||||
// outside hit
|
||||
normal *= -1.0;
|
||||
mGiObjInside[OId]++;
|
||||
mGiObjDistance[OId] = -1.0;
|
||||
//errMsg("IIO"," oid:"<<OId<<" org"<<org<<" norg"<<norg);
|
||||
} else {
|
||||
// inside hit
|
||||
mGiObjInside[OId]++;
|
||||
mGiObjDistance[OId] = distance;
|
||||
//errMsg("III"," oid:"<<OId<<" org"<<org<<" norg"<<norg);
|
||||
}
|
||||
norg += normal * getVecEpsilon();
|
||||
ray = ntlRay(norg, dir, 0, 1.0, mpGlob);
|
||||
if(firstHit<0.0) firstHit = distance;
|
||||
//if((OId<0) && ())
|
||||
//insCnt++;
|
||||
/*
|
||||
// check outside intersect
|
||||
LbmFloat orientation = dot(normal, dir);
|
||||
if(orientation<=0.0) {
|
||||
// do more thorough checks... advance ray
|
||||
ntlVec3Gfx norg = ray.getOrigin() + ray.getDirection()*distance;
|
||||
norg += normal * (-1.0 * getVecEpsilon());
|
||||
ray = ntlRay(norg, dir, 0, 1.0, mpGlob);
|
||||
insCnt++;
|
||||
errMsg("III"," oid:"<<OId<<" org"<<org<<" norg"<<norg<<" insCnt"<<insCnt);
|
||||
} else {
|
||||
if(insCnt>0) {
|
||||
// we have entered this obj before?
|
||||
ntlVec3Gfx norg = ray.getOrigin() + ray.getDirection()*distance;
|
||||
norg += normal * (-1.0 * getVecEpsilon());
|
||||
ray = ntlRay(norg, dir, 0, 1.0, mpGlob);
|
||||
insCnt--;
|
||||
errMsg("IIIS"," oid:"<<OId<<" org"<<org<<" norg"<<norg<<" insCnt"<<insCnt);
|
||||
} else {
|
||||
// first inside intersection -> ok
|
||||
OId = triIns->getObjectId();
|
||||
done = inside = true;
|
||||
}
|
||||
}
|
||||
*/
|
||||
} else {
|
||||
// no more intersections... return false
|
||||
done = true;
|
||||
//if(insCnt%2) inside=true;
|
||||
}
|
||||
}
|
||||
|
||||
distance = -1.0;
|
||||
for(size_t i=0; i<mGiObjInside.size(); i++) {
|
||||
//errMsg("CHIII","i"<<i<<" ins="<<mGiObjInside[i]<<" t"<<mGiObjDistance[i]<<" d"<<distance);
|
||||
if(((mGiObjInside[i]%2)==1)&&(mGiObjDistance[i]>0.0)) {
|
||||
if(distance<0.0) {
|
||||
// first intersection -> good
|
||||
distance = mGiObjDistance[i];
|
||||
OId = i;
|
||||
inside = true;
|
||||
} else {
|
||||
if(distance>mGiObjDistance[i]) {
|
||||
// more than one intersection -> use closest one
|
||||
distance = mGiObjDistance[i];
|
||||
OId = i;
|
||||
inside = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!inside) {
|
||||
distance = firstHit;
|
||||
}
|
||||
|
||||
return inside;
|
||||
} else {
|
||||
|
||||
// find first inside intersection
|
||||
ntlTriangle *triIns = NULL;
|
||||
distance = -1.0;
|
||||
ntlVec3Gfx normal(0.0);
|
||||
mpGiTree->intersect(ray,distance,normal, triIns, flags, true);
|
||||
if(triIns) {
|
||||
// check outside intersect
|
||||
LbmFloat orientation = dot(normal, dir);
|
||||
if(orientation<=0.0) return false;
|
||||
|
||||
OId = triIns->getObjectId();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*! get max. velocity of all objects to initialize as fluid regions */
|
||||
ntlVec3Gfx LbmSolverInterface::getGeoMaxInitialVelocity() {
|
||||
ntlScene *scene = mpGlob->getScene();
|
||||
mpGiObjects = scene->getObjects();
|
||||
ntlVec3Gfx max(0.0);
|
||||
|
||||
for(int i=0; i< (int)mpGiObjects->size(); i++) {
|
||||
if( (*mpGiObjects)[i]->getGeoInitType() & FGI_FLUID ){
|
||||
ntlVec3Gfx ovel = (*mpGiObjects)[i]->getInitialVelocity();
|
||||
if( normNoSqrt(ovel) > normNoSqrt(max) ) { max = ovel; }
|
||||
//errMsg("IVT","i"<<i<<" "<< (*mpGiObjects)[i]->getInitialVelocity() ); // DEBUG
|
||||
}
|
||||
}
|
||||
//errMsg("IVT","max "<<" "<< max ); // DEBUG
|
||||
// unused !? mGiInsideCnt.resize( mpGiObjects->size() );
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************/
|
||||
/*! "traditional" initialization */
|
||||
/*******************************************************************************/
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
// handle generic test cases (currently only reset geo init)
|
||||
bool LbmSolverInterface::initGenericTestCases() {
|
||||
bool initTypeFound = false;
|
||||
LbmSolverInterface::CellIdentifier cid = getFirstCell();
|
||||
// deprecated! - only check for invalid cells...
|
||||
|
||||
// this is the default init - check if the geometry flag init didnt
|
||||
initTypeFound = true;
|
||||
|
||||
while(noEndCell(cid)) {
|
||||
// check node
|
||||
if( (getCellFlag(cid,0)==CFInvalid) || (getCellFlag(cid,1)==CFInvalid) ) {
|
||||
warnMsg("LbmSolverInterface::initGenericTestCases","GeoInit produced invalid Flag at "<<cid->getAsString()<<"!" );
|
||||
}
|
||||
advanceCell( cid );
|
||||
}
|
||||
|
||||
deleteCellIterator( &cid );
|
||||
return initTypeFound;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************/
|
||||
/*! cell iteration functions */
|
||||
/*******************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
//! add cell to mMarkedCells list
|
||||
void
|
||||
LbmSolverInterface::addCellToMarkedList( CellIdentifierInterface *cid ) {
|
||||
for(size_t i=0; i<mMarkedCells.size(); i++) {
|
||||
// check if cids alreay in
|
||||
if( mMarkedCells[i]->equal(cid) ) return;
|
||||
mMarkedCells[i]->setEnd(false);
|
||||
}
|
||||
mMarkedCells.push_back( cid );
|
||||
cid->setEnd(true);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
//! marked cell iteration methods
|
||||
CellIdentifierInterface*
|
||||
LbmSolverInterface::markedGetFirstCell( ) {
|
||||
/*MarkedCellIdentifier *newcid = new MarkedCellIdentifier();
|
||||
if(mMarkedCells.size() < 1){
|
||||
newcid->setEnd( true );
|
||||
} else {
|
||||
newcid->mpCell = mMarkedCells[0];
|
||||
}
|
||||
return newcid;*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
LbmSolverInterface::markedAdvanceCell( CellIdentifierInterface* basecid ) {
|
||||
if(!basecid) return;
|
||||
basecid->setEnd( true );
|
||||
/*MarkedCellIdentifier *cid = dynamic_cast<MarkedCellIdentifier*>( basecid );
|
||||
CellIdentifierInterface *cid = basecid;
|
||||
cid->mIndex++;
|
||||
if(cid->mIndex >= (int)mMarkedCells.size()) {
|
||||
cid->setEnd( true );
|
||||
}
|
||||
cid->mpCell = mMarkedCells[ cid->mIndex ];
|
||||
*/
|
||||
}
|
||||
|
||||
bool
|
||||
LbmSolverInterface::markedNoEndCell( CellIdentifierInterface* cid ) {
|
||||
if(!cid) return false;
|
||||
return(! cid->getEnd() );
|
||||
}
|
||||
|
||||
void LbmSolverInterface::markedClearList() {
|
||||
// FIXME free cids?
|
||||
mMarkedCells.clear();
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
/*! string helper functions */
|
||||
/*******************************************************************************/
|
||||
|
||||
|
||||
|
||||
// 32k
|
||||
std::string convertSingleFlag2String(CellFlagType cflag) {
|
||||
CellFlagType flag = cflag;
|
||||
if(flag == CFUnused ) return string("cCFUnused");
|
||||
if(flag == CFEmpty ) return string("cCFEmpty");
|
||||
if(flag == CFBnd ) return string("cCFBnd");
|
||||
if(flag == CFNoInterpolSrc ) return string("cCFNoInterpolSrc");
|
||||
if(flag == CFFluid ) return string("cCFFluid");
|
||||
if(flag == CFInter ) return string("cCFInter");
|
||||
if(flag == CFNoNbFluid ) return string("cCFNoNbFluid");
|
||||
if(flag == CFNoNbEmpty ) return string("cCFNoNbEmpty");
|
||||
if(flag == CFNoDelete ) return string("cCFNoDelete");
|
||||
if(flag == CFNoBndFluid ) return string("cCFNoBndFluid");
|
||||
if(flag == CFBndMARK ) return string("cCFBndMARK");
|
||||
if(flag == CFGrNorm ) return string("cCFGrNorm");
|
||||
if(flag == CFGrFromFine ) return string("cCFGrFromFine");
|
||||
if(flag == CFGrFromCoarse ) return string("cCFGrFromCoarse");
|
||||
if(flag == CFGrCoarseInited ) return string("cCFGrCoarseInited");
|
||||
if(flag == CFInvalid ) return string("cfINVALID");
|
||||
|
||||
std::ostringstream mult;
|
||||
int val = 0;
|
||||
if(flag != 0) {
|
||||
while(! (flag&1) ) {
|
||||
flag = flag>>1;
|
||||
val++;
|
||||
}
|
||||
} else {
|
||||
val = -1;
|
||||
}
|
||||
mult << "cfUNKNOWN_" << val <<"_TYPE";
|
||||
return mult.str();
|
||||
}
|
||||
|
||||
//! helper function to convert flag to string (for debuggin)
|
||||
std::string convertCellFlagType2String( CellFlagType cflag ) {
|
||||
int flag = cflag;
|
||||
|
||||
const int jmax = sizeof(CellFlagType)*8;
|
||||
bool somefound = false;
|
||||
std::ostringstream mult;
|
||||
mult << "[";
|
||||
for(int j=0; j<jmax ; j++) {
|
||||
if(flag& (1<<j)) {
|
||||
if(somefound) mult << "|";
|
||||
mult << convertSingleFlag2String( (CellFlagType)(1<<j) ); // this call should always be _non_-recursive
|
||||
somefound = true;
|
||||
}
|
||||
};
|
||||
mult << "]";
|
||||
|
||||
// return concatenated string
|
||||
if(somefound) return mult.str();
|
||||
|
||||
// empty?
|
||||
return string("[emptyCFT]");
|
||||
}
|
||||
|
564
intern/elbeem/intern/lbminterface.h
Normal file
564
intern/elbeem/intern/lbminterface.h
Normal file
@ -0,0 +1,564 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* All code distributed as part of El'Beem is covered by the version 2 of the
|
||||
* GNU General Public License. See the file COPYING for details.
|
||||
* Copyright 2003-2005 Nils Thuerey
|
||||
*
|
||||
* Header for Combined 2D/3D Lattice Boltzmann Interface Class
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef LBMINTERFACE_H
|
||||
#define LBMINTERFACE_H
|
||||
|
||||
//! include gui support?
|
||||
#ifndef NOGUI
|
||||
#define LBM_USE_GUI 1
|
||||
#else
|
||||
#define LBM_USE_GUI 0
|
||||
#endif
|
||||
|
||||
#if LBM_USE_GUI==1
|
||||
#define USE_GLUTILITIES
|
||||
// for debug display
|
||||
#include <GL/gl.h>
|
||||
#include "../gui/guifuncs.h"
|
||||
#endif
|
||||
|
||||
#include <sstream>
|
||||
#include "utilities.h"
|
||||
#include "ntl_bsptree.h"
|
||||
#include "ntl_geometryobject.h"
|
||||
#include "ntl_rndstream.h"
|
||||
#include "parametrizer.h"
|
||||
#include "attributes.h"
|
||||
#include "particletracer.h"
|
||||
#include "isosurface.h"
|
||||
|
||||
// use which fp-precision for LBM? 1=float, 2=double
|
||||
#ifdef PRECISION_LBM_SINGLE
|
||||
#define LBM_PRECISION 1
|
||||
#else
|
||||
#ifdef PRECISION_LBM_DOUBLE
|
||||
#define LBM_PRECISION 2
|
||||
#else
|
||||
// default to floats
|
||||
#define LBM_PRECISION 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// default to 3dim
|
||||
#ifndef LBMDIM
|
||||
#define LBMDIM 3
|
||||
#endif // LBMDIM
|
||||
|
||||
#if LBM_PRECISION==1
|
||||
/* low precision for LBM solver */
|
||||
typedef float LbmFloat;
|
||||
typedef ntlVec3f LbmVec;
|
||||
#define LBM_EPSILON (1e-5)
|
||||
#else
|
||||
/* standard precision for LBM solver */
|
||||
typedef double LbmFloat;
|
||||
typedef ntlVec3d LbmVec;
|
||||
#define LBM_EPSILON (1e-10)
|
||||
#endif
|
||||
|
||||
// conversions (lbm and parametrizer)
|
||||
template<class T> inline LbmVec vec2L(T v) { return LbmVec(v[0],v[1],v[2]); }
|
||||
template<class T> inline ParamVec vec2P(T v) { return ParamVec(v[0],v[1],v[2]); }
|
||||
|
||||
|
||||
// bubble id type
|
||||
typedef int BubbleId;
|
||||
|
||||
// for both short int/char
|
||||
// 1
|
||||
#define CFUnused (1<< 0)
|
||||
// 2
|
||||
#define CFEmpty (1<< 1)
|
||||
// 4
|
||||
#define CFBnd (1<< 2)
|
||||
// 8, force symmetry for flag reinit
|
||||
#define CFNoInterpolSrc (1<< 3)
|
||||
// 16
|
||||
#define CFFluid (1<< 4)
|
||||
// 32
|
||||
#define CFInter (1<< 5)
|
||||
// 64
|
||||
#define CFNoNbFluid (1<< 6)
|
||||
// 128
|
||||
#define CFNoNbEmpty (1<< 7)
|
||||
// 256
|
||||
#define CFNoDelete (1<< 8)
|
||||
|
||||
// 512
|
||||
#define CFNoBndFluid (1<< 9)
|
||||
// 1024
|
||||
#define CFBndMARK (1<<10)
|
||||
|
||||
//! refinement tags
|
||||
// cell treated normally on coarser grids
|
||||
// 2048
|
||||
#define CFGrNorm (1<<11)
|
||||
// border cells to be interpolated from finer grid
|
||||
// 4096
|
||||
#define CFGrFromFine (1<<12)
|
||||
// 8192
|
||||
#define CFGrFromCoarse (1<<13)
|
||||
// 16384
|
||||
#define CFGrCoarseInited (1<<14)
|
||||
// 32k (aux marker, no real action)
|
||||
#define CFGrToFine (1<<15)
|
||||
|
||||
// nk
|
||||
#define CFInvalid (CellFlagType)(1<<31)
|
||||
|
||||
// use 16bit flag types
|
||||
//#define CellFlagType unsigned short int
|
||||
// use 32bit flag types
|
||||
#define CellFlagType unsigned long int
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/*! a single lbm cell */
|
||||
/* the template is only needed for
|
||||
* dimension dependend constants e.g.
|
||||
* number of df's in model */
|
||||
template<typename D>
|
||||
class LbmCellTemplate {
|
||||
public:
|
||||
LbmFloat df[ 27 ]; // be on the safe side here...
|
||||
LbmFloat rho;
|
||||
LbmVec vel;
|
||||
LbmFloat mass;
|
||||
CellFlagType flag;
|
||||
BubbleId bubble;
|
||||
LbmFloat ffrac;
|
||||
|
||||
//! test if a flag is set
|
||||
inline bool test(CellFlagType t) {
|
||||
return ((flag & t)==t);
|
||||
}
|
||||
//! test if any of the given flags is set
|
||||
inline bool testAny(CellFlagType t) {
|
||||
return ((flag & t)!=0);
|
||||
}
|
||||
//! test if the cell is empty
|
||||
inline bool isEmpty() {
|
||||
return (flag == CFEmpty);
|
||||
}
|
||||
|
||||
//! init default values for a certain flag type
|
||||
inline void initDefaults(CellFlagType type) {
|
||||
flag = type;
|
||||
vel = LbmVec(0.0);
|
||||
for(int l=0; l<D::cDfNum;l++) df[l] = D::dfEquil[l];
|
||||
|
||||
if(type & CFFluid) {
|
||||
rho = mass = ffrac = 1.0;
|
||||
bubble = -1;
|
||||
}
|
||||
else if(type & CFInter) {
|
||||
rho = mass = ffrac = 0.0;
|
||||
bubble = 0;
|
||||
}
|
||||
else if(type & CFBnd) {
|
||||
rho = mass = ffrac = 0.0;
|
||||
bubble = -1;
|
||||
}
|
||||
else if(type & CFEmpty) {
|
||||
rho = mass = ffrac = 0.0;
|
||||
bubble = 0;
|
||||
} else {
|
||||
// ?
|
||||
rho = mass = ffrac = 0.0;
|
||||
bubble = -1;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO add init method?
|
||||
};
|
||||
|
||||
|
||||
/* struct for the coordinates of a cell in the grid */
|
||||
typedef struct {
|
||||
int x,y,z;
|
||||
} LbmPoint;
|
||||
|
||||
|
||||
/* struct for the coordinates of a cell in the grid */
|
||||
typedef struct {
|
||||
char active; // bubble in use, oder may be overwritten?
|
||||
LbmFloat volume; // volume of this bubble (0 vor atmosphere)
|
||||
LbmFloat mass; // "mass" of bubble
|
||||
int i,j,k; // index of a cell in the bubble
|
||||
} LbmBubble;
|
||||
|
||||
|
||||
|
||||
|
||||
//! choose which data to display
|
||||
#define FLUIDDISPINVALID 0
|
||||
#define FLUIDDISPNothing 1
|
||||
#define FLUIDDISPCelltypes 2
|
||||
#define FLUIDDISPVelocities 3
|
||||
#define FLUIDDISPCellfills 4
|
||||
#define FLUIDDISPDensity 5
|
||||
#define FLUIDDISPGrid 6
|
||||
#define FLUIDDISPSurface 7
|
||||
|
||||
//! settings for a debug display
|
||||
typedef struct fluidDispSettings_T {
|
||||
int type; // what to display
|
||||
bool on; // display enabled?
|
||||
float scale; // additional scale param
|
||||
} fluidDispSettings;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
//! cell identifier interface
|
||||
class CellIdentifierInterface {
|
||||
public:
|
||||
//! reset constructor
|
||||
CellIdentifierInterface() : mEnd (false) { };
|
||||
//! virtual destructor
|
||||
virtual ~CellIdentifierInterface() {};
|
||||
|
||||
//! return node as string (with some basic info)
|
||||
virtual std::string getAsString() = 0;
|
||||
|
||||
//! compare cids
|
||||
virtual bool equal(CellIdentifierInterface* other) = 0;
|
||||
|
||||
//! set/get end flag
|
||||
inline void setEnd(bool set){ mEnd = set; }
|
||||
inline bool getEnd( ) { return mEnd; }
|
||||
|
||||
protected:
|
||||
|
||||
//! has the grid been traversed?
|
||||
bool mEnd;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/*! marked cell access class *
|
||||
class MarkedCellIdentifier :
|
||||
public CellIdentifierInterface
|
||||
{
|
||||
public:
|
||||
//! cell pointer
|
||||
CellIdentifierInterface *mpCell;
|
||||
//! location in mMarkedCells vector
|
||||
int mIndex;
|
||||
|
||||
//! reset constructor
|
||||
MarkedCellIdentifier() :
|
||||
mpCell( NULL ), mIndex(0)
|
||||
{ };
|
||||
|
||||
// implement CellIdentifierInterface
|
||||
virtual std::string getAsString() {
|
||||
std::ostringstream ret;
|
||||
ret <<"{MC i"<<mIndex<<" }";
|
||||
return ret.str();
|
||||
}
|
||||
|
||||
virtual bool equal(CellIdentifierInterface* other) {
|
||||
MarkedCellIdentifier *cid = dynamic_cast<MarkedCellIdentifier *>( other );
|
||||
if(!cid) return false;
|
||||
if( mpCell==cid->mpCell ) return true;
|
||||
return false;
|
||||
}
|
||||
}; */
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/*! class defining abstract function interface */
|
||||
/* has to provide iterating functionality */
|
||||
class LbmSolverInterface
|
||||
{
|
||||
public:
|
||||
//! Constructor
|
||||
LbmSolverInterface();
|
||||
//! Destructor
|
||||
virtual ~LbmSolverInterface() { };
|
||||
//! id string of solver
|
||||
virtual string getIdString() = 0;
|
||||
|
||||
/*! finish the init with config file values (allocate arrays...) */
|
||||
virtual bool initialize( ntlTree *tree, vector<ntlGeometryObject*> *objects ) = 0;
|
||||
/*! generic test case setup using iterator interface */
|
||||
bool initGenericTestCases();
|
||||
|
||||
/*! parse a boundary flag string */
|
||||
CellFlagType readBoundaryFlagInt(string name, int defaultValue, string source,string target, bool needed);
|
||||
/*! parse standard attributes */
|
||||
void parseStdAttrList();
|
||||
/*! initilize variables fom attribute list (should at least call std parse) */
|
||||
virtual void parseAttrList() = 0;
|
||||
|
||||
virtual void step() = 0;
|
||||
virtual void prepareVisualization() { /* by default off */ };
|
||||
|
||||
/*! particle handling */
|
||||
virtual int initParticles(ParticleTracer *partt) = 0;
|
||||
virtual void advanceParticles(ParticleTracer *partt ) = 0;
|
||||
/*! get surface object (NULL if no surface) */
|
||||
ntlGeometryObject* getSurfaceGeoObj() { return mpIso; }
|
||||
|
||||
/*! debug object display */
|
||||
virtual vector<ntlGeometryObject*> getDebugObjects() { vector<ntlGeometryObject*> empty(0); return empty; }
|
||||
|
||||
#if LBM_USE_GUI==1
|
||||
/*! show simulation info */
|
||||
virtual void debugDisplay(fluidDispSettings *) = 0;
|
||||
#endif
|
||||
|
||||
/*! init tree for certain geometry init */
|
||||
void initGeoTree(int id);
|
||||
/*! destroy tree etc. when geometry init done */
|
||||
void freeGeoTree();
|
||||
/*! get fluid init type at certain position */
|
||||
// DEPRECATED CellFlagType geoInitGetPointType(ntlVec3Gfx org, ntlVec3Gfx nodesize, ntlGeometryObject **mpObj, gfxReal &distance);
|
||||
/*! check for a certain flag type at position org (needed for e.g. quadtree refinement) */
|
||||
bool geoInitCheckPointInside(ntlVec3Gfx org, int flags, int &OId, gfxReal &distance);
|
||||
/*! set render globals, for scene/tree access */
|
||||
void setRenderGlobals(ntlRenderGlobals *glob) { mpGlob = glob; };
|
||||
/*! get max. velocity of all objects to initialize as fluid regions */
|
||||
ntlVec3Gfx getGeoMaxInitialVelocity();
|
||||
|
||||
/* rt interface functions */
|
||||
unsigned int getIsoVertexCount() { return mpIso->getIsoVertexCount(); }
|
||||
unsigned int getIsoIndexCount() { return mpIso->getIsoIndexCount(); }
|
||||
char* getIsoVertexArray() { return mpIso->getIsoVertexArray(); }
|
||||
unsigned int *getIsoIndexArray() { return mpIso->getIsoIndexArray(); }
|
||||
void triangulateSurface() { return mpIso->triangulate(); }
|
||||
// drop stuff
|
||||
//virtual void addDrop(bool active, float mx, float my) = 0;
|
||||
//! avg. used cell count stats
|
||||
//virtual void printCellStats() = 0;
|
||||
//! check end time for gfx ani
|
||||
//virtual int checkGfxEndTime() = 0;
|
||||
//virtual int getGfxGeoSetup() = 0;
|
||||
|
||||
/* access functions */
|
||||
|
||||
/*! return grid sizes */
|
||||
int getSizeX( void ) { return mSizex; }
|
||||
int getSizeY( void ) { return mSizey; }
|
||||
int getSizeZ( void ) { return mSizez; }
|
||||
/*! return grid sizes */
|
||||
void setSizeX( int ns ) { mSizex = ns; }
|
||||
void setSizeY( int ns ) { mSizey = ns; }
|
||||
void setSizeZ( int ns ) { mSizez = ns; }
|
||||
|
||||
/*! set attr list pointer */
|
||||
void setAttrList(AttributeList *set) { mpAttrs = set; }
|
||||
/*! Returns the attribute list pointer */
|
||||
inline AttributeList *getAttributeList() { return mpAttrs; }
|
||||
|
||||
/*! set parametrizer pointer */
|
||||
inline void setParametrizer(Parametrizer *set) { mpParam = set; }
|
||||
/*! get parametrizer pointer */
|
||||
inline Parametrizer *getParametrizer() { return mpParam; }
|
||||
|
||||
/*! set density gradient init from e.g. init test cases */
|
||||
inline void setInitDensityGradient(bool set) { mInitDensityGradient = set; }
|
||||
|
||||
/*! access geometry start vector */
|
||||
inline void setGeoStart(ntlVec3Gfx set) { mvGeoStart = set; }
|
||||
inline ntlVec3Gfx getGeoStart() const { return mvGeoStart; }
|
||||
|
||||
/*! access geometry end vector */
|
||||
inline void setGeoEnd(ntlVec3Gfx set) { mvGeoEnd = set; }
|
||||
inline ntlVec3Gfx getGeoEnd() const { return mvGeoEnd; }
|
||||
|
||||
/*! access name string */
|
||||
inline void setName(string set) { mName = set; }
|
||||
inline string getName() const { return mName; }
|
||||
|
||||
/*! access string for node info debugging output */
|
||||
inline string getNodeInfoString() const { return mNodeInfoString; }
|
||||
|
||||
/*! get panic flag */
|
||||
inline bool getPanic() { return mPanic; }
|
||||
|
||||
//! set silent mode?
|
||||
inline void setSilent(bool set){ mSilent = set; }
|
||||
|
||||
|
||||
// cell iterator interface
|
||||
|
||||
// cell id type
|
||||
typedef CellIdentifierInterface* CellIdentifier;
|
||||
|
||||
//! cell iteration methods
|
||||
virtual CellIdentifierInterface* getFirstCell( ) = 0;
|
||||
virtual void advanceCell( CellIdentifierInterface* ) = 0;
|
||||
virtual bool noEndCell( CellIdentifierInterface* ) = 0;
|
||||
//! clean up iteration, this should be called, when the iteration is not completely finished
|
||||
virtual void deleteCellIterator( CellIdentifierInterface** ) = 0;
|
||||
|
||||
//! find cell at a given position (returns NULL if not in domain)
|
||||
virtual CellIdentifierInterface* getCellAt( ntlVec3Gfx pos ) = 0;
|
||||
|
||||
//! return node information
|
||||
virtual int getCellSet ( CellIdentifierInterface* ) = 0;
|
||||
virtual ntlVec3Gfx getCellOrigin ( CellIdentifierInterface* ) = 0;
|
||||
virtual ntlVec3Gfx getCellSize ( CellIdentifierInterface* ) = 0;
|
||||
virtual int getCellLevel ( CellIdentifierInterface* ) = 0;
|
||||
virtual LbmFloat getCellDensity ( CellIdentifierInterface*,int ) = 0;
|
||||
virtual LbmVec getCellVelocity ( CellIdentifierInterface*,int ) = 0;
|
||||
/*! get equilibrium distribution functions */
|
||||
virtual LbmFloat getEquilDf ( int ) = 0;
|
||||
/*! get number of distribution functions */
|
||||
virtual int getDfNum ( ) = 0;
|
||||
/*! redundant cell functions */
|
||||
virtual LbmFloat getCellDf ( CellIdentifierInterface* ,int set, int dir) = 0;
|
||||
virtual LbmFloat getCellMass ( CellIdentifierInterface* ,int set) = 0;
|
||||
virtual LbmFloat getCellFill ( CellIdentifierInterface* ,int set) = 0;
|
||||
virtual CellFlagType getCellFlag ( CellIdentifierInterface* ,int set) = 0;
|
||||
|
||||
|
||||
// debugging cell marker functions
|
||||
|
||||
//! add cell to mMarkedCells list
|
||||
void addCellToMarkedList( CellIdentifierInterface *cid );
|
||||
//! marked cell iteration methods
|
||||
CellIdentifierInterface* markedGetFirstCell( );
|
||||
void markedAdvanceCell( CellIdentifierInterface* pcid );
|
||||
bool markedNoEndCell( CellIdentifierInterface* cid );
|
||||
void markedClearList();
|
||||
|
||||
#ifndef LBMDIM
|
||||
LBMDIM has to be defined
|
||||
#endif
|
||||
#if LBMDIM==2
|
||||
//! minimal and maximal z-coords (for 2D/3D loops) , this is always 0-1 for 2D
|
||||
int getForZMinBnd() { return 0; };
|
||||
int getForZMaxBnd() { return 1; };
|
||||
int getForZMin1() { return 0; };
|
||||
int getForZMax1() { return 1; };
|
||||
#else // LBMDIM==2
|
||||
//! minimal and maximal z-coords (for 2D/3D loops)
|
||||
int getForZMinBnd() { return 0; };
|
||||
int getForZMaxBnd() { return getSizeZ()-0; };
|
||||
int getForZMin1() { return 1; };
|
||||
int getForZMax1() { return getSizeZ()-1; };
|
||||
#endif // LBMDIM==2
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
/*! abort simulation on error... */
|
||||
bool mPanic;
|
||||
|
||||
|
||||
/*! Size of the array in x,y,z direction */
|
||||
int mSizex, mSizey, mSizez;
|
||||
|
||||
|
||||
/*! step counter */
|
||||
int mStepCnt;
|
||||
|
||||
/*! mass change from one step to the next, for extreme cases fix globally */
|
||||
LbmFloat mFixMass;
|
||||
|
||||
// deprecated param vars
|
||||
/*! omega for lbm */
|
||||
LbmFloat mOmega;
|
||||
/*! gravity strength in neg. z direction */
|
||||
LbmVec mGravity;
|
||||
/*! Surface tension of the fluid */
|
||||
LbmFloat mSurfaceTension;
|
||||
|
||||
|
||||
/*! initial mass to display changes */
|
||||
LbmFloat mInitialMass;
|
||||
/* boundary inits */
|
||||
CellFlagType mBoundaryEast, mBoundaryWest,
|
||||
mBoundaryNorth, mBoundarySouth,
|
||||
mBoundaryTop, mBoundaryBottom;
|
||||
|
||||
/*! initialization from config file done? */
|
||||
int mInitDone;
|
||||
|
||||
/*! init density gradient? */
|
||||
bool mInitDensityGradient;
|
||||
|
||||
/*! pointer to the attribute list */
|
||||
AttributeList *mpAttrs;
|
||||
|
||||
/*! get parameters from this parametrize in finishInit */
|
||||
Parametrizer *mpParam;
|
||||
|
||||
/*! number of particles lost so far */
|
||||
int mNumParticlesLost;
|
||||
/*! number of particles lost so far */
|
||||
int mNumInvalidDfs;
|
||||
/*! no of filled/emptied cells per time step */
|
||||
int mNumFilledCells, mNumEmptiedCells;
|
||||
/*! counter number of used cells for performance */
|
||||
int mNumUsedCells;
|
||||
/*! MLSUPS counter */
|
||||
LbmFloat mMLSUPS;
|
||||
/*! debug - velocity output scaling factor */
|
||||
LbmFloat mDebugVelScale;
|
||||
/*! string for node info debugging output */
|
||||
string mNodeInfoString;
|
||||
|
||||
|
||||
/*! an own random stream */
|
||||
ntlRandomStream mRandom;
|
||||
|
||||
|
||||
// geo init vars
|
||||
// TODO deprecate SimulationObject vars
|
||||
|
||||
/*! for display - start and end vectors for geometry */
|
||||
ntlVec3Gfx mvGeoStart, mvGeoEnd;
|
||||
|
||||
/*! perform geometry init? */
|
||||
bool mPerformGeoInit;
|
||||
/*! perform accurate geometry init? */
|
||||
bool mAccurateGeoinit;
|
||||
|
||||
/*! name of this lbm object (for debug output) */
|
||||
string mName;
|
||||
|
||||
//! Mcubes object for surface reconstruction
|
||||
IsoSurface *mpIso;
|
||||
/*! isolevel value for marching cubes surface reconstruction */
|
||||
LbmFloat mIsoValue;
|
||||
|
||||
//! debug output?
|
||||
bool mSilent;
|
||||
|
||||
/*! geometry init id */
|
||||
int mGeoInitId;
|
||||
/*! tree object for geomerty initialization */
|
||||
ntlTree *mpGiTree;
|
||||
/*! object vector for geo init */
|
||||
vector<ntlGeometryObject*> *mpGiObjects;
|
||||
/*! inside which objects? */
|
||||
vector<int> mGiObjInside;
|
||||
/*! inside which objects? */
|
||||
vector<gfxReal> mGiObjDistance;
|
||||
/*! remember globals */
|
||||
ntlRenderGlobals *mpGlob;
|
||||
|
||||
// list for marked cells
|
||||
std::vector<CellIdentifierInterface *> mMarkedCells;
|
||||
};
|
||||
|
||||
|
||||
//! helper function to convert flag to string (for debuggin)
|
||||
std::string convertCellFlagType2String( CellFlagType flag );
|
||||
std::string convertSingleFlag2String(CellFlagType cflag);
|
||||
|
||||
#endif // LBMINTERFACE_H
|
298
intern/elbeem/intern/mcubes_tables.h
Normal file
298
intern/elbeem/intern/mcubes_tables.h
Normal file
@ -0,0 +1,298 @@
|
||||
|
||||
/* which edges are needed ? */
|
||||
/* cf. http://astronomy.swin.edu.au/~pbourke/modelling/polygonise/ */
|
||||
static const short mcEdgeTable[256]={
|
||||
0x0 , 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
|
||||
0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
|
||||
0x190, 0x99 , 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,
|
||||
0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
|
||||
0x230, 0x339, 0x33 , 0x13a, 0x636, 0x73f, 0x435, 0x53c,
|
||||
0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
|
||||
0x3a0, 0x2a9, 0x1a3, 0xaa , 0x7a6, 0x6af, 0x5a5, 0x4ac,
|
||||
0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
|
||||
0x460, 0x569, 0x663, 0x76a, 0x66 , 0x16f, 0x265, 0x36c,
|
||||
0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
|
||||
0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff , 0x3f5, 0x2fc,
|
||||
0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
|
||||
0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55 , 0x15c,
|
||||
0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
|
||||
0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc ,
|
||||
0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
|
||||
0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,
|
||||
0xcc , 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
|
||||
0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,
|
||||
0x15c, 0x55 , 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
|
||||
0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,
|
||||
0x2fc, 0x3f5, 0xff , 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
|
||||
0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,
|
||||
0x36c, 0x265, 0x16f, 0x66 , 0x76a, 0x663, 0x569, 0x460,
|
||||
0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
|
||||
0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa , 0x1a3, 0x2a9, 0x3a0,
|
||||
0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,
|
||||
0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33 , 0x339, 0x230,
|
||||
0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,
|
||||
0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99 , 0x190,
|
||||
0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,
|
||||
0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 };
|
||||
|
||||
/* triangles for the 256 intersection possibilities */
|
||||
/* cf. http://astronomy.swin.edu.au/~pbourke/modelling/polygonise/ */
|
||||
static const short mcTriTable[256][16] = {
|
||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1},
|
||||
{3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1},
|
||||
{3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1},
|
||||
{3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1},
|
||||
{9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1},
|
||||
{9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1},
|
||||
{2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1},
|
||||
{8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1},
|
||||
{9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1},
|
||||
{4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1},
|
||||
{3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1},
|
||||
{1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1},
|
||||
{4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1},
|
||||
{4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1},
|
||||
{9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1},
|
||||
{1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1},
|
||||
{5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1},
|
||||
{2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1},
|
||||
{9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1},
|
||||
{0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1},
|
||||
{2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1},
|
||||
{10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1},
|
||||
{4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1},
|
||||
{5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1},
|
||||
{5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1},
|
||||
{9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1},
|
||||
{0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1},
|
||||
{1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1},
|
||||
{10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1},
|
||||
{8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1},
|
||||
{2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1},
|
||||
{7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1},
|
||||
{9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1},
|
||||
{2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1},
|
||||
{11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1},
|
||||
{9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1},
|
||||
{5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1},
|
||||
{11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1},
|
||||
{11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1},
|
||||
{1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1},
|
||||
{9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1},
|
||||
{5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1},
|
||||
{2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1},
|
||||
{0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1},
|
||||
{5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1},
|
||||
{6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1},
|
||||
{0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1},
|
||||
{3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1},
|
||||
{6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1},
|
||||
{5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1},
|
||||
{1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1},
|
||||
{10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1},
|
||||
{6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1},
|
||||
{1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1},
|
||||
{8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1},
|
||||
{7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1},
|
||||
{3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1},
|
||||
{5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1},
|
||||
{0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1},
|
||||
{9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1},
|
||||
{8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1},
|
||||
{5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1},
|
||||
{0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1},
|
||||
{6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1},
|
||||
{10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1},
|
||||
{10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1},
|
||||
{8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1},
|
||||
{1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1},
|
||||
{3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1},
|
||||
{0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1},
|
||||
{10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1},
|
||||
{0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1},
|
||||
{3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1},
|
||||
{6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1},
|
||||
{9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1},
|
||||
{8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1},
|
||||
{3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1},
|
||||
{6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1},
|
||||
{0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1},
|
||||
{10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1},
|
||||
{10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1},
|
||||
{1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1},
|
||||
{2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1},
|
||||
{7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1},
|
||||
{7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1},
|
||||
{2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1},
|
||||
{1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1},
|
||||
{11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1},
|
||||
{8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1},
|
||||
{0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1},
|
||||
{7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1},
|
||||
{10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1},
|
||||
{2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1},
|
||||
{6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1},
|
||||
{7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1},
|
||||
{2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1},
|
||||
{1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1},
|
||||
{10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1},
|
||||
{10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1},
|
||||
{0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1},
|
||||
{7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1},
|
||||
{6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1},
|
||||
{8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1},
|
||||
{6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1},
|
||||
{4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1},
|
||||
{10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1},
|
||||
{8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1},
|
||||
{0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1},
|
||||
{1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1},
|
||||
{8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1},
|
||||
{10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1},
|
||||
{4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1},
|
||||
{10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1},
|
||||
{5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1},
|
||||
{11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1},
|
||||
{9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1},
|
||||
{6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1},
|
||||
{7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1},
|
||||
{3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1},
|
||||
{7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1},
|
||||
{9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1},
|
||||
{3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1},
|
||||
{6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1},
|
||||
{9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1},
|
||||
{1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1},
|
||||
{4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1},
|
||||
{7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1},
|
||||
{6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1},
|
||||
{3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1},
|
||||
{0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1},
|
||||
{6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1},
|
||||
{0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1},
|
||||
{11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1},
|
||||
{6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1},
|
||||
{5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1},
|
||||
{9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1},
|
||||
{1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1},
|
||||
{1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1},
|
||||
{10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1},
|
||||
{0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1},
|
||||
{5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1},
|
||||
{10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1},
|
||||
{11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1},
|
||||
{9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1},
|
||||
{7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1},
|
||||
{2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1},
|
||||
{8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1},
|
||||
{9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1},
|
||||
{9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1},
|
||||
{1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1},
|
||||
{9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1},
|
||||
{9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1},
|
||||
{5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1},
|
||||
{0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1},
|
||||
{10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1},
|
||||
{2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1},
|
||||
{0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1},
|
||||
{0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1},
|
||||
{9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1},
|
||||
{5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1},
|
||||
{3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1},
|
||||
{5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1},
|
||||
{8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1},
|
||||
{9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1},
|
||||
{0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1},
|
||||
{1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1},
|
||||
{3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1},
|
||||
{4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1},
|
||||
{9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1},
|
||||
{11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1},
|
||||
{11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1},
|
||||
{2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1},
|
||||
{9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1},
|
||||
{3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1},
|
||||
{1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1},
|
||||
{4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1},
|
||||
{4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1},
|
||||
{0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1},
|
||||
{3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1},
|
||||
{3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1},
|
||||
{0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1},
|
||||
{9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1},
|
||||
{1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
|
||||
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}
|
||||
};
|
||||
|
216
intern/elbeem/intern/ntl_blenderdumper.cpp
Normal file
216
intern/elbeem/intern/ntl_blenderdumper.cpp
Normal file
@ -0,0 +1,216 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* Replaces std. raytracer, and only dumps time dep. objects to disc
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#include <fstream>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "utilities.h"
|
||||
#include "ntl_matrices.h"
|
||||
#include "ntl_blenderdumper.h"
|
||||
#include "ntl_scene.h"
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Constructor
|
||||
*****************************************************************************/
|
||||
ntlBlenderDumper::ntlBlenderDumper(string filename, bool commandlineMode) :
|
||||
ntlRaytracer(filename,commandlineMode),
|
||||
mpTrafo(NULL)
|
||||
{
|
||||
ntlRenderGlobals *glob = mpGlob;
|
||||
AttributeList *pAttrs = glob->getBlenderAttributes();
|
||||
mpTrafo = new ntlMat4Gfx(0.0);
|
||||
mpTrafo->initId();
|
||||
(*mpTrafo) = pAttrs->readMat4Gfx("transform" , (*mpTrafo), "ntlBlenderDumper","mpTrafo", false );
|
||||
|
||||
//for(int i=0; i<4;i++) { for(int j=0; j<4;j++) { errMsg("T"," "<<i<<","<<j<<" "<<mpTrafo->value[i][j]); } } // DEBUG
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Destructor
|
||||
*****************************************************************************/
|
||||
ntlBlenderDumper::~ntlBlenderDumper()
|
||||
{
|
||||
delete mpTrafo;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Only dump time dep. objects to file
|
||||
*****************************************************************************/
|
||||
int ntlBlenderDumper::renderScene( void )
|
||||
{
|
||||
char nrStr[5]; /* nr conversion */
|
||||
ntlRenderGlobals *glob = mpGlob;
|
||||
ntlScene *scene = mpGlob->getScene();
|
||||
bool debugOut = true;
|
||||
bool otherOut = true;
|
||||
#if ELBEEM_BLENDER==1
|
||||
debugOut = false;
|
||||
otherOut = false;
|
||||
#endif // ELBEEM_BLENDER==1
|
||||
|
||||
// output path
|
||||
/*std::ostringstream ecrpath("");
|
||||
ecrpath << "/tmp/ecr_" << getpid() <<"/";
|
||||
// make sure the dir exists
|
||||
std::ostringstream ecrpath_create("");
|
||||
ecrpath_create << "mkdir " << ecrpath.str();
|
||||
system( ecrpath_create.str().c_str() );
|
||||
// */
|
||||
|
||||
vector<string> hideObjs; // geom shaders to hide
|
||||
vector<string> gmName; // gm names
|
||||
vector<string> gmMat; // materials for gm
|
||||
int numGMs = 0; // no. of .obj models created
|
||||
|
||||
if(debugOut) debMsgStd("ntlBlenderDumper::renderScene",DM_NOTIFY,"Dumping geometry data", 1);
|
||||
long startTime = getTime();
|
||||
|
||||
/* check if picture already exists... */
|
||||
snprintf(nrStr, 5, "%04d", glob->getAniCount() );
|
||||
|
||||
// local scene vars
|
||||
vector<ntlTriangle> Triangles;
|
||||
vector<ntlVec3Gfx> Vertices;
|
||||
vector<ntlVec3Gfx> VertNormals;
|
||||
|
||||
/* init geometry array, first all standard objects */
|
||||
int idCnt = 0; // give IDs to objects
|
||||
for (vector<ntlGeometryClass*>::iterator iter = scene->getGeoClasses()->begin();
|
||||
iter != scene->getGeoClasses()->end(); iter++) {
|
||||
if(!(*iter)->getVisible()) continue;
|
||||
int tid = (*iter)->getTypeId();
|
||||
|
||||
if(tid & GEOCLASSTID_OBJECT) {
|
||||
// normal geom. objects dont change... -> ignore
|
||||
//if(buildInfo) debMsgStd("ntlBlenderDumper::BuildScene",DM_MSG,"added GeoObj "<<geoobj->getName(), 8 );
|
||||
}
|
||||
if(tid & GEOCLASSTID_SHADER) {
|
||||
ntlGeometryShader *geoshad = (ntlGeometryShader*)(*iter); //dynamic_cast<ntlGeometryShader*>(*iter);
|
||||
hideObjs.push_back( (*iter)->getName() );
|
||||
for (vector<ntlGeometryObject*>::iterator siter = geoshad->getObjectsBegin();
|
||||
siter != geoshad->getObjectsEnd();
|
||||
siter++) {
|
||||
if(debugOut) debMsgStd("ntlBlenderDumper::BuildScene",DM_MSG,"added shader geometry "<<(*siter)->getName(), 8);
|
||||
|
||||
// only dump geo shader objects
|
||||
Triangles.clear();
|
||||
Vertices.clear();
|
||||
VertNormals.clear();
|
||||
(*siter)->initialize( mpGlob );
|
||||
(*siter)->getTriangles(&Triangles, &Vertices, &VertNormals, idCnt);
|
||||
idCnt ++;
|
||||
|
||||
// always dump mesh, even empty ones...
|
||||
//if(Vertices.size() <= 0) continue;
|
||||
//if(Triangles.size() <= 0) continue;
|
||||
|
||||
for(size_t i=0; i<Vertices.size(); i++) {
|
||||
Vertices[i] = (*mpTrafo) * Vertices[i];
|
||||
}
|
||||
|
||||
// dump to binary file
|
||||
std::ostringstream boutfilename("");
|
||||
//boutfilename << ecrpath.str() << glob->getOutFilename() <<"_"<< (*siter)->getName() <<"_" << nrStr << ".obj";
|
||||
boutfilename << glob->getOutFilename() <<"_"<< (*siter)->getName() <<"_" << nrStr << ".bobj";
|
||||
if(debugOut) debMsgStd("ntlBlenderDumper::renderScene",DM_MSG,"B-Dumping: "<< (*siter)->getName()
|
||||
<<", triangles:"<<Triangles.size()<<", vertices:"<<Vertices.size()<<
|
||||
" to "<<boutfilename.str() , 7);
|
||||
bool isPreview = false;
|
||||
if( (*siter)->getName().find( "preview" ) != string::npos) {
|
||||
isPreview = true;
|
||||
}
|
||||
boutfilename << ".gz";
|
||||
|
||||
// compress all bobj's except for preview ones...
|
||||
gzFile gzf;
|
||||
if(isPreview) {
|
||||
gzf = gzopen(boutfilename.str().c_str(), "wb1");
|
||||
} else {
|
||||
gzf = gzopen(boutfilename.str().c_str(), "wb9");
|
||||
}
|
||||
if (!gzf) {
|
||||
errMsg("ntlBlenderDumper::renderScene","Unable to open output '"<<boutfilename<<"' ");
|
||||
return 1; }
|
||||
|
||||
int wri;
|
||||
float wrf;
|
||||
if(sizeof(wri)!=4) { errMsg("ntlBlenderDumper::renderScene","Invalid int size"); return 1; }
|
||||
wri = Vertices.size();
|
||||
gzwrite(gzf, &wri, sizeof(wri));
|
||||
for(size_t i=0; i<Vertices.size(); i++) {
|
||||
for(int j=0; j<3; j++) {
|
||||
wrf = Vertices[i][j];
|
||||
gzwrite(gzf, &wrf, sizeof(wrf)); }
|
||||
}
|
||||
|
||||
// should be the same as Vertices.size
|
||||
wri = VertNormals.size();
|
||||
gzwrite(gzf, &wri, sizeof(wri));
|
||||
for(size_t i=0; i<VertNormals.size(); i++) {
|
||||
for(int j=0; j<3; j++) {
|
||||
wrf = VertNormals[i][j];
|
||||
gzwrite(gzf, &wrf, sizeof(wrf)); }
|
||||
}
|
||||
|
||||
wri = Triangles.size();
|
||||
gzwrite(gzf, &wri, sizeof(wri));
|
||||
for(size_t i=0; i<Triangles.size(); i++) {
|
||||
for(int j=0; j<3; j++) {
|
||||
wri = Triangles[i].getPoints()[j];
|
||||
gzwrite(gzf, &wri, sizeof(wri)); }
|
||||
}
|
||||
gzclose( gzf );
|
||||
if(otherOut)
|
||||
debMsgDirect(" Wrote: '"<<boutfilename.str()<<"'. ");
|
||||
numGMs++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// output ecr config file
|
||||
if(numGMs>0) {
|
||||
if(debugOut) debMsgStd("ntlBlenderDumper::renderScene",DM_MSG,"Objects dumped: "<<numGMs, 10);
|
||||
} else {
|
||||
errMsg("ntlBlenderDumper::renderScene","No objects to dump! Aborting...");
|
||||
#if ELBEEM_BLENDER==1
|
||||
// TODO ... D::mPanic=1;
|
||||
return 1;
|
||||
#else // ELBEEM_BLENDER==1
|
||||
exit(1);
|
||||
#endif // ELBEEM_BLENDER==1
|
||||
}
|
||||
|
||||
/* next frame */
|
||||
//glob->setAniCount( glob->getAniCount() +1 );
|
||||
long stopTime = getTime();
|
||||
if(debugOut)
|
||||
debMsgStd("ntlBlenderDumper::renderScene",DM_MSG,"Scene #"<<nrStr<<" dump time: "<< getTimeString(stopTime-startTime) <<" ", 10);
|
||||
|
||||
// still render for preview...
|
||||
if(debugOut) {
|
||||
debMsgStd("ntlBlenderDumper::renderScene",DM_NOTIFY,"Performing preliminary render", 1);
|
||||
ntlRaytracer::renderScene(); }
|
||||
else {
|
||||
// next frame
|
||||
glob->setAniCount( glob->getAniCount() +1 );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
34
intern/elbeem/intern/ntl_blenderdumper.h
Normal file
34
intern/elbeem/intern/ntl_blenderdumper.h
Normal file
@ -0,0 +1,34 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* Replaces std. raytracer, and only dumps time dep. objects to disc, header
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef NTL_BLENDERDUMPER_H
|
||||
#include "ntl_raytracer.h"
|
||||
|
||||
template<class Scalar> class ntlMatrix4x4;
|
||||
|
||||
class ntlBlenderDumper :
|
||||
public ntlRaytracer
|
||||
{
|
||||
public:
|
||||
/*! Constructor */
|
||||
ntlBlenderDumper(string filename, bool commandlineMode);
|
||||
/*! Destructor */
|
||||
virtual ~ntlBlenderDumper( void );
|
||||
|
||||
/*! render scene (a single pictures) */
|
||||
virtual int renderScene( void );
|
||||
|
||||
protected:
|
||||
|
||||
//! transform matrix
|
||||
ntlMatrix4x4<gfxReal> *mpTrafo;
|
||||
};
|
||||
|
||||
#define NTL_BLENDERDUMPER_H
|
||||
#endif
|
||||
|
668
intern/elbeem/intern/ntl_bsptree.cpp
Normal file
668
intern/elbeem/intern/ntl_bsptree.cpp
Normal file
@ -0,0 +1,668 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* Tree container for fast triangle intersects
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#include "ntl_bsptree.h"
|
||||
#include "ntl_scene.h"
|
||||
#include "utilities.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
/*! Static global variable for sorting direction */
|
||||
int globalSortingAxis;
|
||||
/*! Access to points array for sorting */
|
||||
vector<ntlVec3Gfx> *globalSortingPoints;
|
||||
|
||||
#define TREE_DOUBLEI 300
|
||||
|
||||
/* try axis selection? */
|
||||
bool chooseAxis = 0;
|
||||
/* do median search? */
|
||||
int doSort = 0;
|
||||
|
||||
|
||||
//! struct for a single node in the bsp tree
|
||||
class BSPNode {
|
||||
public:
|
||||
ntlVec3Gfx min,max; /* AABB for node */
|
||||
vector<ntlTriangle *> *members; /* stored triangles */
|
||||
BSPNode *child[2]; /* pointer to children nodes */
|
||||
char axis; /* division axis */
|
||||
char cloneVec; /* is this vector a clone? */
|
||||
|
||||
//! check if node is a leaf
|
||||
inline bool isLeaf() const {
|
||||
return (child[0] == NULL);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! an element node stack
|
||||
class BSPStackElement {
|
||||
public:
|
||||
//! tree node
|
||||
BSPNode *node;
|
||||
//! min and maximum distance along axis
|
||||
gfxReal mindist, maxdist;
|
||||
};
|
||||
|
||||
//! bsp tree stack
|
||||
class BSPStack {
|
||||
public:
|
||||
//! current stack element
|
||||
int stackPtr;
|
||||
//! stack storage
|
||||
BSPStackElement elem[ BSP_STACK_SIZE ];
|
||||
};
|
||||
|
||||
//! triangle bounding box for quick tree subdivision
|
||||
class TriangleBBox {
|
||||
public:
|
||||
//! start and end of triangle bounding box
|
||||
ntlVec3Gfx start, end;
|
||||
};
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* calculate tree statistics
|
||||
*****************************************************************************/
|
||||
void calcStats(BSPNode *node, int depth, int &noLeafs, gfxReal &avgDepth, gfxReal &triPerLeaf,int &totalTris)
|
||||
{
|
||||
if(node->members != NULL) {
|
||||
totalTris += node->members->size();
|
||||
}
|
||||
//depth = 15; // DBEUG!
|
||||
|
||||
if( (node->child[0]==NULL) && (node->child[1]==NULL) ) {
|
||||
// leaf
|
||||
noLeafs++;
|
||||
avgDepth += depth;
|
||||
triPerLeaf += node->members->size();
|
||||
} else {
|
||||
for(int i=0;i<2;i++)
|
||||
calcStats(node->child[i], depth+1, noLeafs, avgDepth, triPerLeaf, totalTris);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* triangle comparison function for median search
|
||||
*****************************************************************************/
|
||||
bool lessTriangleAverage(const ntlTriangle *x, const ntlTriangle *y)
|
||||
{
|
||||
return x->getAverage(globalSortingAxis) < y->getAverage(globalSortingAxis);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* triangle AABB intersection
|
||||
*****************************************************************************/
|
||||
bool ntlTree::checkAABBTriangle(ntlVec3Gfx &min, ntlVec3Gfx &max, ntlTriangle *tri)
|
||||
{
|
||||
// test only BB of triangle
|
||||
TriangleBBox *bbox = &mpTBB[ tri->getBBoxId() ];
|
||||
if( bbox->end[0] < min[0] ) return false;
|
||||
if( bbox->start[0] > max[0] ) return false;
|
||||
if( bbox->end[1] < min[1] ) return false;
|
||||
if( bbox->start[1] > max[1] ) return false;
|
||||
if( bbox->end[2] < min[2] ) return false;
|
||||
if( bbox->start[2] > max[2] ) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Default constructor
|
||||
*****************************************************************************/
|
||||
ntlTree::ntlTree() :
|
||||
mStart(0.0), mEnd(0.0), mMaxDepth( 5 ), mMaxListLength( 5 ), mpRoot( NULL) ,
|
||||
mpNodeStack( NULL), mpVertices( NULL ), mpVertNormals( NULL ), mpTriangles( NULL ),
|
||||
mCurrentDepth(0), mCurrentNodes(0), mTriDoubles(0)
|
||||
{
|
||||
errorOut( "ntlTree Cons: Uninitialized BSP Tree!\n" );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Constructor with init
|
||||
*****************************************************************************/
|
||||
//ntlTree::ntlTree(int depth, int objnum, vector<ntlVec3Gfx> *vertices, vector<ntlVec3Gfx> *normals, vector<ntlTriangle> *trilist) :
|
||||
ntlTree::ntlTree(int depth, int objnum, ntlScene *scene, int triFlagMask) :
|
||||
mStart(0.0), mEnd(0.0), mMaxDepth( depth ), mMaxListLength( objnum ), mpRoot( NULL) ,
|
||||
mpNodeStack( NULL), mpTBB( NULL ),
|
||||
mTriangleMask( 0xFFFF ),
|
||||
mCurrentDepth(0), mCurrentNodes(0)
|
||||
{
|
||||
// init scene data pointers
|
||||
mpVertices = scene->getVertexPointer();
|
||||
mpVertNormals = scene->getVertexNormalPointer();
|
||||
mpTriangles = scene->getTrianglePointer();
|
||||
mTriangleMask = triFlagMask;
|
||||
|
||||
if(mpTriangles == NULL) {
|
||||
errorOut( "ntlTree Cons: no triangle list!\n");
|
||||
exit(1);
|
||||
}
|
||||
if(mpTriangles->size() == 0) {
|
||||
warnMsg( "ntlTree::ntlTree","No triangles ("<< mpTriangles->size() <<")!\n");
|
||||
mStart = mEnd = ntlVec3Gfx(0,0,0);
|
||||
return;
|
||||
}
|
||||
if(depth>=BSP_STACK_SIZE) {
|
||||
errMsg( "ntlTree::ntlTree","Depth to high ("<< mMaxDepth <<")!\n" );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* check triangles (a bit inefficient, but we dont know which vertices belong
|
||||
to this tree), and generate bounding boxes */
|
||||
mppTriangles = new vector<ntlTriangle *>;
|
||||
int noOfTriangles = mpTriangles->size();
|
||||
mpTBB = new TriangleBBox[ noOfTriangles ];
|
||||
int bbCount = 0;
|
||||
mStart = mEnd = (*mpVertices)[ mpTriangles->front().getPoints()[0] ];
|
||||
for (vector<ntlTriangle>::iterator iter = mpTriangles->begin();
|
||||
iter != mpTriangles->end();
|
||||
iter++ ) {
|
||||
// discard triangles that dont match mask
|
||||
//errorOut(" d "<<(int)(*iter).getFlags() <<" "<< (int)mTriangleMask );
|
||||
if( ((int)(*iter).getFlags() & (int)mTriangleMask) == 0 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// test? TODO
|
||||
ntlVec3Gfx tnormal = (*mpVertNormals)[ (*iter).getPoints()[0] ]+
|
||||
(*mpVertNormals)[ (*iter).getPoints()[1] ]+
|
||||
(*mpVertNormals)[ (*iter).getPoints()[2] ];
|
||||
ntlVec3Gfx triangleNormal = (*iter).getNormal();
|
||||
if( equal(triangleNormal, ntlVec3Gfx(0.0)) ) continue;
|
||||
if( equal( tnormal, ntlVec3Gfx(0.0)) ) continue;
|
||||
// */
|
||||
|
||||
ntlVec3Gfx bbs, bbe;
|
||||
for(int i=0;i<3;i++) {
|
||||
int index = (*iter).getPoints()[i];
|
||||
ntlVec3Gfx tp = (*mpVertices)[ index ];
|
||||
if(tp[0] < mStart[0]) mStart[0]= tp[0];
|
||||
if(tp[0] > mEnd[0]) mEnd[0]= tp[0];
|
||||
if(tp[1] < mStart[1]) mStart[1]= tp[1];
|
||||
if(tp[1] > mEnd[1]) mEnd[1]= tp[1];
|
||||
if(tp[2] < mStart[2]) mStart[2]= tp[2];
|
||||
if(tp[2] > mEnd[2]) mEnd[2]= tp[2];
|
||||
if(i==0) {
|
||||
bbs = bbe = tp;
|
||||
} else {
|
||||
if( tp[0] < bbs[0] ) bbs[0] = tp[0];
|
||||
if( tp[0] > bbe[0] ) bbe[0] = tp[0];
|
||||
if( tp[1] < bbs[1] ) bbs[1] = tp[1];
|
||||
if( tp[1] > bbe[1] ) bbe[1] = tp[1];
|
||||
if( tp[2] < bbs[2] ) bbs[2] = tp[2];
|
||||
if( tp[2] > bbe[2] ) bbe[2] = tp[2];
|
||||
}
|
||||
}
|
||||
mppTriangles->push_back( &(*iter) );
|
||||
|
||||
// add BB
|
||||
mpTBB[ bbCount ].start = bbs;
|
||||
mpTBB[ bbCount ].end = bbe;
|
||||
(*iter).setBBoxId( bbCount );
|
||||
bbCount++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* slighlty enlarge bounding tolerance for tree
|
||||
to avoid problems with triangles paralell to slabs */
|
||||
mStart -= ntlVec3Gfx( getVecEpsilon() );
|
||||
mEnd += ntlVec3Gfx( getVecEpsilon() );
|
||||
|
||||
/* init root node and stack */
|
||||
mpNodeStack = new BSPStack;
|
||||
mpRoot = new BSPNode;
|
||||
mpRoot->min = mStart;
|
||||
mpRoot->max = mEnd;
|
||||
mpRoot->axis = AXIS_X;
|
||||
mpRoot->members = mppTriangles;
|
||||
mpRoot->child[0] = mpRoot->child[1] = NULL;
|
||||
mpRoot->cloneVec = 0;
|
||||
globalSortingPoints = mpVertices;
|
||||
mpTriDist = new char[ mppTriangles->size() ];
|
||||
|
||||
/* create tree */
|
||||
debugOutInter( "Generating BSP Tree... (Nodes "<< mCurrentNodes <<
|
||||
", Depth "<<mCurrentDepth<< ") ", 2, 2000 );
|
||||
subdivide(mpRoot, 0, AXIS_X);
|
||||
debMsgStd("ntlTree::ntlTree",DM_MSG,"Generated Tree: Nodes "<< mCurrentNodes <<
|
||||
", Depth "<<mCurrentDepth<< " with "<<noOfTriangles<<" triangles", 2 );
|
||||
|
||||
delete [] mpTriDist;
|
||||
delete [] mpTBB;
|
||||
mpTriDist = NULL;
|
||||
mpTBB = NULL;
|
||||
|
||||
/* calculate some stats about tree */
|
||||
int noLeafs = 0;
|
||||
gfxReal avgDepth = 0.0;
|
||||
gfxReal triPerLeaf = 0.0;
|
||||
int totalTris = 0;
|
||||
|
||||
calcStats(mpRoot,0, noLeafs, avgDepth, triPerLeaf, totalTris);
|
||||
avgDepth /= (gfxReal)noLeafs;
|
||||
triPerLeaf /= (gfxReal)noLeafs;
|
||||
debMsgStd("ntlTree::ntlTree",DM_MSG,"Tree ("<<doSort<<","<<chooseAxis<<") Stats: Leafs:"<<noLeafs<<", avgDepth:"<<avgDepth<<
|
||||
", triPerLeaf:"<<triPerLeaf<<", triDoubles:"<<mTriDoubles<<", totalTris:"<<totalTris
|
||||
//<<" T"<< (totalTris%3) // 0=ich, 1=f, 2=a
|
||||
, 2 );
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Destructor
|
||||
*****************************************************************************/
|
||||
ntlTree::~ntlTree()
|
||||
{
|
||||
/* delete tree, and all members except for the root node */
|
||||
deleteNode(mpRoot);
|
||||
if(mpNodeStack) delete mpNodeStack;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* subdivide tree
|
||||
*****************************************************************************/
|
||||
void ntlTree::subdivide(BSPNode *node, int depth, int axis)
|
||||
{
|
||||
int nextAxis; /* next axis to partition */
|
||||
int allTriDistSet = (1<<0)|(1<<1); // all mpTriDist flags set?
|
||||
//errorOut(" "<<node<<" depth:"<<depth<<" m:"<<node->members->size() <<" "<<node->min<<" - "<<node->max );
|
||||
|
||||
if(depth>mCurrentDepth) mCurrentDepth = depth;
|
||||
node->child[0] = node->child[1] = NULL;
|
||||
if( ( (int)node->members->size() > mMaxListLength) &&
|
||||
(depth < mMaxDepth )
|
||||
&& (node->cloneVec<10)
|
||||
) {
|
||||
|
||||
gfxReal planeDiv = 0.499999; // position of plane division
|
||||
|
||||
// determine next subdivision axis
|
||||
int newaxis = 0;
|
||||
gfxReal extX = node->max[0]-node->min[0];
|
||||
gfxReal extY = node->max[1]-node->min[1];
|
||||
gfxReal extZ = node->max[2]-node->min[2];
|
||||
|
||||
if( extY>extX ) {
|
||||
if( extZ>extY ) {
|
||||
newaxis = 2;
|
||||
} else {
|
||||
newaxis = 1;
|
||||
}
|
||||
} else {
|
||||
if( extZ>extX ) {
|
||||
newaxis = 2;
|
||||
} else {
|
||||
newaxis = 0;
|
||||
}
|
||||
}
|
||||
axis = node->axis = newaxis;
|
||||
|
||||
// init child nodes
|
||||
for( int i=0; i<2; i++) {
|
||||
/* status output */
|
||||
mCurrentNodes++;
|
||||
if(mCurrentNodes % 13973 ==0) {
|
||||
debugOutInter( "NTL Generating BSP Tree ("<<doSort<<","<<chooseAxis<<") ... (Nodes "<< mCurrentNodes <<
|
||||
", Depth "<<mCurrentDepth<< ") " , 2, 2000);
|
||||
}
|
||||
|
||||
/* create new node */
|
||||
node->child[i] = new BSPNode;
|
||||
node->child[i]->min = node->min;
|
||||
node->child[i]->max = node->max;
|
||||
node->child[i]->max = node->max;
|
||||
node->child[i]->child[0] = NULL;
|
||||
node->child[i]->child[1] = NULL;
|
||||
node->child[i]->members = NULL;
|
||||
nextAxis = (axis+1)%3;
|
||||
node->child[i]->axis = nextAxis;
|
||||
|
||||
/* current division plane */
|
||||
if(!i) {
|
||||
node->child[i]->min[axis] = node->min[axis];
|
||||
node->child[i]->max[axis] = node->min[axis] + planeDiv*
|
||||
(node->max[axis]-node->min[axis]);
|
||||
} else {
|
||||
node->child[i]->min[axis] = node->min[axis] + planeDiv*
|
||||
(node->max[axis]-node->min[axis]);
|
||||
node->child[i]->max[axis] = node->max[axis];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* process the two children */
|
||||
int thisTrisFor[2] = {0,0};
|
||||
int thisTriDoubles[2] = {0,0};
|
||||
for(int t=0;t<(int)node->members->size();t++) mpTriDist[t] = 0;
|
||||
for( int i=0; i<2; i++) {
|
||||
/* distribute triangles */
|
||||
int t = 0;
|
||||
for (vector<ntlTriangle *>::iterator iter = node->members->begin();
|
||||
iter != node->members->end(); iter++ ) {
|
||||
|
||||
/* add triangle, check bounding box axis */
|
||||
TriangleBBox *bbox = &mpTBB[ (*iter)->getBBoxId() ];
|
||||
bool intersect = true;
|
||||
if( bbox->end[axis] < node->child[i]->min[axis] ) intersect = false;
|
||||
else if( bbox->start[axis] > node->child[i]->max[axis] ) intersect = false;
|
||||
if(intersect) {
|
||||
// add flag to vector
|
||||
mpTriDist[t] |= (1<<i);
|
||||
// count no. of triangles for vector init
|
||||
thisTrisFor[i]++;
|
||||
}
|
||||
|
||||
if(mpTriDist[t] == allTriDistSet) {
|
||||
thisTriDoubles[i]++;
|
||||
mTriDoubles++; // TODO check for small geo tree??
|
||||
}
|
||||
t++;
|
||||
} /* end of loop over all triangles */
|
||||
} // i
|
||||
|
||||
/* distribute triangles */
|
||||
bool haveCloneVec[2] = {false, false};
|
||||
for( int i=0; i<2; i++) {
|
||||
/*if(thisTriDoubles[i] == (int)node->members->size()) {
|
||||
node->child[i]->members = node->members;
|
||||
node->child[i]->cloneVec = (node->cloneVec+1);
|
||||
haveCloneVec[i] = true;
|
||||
} else */
|
||||
{
|
||||
node->child[i]->members = new vector<ntlTriangle *>( thisTrisFor[i] );
|
||||
node->child[i]->cloneVec = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int tind0 = 0;
|
||||
int tind1 = 0;
|
||||
if( (!haveCloneVec[0]) || (!haveCloneVec[1]) ){
|
||||
int t = 0; // triangle index counter
|
||||
for (vector<ntlTriangle *>::iterator iter = node->members->begin();
|
||||
iter != node->members->end(); iter++ ) {
|
||||
if(!haveCloneVec[0]) {
|
||||
if( (mpTriDist[t] & 1) == 1) {
|
||||
(*node->child[0]->members)[tind0] = (*iter); // dont use push_back for preinited size!
|
||||
tind0++;
|
||||
}
|
||||
}
|
||||
if(!haveCloneVec[1]) {
|
||||
if( (mpTriDist[t] & 2) == 2) {
|
||||
(*node->child[1]->members)[tind1] = (*iter); // dont use push_back for preinited size!
|
||||
tind1++;
|
||||
}
|
||||
}
|
||||
|
||||
//if(depth>38) errorOut(" N d"<<depth<<" t"<<t<<" td"<<(int)mpTriDist[t]<<" S"<<(int)allTriDistSet);
|
||||
t++;
|
||||
} /* end of loop over all triangles */
|
||||
}
|
||||
//D errorOut( " MMM"<<i<<": "<<(unsigned int)(node->child[i]->members->size())<<" "<<thisTrisFor[i]<<" tind"<<tind[i] ); // DEBG!
|
||||
|
||||
// subdivide children
|
||||
for( int i=0; i<2; i++) {
|
||||
/* recurse */
|
||||
subdivide( node->child[i], depth+1, nextAxis );
|
||||
}
|
||||
|
||||
/* if we are here, this are childs, so we dont need the members any more... */
|
||||
/* delete unecessary members */
|
||||
if( (!haveCloneVec[0]) && (!haveCloneVec[1]) && (node->cloneVec == 0) ){ // ??? FIXME?
|
||||
//if( (!haveCloneVec[0]) && (!haveCloneVec[1]) ){
|
||||
delete node->members;
|
||||
}
|
||||
else {
|
||||
errMsg("LLLLLLLL","ASD"); }
|
||||
node->members = NULL;
|
||||
|
||||
} /* subdivision necessary */
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* intersect ray with BSPtree
|
||||
*****************************************************************************/
|
||||
void ntlTree::intersect(const ntlRay &ray, gfxReal &distance,
|
||||
ntlVec3Gfx &normal,
|
||||
ntlTriangle *&tri,
|
||||
int flags, bool forceNonsmooth) const
|
||||
{
|
||||
gfxReal mint = GFX_REAL_MAX; /* current minimal t */
|
||||
ntlVec3Gfx retnormal; /* intersection (interpolated) normal */
|
||||
gfxReal mintu=0.0, mintv=0.0; /* u,v for min t intersection */
|
||||
|
||||
BSPNode *curr, *nearChild, *farChild; /* current node and children */
|
||||
gfxReal planedist, mindist, maxdist;
|
||||
ntlVec3Gfx pos;
|
||||
|
||||
ntlTriangle *hit = NULL;
|
||||
tri = NULL;
|
||||
|
||||
ray.intersectCompleteAABB(mStart,mEnd,mindist,maxdist);
|
||||
|
||||
if((maxdist < 0.0) ||
|
||||
(mindist == GFX_REAL_MAX) ||
|
||||
(maxdist == GFX_REAL_MAX) ) {
|
||||
distance = -1.0;
|
||||
return;
|
||||
}
|
||||
mindist -= getVecEpsilon();
|
||||
maxdist += getVecEpsilon();
|
||||
|
||||
/* stack init */
|
||||
mpNodeStack->elem[0].node = NULL;
|
||||
mpNodeStack->stackPtr = 1;
|
||||
|
||||
curr = mpRoot;
|
||||
mint = GFX_REAL_MAX;
|
||||
while(curr != NULL) {
|
||||
|
||||
while( !curr->isLeaf() ) {
|
||||
planedist = distanceToPlane(curr, curr->child[0]->max, ray );
|
||||
getChildren(curr, ray.getOrigin(), nearChild, farChild );
|
||||
|
||||
// check ray direction for small plane distances
|
||||
if( (planedist>-getVecEpsilon() )&&(planedist< getVecEpsilon() ) ) {
|
||||
// ray origin on intersection plane
|
||||
planedist = 0.0;
|
||||
if(ray.getDirection()[curr->axis]>getVecEpsilon() ) {
|
||||
// larger coords
|
||||
curr = curr->child[1];
|
||||
} else if(ray.getDirection()[curr->axis]<-getVecEpsilon() ) {
|
||||
// smaller coords
|
||||
curr = curr->child[0];
|
||||
} else {
|
||||
// paralell, order doesnt really matter are min/max/plane ok?
|
||||
mpNodeStack->elem[ mpNodeStack->stackPtr ].node = curr->child[0];
|
||||
mpNodeStack->elem[ mpNodeStack->stackPtr ].mindist = planedist;
|
||||
mpNodeStack->elem[ mpNodeStack->stackPtr ].maxdist = maxdist;
|
||||
(mpNodeStack->stackPtr)++;
|
||||
curr = curr->child[1];
|
||||
maxdist = planedist;
|
||||
}
|
||||
} else {
|
||||
// normal ray
|
||||
if( (planedist>maxdist) || (planedist<0.0-getVecEpsilon() ) ) {
|
||||
curr = nearChild;
|
||||
} else if(planedist < mindist) {
|
||||
curr = farChild;
|
||||
} else {
|
||||
mpNodeStack->elem[ mpNodeStack->stackPtr ].node = farChild;
|
||||
mpNodeStack->elem[ mpNodeStack->stackPtr ].mindist = planedist;
|
||||
mpNodeStack->elem[ mpNodeStack->stackPtr ].maxdist = maxdist;
|
||||
(mpNodeStack->stackPtr)++;
|
||||
|
||||
curr = nearChild;
|
||||
maxdist = planedist;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* intersect with current node */
|
||||
for (vector<ntlTriangle *>::iterator iter = curr->members->begin();
|
||||
iter != curr->members->end(); iter++ ) {
|
||||
|
||||
/* check for triangle flags before intersecting */
|
||||
if((!flags) || ( ((*iter)->getFlags() & flags) > 0 )) {
|
||||
|
||||
if( ((*iter)->getLastRay() == ray.getID() )&&((*iter)->getLastRay()>0) ) {
|
||||
// was already intersected...
|
||||
} else {
|
||||
// we still need to intersect this triangle
|
||||
gfxReal u=0.0,v=0.0, t=-1.0;
|
||||
ray.intersectTriangle( mpVertices, (*iter), t,u,v);
|
||||
(*iter)->setLastRay( ray.getID() );
|
||||
|
||||
if( (t > 0.0) && (t<mint) ) {
|
||||
mint = t;
|
||||
hit = (*iter);
|
||||
mintu = u; mintv = v;
|
||||
|
||||
if((ray.getRenderglobals())&&(ray.getRenderglobals()->getDebugOut() > 5)) { // DEBUG!!!
|
||||
errorOut("Tree tri hit at "<<t<<","<<mint<<" triangle: "<<PRINT_TRIANGLE( (*hit), (*mpVertices) ) );
|
||||
gfxReal u1=0.0,v1=0.0, t1=-1.0;
|
||||
ray.intersectTriangle( mpVertices, hit, t1,u1,v1);
|
||||
errorOut("Tree second test1 :"<<t1<<" u1:"<<u1<<" v1:"<<v1 );
|
||||
if(t==GFX_REAL_MAX) errorOut( "Tree MAX t " );
|
||||
//errorOut( mpVertices[ (*iter).getPoints()[0] ][0] );
|
||||
}
|
||||
|
||||
//retnormal = -(e2-e0).crossProd(e1-e0); // DEBUG
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
} // flags check
|
||||
}
|
||||
|
||||
/* check if intersection is valid */
|
||||
if( (mint>0.0) && (mint < GFX_REAL_MAX) ) {
|
||||
pos = ray.getOrigin() + ray.getDirection()*mint;
|
||||
|
||||
if( (pos[0] >= curr->min[0]) && (pos[0] <= curr->max[0]) &&
|
||||
(pos[1] >= curr->min[1]) && (pos[1] <= curr->max[1]) &&
|
||||
(pos[2] >= curr->min[2]) && (pos[2] <= curr->max[2]) )
|
||||
{
|
||||
|
||||
if(forceNonsmooth) {
|
||||
// calculate triangle normal
|
||||
ntlVec3Gfx e0,e1,e2;
|
||||
e0 = (*mpVertices)[ hit->getPoints()[0] ];
|
||||
e1 = (*mpVertices)[ hit->getPoints()[1] ];
|
||||
e2 = (*mpVertices)[ hit->getPoints()[2] ];
|
||||
retnormal = cross( -(e2-e0), (e1-e0) );
|
||||
} else {
|
||||
// calculate interpolated normal
|
||||
retnormal = (*mpVertNormals)[ hit->getPoints()[0] ] * (1.0-mintu-mintv)+
|
||||
(*mpVertNormals)[ hit->getPoints()[1] ]*mintu +
|
||||
(*mpVertNormals)[ hit->getPoints()[2] ]*mintv;
|
||||
}
|
||||
normalize(retnormal);
|
||||
normal = retnormal;
|
||||
distance = mint;
|
||||
tri = hit;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
(mpNodeStack->stackPtr)--;
|
||||
curr = mpNodeStack->elem[ mpNodeStack->stackPtr ].node;
|
||||
mindist = mpNodeStack->elem[ mpNodeStack->stackPtr ].mindist;
|
||||
maxdist = mpNodeStack->elem[ mpNodeStack->stackPtr ].maxdist;
|
||||
} /* traverse tree */
|
||||
|
||||
if(mint == GFX_REAL_MAX) {
|
||||
distance = -1.0;
|
||||
} else {
|
||||
if((ray.getRenderglobals())&&(ray.getRenderglobals()->getDebugOut() > 5)) { // DEBUG!!!
|
||||
errorOut("Intersection outside BV ");
|
||||
}
|
||||
|
||||
// intersection outside the BSP bounding volumes might occur due to roundoff...
|
||||
//retnormal = (*mpVertNormals)[ hit->getPoints()[0] ] * (1.0-mintu-mintv)+ (*mpVertNormals)[ hit->getPoints()[1] ]*mintu + (*mpVertNormals)[ hit->getPoints()[2] ]*mintv;
|
||||
if(forceNonsmooth) {
|
||||
// calculate triangle normal
|
||||
ntlVec3Gfx e0,e1,e2;
|
||||
e0 = (*mpVertices)[ hit->getPoints()[0] ];
|
||||
e1 = (*mpVertices)[ hit->getPoints()[1] ];
|
||||
e2 = (*mpVertices)[ hit->getPoints()[2] ];
|
||||
retnormal = cross( -(e2-e0), (e1-e0) );
|
||||
} else {
|
||||
// calculate interpolated normal
|
||||
retnormal = (*mpVertNormals)[ hit->getPoints()[0] ] * (1.0-mintu-mintv)+
|
||||
(*mpVertNormals)[ hit->getPoints()[1] ]*mintu +
|
||||
(*mpVertNormals)[ hit->getPoints()[2] ]*mintv;
|
||||
}
|
||||
|
||||
normalize(retnormal);
|
||||
normal = retnormal;
|
||||
distance = mint;
|
||||
tri = hit;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* distance to plane function for nodes
|
||||
*****************************************************************************/
|
||||
gfxReal ntlTree::distanceToPlane(BSPNode *curr, ntlVec3Gfx plane, ntlRay ray) const
|
||||
{
|
||||
return ( (plane[curr->axis]-ray.getOrigin()[curr->axis]) / ray.getDirection()[curr->axis] );
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* return ordering of children nodes relatice to origin point
|
||||
*****************************************************************************/
|
||||
void ntlTree::getChildren(BSPNode *curr, ntlVec3Gfx origin, BSPNode *&near, BSPNode *&far) const
|
||||
{
|
||||
if(curr->child[0]->max[ curr->axis ] >= origin[ curr->axis ]) {
|
||||
near = curr->child[0];
|
||||
far = curr->child[1];
|
||||
} else {
|
||||
near = curr->child[1];
|
||||
far = curr->child[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* delete a node of the tree with all sub nodes
|
||||
* dont delete root members
|
||||
*****************************************************************************/
|
||||
void ntlTree::deleteNode(BSPNode *curr)
|
||||
{
|
||||
if(!curr) return;
|
||||
|
||||
if(curr->child[0] != NULL)
|
||||
deleteNode(curr->child[0]);
|
||||
if(curr->child[1] != NULL)
|
||||
deleteNode(curr->child[1]);
|
||||
|
||||
if(curr->members != NULL) delete curr->members;
|
||||
delete curr;
|
||||
}
|
||||
|
||||
|
121
intern/elbeem/intern/ntl_bsptree.h
Normal file
121
intern/elbeem/intern/ntl_bsptree.h
Normal file
@ -0,0 +1,121 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* Tree container for fast triangle intersects
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#ifndef NTL_TREE_HH
|
||||
#define NTL_TREE_HH
|
||||
|
||||
#include "ntl_vector3dim.h"
|
||||
#include "ntl_ray.h"
|
||||
#include "ntl_triangle.h"
|
||||
|
||||
|
||||
#define AXIS_X 0
|
||||
#define AXIS_Y 1
|
||||
#define AXIS_Z 2
|
||||
|
||||
#define BSP_STACK_SIZE 50
|
||||
|
||||
|
||||
//! bsp tree stack classes, defined in ntl_bsptree.cpp,
|
||||
// detailed definition unnecesseary here
|
||||
class BSPNode;
|
||||
class BSPStackElement;
|
||||
class BSPStack;
|
||||
class TriangleBBox;
|
||||
|
||||
|
||||
//! Class for a bsp tree for triangles
|
||||
class ntlTree
|
||||
{
|
||||
public:
|
||||
|
||||
//! Default constructor
|
||||
ntlTree();
|
||||
//! Constructor with init
|
||||
ntlTree(int depth, int objnum, ntlScene *scene, int triFlagMask);
|
||||
//! Destructor
|
||||
~ntlTree();
|
||||
|
||||
//! subdivide tree
|
||||
void subdivide(BSPNode *node, int depth, int axis);
|
||||
|
||||
//! intersect ray with BSPtree
|
||||
void intersect(const ntlRay &ray, gfxReal &distance, ntlVec3Gfx &normal, ntlTriangle *&tri, int flags, bool forceNonsmooth) const;
|
||||
|
||||
//! Returns number of nodes
|
||||
int getCurrentNodes( void ) { return mCurrentNodes; }
|
||||
|
||||
protected:
|
||||
|
||||
// check if a triangle is in a node
|
||||
bool checkAABBTriangle(ntlVec3Gfx &min, ntlVec3Gfx &max, ntlTriangle *tri);
|
||||
|
||||
|
||||
// VARs
|
||||
|
||||
//! distance to plane function for nodes
|
||||
gfxReal distanceToPlane(BSPNode *curr, ntlVec3Gfx plane, ntlRay ray) const;
|
||||
|
||||
//! return ordering of children nodes relatice to origin point
|
||||
void getChildren(BSPNode *curr, ntlVec3Gfx origin, BSPNode *&near, BSPNode *&far) const;
|
||||
|
||||
//! delete a node of the tree with all sub nodes, dont delete root members
|
||||
void deleteNode(BSPNode *curr);
|
||||
|
||||
//inline bool isLeaf(BSPNode *node) const { return (node->child[0] == NULL); }
|
||||
|
||||
|
||||
//! AABB for tree
|
||||
ntlVec3Gfx mStart,mEnd;
|
||||
|
||||
//! maximum depth of tree
|
||||
int mMaxDepth;
|
||||
|
||||
//! maximum number of objects in one node
|
||||
int mMaxListLength;
|
||||
|
||||
//! root node pointer
|
||||
BSPNode *mpRoot;
|
||||
|
||||
//! stack for the node pointers
|
||||
BSPStack *mpNodeStack;
|
||||
//stack<BSPNode *> nodestack;
|
||||
|
||||
//! pointer to vertex array
|
||||
vector<ntlVec3Gfx> *mpVertices;
|
||||
|
||||
//! pointer to vertex array
|
||||
vector<ntlVec3Gfx> *mpVertNormals;
|
||||
|
||||
//! vector for all the triangles
|
||||
vector<ntlTriangle> *mpTriangles;
|
||||
vector<ntlTriangle *> *mppTriangles;
|
||||
|
||||
//! temporary array for triangle distribution to nodes
|
||||
char *mpTriDist;
|
||||
|
||||
//! temporary array for triangle bounding boxes
|
||||
TriangleBBox *mpTBB;
|
||||
|
||||
//! triangle mask - include only triangles that match mask
|
||||
int mTriangleMask;
|
||||
|
||||
//! Status vars (max depth, # of current nodes)
|
||||
int mCurrentDepth, mCurrentNodes;
|
||||
|
||||
//! duplicated triangles, inited during subdivide
|
||||
int mTriDoubles;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
302
intern/elbeem/intern/ntl_geometrybox.cpp
Normal file
302
intern/elbeem/intern/ntl_geometrybox.cpp
Normal file
@ -0,0 +1,302 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* A simple box object
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "ntl_geometrybox.h"
|
||||
#include "ntl_ray.h"
|
||||
#include "ntl_scene.h"
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Default Constructor
|
||||
*****************************************************************************/
|
||||
ntlGeometryBox::ntlGeometryBox( void ) :
|
||||
ntlGeometryObject(),
|
||||
mvStart( 0.0 ),
|
||||
mvEnd( 1.0 ),
|
||||
mRefinement(0)
|
||||
{
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Init Constructor
|
||||
*****************************************************************************/
|
||||
/*ntlGeometryBox::ntlGeometryBox( ntlVec3Gfx start, ntlVec3Gfx end ) :
|
||||
ntlGeometryObject(),
|
||||
mvStart( start ),
|
||||
mvEnd( end ),
|
||||
mRefinement(0)
|
||||
{
|
||||
}*/
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Init refinement attribute */
|
||||
/*****************************************************************************/
|
||||
void ntlGeometryBox::initialize(ntlRenderGlobals *glob) {
|
||||
ntlGeometryObject::initialize(glob);
|
||||
//READATTR(ntlGeometryBox, mRefinement, refine, Int, false);
|
||||
mRefinement = mpAttrs->readInt("refine", mRefinement,"ntlGeometryBox", "mRefinement", false);
|
||||
|
||||
checkBoundingBox(mvStart,mvEnd, "ntlGeometryBox::initialize");
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*****************************************************************************/
|
||||
void
|
||||
ntlGeometryBox::getTriangles( vector<ntlTriangle> *triangles,
|
||||
vector<ntlVec3Gfx> *vertices,
|
||||
vector<ntlVec3Gfx> *normals, int objectId )
|
||||
{
|
||||
int doBack = 1;
|
||||
int doFront = 1;
|
||||
int doTop = 1;
|
||||
int doBottom = 1;
|
||||
int doLeft = 1;
|
||||
int doRight = 1;
|
||||
|
||||
/*int mRefinement = 0;
|
||||
string refineAttr("refine");
|
||||
if(mpAttrs->exists(refineAttr)) {
|
||||
mRefinement = mpAttrs->find(refineAttr)->getAsInt();
|
||||
//debugOut("GeoBox Ref set to '"<< mpAttrs->find(refineAttr)->getCompleteString() <<"' " , 3);
|
||||
mpAttrs->find(refineAttr)->setUsed(true);
|
||||
}*/
|
||||
|
||||
if(mRefinement==0) {
|
||||
gfxReal s0 = mvStart[0];
|
||||
gfxReal s1 = mvStart[1];
|
||||
gfxReal s2 = mvStart[2];
|
||||
gfxReal e0 = mvEnd[0];
|
||||
gfxReal e1 = mvEnd[1];
|
||||
gfxReal e2 = mvEnd[2];
|
||||
ntlVec3Gfx p1,p2,p3;
|
||||
ntlVec3Gfx n1,n2,n3;
|
||||
|
||||
/* front plane */
|
||||
if(doFront) {
|
||||
n1 = n2 = n3 = ntlVec3Gfx( 0.0, 0.0, -1.0 );
|
||||
p1 = ntlVec3Gfx( s0, s1, s2 );
|
||||
p3 = ntlVec3Gfx( e0, s1, s2 );
|
||||
p2 = ntlVec3Gfx( s0, e1, s2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
p1 = ntlVec3Gfx( e0, e1, s2 );
|
||||
p3 = ntlVec3Gfx( s0, e1, s2 );
|
||||
p2 = ntlVec3Gfx( e0, s1, s2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
}
|
||||
|
||||
/* back plane k */
|
||||
if(doBack) {
|
||||
n1 = n2 = n3 = ntlVec3Gfx( 0.0, 0.0, 1.0 );
|
||||
p1 = ntlVec3Gfx( s0, s1, e2 );
|
||||
p3 = ntlVec3Gfx( s0, e1, e2 );
|
||||
p2 = ntlVec3Gfx( e0, s1, e2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
p1 = ntlVec3Gfx( s0, e1, e2 );
|
||||
p3 = ntlVec3Gfx( e0, e1, e2 );
|
||||
p2 = ntlVec3Gfx( e0, s1, e2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
}
|
||||
|
||||
/* bottom plane k */
|
||||
if(doBottom) {
|
||||
n1 = n2 = n3 = ntlVec3Gfx( 0.0, -1.0, 0.0 );
|
||||
p1 = ntlVec3Gfx( e0, s1, s2 );
|
||||
p3 = ntlVec3Gfx( s0, s1, s2 );
|
||||
p2 = ntlVec3Gfx( s0, s1, e2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
p1 = ntlVec3Gfx( s0, s1, e2 );
|
||||
p3 = ntlVec3Gfx( e0, s1, e2 );
|
||||
p2 = ntlVec3Gfx( e0, s1, s2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
}
|
||||
|
||||
/* top plane k */
|
||||
if(doTop) {
|
||||
n1 = n2 = n3 = ntlVec3Gfx( 0.0, 1.0, 0.0 );
|
||||
p1 = ntlVec3Gfx( e0, e1, e2 );
|
||||
p2 = ntlVec3Gfx( e0, e1, s2 );
|
||||
p3 = ntlVec3Gfx( s0, e1, e2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
p1 = ntlVec3Gfx( s0, e1, s2 );
|
||||
p2 = ntlVec3Gfx( s0, e1, e2 );
|
||||
p3 = ntlVec3Gfx( e0, e1, s2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
}
|
||||
|
||||
/* left plane k */
|
||||
if(doLeft) {
|
||||
n1 = n2 = n3 = ntlVec3Gfx( -1.0, 0.0, 0.0 );
|
||||
p1 = ntlVec3Gfx( s0, s1, e2 );
|
||||
p3 = ntlVec3Gfx( s0, s1, s2 );
|
||||
p2 = ntlVec3Gfx( s0, e1, s2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
p1 = ntlVec3Gfx( s0, e1, s2 );
|
||||
p3 = ntlVec3Gfx( s0, e1, e2 );
|
||||
p2 = ntlVec3Gfx( s0, s1, e2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
}
|
||||
|
||||
/* right plane k */
|
||||
if(doRight) {
|
||||
n1 = n2 = n3 = ntlVec3Gfx( 1.0, 0.0, 0.0 );
|
||||
p1 = ntlVec3Gfx( e0, e1, e2 );
|
||||
p3 = ntlVec3Gfx( e0, e1, s2 );
|
||||
p2 = ntlVec3Gfx( e0, s1, e2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
p1 = ntlVec3Gfx( e0, e1, s2 );
|
||||
p3 = ntlVec3Gfx( e0, s1, s2 );
|
||||
p2 = ntlVec3Gfx( e0, s1, e2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
}
|
||||
|
||||
} else {
|
||||
// refined box
|
||||
gfxReal S0 = mvStart[0];
|
||||
gfxReal S1 = mvStart[1];
|
||||
gfxReal S2 = mvStart[2];
|
||||
gfxReal v0 = (mvEnd[0]-mvStart[0])/(gfxReal)(mRefinement+1);
|
||||
gfxReal v1 = (mvEnd[1]-mvStart[1])/(gfxReal)(mRefinement+1);
|
||||
gfxReal v2 = (mvEnd[2]-mvStart[2])/(gfxReal)(mRefinement+1);
|
||||
ntlVec3Gfx p1,p2,p3;
|
||||
ntlVec3Gfx n1,n2,n3;
|
||||
|
||||
for(int i=0; i<=mRefinement; i++)
|
||||
for(int j=0; j<=mRefinement; j++) {
|
||||
gfxReal s0 = S0 + i*v0;
|
||||
gfxReal s1 = S1 + j*v1;
|
||||
gfxReal s2 = S2;
|
||||
gfxReal e0 = S0 + (i+1.0)*v0;
|
||||
gfxReal e1 = S1 + (j+1.0)*v1;
|
||||
/* front plane */
|
||||
if(doFront) {
|
||||
n1 = n2 = n3 = ntlVec3Gfx( 0.0, 0.0, -1.0 );
|
||||
p1 = ntlVec3Gfx( s0, s1, s2 );
|
||||
p3 = ntlVec3Gfx( e0, s1, s2 );
|
||||
p2 = ntlVec3Gfx( s0, e1, s2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
p1 = ntlVec3Gfx( e0, e1, s2 );
|
||||
p3 = ntlVec3Gfx( s0, e1, s2 );
|
||||
p2 = ntlVec3Gfx( e0, s1, s2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
}
|
||||
} // i,j
|
||||
for(int i=0; i<=mRefinement; i++)
|
||||
for(int j=0; j<=mRefinement; j++) {
|
||||
gfxReal s0 = S0 + i*v0;
|
||||
gfxReal s1 = S1 + j*v1;
|
||||
gfxReal e0 = S0 + (i+1.0)*v0;
|
||||
gfxReal e1 = S1 + (j+1.0)*v1;
|
||||
gfxReal e2 = S2 + (mRefinement+1.0)*v2;
|
||||
/* back plane k */
|
||||
if(doBack) {
|
||||
n1 = n2 = n3 = ntlVec3Gfx( 0.0, 0.0, 1.0 );
|
||||
p1 = ntlVec3Gfx( s0, s1, e2 );
|
||||
p3 = ntlVec3Gfx( s0, e1, e2 );
|
||||
p2 = ntlVec3Gfx( e0, s1, e2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
p1 = ntlVec3Gfx( s0, e1, e2 );
|
||||
p3 = ntlVec3Gfx( e0, e1, e2 );
|
||||
p2 = ntlVec3Gfx( e0, s1, e2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<=mRefinement; i++)
|
||||
for(int j=0; j<=mRefinement; j++) {
|
||||
|
||||
gfxReal s0 = S0 + i*v0;
|
||||
gfxReal s1 = S1;
|
||||
gfxReal s2 = S2 + j*v2;
|
||||
gfxReal e0 = S0 + (i+1.0)*v0;
|
||||
gfxReal e2 = S2 + (j+1.0)*v2;
|
||||
/* bottom plane k */
|
||||
if(doBottom) {
|
||||
n1 = n2 = n3 = ntlVec3Gfx( 0.0, -1.0, 0.0 );
|
||||
p1 = ntlVec3Gfx( e0, s1, s2 );
|
||||
p3 = ntlVec3Gfx( s0, s1, s2 );
|
||||
p2 = ntlVec3Gfx( s0, s1, e2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
p1 = ntlVec3Gfx( s0, s1, e2 );
|
||||
p3 = ntlVec3Gfx( e0, s1, e2 );
|
||||
p2 = ntlVec3Gfx( e0, s1, s2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<=mRefinement; i++)
|
||||
for(int j=0; j<=mRefinement; j++) {
|
||||
|
||||
gfxReal s0 = S0 + i*v0;
|
||||
gfxReal s2 = S2 + j*v2;
|
||||
gfxReal e0 = S0 + (i+1.0)*v0;
|
||||
gfxReal e1 = S1 + (mRefinement+1.0)*v1;
|
||||
gfxReal e2 = S2 + (j+1.0)*v2;
|
||||
/* top plane k */
|
||||
if(doTop) {
|
||||
n1 = n2 = n3 = ntlVec3Gfx( 0.0, 1.0, 0.0 );
|
||||
p1 = ntlVec3Gfx( e0, e1, e2 );
|
||||
p2 = ntlVec3Gfx( e0, e1, s2 );
|
||||
p3 = ntlVec3Gfx( s0, e1, e2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
p1 = ntlVec3Gfx( s0, e1, s2 );
|
||||
p2 = ntlVec3Gfx( s0, e1, e2 );
|
||||
p3 = ntlVec3Gfx( e0, e1, s2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<=mRefinement; i++)
|
||||
for(int j=0; j<=mRefinement; j++) {
|
||||
gfxReal s0 = S0;
|
||||
gfxReal s1 = S1 + i*v1;
|
||||
gfxReal s2 = S2 + j*v2;
|
||||
gfxReal e1 = S1 + (i+1.0)*v1;
|
||||
gfxReal e2 = S2 + (j+1.0)*v2;
|
||||
/* left plane k */
|
||||
if(doLeft) {
|
||||
n1 = n2 = n3 = ntlVec3Gfx( -1.0, 0.0, 0.0 );
|
||||
p1 = ntlVec3Gfx( s0, s1, e2 );
|
||||
p3 = ntlVec3Gfx( s0, s1, s2 );
|
||||
p2 = ntlVec3Gfx( s0, e1, s2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
p1 = ntlVec3Gfx( s0, e1, s2 );
|
||||
p3 = ntlVec3Gfx( s0, e1, e2 );
|
||||
p2 = ntlVec3Gfx( s0, s1, e2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<=mRefinement; i++)
|
||||
for(int j=0; j<=mRefinement; j++) {
|
||||
gfxReal s1 = S1 + i*v1;
|
||||
gfxReal s2 = S2 + j*v2;
|
||||
gfxReal e0 = S0 + (mRefinement+1.0)*v0;
|
||||
gfxReal e1 = S1 + (i+1.0)*v1;
|
||||
gfxReal e2 = S2 + (j+1.0)*v2;
|
||||
/* right plane k */
|
||||
if(doRight) {
|
||||
n1 = n2 = n3 = ntlVec3Gfx( 1.0, 0.0, 0.0 );
|
||||
p1 = ntlVec3Gfx( e0, e1, e2 );
|
||||
p3 = ntlVec3Gfx( e0, e1, s2 );
|
||||
p2 = ntlVec3Gfx( e0, s1, e2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
p1 = ntlVec3Gfx( e0, e1, s2 );
|
||||
p3 = ntlVec3Gfx( e0, s1, s2 );
|
||||
p2 = ntlVec3Gfx( e0, s1, e2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
}
|
||||
}
|
||||
|
||||
} // do ref
|
||||
|
||||
}
|
||||
|
||||
|
63
intern/elbeem/intern/ntl_geometrybox.h
Normal file
63
intern/elbeem/intern/ntl_geometrybox.h
Normal file
@ -0,0 +1,63 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* A simple box object
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef NTL_GEOBOX_HH
|
||||
#define NTL_GEOBOX_HH
|
||||
|
||||
#include "ntl_geometryobject.h"
|
||||
|
||||
|
||||
/*! A simple box object generatedd by 12 triangles */
|
||||
class ntlGeometryBox : public ntlGeometryObject
|
||||
{
|
||||
|
||||
public:
|
||||
/* Init constructor */
|
||||
ntlGeometryBox( void );
|
||||
/* Init constructor */
|
||||
//ntlGeometryBox( ntlVec3Gfx start, ntlVec3Gfx end );
|
||||
|
||||
//! Return type id
|
||||
virtual int getTypeId() { return GEOCLASSTID_BOX; }
|
||||
|
||||
virtual void getTriangles( vector<ntlTriangle> *triangles,
|
||||
vector<ntlVec3Gfx> *vertices,
|
||||
vector<ntlVec3Gfx> *normals, int objectId );
|
||||
|
||||
/*! for easy GUI detection get start of axis aligned bounding box, return NULL of no BB */
|
||||
virtual inline ntlVec3Gfx *getBBStart() { return &mvStart; }
|
||||
virtual inline ntlVec3Gfx *getBBEnd() { return &mvEnd; }
|
||||
|
||||
/*! Init refinement attribute */
|
||||
virtual void initialize(ntlRenderGlobals *glob);
|
||||
|
||||
private:
|
||||
|
||||
/*! Start and end points of box */
|
||||
ntlVec3Gfx mvStart, mvEnd;
|
||||
|
||||
/*! refinement factor */
|
||||
int mRefinement;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/* Access methods */
|
||||
/*! Access start vector */
|
||||
inline ntlVec3Gfx getStart( void ){ return mvStart; }
|
||||
inline void setStart( const ntlVec3Gfx &set ){ mvStart = set; }
|
||||
/*! Access end vector */
|
||||
inline ntlVec3Gfx getEnd( void ){ return mvEnd; }
|
||||
inline void setEnd( const ntlVec3Gfx &set ){ mvEnd = set; }
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
92
intern/elbeem/intern/ntl_geometryclass.h
Normal file
92
intern/elbeem/intern/ntl_geometryclass.h
Normal file
@ -0,0 +1,92 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* Base class for geometry shaders and objects
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#ifndef NTL_GEOMETRYCLASS_H
|
||||
#define NTL_GEOMETRYCLASS_H
|
||||
|
||||
#include "attributes.h"
|
||||
|
||||
//! geometry class type ids
|
||||
#define GEOCLASSTID_OBJECT 1
|
||||
#define GEOCLASSTID_SHADER 2
|
||||
#define GEOCLASSTID_BOX (GEOCLASSTID_OBJECT| 4)
|
||||
#define GEOCLASSTID_OBJMODEL (GEOCLASSTID_OBJECT| 8)
|
||||
#define GEOCLASSTID_SPHERE (GEOCLASSTID_OBJECT| 16)
|
||||
|
||||
class ntlGeometryClass
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//! Default constructor
|
||||
inline ntlGeometryClass() :
|
||||
mVisible( 1 ), mName( "[ObjNameUndef]" ),
|
||||
mpAttrs( NULL )
|
||||
{
|
||||
mpAttrs = new AttributeList("objAttrs");
|
||||
};
|
||||
|
||||
//! Default destructor
|
||||
virtual ~ntlGeometryClass() {
|
||||
delete mpAttrs;
|
||||
};
|
||||
|
||||
//! Return type id
|
||||
virtual int getTypeId() = 0;
|
||||
|
||||
/*! Set the object name */
|
||||
inline void setName(string set) { mName = set; }
|
||||
/*! Get the object name */
|
||||
inline string getName( void ) { return mName; }
|
||||
|
||||
/*! Sets the visibility attribute
|
||||
* visibility can be determined at shader _and_ object level , hiding a shader
|
||||
* means comepletely decativating it */
|
||||
inline void setVisible(int set) { mVisible=set; }
|
||||
/*! Returns the visibility attribute */
|
||||
inline int getVisible() const { return mVisible; }
|
||||
|
||||
/*! Sets the attribute list pointer */
|
||||
inline void setAttributeList(AttributeList *set) { mpAttrs=set; }
|
||||
/*! Returns the attribute list pointer */
|
||||
inline AttributeList *getAttributeList() { return mpAttrs; }
|
||||
|
||||
/*! for easy GUI detection get start of axis aligned bounding box, return NULL of no BB */
|
||||
virtual inline ntlVec3Gfx *getBBStart() { return NULL; }
|
||||
virtual inline ntlVec3Gfx *getBBEnd() { return NULL; }
|
||||
|
||||
/*! GUI - this function is called for selected objects to display debugging information with OpenGL */
|
||||
virtual void drawDebugDisplay() { /* do nothing by default */ }
|
||||
/*! GUI - this function is called for selected objects to display interactive information with OpenGL */
|
||||
virtual void drawInteractiveDisplay() { /* do nothing by default */ }
|
||||
/*! GUI - handle mouse movement for selection */
|
||||
virtual void setMousePos(int ,int , ntlVec3Gfx , ntlVec3Gfx ) { /* do nothing by default */ }
|
||||
/*! GUI - notify object that mouse was clicked at last pos */
|
||||
virtual void setMouseClick() { /* do nothing by default */ }
|
||||
|
||||
protected:
|
||||
|
||||
/*! Object visible on/off */
|
||||
int mVisible;
|
||||
|
||||
/*! Name of this object */
|
||||
string mName;
|
||||
|
||||
/*! configuration attributes */
|
||||
AttributeList *mpAttrs;
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
204
intern/elbeem/intern/ntl_geometrymodel.cpp
Normal file
204
intern/elbeem/intern/ntl_geometrymodel.cpp
Normal file
@ -0,0 +1,204 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* A simple box object
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "ntl_geometrymodel.h"
|
||||
#include "ntl_ray.h"
|
||||
#include "ntl_scene.h"
|
||||
#include "zlib.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#ifndef strncasecmp
|
||||
#define strncasecmp(a,b,c) strcmp(a,b)
|
||||
#endif
|
||||
#endif // WIN32
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Default Constructor
|
||||
*****************************************************************************/
|
||||
ntlGeometryObjModel::ntlGeometryObjModel( void ) :
|
||||
ntlGeometryObject(),
|
||||
mvStart( 0.0 ), mvEnd( 1.0 ),
|
||||
mLoaded( false ),
|
||||
mTriangles(), mVertices(), mNormals()
|
||||
{
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Destructor
|
||||
*****************************************************************************/
|
||||
ntlGeometryObjModel::~ntlGeometryObjModel()
|
||||
{
|
||||
if(!mLoaded) {
|
||||
errMsg("ntlGeometryObjModel","delete obj...");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Init attributes etc. of this object */
|
||||
/*****************************************************************************/
|
||||
void ntlGeometryObjModel::initialize(ntlRenderGlobals *glob)
|
||||
{
|
||||
ntlGeometryObject::initialize(glob);
|
||||
mFilename = mpAttrs->readString("filename", mFilename,"ntlGeometryObjModel", "mFilename", true);
|
||||
|
||||
if(mFilename == "") {
|
||||
errMsg("ntlGeometryObjModel::getTriangles","Filename not given!");
|
||||
return;
|
||||
}
|
||||
|
||||
const char *suffix = strrchr(mFilename.c_str(), '.');
|
||||
if (suffix) {
|
||||
if (!strncasecmp(suffix, ".obj", 4)) {
|
||||
errMsg("ntlGeometryObjModel::getTriangles",".obj files not supported!");
|
||||
return;
|
||||
} else if (!strncasecmp(suffix, ".gz", 3)) {
|
||||
//mType = 1; // assume its .bobj.gz
|
||||
} else if (!strncasecmp(suffix, ".bobj", 5)) {
|
||||
//mType = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// continue with standard obj
|
||||
if(loadBobjModel(mFilename)==0) mLoaded=1;
|
||||
if(!mLoaded) {
|
||||
debMsgStd("ntlGeometryObjModel",DM_WARNING,"Unable to load object file '"<<mFilename<<"' !", 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* defines */
|
||||
#define T(x) model->triangles[(x)]
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*****************************************************************************/
|
||||
void
|
||||
ntlGeometryObjModel::getTriangles( vector<ntlTriangle> *triangles,
|
||||
vector<ntlVec3Gfx> *vertices,
|
||||
vector<ntlVec3Gfx> *normals, int objectId )
|
||||
{
|
||||
if(!mLoaded) { // invalid type...
|
||||
return;
|
||||
}
|
||||
|
||||
for(int i=0; i<(int)mTriangles.size(); i+=3) {
|
||||
int trip[3];
|
||||
trip[0] = mTriangles[i+0];
|
||||
trip[1] = mTriangles[i+1];
|
||||
trip[2] = mTriangles[i+2];
|
||||
sceneAddTriangle(
|
||||
mVertices[trip[0]], mVertices[trip[1]], mVertices[trip[2]],
|
||||
mNormals[trip[0]], mNormals[trip[1]], mNormals[trip[2]],
|
||||
ntlVec3Gfx(0.0), 1 ); /* normal unused */
|
||||
}
|
||||
// bobj
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* load model from .obj file
|
||||
*****************************************************************************/
|
||||
|
||||
int ntlGeometryObjModel::loadBobjModel(string filename)
|
||||
{
|
||||
const bool debugPrint=false;
|
||||
gzFile gzf;
|
||||
gzf = gzopen(filename.c_str(), "rb");
|
||||
if (!gzf) {
|
||||
errMsg("ntlGeometryObjModel::loadBobjModel","Reading GZ_BOBJ, Unable to open '"<< filename <<"'...\n" );
|
||||
#if ELBEEM_BLENDER==1
|
||||
exit(1);
|
||||
#else // ELBEEM_BLENDER==1
|
||||
return 1;
|
||||
#endif // ELBEEM_BLENDER==1
|
||||
}
|
||||
|
||||
int wri;
|
||||
int gotbytes = -1;
|
||||
gotbytes = gzread(gzf, &wri, sizeof(wri) );
|
||||
if(gotbytes != sizeof(int)){ errMsg("Reading GZ_BOBJ"," Invalid readNV size "<< wri); goto gzreaderror; }
|
||||
if(sizeof(wri)!=4) { // paranoia check
|
||||
errMsg("Reading GZ_BOBJ"," Invalid int size "<< wri);
|
||||
goto gzreaderror;
|
||||
}
|
||||
if(wri<0 || wri>1e9) {
|
||||
errMsg("Reading GZ_BOBJ"," invalid num vertices "<< wri);
|
||||
goto gzreaderror;
|
||||
}
|
||||
mVertices.clear();
|
||||
mVertices.resize( wri );
|
||||
for(int i=0; i<wri; i++) {
|
||||
float x[3];
|
||||
for(int j=0; j<3; j++) {
|
||||
gotbytes = gzread(gzf, &(x[j]), sizeof( (x[j]) ) );
|
||||
if(gotbytes != sizeof(float)){ errMsg("Reading GZ_BOBJ"," Invalid readV size "<< wri); goto gzreaderror; } // CHECK
|
||||
}
|
||||
mVertices[i] = ntlVec3Gfx(x[0],x[1],x[2]);
|
||||
}
|
||||
if(debugPrint) errMsg("NV"," "<<wri<<" "<< mVertices.size() );
|
||||
|
||||
// should be the same as Vertices.size
|
||||
gotbytes = gzread(gzf, &wri, sizeof(wri) );
|
||||
if(gotbytes != sizeof(int)){ errMsg("Reading GZ_BOBJ","Invalid readNN size "<< wri); goto gzreaderror; }
|
||||
if(wri<0 || wri>1e9) {
|
||||
errMsg("Reading GZ_BOBJ","invalid num normals "<< wri);
|
||||
goto gzreaderror;
|
||||
}
|
||||
mNormals.clear();
|
||||
mNormals.resize( wri );
|
||||
for(int i=0; i<wri; i++) {
|
||||
float n[3];
|
||||
for(int j=0; j<3; j++) {
|
||||
gotbytes = gzread(gzf, &(n[j]), sizeof( (n[j]) ) );
|
||||
if(gotbytes != sizeof(float)){ errMsg("Reading GZ_BOBJ","Invalid readN size "<< wri); goto gzreaderror; }
|
||||
}
|
||||
mNormals[i] = ntlVec3Gfx(n[0],n[1],n[2]);
|
||||
}
|
||||
if(debugPrint) errMsg("NN"," "<<wri<<" "<< mNormals.size() );
|
||||
|
||||
gotbytes = gzread(gzf, &wri, sizeof(wri) );
|
||||
if(gotbytes != sizeof(int)){ errMsg("Reading GZ_BOBJ","Invalid readNT size "<< wri); goto gzreaderror; }
|
||||
if(wri<0 || wri>1e9) {
|
||||
errMsg("Reading GZ_BOBJ","invalid num normals "<< wri);
|
||||
goto gzreaderror;
|
||||
}
|
||||
mTriangles.resize( 3*wri );
|
||||
for(int i=0; i<wri; i++) {
|
||||
int tri[3];
|
||||
for(int j=0; j<3; j++) {
|
||||
gotbytes = gzread(gzf, &(tri[j]), sizeof( (tri[j]) ) );
|
||||
if(gotbytes != sizeof(int)){ errMsg("Reading GZ_BOBJ","Invalid readT size "<< wri); goto gzreaderror; }
|
||||
}
|
||||
mTriangles[3*i+0] = tri[0];
|
||||
mTriangles[3*i+1] = tri[1];
|
||||
mTriangles[3*i+2] = tri[2];
|
||||
}
|
||||
if(debugPrint) errMsg("NT"," "<<wri<<" "<< mTriangles.size() );
|
||||
|
||||
debMsgStd("ntlGeometryObjModel::loadBobjModel",DM_MSG, "File '"<<filename<<"' loaded, #Vertices: "<<mVertices.size()<<", #Normals: "<<mNormals.size()<<", #Triangles: "<<(mTriangles.size()/3)<<" ", 1 );
|
||||
|
||||
gzclose( gzf );
|
||||
return 0;
|
||||
gzreaderror:
|
||||
gzclose( gzf );
|
||||
#if ELBEEM_BLENDER==1
|
||||
errMsg("ntlGeometryObjModel::loadBobjModel","Reading GZ_BOBJ, Unable to load '"<< filename <<"', exiting...\n" );
|
||||
exit(1);
|
||||
#else // ELBEEM_BLENDER==1
|
||||
return 1;
|
||||
#endif // ELBEEM_BLENDER==1
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
71
intern/elbeem/intern/ntl_geometrymodel.h
Normal file
71
intern/elbeem/intern/ntl_geometrymodel.h
Normal file
@ -0,0 +1,71 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* A model laoded from Wavefront .obj file
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef NTL_GEOMODEL_H
|
||||
#define NTL_GEOMODEL_H
|
||||
|
||||
#include "ntl_geometryobject.h"
|
||||
|
||||
/*! A simple box object generatedd by 12 triangles */
|
||||
class ntlGeometryObjModel : public ntlGeometryObject
|
||||
{
|
||||
public:
|
||||
/* Init constructor */
|
||||
ntlGeometryObjModel( void );
|
||||
/* Init constructor */
|
||||
//ntlGeometryObjModel( ntlVec3Gfx start, ntlVec3Gfx end );
|
||||
/* Destructor */
|
||||
virtual ~ntlGeometryObjModel( void );
|
||||
|
||||
//! Return type id
|
||||
virtual int getTypeId() { return GEOCLASSTID_OBJMODEL; }
|
||||
|
||||
/*! Filename setting etc. */
|
||||
virtual void initialize(ntlRenderGlobals *glob);
|
||||
|
||||
|
||||
/* create triangles from obj */
|
||||
virtual void getTriangles( vector<ntlTriangle> *triangles,
|
||||
vector<ntlVec3Gfx> *vertices,
|
||||
vector<ntlVec3Gfx> *normals, int objectId );
|
||||
|
||||
/*! load model from .bobj file, returns !=0 upon error */
|
||||
int loadBobjModel(string filename);
|
||||
|
||||
private:
|
||||
|
||||
/*! Start and end points of box */
|
||||
ntlVec3Gfx mvStart, mvEnd;
|
||||
|
||||
/*! was the model loaded? */
|
||||
bool mLoaded;
|
||||
|
||||
/*! filename of the obj file */
|
||||
string mFilename;
|
||||
|
||||
/*! for bobj models */
|
||||
vector<int> mTriangles;
|
||||
vector<ntlVec3Gfx> mVertices;
|
||||
vector<ntlVec3Gfx> mNormals;
|
||||
|
||||
public:
|
||||
|
||||
/* Access methods */
|
||||
/*! Access start vector */
|
||||
inline ntlVec3Gfx getStart( void ){ return mvStart; }
|
||||
inline void setStart( const ntlVec3Gfx &set ){ mvStart = set; }
|
||||
/*! Access end vector */
|
||||
inline ntlVec3Gfx getEnd( void ){ return mvEnd; }
|
||||
inline void setEnd( const ntlVec3Gfx &set ){ mvEnd = set; }
|
||||
|
||||
/*! set data file name */
|
||||
inline void setFilename(string set) { mFilename = set; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
128
intern/elbeem/intern/ntl_geometryobject.cpp
Normal file
128
intern/elbeem/intern/ntl_geometryobject.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* a geometry object
|
||||
* all other geometry objects are derived from this one
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#include "ntl_geometryobject.h"
|
||||
#include "ntl_renderglobals.h"
|
||||
|
||||
// for FGI
|
||||
#include "ntl_scene.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Default constructor */
|
||||
/*****************************************************************************/
|
||||
ntlGeometryObject::ntlGeometryObject() :
|
||||
mpMaterial( NULL ),
|
||||
mMaterialName( "default" ),
|
||||
mCastShadows( 1 ),
|
||||
mReceiveShadows( 1 ),
|
||||
mGeoInitId( -1 ), mGeoInitType( 0 ),
|
||||
mInitialVelocity(0.0),
|
||||
mGeoInitIntersect(false)
|
||||
{
|
||||
};
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Default destructor */
|
||||
/*****************************************************************************/
|
||||
ntlGeometryObject::~ntlGeometryObject()
|
||||
{
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Init attributes etc. of this object */
|
||||
/*****************************************************************************/
|
||||
void ntlGeometryObject::initialize(ntlRenderGlobals *glob)
|
||||
{
|
||||
//debugOut("ntlGeometryObject::initialize: '"<<getName()<<"' ", 10);
|
||||
|
||||
mGeoInitId = mpAttrs->readInt("geoinitid", mGeoInitId,"ntlGeometryObject", "mGeoInitId", false);
|
||||
mGeoInitIntersect = mpAttrs->readInt("geoinit_intersect", mGeoInitIntersect,"ntlGeometryObject", "mGeoInitIntersect", false);
|
||||
if(mGeoInitId>=0) {
|
||||
string initStr = mpAttrs->readString("geoinittype", "", "ntlGeometryObject", "mGeoInitType", false);
|
||||
if(initStr== "fluid") {
|
||||
mGeoInitType = FGI_FLUID;
|
||||
} else
|
||||
if((initStr== "bnd_no") || (initStr=="bnd_noslip")) {
|
||||
mGeoInitType = FGI_BNDNO;
|
||||
} else
|
||||
if((initStr== "bnd_free") || (initStr=="bnd_freeslip")) {
|
||||
mGeoInitType = FGI_BNDFREE;
|
||||
} else
|
||||
if((initStr== "acc") || (initStr=="accelerator")) {
|
||||
mGeoInitType = FGI_ACC;
|
||||
ntlVec3d force = mpAttrs->readVec3d("geoinitforce", ntlVec3d(0.0), "ntlGeometryObject", "mGeoInitForce", true);
|
||||
errMsg("ntlGeometryObject::initialize","Deprectated acc object used!"); exit(1);
|
||||
} else
|
||||
if((initStr== "set") || (initStr=="speedset")) {
|
||||
mGeoInitType = FGI_SPEEDSET;
|
||||
ntlVec3d force = mpAttrs->readVec3d("geoinitforce", ntlVec3d(0.0), "ntlGeometryObject", "mGeoInitForce", true);
|
||||
errMsg("ntlGeometryObject::initialize","Deprectated speedset object used!"); exit(1);
|
||||
} else
|
||||
// not so nice - define refinement types...
|
||||
if(initStr== "p1") {
|
||||
mGeoInitType = FGI_REFP1;
|
||||
} else
|
||||
if(initStr== "p2") {
|
||||
mGeoInitType = FGI_REFP2;
|
||||
} else
|
||||
if(initStr== "p3") {
|
||||
mGeoInitType = FGI_REFP3;
|
||||
// nothing found
|
||||
} else {
|
||||
errorOut("ntlGeometryObject::initialize error: Unkown 'geoinittype' value: '"<< initStr <<"' ");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int geoActive = mpAttrs->readInt("geoinitactive", 1,"ntlGeometryObject", "mGeoInitId", false);
|
||||
if(!geoActive) {
|
||||
// disable geo init again...
|
||||
mGeoInitId = -1;
|
||||
}
|
||||
mInitialVelocity = vec2G( mpAttrs->readVec3d("initial_velocity", vec2D(mInitialVelocity),"ntlGeometryObject", "mInitialVelocity", false));
|
||||
|
||||
// override cfg types
|
||||
mVisible = mpAttrs->readBool("visible", mVisible,"ntlGeometryObject", "mVisible", false);
|
||||
mReceiveShadows = mpAttrs->readBool("recv_shad", mReceiveShadows,"ntlGeometryObject", "mReceiveShadows", false);
|
||||
mCastShadows = mpAttrs->readBool("cast_shad", mCastShadows,"ntlGeometryObject", "mCastShadows", false);
|
||||
|
||||
// init material
|
||||
searchMaterial( glob->getMaterials() );
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Search the material for this object from the material list */
|
||||
/*****************************************************************************/
|
||||
void ntlGeometryObject::searchMaterial(vector<ntlMaterial *> *mat)
|
||||
{
|
||||
//errorOut("my: "<<mMaterialName); // DEBUG
|
||||
/* search the list... */
|
||||
int i=0;
|
||||
for (vector<ntlMaterial*>::iterator iter = mat->begin();
|
||||
iter != mat->end(); iter++) {
|
||||
//if(strcmp(mMaterialName, (*iter)->getName()) == 0) { // DEBUG
|
||||
if( mMaterialName == (*iter)->getName() ) {
|
||||
//warnMsg("ntlGeometryObject::searchMaterial","for obj '"<<getName()<<"' found - '"<<(*iter)->getName()<<"' "<<i); // DEBUG
|
||||
mpMaterial = (*iter);
|
||||
return;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
errMsg("ntlGeometryObject::searchMaterial","Unknown material '"<<mMaterialName<<"' ! ");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
|
104
intern/elbeem/intern/ntl_geometryobject.h
Normal file
104
intern/elbeem/intern/ntl_geometryobject.h
Normal file
@ -0,0 +1,104 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* a geometry object
|
||||
* all other geometry objects are derived from this one
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef NTL_GEOMETRYOBJECT_HH
|
||||
|
||||
#include "ntl_geometryclass.h"
|
||||
#include "ntl_material.h"
|
||||
#include "ntl_triangle.h"
|
||||
class ntlRay;
|
||||
class ntlRenderGlobals;
|
||||
|
||||
|
||||
class ntlGeometryObject : public ntlGeometryClass
|
||||
{
|
||||
|
||||
public:
|
||||
//! Default constructor
|
||||
ntlGeometryObject();
|
||||
//! Default destructor
|
||||
virtual ~ntlGeometryObject();
|
||||
|
||||
//! Return type id
|
||||
virtual int getTypeId() { return GEOCLASSTID_OBJECT; }
|
||||
|
||||
/*! Get the triangles from this object */
|
||||
virtual void getTriangles( vector<ntlTriangle> *triangles,
|
||||
vector<ntlVec3Gfx> *vertices,
|
||||
vector<ntlVec3Gfx> *normals, int objectId ) = 0;
|
||||
|
||||
/*! Init attributes etc. of this object */
|
||||
virtual void initialize(ntlRenderGlobals *glob);
|
||||
|
||||
/*! Search the material for this object from the material list */
|
||||
void searchMaterial(vector<ntlMaterial *> *mat);
|
||||
|
||||
/* Acces methods */
|
||||
/*! Set the property of this object */
|
||||
inline void setMaterial(ntlMaterial *p) { mpMaterial = p; }
|
||||
/*! Get the surface property of this object */
|
||||
inline ntlMaterial *getMaterial( void ) { return mpMaterial; }
|
||||
/*! Set the object property name */
|
||||
inline void setMaterialName(string set) { mMaterialName = set; }
|
||||
/*! Get the object property name */
|
||||
inline string getMaterialName( void ) { return mMaterialName; }
|
||||
|
||||
/*! Sets the receive shadows attribute */
|
||||
inline void setReceiveShadows(int set) { mReceiveShadows=set; }
|
||||
/*! Returns the receive shadows attribute */
|
||||
inline int getReceiveShadows() const { return mReceiveShadows; }
|
||||
|
||||
/*! Sets the cast shadows attribute */
|
||||
inline void setCastShadows(int set) { mCastShadows=set; }
|
||||
/*! Returns the cast shadows attribute */
|
||||
inline int getCastShadows() const { return mCastShadows; }
|
||||
|
||||
/*! Returns the geo init id */
|
||||
inline int getGeoInitId() const { return mGeoInitId; }
|
||||
/*! Returns the geo init typ */
|
||||
inline int getGeoInitType() const { return mGeoInitType; }
|
||||
|
||||
/*! Set/get the cast initial veocity attribute */
|
||||
inline void setInitialVelocity(ntlVec3Gfx set) { mInitialVelocity=set; }
|
||||
inline ntlVec3Gfx getInitialVelocity() const { return mInitialVelocity; }
|
||||
|
||||
/*! Set/get the intersect init flag */
|
||||
inline bool getGeoInitIntersect() const { return mGeoInitIntersect; }
|
||||
inline void setGeoInitIntersect(bool set) { mGeoInitIntersect=set; }
|
||||
|
||||
protected:
|
||||
|
||||
/*! Point to a property object describing the surface of this object */
|
||||
ntlMaterial *mpMaterial;
|
||||
|
||||
/*! Name of the surcace property */
|
||||
string mMaterialName;
|
||||
|
||||
/*! Cast shadows on/off */
|
||||
int mCastShadows;
|
||||
/*! REceive shadows on/off */
|
||||
int mReceiveShadows;
|
||||
|
||||
/* fluid init data */
|
||||
/*! id of fluid init (is used in solver initialization) */
|
||||
int mGeoInitId;
|
||||
/*! fluid object type (fluid, obstacle, accelerator etc.) */
|
||||
int mGeoInitType;
|
||||
/*! initial velocity for fluid objects */
|
||||
ntlVec3Gfx mInitialVelocity;
|
||||
/*! perform more accurate intersecting geo init for this object? */
|
||||
bool mGeoInitIntersect;
|
||||
|
||||
public:
|
||||
|
||||
};
|
||||
|
||||
#define NTL_GEOMETRYOBJECT_HH
|
||||
#endif
|
||||
|
50
intern/elbeem/intern/ntl_geometryshader.h
Normal file
50
intern/elbeem/intern/ntl_geometryshader.h
Normal file
@ -0,0 +1,50 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* Interface for a geometry shader
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef NTL_GEOMETRYSHADER_H
|
||||
#define NTL_GEOMETRYSHADER_H
|
||||
|
||||
#include "ntl_geometryclass.h"
|
||||
class ntlGeometryObject;
|
||||
class ntlRenderGlobals;
|
||||
|
||||
class ntlGeometryShader :
|
||||
public ntlGeometryClass
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//! Default constructor
|
||||
inline ntlGeometryShader() :
|
||||
ntlGeometryClass() {};
|
||||
//! Default destructor
|
||||
virtual ~ntlGeometryShader() {};
|
||||
|
||||
//! Return type id
|
||||
virtual int getTypeId() { return GEOCLASSTID_SHADER; }
|
||||
|
||||
/*! Initialize object, should return !=0 upon error */
|
||||
virtual int initializeShader() = 0;
|
||||
|
||||
/*! Do further object initialization after all geometry has been constructed, should return !=0 upon error */
|
||||
virtual int postGeoConstrInit(ntlRenderGlobals *glob) { return 0; };
|
||||
|
||||
/*! Get start iterator for all objects */
|
||||
virtual std::vector<ntlGeometryObject *>::iterator getObjectsBegin() { return mObjects.begin(); }
|
||||
/*! Get end iterator for all objects */
|
||||
virtual std::vector<ntlGeometryObject *>::iterator getObjectsEnd() { return mObjects.end(); }
|
||||
|
||||
protected:
|
||||
|
||||
//! vector for the objects
|
||||
std::vector<ntlGeometryObject *> mObjects;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
229
intern/elbeem/intern/ntl_geometrysphere.cpp
Normal file
229
intern/elbeem/intern/ntl_geometrysphere.cpp
Normal file
@ -0,0 +1,229 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* A simple sphere object
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "ntl_geometrysphere.h"
|
||||
#include "ntl_ray.h"
|
||||
#include "ntl_scene.h"
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Default Constructor
|
||||
*****************************************************************************/
|
||||
ntlGeometrySphere::ntlGeometrySphere() :
|
||||
ntlGeometryObject(),
|
||||
mvCenter( 0.0 ),
|
||||
mRadius( 1.0 ),
|
||||
mRefPolar(5), mRefAzim(5)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Init attributes */
|
||||
/*****************************************************************************/
|
||||
void ntlGeometrySphere::initialize(ntlRenderGlobals *glob) {
|
||||
ntlGeometryObject::initialize(glob);
|
||||
|
||||
mvCenter = vec2G(mpAttrs->readVec3d("center", vec2D(mvCenter) ,"ntlGeometrySphere", "mvCenter", false));
|
||||
mRadius = mpAttrs->readFloat("radius", mRadius ,"ntlGeometrySphere", "mRadius", false);
|
||||
mRefPolar = mpAttrs->readInt ("refpolar", mRefPolar,"ntlGeometrySphere", "mRefPolar", false);
|
||||
mRefAzim = mpAttrs->readInt ("refazim", mRefAzim ,"ntlGeometrySphere", "mRefAzim", false);
|
||||
if(mRefPolar<1) mRefPolar = 1;
|
||||
if(mRefAzim<1) mRefAzim = 1;
|
||||
mRefAzim *= 4;
|
||||
|
||||
mvBBStart = mvCenter - ntlVec3Gfx(mRadius);
|
||||
mvBBEnd = mvCenter + ntlVec3Gfx(mRadius);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
ntlVec3Gfx getSphereCoord(gfxReal radius, gfxReal phi, gfxReal theta) {
|
||||
return ntlVec3Gfx(
|
||||
radius * cos(theta) * sin(phi),
|
||||
radius * sin(theta) * sin(phi),
|
||||
radius * cos(phi)
|
||||
);
|
||||
};
|
||||
|
||||
void
|
||||
ntlGeometrySphere::getTriangles( vector<ntlTriangle> *triangles,
|
||||
vector<ntlVec3Gfx> *vertices,
|
||||
vector<ntlVec3Gfx> *normals, int objectId )
|
||||
{
|
||||
|
||||
gfxReal phiD = 0.5* M_PI/ (gfxReal)mRefPolar;
|
||||
gfxReal thetaD = 2.0* M_PI/ (gfxReal)mRefAzim;
|
||||
gfxReal phi = 0.0;
|
||||
for(int i=0; i<mRefPolar; i++) {
|
||||
gfxReal theta = 0.0;
|
||||
for(int j=0; j<mRefAzim; j++) {
|
||||
ntlVec3Gfx p1,p2,p3;
|
||||
ntlVec3Gfx n1,n2,n3;
|
||||
|
||||
p1 = getSphereCoord(mRadius, phi , theta );
|
||||
p2 = getSphereCoord(mRadius, phi+phiD, theta );
|
||||
p3 = getSphereCoord(mRadius, phi+phiD, theta+thetaD );
|
||||
n1 = getNormalized(p1);
|
||||
n2 = getNormalized(p2);
|
||||
n3 = getNormalized(p3);
|
||||
//n3 = n2 = n1;
|
||||
p1 += mvCenter;
|
||||
p2 += mvCenter;
|
||||
p3 += mvCenter;
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
|
||||
n1[2] *= -1.0;
|
||||
n2[2] *= -1.0;
|
||||
n3[2] *= -1.0;
|
||||
p1[2] -= mvCenter[2];
|
||||
p2[2] -= mvCenter[2];
|
||||
p3[2] -= mvCenter[2];
|
||||
p1[2] *= -1.0;
|
||||
p2[2] *= -1.0;
|
||||
p3[2] *= -1.0;
|
||||
p1[2] += mvCenter[2];
|
||||
p2[2] += mvCenter[2];
|
||||
p3[2] += mvCenter[2];
|
||||
sceneAddTriangle( p1,p3,p2, n1,n3,n2, ntlVec3Gfx(0.0), 1 );
|
||||
|
||||
p1 = getSphereCoord(mRadius, phi , theta );
|
||||
p3 = getSphereCoord(mRadius, phi , theta+thetaD );
|
||||
p2 = getSphereCoord(mRadius, phi+phiD, theta+thetaD );
|
||||
n1 = getNormalized(p1);
|
||||
n2 = getNormalized(p2);
|
||||
n3 = getNormalized(p3);
|
||||
//n3 = n2 = n1;
|
||||
p1 += mvCenter;
|
||||
p2 += mvCenter;
|
||||
p3 += mvCenter;
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
|
||||
n1[2] *= -1.0;
|
||||
n2[2] *= -1.0;
|
||||
n3[2] *= -1.0;
|
||||
p1[2] -= mvCenter[2];
|
||||
p2[2] -= mvCenter[2];
|
||||
p3[2] -= mvCenter[2];
|
||||
p1[2] *= -1.0;
|
||||
p2[2] *= -1.0;
|
||||
p3[2] *= -1.0;
|
||||
p1[2] += mvCenter[2];
|
||||
p2[2] += mvCenter[2];
|
||||
p3[2] += mvCenter[2];
|
||||
sceneAddTriangle( p1,p3,p2, n1,n3,n2, ntlVec3Gfx(0.0), 1 );
|
||||
|
||||
theta += thetaD;
|
||||
}
|
||||
phi += phiD;
|
||||
}
|
||||
|
||||
int doBack = 0;
|
||||
int doFront = 0;
|
||||
int doTop = 0;
|
||||
int doBottom = 0;
|
||||
int doLeft = 0;
|
||||
int doRight = 0;
|
||||
ntlVec3Gfx mvStart = mvBBStart;
|
||||
ntlVec3Gfx mvEnd = mvBBEnd;
|
||||
|
||||
gfxReal s0 = mvStart[0];
|
||||
gfxReal s1 = mvStart[1];
|
||||
gfxReal s2 = mvStart[2];
|
||||
gfxReal e0 = mvEnd[0];
|
||||
gfxReal e1 = mvEnd[1];
|
||||
gfxReal e2 = mvEnd[2];
|
||||
ntlVec3Gfx p1,p2,p3;
|
||||
ntlVec3Gfx n1,n2,n3;
|
||||
|
||||
/* front plane */
|
||||
if(doFront) {
|
||||
n1 = n2 = n3 = ntlVec3Gfx( 0.0, 0.0, -1.0 );
|
||||
p1 = ntlVec3Gfx( s0, s1, s2 );
|
||||
p3 = ntlVec3Gfx( e0, s1, s2 );
|
||||
p2 = ntlVec3Gfx( s0, e1, s2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
p1 = ntlVec3Gfx( e0, e1, s2 );
|
||||
p3 = ntlVec3Gfx( s0, e1, s2 );
|
||||
p2 = ntlVec3Gfx( e0, s1, s2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
}
|
||||
|
||||
/* back plane k */
|
||||
if(doBack) {
|
||||
n1 = n2 = n3 = ntlVec3Gfx( 0.0, 0.0, 1.0 );
|
||||
p1 = ntlVec3Gfx( s0, s1, e2 );
|
||||
p3 = ntlVec3Gfx( s0, e1, e2 );
|
||||
p2 = ntlVec3Gfx( e0, s1, e2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
p1 = ntlVec3Gfx( s0, e1, e2 );
|
||||
p3 = ntlVec3Gfx( e0, e1, e2 );
|
||||
p2 = ntlVec3Gfx( e0, s1, e2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
}
|
||||
|
||||
/* bottom plane k */
|
||||
if(doBottom) {
|
||||
n1 = n2 = n3 = ntlVec3Gfx( 0.0, -1.0, 0.0 );
|
||||
p1 = ntlVec3Gfx( e0, s1, s2 );
|
||||
p3 = ntlVec3Gfx( s0, s1, s2 );
|
||||
p2 = ntlVec3Gfx( s0, s1, e2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
p1 = ntlVec3Gfx( s0, s1, e2 );
|
||||
p3 = ntlVec3Gfx( e0, s1, e2 );
|
||||
p2 = ntlVec3Gfx( e0, s1, s2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
}
|
||||
|
||||
/* top plane k */
|
||||
if(doTop) {
|
||||
n1 = n2 = n3 = ntlVec3Gfx( 0.0, 1.0, 0.0 );
|
||||
p1 = ntlVec3Gfx( e0, e1, e2 );
|
||||
p2 = ntlVec3Gfx( e0, e1, s2 );
|
||||
p3 = ntlVec3Gfx( s0, e1, e2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
p1 = ntlVec3Gfx( s0, e1, s2 );
|
||||
p2 = ntlVec3Gfx( s0, e1, e2 );
|
||||
p3 = ntlVec3Gfx( e0, e1, s2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
}
|
||||
|
||||
/* left plane k */
|
||||
if(doLeft) {
|
||||
n1 = n2 = n3 = ntlVec3Gfx( -1.0, 0.0, 0.0 );
|
||||
p1 = ntlVec3Gfx( s0, s1, e2 );
|
||||
p3 = ntlVec3Gfx( s0, s1, s2 );
|
||||
p2 = ntlVec3Gfx( s0, e1, s2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
p1 = ntlVec3Gfx( s0, e1, s2 );
|
||||
p3 = ntlVec3Gfx( s0, e1, e2 );
|
||||
p2 = ntlVec3Gfx( s0, s1, e2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
}
|
||||
|
||||
/* right plane k */
|
||||
if(doRight) {
|
||||
n1 = n2 = n3 = ntlVec3Gfx( 1.0, 0.0, 0.0 );
|
||||
p1 = ntlVec3Gfx( e0, e1, e2 );
|
||||
p3 = ntlVec3Gfx( e0, e1, s2 );
|
||||
p2 = ntlVec3Gfx( e0, s1, e2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
p1 = ntlVec3Gfx( e0, e1, s2 );
|
||||
p3 = ntlVec3Gfx( e0, s1, s2 );
|
||||
p2 = ntlVec3Gfx( e0, s1, e2 );
|
||||
sceneAddTriangle( p1,p2,p3, n1,n2,n3, ntlVec3Gfx(0.0), 1 );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
65
intern/elbeem/intern/ntl_geometrysphere.h
Normal file
65
intern/elbeem/intern/ntl_geometrysphere.h
Normal file
@ -0,0 +1,65 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* A simple sphere object
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef NTL_GEOSPHERE_H
|
||||
|
||||
#include "ntl_geometryobject.h"
|
||||
|
||||
|
||||
/*! A simple box object generatedd by 12 triangles */
|
||||
class ntlGeometrySphere : public ntlGeometryObject
|
||||
{
|
||||
|
||||
public:
|
||||
/* Init constructor */
|
||||
ntlGeometrySphere( void );
|
||||
|
||||
//! Return type id
|
||||
virtual int getTypeId() { return GEOCLASSTID_SPHERE; }
|
||||
|
||||
virtual void getTriangles( vector<ntlTriangle> *triangles,
|
||||
vector<ntlVec3Gfx> *vertices,
|
||||
vector<ntlVec3Gfx> *normals, int objectId );
|
||||
|
||||
/*! for easy GUI detection get start of axis aligned bounding box, return NULL of no BB */
|
||||
virtual inline ntlVec3Gfx *getBBStart() { return &mvBBStart; }
|
||||
virtual inline ntlVec3Gfx *getBBEnd() { return &mvBBEnd; }
|
||||
|
||||
/*! Init refinement attribute */
|
||||
virtual void initialize(ntlRenderGlobals *glob);
|
||||
|
||||
private:
|
||||
|
||||
/*! Center of the sphere */
|
||||
ntlVec3Gfx mvCenter;
|
||||
|
||||
/*! radius */
|
||||
gfxReal mRadius;
|
||||
|
||||
/*! refinement factor along polar angle */
|
||||
int mRefPolar;
|
||||
/*! refinement factor per segment (azimuthal angle) */
|
||||
int mRefAzim;
|
||||
|
||||
/*! Start and end points of bounding box */
|
||||
ntlVec3Gfx mvBBStart, mvBBEnd;
|
||||
|
||||
public:
|
||||
|
||||
/* Access methods */
|
||||
/*! Access start vector */
|
||||
inline ntlVec3Gfx getCenter( void ){ return mvCenter; }
|
||||
inline void setCenter( const ntlVec3Gfx &set ){ mvCenter = set; }
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define NTL_GEOSPHERE_H
|
||||
#endif
|
13
intern/elbeem/intern/ntl_image.cpp
Normal file
13
intern/elbeem/intern/ntl_image.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* a templated image class
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "ntl_image.h"
|
||||
|
||||
|
||||
|
167
intern/elbeem/intern/ntl_image.h
Normal file
167
intern/elbeem/intern/ntl_image.h
Normal file
@ -0,0 +1,167 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* a templated image class
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef NTL_IMAGE_HH
|
||||
#define NTL_IMAGE_HH
|
||||
|
||||
#include "ntl_vector3dim.h"
|
||||
#include "utilities.h"
|
||||
|
||||
|
||||
template<class Value>
|
||||
class ntlImage
|
||||
{
|
||||
public:
|
||||
/*! Default constructor */
|
||||
ntlImage();
|
||||
/*! Init constructor */
|
||||
ntlImage(int x,int y, Value def);
|
||||
/*! Destructor, delete contents */
|
||||
~ntlImage();
|
||||
|
||||
/*! Write the image to a ppm file */
|
||||
void writePpm(const char* name);
|
||||
|
||||
/*! normalize values into range 0..1 */
|
||||
void normalize( void );
|
||||
|
||||
/*! Get a pixel from the image */
|
||||
inline Value get(int x, int y) { return mpC[y*mSizex+x]; }
|
||||
|
||||
/*! Set a pixel in the image */
|
||||
inline void set(int x, int y, Value set) { mpC[y*mSizex+x] = set; }
|
||||
|
||||
protected:
|
||||
private:
|
||||
|
||||
/*! size in x dimension */
|
||||
int mSizex;
|
||||
|
||||
/*! size in y dimension */
|
||||
int mSizey;
|
||||
|
||||
/*! Image contents */
|
||||
Value *mpC;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*! Default constructor */
|
||||
template<class Value>
|
||||
ntlImage<Value>::ntlImage()
|
||||
{
|
||||
mSizex = 0;
|
||||
mSizey = 0;
|
||||
mpC = NULL;
|
||||
}
|
||||
|
||||
/*! Init constructor */
|
||||
template<class Value>
|
||||
ntlImage<Value>::ntlImage(int x,int y,Value def)
|
||||
{
|
||||
mSizex = x;
|
||||
mSizey = y;
|
||||
mpC = new Value[x*y];
|
||||
|
||||
for(int i=0;i<(x*y);i++) mpC[i] = def;
|
||||
}
|
||||
|
||||
/*! Destructor, delete contents */
|
||||
template<class Value>
|
||||
ntlImage<Value>::~ntlImage()
|
||||
{
|
||||
if(mpC != NULL) {
|
||||
delete [] mpC;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*! Write the image to a ppm file */
|
||||
template<class Value>
|
||||
void ntlImage<Value>::writePpm(const char* name)
|
||||
{
|
||||
/* write file */
|
||||
/* open output file */
|
||||
FILE *outfile;
|
||||
if ( (outfile = fopen(name,"w")) == NULL ) {
|
||||
errorOut( "ntlImage::writePpm ERROR: Open out file failed "<<name<<"!\n" );
|
||||
return;
|
||||
}
|
||||
|
||||
int maxColVal = 255;
|
||||
|
||||
/* write ppm header */
|
||||
fprintf(outfile,"P3\n%d %d\n%d\n",mSizex,mSizey, maxColVal );
|
||||
|
||||
/* get min max values */
|
||||
Value min = mpC[0];
|
||||
Value max = mpC[0];
|
||||
for(int j=0;j<(mSizey*mSizex);j++) {
|
||||
if(mpC[j]<min) min = mpC[j];
|
||||
if(mpC[j]>max) max = mpC[j];
|
||||
}
|
||||
|
||||
/* check colors for overflow */
|
||||
for(int j=0;j<mSizey;j++) {
|
||||
for(int i=0;i<mSizex;i++) {
|
||||
|
||||
Value grey;
|
||||
if(max-min>0) {
|
||||
grey = 1.0-(mpC[j*mSizex+i]-min)/(max-min);
|
||||
} else { grey = 1.0; }
|
||||
//mpC[j*mSizex+i] /= max;
|
||||
ntlColor col = ntlColor(grey,grey,grey);
|
||||
unsigned int cCol[3];
|
||||
for (unsigned int cc=0; cc<3; cc++) {
|
||||
if(col[cc] <= 0.0)
|
||||
cCol[cc] = 0;
|
||||
else if(col[cc] >= 1.0)
|
||||
cCol[cc] = maxColVal;
|
||||
else
|
||||
cCol[cc] = (unsigned int)(maxColVal * col[cc]);
|
||||
}
|
||||
|
||||
/* write pixel to ppm file */
|
||||
fprintf(outfile,"%4d %4d %4d ",cCol[0],cCol[1],cCol[2]);
|
||||
|
||||
} /* foreach x */
|
||||
|
||||
fprintf(outfile,"\n");
|
||||
} /* foreach y */
|
||||
|
||||
/* clean up */
|
||||
fclose(outfile);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*! Write the image to a ppm file */
|
||||
template<class Value>
|
||||
void ntlImage<Value>::normalize( void )
|
||||
{
|
||||
/* get min max values */
|
||||
Value min = mpC[0];
|
||||
Value max = mpC[0];
|
||||
for(int j=0;j<(mSizey*mSizex);j++) {
|
||||
if(mpC[j]<min) min = mpC[j];
|
||||
if(mpC[j]>max) max = mpC[j];
|
||||
}
|
||||
|
||||
/* check colors for overflow */
|
||||
for(int j=0;j<mSizey;j++) {
|
||||
for(int i=0;i<mSizex;i++) {
|
||||
Value grey = 1.0-(mpC[j*mSizex+i]-min)/(max-min);
|
||||
mpC[j*mSizex+i] = grey;
|
||||
} /* foreach x */
|
||||
} /* foreach y */
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
143
intern/elbeem/intern/ntl_lightobject.cpp
Normal file
143
intern/elbeem/intern/ntl_lightobject.cpp
Normal file
@ -0,0 +1,143 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* a light object
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#include "ntl_lightobject.h"
|
||||
#include "ntl_ray.h"
|
||||
#include "ntl_scene.h"
|
||||
#include "ntl_renderglobals.h"
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Default Constructor
|
||||
*****************************************************************************/
|
||||
ntlLightObject::ntlLightObject(ntlRenderGlobals *glob) :
|
||||
mpGlob( glob ),
|
||||
mActive( 1 ),
|
||||
mCastShadows( 1 ),
|
||||
mcColor( ntlColor(1.0) ),
|
||||
mvPosition( ntlVec3Gfx(0.0) )
|
||||
{
|
||||
// nothing to do...
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Constructor with parameters
|
||||
*****************************************************************************/
|
||||
ntlLightObject::ntlLightObject(ntlRenderGlobals *glob, const ntlColor& col) :
|
||||
mpGlob( glob ),
|
||||
mActive( 1 ),
|
||||
mCastShadows( 1 ),
|
||||
mcColor( col )
|
||||
{
|
||||
// nothing to do...
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Destructor
|
||||
*****************************************************************************/
|
||||
ntlLightObject::~ntlLightObject()
|
||||
{
|
||||
// nothing to do...
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Determine color contribution of a lightsource (Phong model)
|
||||
* Specular part is returned in seperate parameter and added later
|
||||
*****************************************************************************/
|
||||
const ntlColor
|
||||
ntlLightObject::getShadedColor(const ntlRay &reflectedRay, const ntlVec3Gfx lightDir,
|
||||
ntlMaterial *surf, ntlColor &highlight) const
|
||||
{
|
||||
gfxReal ldot = dot(lightDir, reflectedRay.getNormal()); /* equals cos( angle(L,N) ) */
|
||||
ntlColor reflected_color = ntlColor(0.0); /* adds up to total reflected color */
|
||||
if(mpGlob->getDebugOut() > 5) errorOut("Lighting dir:"<<lightDir<<" norm:"<<reflectedRay.getNormal()<<" "<<ldot );
|
||||
|
||||
/* lambertian reflection model */
|
||||
if (ldot > 0.0) {
|
||||
//ldot *= -1.0;
|
||||
reflected_color += surf->getDiffuseRefl() * (getColor() * ldot );
|
||||
|
||||
/* specular part */
|
||||
/* specular reflection only makes sense, when the light is facing the surface,
|
||||
as the highlight is supposed to be a reflection of the lightsource, it cannot
|
||||
be reflected on surfaces with ldot<=0, as this means the arc between light
|
||||
and normal is more than 90 degrees. If this isn't done, ugly moiree patterns appear
|
||||
in the highlights, and refractions have strange patterns due to highlights on the
|
||||
inside of the surface */
|
||||
gfxReal spec = dot(reflectedRay.getDirection(), lightDir); // equals cos( angle(R,L) )
|
||||
if((spec > 0.0) && (surf->getSpecular()>0)) {
|
||||
spec = pow( spec, surf->getSpecExponent() ); /* phong exponent */
|
||||
highlight += getColor() * surf->getSpecular() * spec;
|
||||
//errorOut( " "<< surf->getName() <<" S "<<highlight<<" "<<spec<<" "<<surf->getSpecular()<<" "<<surf->getSpecExponent() );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ntlColor(reflected_color);
|
||||
}
|
||||
|
||||
|
||||
// omni light implementation
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*! prepare shadow maps if necessary
|
||||
*****************************************************************************/
|
||||
void ntlLightObject::prepare( bool doCaustics )
|
||||
{
|
||||
if(!mActive) { return; }
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Illuminate the given point on an object
|
||||
*****************************************************************************/
|
||||
ntlColor ntlLightObject::illuminatePoint(ntlRay &reflectedRay, ntlGeometryObject *closest,
|
||||
ntlColor &highlight )
|
||||
{
|
||||
/* is this light active? */
|
||||
if(!mActive) { return ntlColor(0.0); }
|
||||
|
||||
gfxReal visibility = 1.0; // how much of light is visible
|
||||
ntlVec3Gfx intersectionPos = reflectedRay.getOrigin();
|
||||
ntlColor current_color = ntlColor(0.0);
|
||||
ntlMaterial *clossurf = closest->getMaterial();
|
||||
|
||||
ntlVec3Gfx lightDir = (mvPosition - intersectionPos);
|
||||
gfxReal lightDirNorm = normalize(lightDir);
|
||||
|
||||
// where is the lightsource ?
|
||||
ntlRay rayOfLight(intersectionPos, lightDir, 0, 1.0, mpGlob );
|
||||
|
||||
if( (mCastShadows)&&(closest->getReceiveShadows()) ) {
|
||||
ntlTriangle *tri;
|
||||
ntlVec3Gfx triNormal;
|
||||
gfxReal trit;
|
||||
mpGlob->getScene()->intersectScene(rayOfLight, trit, triNormal, tri, TRI_CASTSHADOWS);
|
||||
if(( trit>0 )&&( trit<lightDirNorm )) visibility = 0.0;
|
||||
if(mpGlob->getDebugOut() > 5) errorOut("Omni lighting with "<<visibility );
|
||||
}
|
||||
|
||||
/* is light partly visible ? */
|
||||
if (visibility>0.0) {
|
||||
ntlColor highTemp(0.0); // temporary highlight color to multiply highTemp with offFac
|
||||
current_color = getShadedColor(reflectedRay, lightDir, clossurf, highTemp) * visibility;
|
||||
highlight += highTemp * visibility;
|
||||
if(mpGlob->getDebugOut() > 5) errorOut("Omni lighting color "<<current_color );
|
||||
}
|
||||
return current_color;
|
||||
}
|
||||
|
||||
|
120
intern/elbeem/intern/ntl_lightobject.h
Normal file
120
intern/elbeem/intern/ntl_lightobject.h
Normal file
@ -0,0 +1,120 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* a light object
|
||||
* default omni light implementation
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef NTL_LIGHTOBJECT_HH
|
||||
#define NTL_LIGHTOBJECT_HH
|
||||
|
||||
#include "ntl_vector3dim.h"
|
||||
#include "ntl_material.h"
|
||||
#include "ntl_image.h"
|
||||
class ntlRay;
|
||||
class ntlRenderGlobals;
|
||||
class ntlGeometryObject;
|
||||
|
||||
|
||||
|
||||
/* shadow map directions */
|
||||
#define LSM_RIGHT 0
|
||||
#define LSM_LEFT 1
|
||||
#define LSM_UP 2
|
||||
#define LSM_DOWN 3
|
||||
#define LSM_FRONT 4
|
||||
#define LSM_BACK 5
|
||||
|
||||
/*! Basic object for lights, all other light are derived from this one */
|
||||
class ntlLightObject
|
||||
{
|
||||
public:
|
||||
/* CONSTRUCTORS */
|
||||
/*! Default constructor */
|
||||
ntlLightObject(ntlRenderGlobals *glob);
|
||||
/*! Constructor with parameters */
|
||||
ntlLightObject(ntlRenderGlobals *glob, const ntlColor& col);
|
||||
/*! Destructor */
|
||||
virtual ~ntlLightObject();
|
||||
|
||||
/*! prepare light for rendering (for example shadow maps) */
|
||||
virtual void prepare( bool );
|
||||
|
||||
/*! do the illumination... */
|
||||
virtual ntlColor illuminatePoint(ntlRay &reflectedRay,
|
||||
ntlGeometryObject *closest,
|
||||
ntlColor &highlight);
|
||||
/*! shade the point */
|
||||
const ntlColor
|
||||
getShadedColor(const ntlRay &reflectedray, ntlVec3Gfx lightDir,
|
||||
ntlMaterial *surf, ntlColor &highlight) const;
|
||||
|
||||
|
||||
/* access methods */
|
||||
/*! Access the active flag */
|
||||
inline void setActive(bool set) { mActive = set; }
|
||||
inline bool getActive() const { return mActive; }
|
||||
/*! Access the shadow flag */
|
||||
inline void setCastShadows(bool set) { mCastShadows = set; }
|
||||
inline bool getCastShadows() const { return mCastShadows; }
|
||||
/*! Access the light color */
|
||||
inline void setColor(ntlColor set) { mcColor = set; }
|
||||
inline ntlColor getColor() const { return mcColor; }
|
||||
|
||||
/*! Access the omni light position */
|
||||
void setPosition(ntlVec3Gfx set) { mvPosition = set; }
|
||||
ntlVec3Gfx getPosition() const { return mvPosition; }
|
||||
/*! Init the shadow map */
|
||||
void setShadowMap(int setx, int sety, int sampling) { mUseShadowMap = true; mSMSizeX = setx; mSMSizeY = sety; mSMSampling = sampling; }
|
||||
/*! Init the caustics map */
|
||||
void setCausticsMap(int setx, int sety ) { mUseCausticsMap = true; mCMSizeX = setx; mCMSizeY = sety; }
|
||||
|
||||
|
||||
protected:
|
||||
/*! render globals */
|
||||
ntlRenderGlobals *mpGlob;
|
||||
|
||||
/*! is this light acitve? */
|
||||
bool mActive;
|
||||
|
||||
/*! does it cast shadows? */
|
||||
bool mCastShadows;
|
||||
|
||||
/*! color of this light */
|
||||
ntlColor mcColor;
|
||||
|
||||
/*! light position */
|
||||
ntlVec3Gfx mvPosition;
|
||||
|
||||
/*! shadow map active? */
|
||||
int mUseShadowMap;
|
||||
|
||||
/*! shadow map size */
|
||||
int mSMSizeX;
|
||||
int mSMSizeY;
|
||||
|
||||
/*! Sampling value for shadow map filtering */
|
||||
int mSMSampling;
|
||||
|
||||
/*! Images for shadow map */
|
||||
ntlImage<gfxReal> *mpShadowMap[6];
|
||||
|
||||
|
||||
/*! caustics map active? */
|
||||
int mUseCausticsMap;
|
||||
|
||||
/*! caustics map size */
|
||||
int mCMSizeX;
|
||||
int mCMSizeY;
|
||||
|
||||
/*! Images for caustics map */
|
||||
ntlImage<char> *mpCausticsMap[6];
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
203
intern/elbeem/intern/ntl_material.h
Normal file
203
intern/elbeem/intern/ntl_material.h
Normal file
@ -0,0 +1,203 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* a geometry object
|
||||
* all other geometry objects are derived from this one
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef NTL_MATERIAL_HH
|
||||
#define NTL_MATERIAL_HH
|
||||
|
||||
#include "ntl_vector3dim.h"
|
||||
class ntlRay;
|
||||
|
||||
|
||||
//! Properties of an geo object, describing the reflection properties of the surface
|
||||
class ntlMaterial
|
||||
{
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
//! Default constructor
|
||||
inline ntlMaterial( void );
|
||||
//! Constructor with parameters
|
||||
/*! Sets reflectance, ambient reflection, specular intensity
|
||||
* specular exponent, mirror intensity
|
||||
* transparency, refraction index */
|
||||
inline ntlMaterial( string name,
|
||||
const ntlColor& Ref, const ntlColor& Amb,
|
||||
gfxReal Spec, gfxReal Exp, gfxReal Mirror,
|
||||
gfxReal Trans, gfxReal Refrac, gfxReal TAdd,
|
||||
const ntlColor& Att, int fres);
|
||||
//! Desctructor
|
||||
~ntlMaterial() {};
|
||||
|
||||
//! Calculate reflectance and refratance from Fresnel's law
|
||||
inline void calculateFresnel(const ntlVec3Gfx &dir, const ntlVec3Gfx &normal, gfxReal refIndex,
|
||||
gfxReal &refl, gfxReal &trans );
|
||||
|
||||
protected:
|
||||
|
||||
/* name of the material */
|
||||
string mName;
|
||||
|
||||
//! Vector for reflectance of each color component (used in shade() of ray object)
|
||||
ntlColor mDiffuseRefl;
|
||||
//! Ambient reflectance
|
||||
ntlColor mAmbientRefl;
|
||||
//! Specular reflection intensity
|
||||
gfxReal mSpecular;
|
||||
//! Specular phong exponent
|
||||
gfxReal mSpecExponent;
|
||||
//! Mirror intensity
|
||||
gfxReal mMirror;
|
||||
|
||||
//! Transparence
|
||||
gfxReal mTransparence;
|
||||
//! Refraction index, nu(Air) is assumed 1
|
||||
gfxReal mRefracIndex;
|
||||
//! Should transparence be additive?
|
||||
gfxReal mTransAdditive;
|
||||
//! Color dependent transparency attentuation factors (negative logarithm stored)
|
||||
ntlColor mTransAttCol;
|
||||
//! Should the transparence and reflectivity be determined by fresnel?
|
||||
int mFresnel;
|
||||
|
||||
|
||||
public:
|
||||
// access methods
|
||||
|
||||
//! Returns the material name
|
||||
inline string getName() { return mName; }
|
||||
//! Returns the reflectance
|
||||
inline ntlColor getDiffuseRefl() const { return ntlColor(mDiffuseRefl); }
|
||||
//! Returns the ambience
|
||||
inline ntlColor getAmbientRefl() const { return ntlColor(mAmbientRefl); }
|
||||
//! Returns the specular component
|
||||
inline gfxReal getSpecular() const { return mSpecular; }
|
||||
//! Returns the specular exponent component
|
||||
inline gfxReal getSpecExponent() const { return mSpecExponent; }
|
||||
//! Returns the mirror component
|
||||
inline gfxReal getMirror() const { return mMirror; }
|
||||
//! Returns the transparence component
|
||||
inline gfxReal getTransparence() const { return mTransparence; }
|
||||
//! Returns the refraction index component
|
||||
inline gfxReal getRefracIndex() const { return mRefracIndex; }
|
||||
//! Returns the transparency additive factor component
|
||||
inline gfxReal getTransAdditive() const { return mTransAdditive; }
|
||||
//! Returns the transparency attentuation
|
||||
inline ntlColor getTransAttCol() const { return mTransAttCol; }
|
||||
//! Get Fresnel flag
|
||||
inline int getFresnel( void ) { return mFresnel; }
|
||||
|
||||
|
||||
|
||||
//! Returns the mat name
|
||||
inline void setName(string set) { mName = set; }
|
||||
//! Returns the reflectance
|
||||
inline void setDiffuseRefl(ntlColor set) { mDiffuseRefl=set; }
|
||||
//! Returns the ambience
|
||||
inline void setAmbientRefl(ntlColor set) { mAmbientRefl=set; }
|
||||
//! Returns the specular component
|
||||
inline void setSpecular(gfxReal set) { mSpecular=set; }
|
||||
//! Returns the specular exponent component
|
||||
inline void setSpecExponent(gfxReal set) { mSpecExponent=set; }
|
||||
//! Returns the mirror component
|
||||
inline void setMirror(gfxReal set) { mMirror=set; }
|
||||
//! Returns the transparence component
|
||||
inline void setTransparence(gfxReal set) { mTransparence=set; }
|
||||
//! Returns the refraction index component
|
||||
inline void setRefracIndex(gfxReal set) { mRefracIndex=set; }
|
||||
//! Returns the transparency additive factor component
|
||||
inline void setTransAdditive(gfxReal set) { mTransAdditive=set; }
|
||||
//! Returns the transparency attentuation
|
||||
inline void setTransAttCol(ntlColor set) {
|
||||
ntlColor setlog = ntlColor( -log(set[0]), -log(set[1]), -log(set[2]) );
|
||||
mTransAttCol=setlog; }
|
||||
//! Set Fresnel on/off
|
||||
inline void setFresnel(int set) { mFresnel = set; }
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Default constructor
|
||||
*****************************************************************************/
|
||||
inline ntlMaterial::ntlMaterial( void ) :
|
||||
mName( "default" ),
|
||||
mDiffuseRefl(0.5,0.5,0.5), mAmbientRefl(0.0,0.0,0.0),
|
||||
mSpecular(0.0), mSpecExponent(0.0), mMirror(0.0),
|
||||
mTransparence(0.0), mRefracIndex(0.0), mTransAdditive(0.0), mTransAttCol(0.0),
|
||||
mFresnel( 0 )
|
||||
//mNtfId(0), mNtfFluid(0), mNtfSolid(0)
|
||||
{
|
||||
// just do default init...
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Init constructor
|
||||
*****************************************************************************/
|
||||
inline
|
||||
ntlMaterial::ntlMaterial( string name,
|
||||
const ntlColor& Ref, const ntlColor& Amb,
|
||||
gfxReal Spec, gfxReal SpecEx, gfxReal Mirr,
|
||||
gfxReal Trans, gfxReal Refrac, gfxReal TAdd,
|
||||
const ntlColor& Att, int fres)
|
||||
{
|
||||
mName = name;
|
||||
mDiffuseRefl = Ref;
|
||||
mAmbientRefl = Amb;
|
||||
mSpecular = Spec;
|
||||
mSpecExponent = SpecEx;
|
||||
mMirror = Mirr;
|
||||
mTransparence = Trans;
|
||||
mRefracIndex = Refrac;
|
||||
mTransAdditive = TAdd;
|
||||
mTransAttCol = Att;
|
||||
mFresnel = fres;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Macro to define the default surface properties for a newly created object
|
||||
*****************************************************************************/
|
||||
#define GET_GLOBAL_DEFAULT_MATERIAL new ntlMaterial( "default",\
|
||||
ntlColor( 0.5 ), ntlColor(0.0), \
|
||||
1.0, 5.0, 0.0, \
|
||||
0.0, 1.0, 0.0, \
|
||||
ntlColor( 0.0 ), 0 );
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Calculate reflectance and refratance from Fresnel's law
|
||||
* cf. Glassner p. 46
|
||||
*****************************************************************************/
|
||||
inline void
|
||||
ntlMaterial::calculateFresnel(const ntlVec3Gfx &dir, const ntlVec3Gfx &normal, gfxReal refIndex,
|
||||
gfxReal &refl, gfxReal &trans)
|
||||
{
|
||||
gfxReal c = -dot(dir, normal);
|
||||
if(c<0) {
|
||||
refl = 0.0; trans = 0.0; return;
|
||||
//c = 0.0;
|
||||
}
|
||||
|
||||
gfxReal r0 = ((refIndex-1.0)*(refIndex-1.0)) /
|
||||
((refIndex+1.0)*(refIndex+1.0));
|
||||
gfxReal omc = (1.0-c);
|
||||
gfxReal r =r0 + (1.0 - r0) * omc*omc*omc*omc*omc;
|
||||
|
||||
//mMirror = r;
|
||||
//mTransparence = (1.0 - r);
|
||||
refl = r;
|
||||
trans = (1.0 - r);
|
||||
//errorOut(" fres ");
|
||||
}
|
||||
|
||||
|
||||
#endif
|
658
intern/elbeem/intern/ntl_matrices.h
Normal file
658
intern/elbeem/intern/ntl_matrices.h
Normal file
@ -0,0 +1,658 @@
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* Basic matrix utility include file
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef NTL_MATRICES_H
|
||||
|
||||
#include "ntl_vector3dim.h"
|
||||
|
||||
|
||||
// The basic vector class
|
||||
template<class Scalar>
|
||||
class ntlMatrix4x4
|
||||
{
|
||||
public:
|
||||
// Constructor
|
||||
inline ntlMatrix4x4(void );
|
||||
// Copy-Constructor
|
||||
inline ntlMatrix4x4(const ntlMatrix4x4<Scalar> &v );
|
||||
// construct a vector from one Scalar
|
||||
inline ntlMatrix4x4(Scalar);
|
||||
// construct a vector from three Scalars
|
||||
inline ntlMatrix4x4(Scalar, Scalar, Scalar);
|
||||
|
||||
// Assignment operator
|
||||
inline const ntlMatrix4x4<Scalar>& operator= (const ntlMatrix4x4<Scalar>& v);
|
||||
// Assignment operator
|
||||
inline const ntlMatrix4x4<Scalar>& operator= (Scalar s);
|
||||
// Assign and add operator
|
||||
inline const ntlMatrix4x4<Scalar>& operator+= (const ntlMatrix4x4<Scalar>& v);
|
||||
// Assign and add operator
|
||||
inline const ntlMatrix4x4<Scalar>& operator+= (Scalar s);
|
||||
// Assign and sub operator
|
||||
inline const ntlMatrix4x4<Scalar>& operator-= (const ntlMatrix4x4<Scalar>& v);
|
||||
// Assign and sub operator
|
||||
inline const ntlMatrix4x4<Scalar>& operator-= (Scalar s);
|
||||
// Assign and mult operator
|
||||
inline const ntlMatrix4x4<Scalar>& operator*= (const ntlMatrix4x4<Scalar>& v);
|
||||
// Assign and mult operator
|
||||
inline const ntlMatrix4x4<Scalar>& operator*= (Scalar s);
|
||||
// Assign and div operator
|
||||
inline const ntlMatrix4x4<Scalar>& operator/= (const ntlMatrix4x4<Scalar>& v);
|
||||
// Assign and div operator
|
||||
inline const ntlMatrix4x4<Scalar>& operator/= (Scalar s);
|
||||
|
||||
|
||||
// unary operator
|
||||
inline ntlMatrix4x4<Scalar> operator- () const;
|
||||
|
||||
// binary operator add
|
||||
inline ntlMatrix4x4<Scalar> operator+ (const ntlMatrix4x4<Scalar>&) const;
|
||||
// binary operator add
|
||||
inline ntlMatrix4x4<Scalar> operator+ (Scalar) const;
|
||||
// binary operator sub
|
||||
inline ntlMatrix4x4<Scalar> operator- (const ntlMatrix4x4<Scalar>&) const;
|
||||
// binary operator sub
|
||||
inline ntlMatrix4x4<Scalar> operator- (Scalar) const;
|
||||
// binary operator mult
|
||||
inline ntlMatrix4x4<Scalar> operator* (const ntlMatrix4x4<Scalar>&) const;
|
||||
// binary operator mult
|
||||
inline ntlVector3Dim<Scalar> operator* (const ntlVector3Dim<Scalar>&) const;
|
||||
// binary operator mult
|
||||
inline ntlMatrix4x4<Scalar> operator* (Scalar) const;
|
||||
// binary operator div
|
||||
inline ntlMatrix4x4<Scalar> operator/ (Scalar) const;
|
||||
|
||||
// init function
|
||||
//! init identity matrix
|
||||
inline void initId();
|
||||
//! init rotation matrix
|
||||
inline void initTranslation(Scalar x, Scalar y, Scalar z);
|
||||
//! init rotation matrix
|
||||
inline void initRotationX(Scalar rot);
|
||||
inline void initRotationY(Scalar rot);
|
||||
inline void initRotationZ(Scalar rot);
|
||||
//! init scaling matrix
|
||||
inline void initScaling(Scalar scale);
|
||||
inline void initScaling(Scalar x, Scalar y, Scalar z);
|
||||
|
||||
//! public to avoid [][] operators
|
||||
Scalar value[4][4]; //< Storage of vector values
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// TYPEDEFS
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// a 3D vector for graphics output, typically float?
|
||||
//typedef ntlMatrix4x4<float> ntlVec3Gfx;
|
||||
|
||||
//typedef ntlMatrix4x4<double> ntlMat4d;
|
||||
typedef ntlMatrix4x4<double> ntlMat4d;
|
||||
|
||||
// a 3D vector with single precision
|
||||
typedef ntlMatrix4x4<float> ntlMat4f;
|
||||
|
||||
// a 3D vector with grafix precision
|
||||
typedef ntlMatrix4x4<gfxReal> ntlMat4Gfx;
|
||||
|
||||
// a 3D integer vector
|
||||
typedef ntlMatrix4x4<int> ntlMat4i;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// STREAM FUNCTIONS
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Outputs the object in human readable form using the format
|
||||
[x,y,z]
|
||||
*/
|
||||
template<class Scalar>
|
||||
std::ostream&
|
||||
operator<<( std::ostream& os, const ntlMatrix4x4<Scalar>& m )
|
||||
{
|
||||
for(int i=0; i<4; i++) {
|
||||
os << '|' << m.value[i][0] << ", " << m.value[i][1] << ", " << m.value[i][2] << ", " << m.value[i][3] << '|';
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Reads the contents of the object from a stream using the same format
|
||||
as the output operator.
|
||||
*/
|
||||
template<class Scalar>
|
||||
std::istream&
|
||||
operator>>( std::istream& is, ntlMatrix4x4<Scalar>& m )
|
||||
{
|
||||
char c;
|
||||
char dummy[3];
|
||||
|
||||
for(int i=0; i<4; i++) {
|
||||
is >> c >> m.value[i][0] >> dummy >> m.value[i][1] >> dummy >> m.value[i][2] >> dummy >> m.value[i][3] >> c;
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// VECTOR inline FUNCTIONS
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Constructor.
|
||||
*/
|
||||
template<class Scalar>
|
||||
inline ntlMatrix4x4<Scalar>::ntlMatrix4x4( void )
|
||||
{
|
||||
#ifdef MATRIX_INIT_ZERO
|
||||
for(int i=0; i<4; i++) {
|
||||
for(int j=0; j<4; j++) {
|
||||
value[i][j] = 0.0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Copy-Constructor.
|
||||
*/
|
||||
template<class Scalar>
|
||||
inline ntlMatrix4x4<Scalar>::ntlMatrix4x4( const ntlMatrix4x4<Scalar> &v )
|
||||
{
|
||||
value[0][0] = v.value[0][0]; value[0][1] = v.value[0][1]; value[0][2] = v.value[0][2]; value[0][3] = v.value[0][3];
|
||||
value[1][0] = v.value[1][0]; value[1][1] = v.value[1][1]; value[1][2] = v.value[1][2]; value[1][3] = v.value[1][3];
|
||||
value[2][0] = v.value[2][0]; value[2][1] = v.value[2][1]; value[2][2] = v.value[2][2]; value[2][3] = v.value[2][3];
|
||||
value[3][0] = v.value[3][0]; value[3][1] = v.value[3][1]; value[3][2] = v.value[3][2]; value[3][3] = v.value[3][3];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Constructor for a vector from a single Scalar. All components of
|
||||
the vector get the same value.
|
||||
\param s The value to set
|
||||
\return The new vector
|
||||
*/
|
||||
template<class Scalar>
|
||||
inline ntlMatrix4x4<Scalar>::ntlMatrix4x4(Scalar s )
|
||||
{
|
||||
for(int i=0; i<4; i++) {
|
||||
for(int j=0; j<4; j++) {
|
||||
value[i][j] = s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Copy a ntlMatrix4x4 componentwise.
|
||||
\param v vector with values to be copied
|
||||
\return Reference to self
|
||||
*/
|
||||
template<class Scalar>
|
||||
inline const ntlMatrix4x4<Scalar>&
|
||||
ntlMatrix4x4<Scalar>::operator=( const ntlMatrix4x4<Scalar> &v )
|
||||
{
|
||||
value[0][0] = v.value[0][0]; value[0][1] = v.value[0][1]; value[0][2] = v.value[0][2]; value[0][3] = v.value[0][3];
|
||||
value[1][0] = v.value[1][0]; value[1][1] = v.value[1][1]; value[1][2] = v.value[1][2]; value[1][3] = v.value[1][3];
|
||||
value[2][0] = v.value[2][0]; value[2][1] = v.value[2][1]; value[2][2] = v.value[2][2]; value[2][3] = v.value[2][3];
|
||||
value[3][0] = v.value[3][0]; value[3][1] = v.value[3][1]; value[3][2] = v.value[3][2]; value[3][3] = v.value[3][3];
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Copy a Scalar to each component.
|
||||
\param s The value to copy
|
||||
\return Reference to self
|
||||
*/
|
||||
template<class Scalar>
|
||||
inline const ntlMatrix4x4<Scalar>&
|
||||
ntlMatrix4x4<Scalar>::operator=(Scalar s)
|
||||
{
|
||||
for(int i=0; i<4; i++) {
|
||||
for(int j=0; j<4; j++) {
|
||||
value[i][j] = s;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Add another ntlMatrix4x4 componentwise.
|
||||
\param v vector with values to be added
|
||||
\return Reference to self
|
||||
*/
|
||||
template<class Scalar>
|
||||
inline const ntlMatrix4x4<Scalar>&
|
||||
ntlMatrix4x4<Scalar>::operator+=( const ntlMatrix4x4<Scalar> &v )
|
||||
{
|
||||
value[0][0] += v.value[0][0]; value[0][1] += v.value[0][1]; value[0][2] += v.value[0][2]; value[0][3] += v.value[0][3];
|
||||
value[1][0] += v.value[1][0]; value[1][1] += v.value[1][1]; value[1][2] += v.value[1][2]; value[1][3] += v.value[1][3];
|
||||
value[2][0] += v.value[2][0]; value[2][1] += v.value[2][1]; value[2][2] += v.value[2][2]; value[2][3] += v.value[2][3];
|
||||
value[3][0] += v.value[3][0]; value[3][1] += v.value[3][1]; value[3][2] += v.value[3][2]; value[3][3] += v.value[3][3];
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Add a Scalar value to each component.
|
||||
\param s Value to add
|
||||
\return Reference to self
|
||||
*/
|
||||
template<class Scalar>
|
||||
inline const ntlMatrix4x4<Scalar>&
|
||||
ntlMatrix4x4<Scalar>::operator+=(Scalar s)
|
||||
{
|
||||
for(int i=0; i<4; i++) {
|
||||
for(int j=0; j<4; j++) {
|
||||
value[i][j] += s;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Subtract another vector componentwise.
|
||||
\param v vector of values to subtract
|
||||
\return Reference to self
|
||||
*/
|
||||
template<class Scalar>
|
||||
inline const ntlMatrix4x4<Scalar>&
|
||||
ntlMatrix4x4<Scalar>::operator-=( const ntlMatrix4x4<Scalar> &v )
|
||||
{
|
||||
value[0][0] -= v.value[0][0]; value[0][1] -= v.value[0][1]; value[0][2] -= v.value[0][2]; value[0][3] -= v.value[0][3];
|
||||
value[1][0] -= v.value[1][0]; value[1][1] -= v.value[1][1]; value[1][2] -= v.value[1][2]; value[1][3] -= v.value[1][3];
|
||||
value[2][0] -= v.value[2][0]; value[2][1] -= v.value[2][1]; value[2][2] -= v.value[2][2]; value[2][3] -= v.value[2][3];
|
||||
value[3][0] -= v.value[3][0]; value[3][1] -= v.value[3][1]; value[3][2] -= v.value[3][2]; value[3][3] -= v.value[3][3];
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Subtract a Scalar value from each component.
|
||||
\param s Value to subtract
|
||||
\return Reference to self
|
||||
*/
|
||||
template<class Scalar>
|
||||
inline const ntlMatrix4x4<Scalar>&
|
||||
ntlMatrix4x4<Scalar>::operator-=(Scalar s)
|
||||
{
|
||||
for(int i=0; i<4; i++) {
|
||||
for(int j=0; j<4; j++) {
|
||||
value[i][j] -= s;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Multiply with another vector componentwise.
|
||||
\param v vector of values to multiply with
|
||||
\return Reference to self
|
||||
*/
|
||||
template<class Scalar>
|
||||
inline const ntlMatrix4x4<Scalar>&
|
||||
ntlMatrix4x4<Scalar>::operator*=( const ntlMatrix4x4<Scalar> &v )
|
||||
{
|
||||
ntlMatrix4x4<Scalar> nv(0.0);
|
||||
for(int i=0; i<4; i++) {
|
||||
for(int j=0; j<4; j++) {
|
||||
|
||||
for(int k=0;k<4;k++)
|
||||
nv.value[i][j] += (value[i][k] * v.value[k][j]);
|
||||
}
|
||||
}
|
||||
*this = nv;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Multiply each component with a Scalar value.
|
||||
\param s Value to multiply with
|
||||
\return Reference to self
|
||||
*/
|
||||
template<class Scalar>
|
||||
inline const ntlMatrix4x4<Scalar>&
|
||||
ntlMatrix4x4<Scalar>::operator*=(Scalar s)
|
||||
{
|
||||
for(int i=0; i<4; i++) {
|
||||
for(int j=0; j<4; j++) {
|
||||
value[i][j] *= s;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Divide each component by a Scalar value.
|
||||
\param s Value to divide by
|
||||
\return Reference to self
|
||||
*/
|
||||
template<class Scalar>
|
||||
inline const ntlMatrix4x4<Scalar>&
|
||||
ntlMatrix4x4<Scalar>::operator/=(Scalar s)
|
||||
{
|
||||
for(int i=0; i<4; i++) {
|
||||
for(int j=0; j<4; j++) {
|
||||
value[i][j] /= s;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// unary operators
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Build componentwise the negative this vector.
|
||||
\return The new (negative) vector
|
||||
*/
|
||||
template<class Scalar>
|
||||
inline ntlMatrix4x4<Scalar>
|
||||
ntlMatrix4x4<Scalar>::operator-() const
|
||||
{
|
||||
ntlMatrix4x4<Scalar> nv;
|
||||
for(int i=0; i<4; i++) {
|
||||
for(int j=0; j<4; j++) {
|
||||
nv[i][j] = -value[i][j];
|
||||
}
|
||||
}
|
||||
return nv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// binary operators
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Build a vector with another vector added componentwise.
|
||||
\param v The second vector to add
|
||||
\return The sum vector
|
||||
*/
|
||||
template<class Scalar>
|
||||
inline ntlMatrix4x4<Scalar>
|
||||
ntlMatrix4x4<Scalar>::operator+( const ntlMatrix4x4<Scalar> &v ) const
|
||||
{
|
||||
ntlMatrix4x4<Scalar> nv;
|
||||
for(int i=0; i<4; i++) {
|
||||
for(int j=0; j<4; j++) {
|
||||
nv[i][j] = value[i][j] + v.value[i][j];
|
||||
}
|
||||
}
|
||||
return nv;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Build a vector with a Scalar value added to each component.
|
||||
\param s The Scalar value to add
|
||||
\return The sum vector
|
||||
*/
|
||||
template<class Scalar>
|
||||
inline ntlMatrix4x4<Scalar>
|
||||
ntlMatrix4x4<Scalar>::operator+(Scalar s) const
|
||||
{
|
||||
ntlMatrix4x4<Scalar> nv;
|
||||
for(int i=0; i<4; i++) {
|
||||
for(int j=0; j<4; j++) {
|
||||
nv[i][j] = value[i][j] + s;
|
||||
}
|
||||
}
|
||||
return nv;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Build a vector with another vector subtracted componentwise.
|
||||
\param v The second vector to subtract
|
||||
\return The difference vector
|
||||
*/
|
||||
template<class Scalar>
|
||||
inline ntlMatrix4x4<Scalar>
|
||||
ntlMatrix4x4<Scalar>::operator-( const ntlMatrix4x4<Scalar> &v ) const
|
||||
{
|
||||
ntlMatrix4x4<Scalar> nv;
|
||||
for(int i=0; i<4; i++) {
|
||||
for(int j=0; j<4; j++) {
|
||||
nv[i][j] = value[i][j] - v.value[i][j];
|
||||
}
|
||||
}
|
||||
return nv;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Build a vector with a Scalar value subtracted componentwise.
|
||||
\param s The Scalar value to subtract
|
||||
\return The difference vector
|
||||
*/
|
||||
template<class Scalar>
|
||||
inline ntlMatrix4x4<Scalar>
|
||||
ntlMatrix4x4<Scalar>::operator-(Scalar s ) const
|
||||
{
|
||||
ntlMatrix4x4<Scalar> nv;
|
||||
for(int i=0; i<4; i++) {
|
||||
for(int j=0; j<4; j++) {
|
||||
nv[i][j] = value[i][j] - s;
|
||||
}
|
||||
}
|
||||
return nv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Build a ntlMatrix4x4 with a Scalar value multiplied to each component.
|
||||
\param s The Scalar value to multiply with
|
||||
\return The product vector
|
||||
*/
|
||||
template<class Scalar>
|
||||
inline ntlMatrix4x4<Scalar>
|
||||
ntlMatrix4x4<Scalar>::operator*(Scalar s) const
|
||||
{
|
||||
ntlMatrix4x4<Scalar> nv;
|
||||
for(int i=0; i<4; i++) {
|
||||
for(int j=0; j<4; j++) {
|
||||
nv[i][j] = value[i][j] * s;
|
||||
}
|
||||
}
|
||||
return nv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Build a vector divided componentwise by a Scalar value.
|
||||
\param s The Scalar value to divide by
|
||||
\return The ratio vector
|
||||
*/
|
||||
template<class Scalar>
|
||||
inline ntlMatrix4x4<Scalar>
|
||||
ntlMatrix4x4<Scalar>::operator/(Scalar s) const
|
||||
{
|
||||
ntlMatrix4x4<Scalar> nv;
|
||||
for(int i=0; i<4; i++) {
|
||||
for(int j=0; j<4; j++) {
|
||||
nv[i][j] = value[i][j] / s;
|
||||
}
|
||||
}
|
||||
return nv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Build a vector with another vector multiplied by componentwise.
|
||||
\param v The second vector to muliply with
|
||||
\return The product vector
|
||||
*/
|
||||
template<class Scalar>
|
||||
inline ntlMatrix4x4<Scalar>
|
||||
ntlMatrix4x4<Scalar>::operator*( const ntlMatrix4x4<Scalar>& v) const
|
||||
{
|
||||
ntlMatrix4x4<Scalar> nv(0.0);
|
||||
for(int i=0; i<4; i++) {
|
||||
for(int j=0; j<4; j++) {
|
||||
|
||||
for(int k=0;k<4;k++)
|
||||
nv.value[i][j] += (value[i][k] * v.value[k][j]);
|
||||
}
|
||||
}
|
||||
return nv;
|
||||
}
|
||||
|
||||
|
||||
template<class Scalar>
|
||||
inline ntlVector3Dim<Scalar>
|
||||
ntlMatrix4x4<Scalar>::operator*( const ntlVector3Dim<Scalar>& v) const
|
||||
{
|
||||
ntlVector3Dim<Scalar> nvec(0.0);
|
||||
for(int i=0; i<3; i++) {
|
||||
for(int j=0; j<3; j++) {
|
||||
nvec[i] += (v[j] * value[i][j]);
|
||||
}
|
||||
}
|
||||
// assume normalized w coord
|
||||
for(int i=0; i<3; i++) {
|
||||
nvec[i] += (1.0 * value[i][3]);
|
||||
}
|
||||
return nvec;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Other helper functions
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//! init identity matrix
|
||||
template<class Scalar>
|
||||
inline void ntlMatrix4x4<Scalar>::initId()
|
||||
{
|
||||
(*this) = (Scalar)(0.0);
|
||||
value[0][0] =
|
||||
value[1][1] =
|
||||
value[2][2] =
|
||||
value[3][3] = (Scalar)(1.0);
|
||||
}
|
||||
|
||||
//! init rotation matrix
|
||||
template<class Scalar>
|
||||
inline void ntlMatrix4x4<Scalar>::initTranslation(Scalar x, Scalar y, Scalar z)
|
||||
{
|
||||
//(*this) = (Scalar)(0.0);
|
||||
this->initId();
|
||||
value[0][3] = x;
|
||||
value[1][3] = y;
|
||||
value[2][3] = z;
|
||||
}
|
||||
|
||||
//! init rotation matrix
|
||||
template<class Scalar>
|
||||
inline void
|
||||
ntlMatrix4x4<Scalar>::initRotationX(Scalar rot)
|
||||
{
|
||||
double drot = (double)rot;
|
||||
while(drot < 0.0) drot += (M_PI*2.0);
|
||||
|
||||
this->initId();
|
||||
value[1][1] = (Scalar) cos(drot);
|
||||
value[1][2] = (Scalar) sin(drot);
|
||||
value[2][1] = (Scalar)(-sin(drot));
|
||||
value[2][2] = (Scalar) cos(drot);
|
||||
}
|
||||
template<class Scalar>
|
||||
inline void
|
||||
ntlMatrix4x4<Scalar>::initRotationY(Scalar rot)
|
||||
{
|
||||
double drot = (double)rot;
|
||||
while(drot < 0.0) drot += (M_PI*2.0);
|
||||
|
||||
this->initId();
|
||||
value[0][0] = (Scalar) cos(drot);
|
||||
value[0][2] = (Scalar)(-sin(drot));
|
||||
value[2][0] = (Scalar) sin(drot);
|
||||
value[2][2] = (Scalar) cos(drot);
|
||||
}
|
||||
template<class Scalar>
|
||||
inline void
|
||||
ntlMatrix4x4<Scalar>::initRotationZ(Scalar rot)
|
||||
{
|
||||
double drot = (double)rot;
|
||||
while(drot < 0.0) drot += (M_PI*2.0);
|
||||
|
||||
this->initId();
|
||||
value[0][0] = (Scalar) cos(drot);
|
||||
value[0][1] = (Scalar) sin(drot);
|
||||
value[1][0] = (Scalar)(-sin(drot));
|
||||
value[1][1] = (Scalar) cos(drot);
|
||||
}
|
||||
|
||||
//! init scaling matrix
|
||||
template<class Scalar>
|
||||
inline void
|
||||
ntlMatrix4x4<Scalar>::initScaling(Scalar scale)
|
||||
{
|
||||
this->initId();
|
||||
value[0][0] = scale;
|
||||
value[1][1] = scale;
|
||||
value[2][2] = scale;
|
||||
}
|
||||
//! init scaling matrix
|
||||
template<class Scalar>
|
||||
inline void
|
||||
ntlMatrix4x4<Scalar>::initScaling(Scalar x, Scalar y, Scalar z)
|
||||
{
|
||||
this->initId();
|
||||
value[0][0] = x;
|
||||
value[1][1] = y;
|
||||
value[2][2] = z;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define NTL_MATRICES_H
|
||||
#endif
|
||||
|
652
intern/elbeem/intern/ntl_ray.cpp
Normal file
652
intern/elbeem/intern/ntl_ray.cpp
Normal file
@ -0,0 +1,652 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* main renderer class
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#include "ntl_ray.h"
|
||||
#include "ntl_scene.h"
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Constructor
|
||||
*****************************************************************************/
|
||||
ntlRay::ntlRay( void )
|
||||
: mOrigin(0.0)
|
||||
, mDirection(0.0)
|
||||
, mvNormal(0.0)
|
||||
, mDepth(0)
|
||||
, mpGlob(NULL)
|
||||
, mIsRefracted(0)
|
||||
{
|
||||
errorOut("ntlRay::ntlRay() Error: don't use uninitialized rays !");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Copy - Constructor
|
||||
*****************************************************************************/
|
||||
ntlRay::ntlRay( const ntlRay &r )
|
||||
{
|
||||
// copy it! initialization is not enough!
|
||||
mOrigin = r.mOrigin;
|
||||
mDirection = r.mDirection;
|
||||
mvNormal = r.mvNormal;
|
||||
mDepth = r.mDepth;
|
||||
mIsRefracted = r.mIsRefracted;
|
||||
mIsReflected = r.mIsReflected;
|
||||
mContribution = r.mContribution;
|
||||
mpGlob = r.mpGlob;
|
||||
|
||||
// get new ID
|
||||
if(mpGlob) {
|
||||
mID = mpGlob->getCounterRays()+1;
|
||||
mpGlob->setCounterRays( mpGlob->getCounterRays()+1 );
|
||||
} else {
|
||||
mID = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Constructor with explicit parameters and global render object
|
||||
*****************************************************************************/
|
||||
ntlRay::ntlRay(const ntlVec3Gfx &o, const ntlVec3Gfx &d, unsigned int i, gfxReal contrib, ntlRenderGlobals *glob)
|
||||
: mOrigin( o )
|
||||
, mDirection( d )
|
||||
, mvNormal(0.0)
|
||||
, mDepth( i )
|
||||
, mContribution( contrib )
|
||||
, mpGlob( glob )
|
||||
, mIsRefracted( 0 )
|
||||
, mIsReflected( 0 )
|
||||
{
|
||||
// get new ID
|
||||
if(mpGlob) {
|
||||
mID = mpGlob->getCounterRays()+1;
|
||||
mpGlob->setCounterRays( mpGlob->getCounterRays()+1 );
|
||||
} else {
|
||||
mID = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Destructor
|
||||
*****************************************************************************/
|
||||
ntlRay::~ntlRay()
|
||||
{
|
||||
/* nothing to do... */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* AABB
|
||||
*****************************************************************************/
|
||||
/* for AABB intersect */
|
||||
#define NUMDIM 3
|
||||
#define RIGHT 0
|
||||
#define LEFT 1
|
||||
#define MIDDLE 2
|
||||
|
||||
//! intersect ray with AABB
|
||||
void ntlRay::intersectFrontAABB(ntlVec3Gfx mStart, ntlVec3Gfx mEnd, gfxReal &t, ntlVec3Gfx &retnormal,ntlVec3Gfx &retcoord) const
|
||||
{
|
||||
char inside = true; /* inside box? */
|
||||
char hit = false; /* ray hits box? */
|
||||
int whichPlane; /* intersection plane */
|
||||
gfxReal candPlane[NUMDIM]; /* candidate plane */
|
||||
gfxReal quadrant[NUMDIM]; /* quadrants */
|
||||
gfxReal maxT[NUMDIM]; /* max intersection T for planes */
|
||||
ntlVec3Gfx coord; /* intersection point */
|
||||
ntlVec3Gfx dir = mDirection;
|
||||
ntlVec3Gfx origin = mOrigin;
|
||||
ntlVec3Gfx normal(0.0, 0.0, 0.0);
|
||||
|
||||
t = GFX_REAL_MAX;
|
||||
|
||||
/* check intersection planes for AABB */
|
||||
for(int i=0;i<NUMDIM;i++) {
|
||||
if(origin[i] < mStart[i]) {
|
||||
quadrant[i] = LEFT;
|
||||
candPlane [i] = mStart[i];
|
||||
inside = false;
|
||||
} else if(origin[i] > mEnd[i]) {
|
||||
quadrant[i] = RIGHT;
|
||||
candPlane[i] = mEnd[i];
|
||||
inside = false;
|
||||
} else {
|
||||
quadrant[i] = MIDDLE;
|
||||
}
|
||||
}
|
||||
|
||||
/* inside AABB? */
|
||||
if(!inside) {
|
||||
/* get t distances to planes */
|
||||
/* treat too small direction components as paralell */
|
||||
for(int i=0;i<NUMDIM;i++) {
|
||||
if((quadrant[i] != MIDDLE) && (fabs(dir[i]) > getVecEpsilon()) ) {
|
||||
maxT[i] = (candPlane[i] - origin[i]) / dir[i];
|
||||
} else {
|
||||
maxT[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* largest max t */
|
||||
whichPlane = 0;
|
||||
for(int i=1;i<NUMDIM;i++) {
|
||||
if(maxT[whichPlane] < maxT[i]) whichPlane = i;
|
||||
}
|
||||
|
||||
/* check final candidate */
|
||||
hit = true;
|
||||
if(maxT[whichPlane] >= 0.0) {
|
||||
|
||||
for(int i=0;i<NUMDIM;i++) {
|
||||
if(whichPlane != i) {
|
||||
coord[i] = origin[i] + maxT[whichPlane] * dir[i];
|
||||
if( (coord[i] < mStart[i]-getVecEpsilon() ) ||
|
||||
(coord[i] > mEnd[i] +getVecEpsilon() ) ) {
|
||||
/* no hit... */
|
||||
hit = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
coord[i] = candPlane[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* AABB hit... */
|
||||
if( hit ) {
|
||||
t = maxT[whichPlane];
|
||||
if(quadrant[whichPlane]==RIGHT) normal[whichPlane] = 1.0;
|
||||
else normal[whichPlane] = -1.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
/* inside AABB... */
|
||||
t = 0.0;
|
||||
coord = origin;
|
||||
return;
|
||||
}
|
||||
|
||||
if(t == GFX_REAL_MAX) t = -1.0;
|
||||
retnormal = normal;
|
||||
retcoord = coord;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! intersect ray with AABB
|
||||
void ntlRay::intersectBackAABB(ntlVec3Gfx mStart, ntlVec3Gfx mEnd, gfxReal &t, ntlVec3Gfx &retnormal,ntlVec3Gfx &retcoord) const
|
||||
{
|
||||
char hit = false; /* ray hits box? */
|
||||
int whichPlane; /* intersection plane */
|
||||
gfxReal candPlane[NUMDIM]; /* candidate plane */
|
||||
gfxReal quadrant[NUMDIM]; /* quadrants */
|
||||
gfxReal maxT[NUMDIM]; /* max intersection T for planes */
|
||||
ntlVec3Gfx coord; /* intersection point */
|
||||
ntlVec3Gfx dir = mDirection;
|
||||
ntlVec3Gfx origin = mOrigin;
|
||||
ntlVec3Gfx normal(0.0, 0.0, 0.0);
|
||||
|
||||
t = GFX_REAL_MAX;
|
||||
for(int i=0;i<NUMDIM;i++) {
|
||||
if(origin[i] < mStart[i]) {
|
||||
quadrant[i] = LEFT;
|
||||
candPlane [i] = mEnd[i];
|
||||
} else if(origin[i] > mEnd[i]) {
|
||||
quadrant[i] = RIGHT;
|
||||
candPlane[i] = mStart[i];
|
||||
} else {
|
||||
if(dir[i] > 0) {
|
||||
quadrant[i] = LEFT;
|
||||
candPlane [i] = mEnd[i];
|
||||
} else
|
||||
if(dir[i] < 0) {
|
||||
quadrant[i] = RIGHT;
|
||||
candPlane[i] = mStart[i];
|
||||
} else {
|
||||
quadrant[i] = MIDDLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* get t distances to planes */
|
||||
/* treat too small direction components as paralell */
|
||||
for(int i=0;i<NUMDIM;i++) {
|
||||
if((quadrant[i] != MIDDLE) && (fabs(dir[i]) > getVecEpsilon()) ) {
|
||||
maxT[i] = (candPlane[i] - origin[i]) / dir[i];
|
||||
} else {
|
||||
maxT[i] = GFX_REAL_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
/* largest max t */
|
||||
whichPlane = 0;
|
||||
for(int i=1;i<NUMDIM;i++) {
|
||||
if(maxT[whichPlane] > maxT[i]) whichPlane = i;
|
||||
}
|
||||
|
||||
/* check final candidate */
|
||||
hit = true;
|
||||
if(maxT[whichPlane] != GFX_REAL_MAX) {
|
||||
|
||||
for(int i=0;i<NUMDIM;i++) {
|
||||
if(whichPlane != i) {
|
||||
coord[i] = origin[i] + maxT[whichPlane] * dir[i];
|
||||
if( (coord[i] < mStart[i]-getVecEpsilon() ) ||
|
||||
(coord[i] > mEnd[i] +getVecEpsilon() ) ) {
|
||||
/* no hit... */
|
||||
hit = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
coord[i] = candPlane[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* AABB hit... */
|
||||
if( hit ) {
|
||||
t = maxT[whichPlane];
|
||||
|
||||
if(quadrant[whichPlane]==RIGHT) normal[whichPlane] = 1.0;
|
||||
else normal[whichPlane] = -1.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(t == GFX_REAL_MAX) t = -1.0;
|
||||
retnormal = normal;
|
||||
retcoord = coord;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//! intersect ray with AABB
|
||||
void ntlRay::intersectCompleteAABB(ntlVec3Gfx mStart, ntlVec3Gfx mEnd, gfxReal &tmin, gfxReal &tmax) const
|
||||
{
|
||||
char inside = true; /* inside box? */
|
||||
char hit = false; /* ray hits box? */
|
||||
int whichPlane; /* intersection plane */
|
||||
gfxReal candPlane[NUMDIM]; /* candidate plane */
|
||||
gfxReal quadrant[NUMDIM]; /* quadrants */
|
||||
gfxReal maxT[NUMDIM]; /* max intersection T for planes */
|
||||
ntlVec3Gfx coord; /* intersection point */
|
||||
ntlVec3Gfx dir = mDirection;
|
||||
ntlVec3Gfx origin = mOrigin;
|
||||
gfxReal t = GFX_REAL_MAX;
|
||||
|
||||
/* check intersection planes for AABB */
|
||||
for(int i=0;i<NUMDIM;i++) {
|
||||
if(origin[i] < mStart[i]) {
|
||||
quadrant[i] = LEFT;
|
||||
candPlane [i] = mStart[i];
|
||||
inside = false;
|
||||
} else if(origin[i] > mEnd[i]) {
|
||||
quadrant[i] = RIGHT;
|
||||
candPlane[i] = mEnd[i];
|
||||
inside = false;
|
||||
} else {
|
||||
/* intersect with backside */
|
||||
if(dir[i] > 0) {
|
||||
quadrant[i] = LEFT;
|
||||
candPlane [i] = mStart[i];
|
||||
} else
|
||||
if(dir[i] < 0) {
|
||||
quadrant[i] = RIGHT;
|
||||
candPlane[i] = mEnd[i];
|
||||
} else {
|
||||
quadrant[i] = MIDDLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* get t distances to planes */
|
||||
for(int i=0;i<NUMDIM;i++) {
|
||||
if((quadrant[i] != MIDDLE) && (fabs(dir[i]) > getVecEpsilon()) ) {
|
||||
maxT[i] = (candPlane[i] - origin[i]) / dir[i];
|
||||
} else {
|
||||
maxT[i] = GFX_REAL_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
/* largest max t */
|
||||
whichPlane = 0;
|
||||
for(int i=1;i<NUMDIM;i++) {
|
||||
if( ((maxT[whichPlane] < maxT[i])&&(maxT[i]!=GFX_REAL_MAX)) ||
|
||||
(maxT[whichPlane]==GFX_REAL_MAX) )
|
||||
whichPlane = i;
|
||||
}
|
||||
|
||||
/* check final candidate */
|
||||
hit = true;
|
||||
if(maxT[whichPlane]<GFX_REAL_MAX) {
|
||||
for(int i=0;i<NUMDIM;i++) {
|
||||
if(whichPlane != i) {
|
||||
coord[i] = origin[i] + maxT[whichPlane] * dir[i];
|
||||
if( (coord[i] < mStart[i]-getVecEpsilon() ) ||
|
||||
(coord[i] > mEnd[i] +getVecEpsilon() ) ) {
|
||||
/* no hit... */
|
||||
hit = false;
|
||||
}
|
||||
}
|
||||
else { coord[i] = candPlane[i]; }
|
||||
}
|
||||
|
||||
/* AABB hit... */
|
||||
if( hit ) {
|
||||
t = maxT[whichPlane];
|
||||
}
|
||||
}
|
||||
tmin = t;
|
||||
|
||||
/* now the backside */
|
||||
t = GFX_REAL_MAX;
|
||||
for(int i=0;i<NUMDIM;i++) {
|
||||
if(origin[i] < mStart[i]) {
|
||||
quadrant[i] = LEFT;
|
||||
candPlane [i] = mEnd[i];
|
||||
} else if(origin[i] > mEnd[i]) {
|
||||
quadrant[i] = RIGHT;
|
||||
candPlane[i] = mStart[i];
|
||||
} else {
|
||||
if(dir[i] > 0) {
|
||||
quadrant[i] = LEFT;
|
||||
candPlane [i] = mEnd[i];
|
||||
} else
|
||||
if(dir[i] < 0) {
|
||||
quadrant[i] = RIGHT;
|
||||
candPlane[i] = mStart[i];
|
||||
} else {
|
||||
quadrant[i] = MIDDLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* get t distances to planes */
|
||||
for(int i=0;i<NUMDIM;i++) {
|
||||
if((quadrant[i] != MIDDLE) && (fabs(dir[i]) > getVecEpsilon()) ) {
|
||||
maxT[i] = (candPlane[i] - origin[i]) / dir[i];
|
||||
} else {
|
||||
maxT[i] = GFX_REAL_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
/* smallest max t */
|
||||
whichPlane = 0;
|
||||
for(int i=1;i<NUMDIM;i++) {
|
||||
if(maxT[whichPlane] > maxT[i]) whichPlane = i;
|
||||
}
|
||||
|
||||
/* check final candidate */
|
||||
hit = true;
|
||||
if(maxT[whichPlane] != GFX_REAL_MAX) {
|
||||
|
||||
for(int i=0;i<NUMDIM;i++) {
|
||||
if(whichPlane != i) {
|
||||
coord[i] = origin[i] + maxT[whichPlane] * dir[i];
|
||||
if( (coord[i] < mStart[i]-getVecEpsilon() ) ||
|
||||
(coord[i] > mEnd[i] +getVecEpsilon() ) ) {
|
||||
/* no hit... */
|
||||
hit = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
coord[i] = candPlane[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* AABB hit... */
|
||||
if( hit ) {
|
||||
t = maxT[whichPlane];
|
||||
}
|
||||
}
|
||||
|
||||
tmax = t;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Determine color of this ray by tracing through the scene
|
||||
*****************************************************************************/
|
||||
const ntlColor ntlRay::shade() //const
|
||||
{
|
||||
ntlGeometryObject *closest = NULL;
|
||||
gfxReal minT = GFX_REAL_MAX;
|
||||
vector<ntlLightObject*> *lightlist = mpGlob->getLightList();
|
||||
mpGlob->setCounterShades( mpGlob->getCounterShades()+1 );
|
||||
bool intersectionInside = 0;
|
||||
if(mpGlob->getDebugOut() > 5) errorOut(std::endl<<"New Ray: depth "<<mDepth<<", org "<<mOrigin<<", dir "<<mDirection );
|
||||
|
||||
/* check if this ray contributes enough */
|
||||
if(mContribution <= RAY_MINCONTRIB) {
|
||||
//return ntlColor(0.0);
|
||||
}
|
||||
|
||||
|
||||
/* find closes object that intersects */
|
||||
ntlTriangle *tri = NULL;
|
||||
ntlVec3Gfx normal;
|
||||
mpGlob->getScene()->intersectScene(*this, minT, normal, tri, 0);
|
||||
if(minT>0) {
|
||||
closest = mpGlob->getScene()->getObject( tri->getObjectId() );
|
||||
}
|
||||
|
||||
/* object hit... */
|
||||
if (closest != NULL) {
|
||||
//return( ntlColor(1.0) );
|
||||
//normal = tri->getNormal(); // no normal smoothing
|
||||
|
||||
ntlVec3Gfx triangleNormal = tri->getNormal();
|
||||
if( equal(triangleNormal, ntlVec3Gfx(0.0)) ) errorOut("ntlRaytracer warning: trinagle normal= 0 "); // DEBUG
|
||||
/* intersection on inside faces? if yes invert normal afterwards */
|
||||
gfxReal valDN; // = mDirection | normal;
|
||||
valDN = dot(mDirection, triangleNormal);
|
||||
if( valDN > 0.0) {
|
||||
intersectionInside = 1;
|
||||
normal = normal * -1.0;
|
||||
triangleNormal = triangleNormal * -1.0;
|
||||
}
|
||||
|
||||
/* ... -> do reflection */
|
||||
ntlVec3Gfx intersectionPosition(mOrigin + (mDirection * (minT)) );
|
||||
ntlMaterial *clossurf = closest->getMaterial();
|
||||
if(mpGlob->getDebugOut() > 5) {
|
||||
errorOut("Ray hit: at "<<intersectionPosition<<" n:"<<normal<<" dn:"<<valDN<<" ins:"<<intersectionInside<<" cl:"<<((unsigned int)closest) );
|
||||
errorOut(" t1:"<<mpGlob->getScene()->getVertex(tri->getPoints()[0])<<" t2:"<<mpGlob->getScene()->getVertex(tri->getPoints()[1])<<" t3:"<<mpGlob->getScene()->getVertex(tri->getPoints()[2]) );
|
||||
errorOut(" trin:"<<tri->getNormal() );
|
||||
}
|
||||
|
||||
/* current transparence and reflectivity */
|
||||
gfxReal currTrans = clossurf->getTransparence();
|
||||
gfxReal currRefl = clossurf->getMirror();
|
||||
|
||||
/* correct intersectopm position */
|
||||
intersectionPosition += ( triangleNormal*getVecEpsilon() );
|
||||
/* reflection at normal */
|
||||
ntlVec3Gfx reflectedDir = getNormalized( reflectVector(mDirection, normal) );
|
||||
int badRefl = 0;
|
||||
if(dot(reflectedDir, triangleNormal)<0.0 ) {
|
||||
badRefl = 1;
|
||||
if(mpGlob->getDebugOut() > 5) { errorOut("Ray Bad reflection...!"); }
|
||||
}
|
||||
|
||||
/* refraction direction, depending on in/outside hit */
|
||||
ntlVec3Gfx refractedDir;
|
||||
int refRefl = 0;
|
||||
/* refraction at normal is handled by inverting normal before */
|
||||
gfxReal myRefIndex = 1.0;
|
||||
if((currTrans>RAY_THRESHOLD)||(clossurf->getFresnel())) {
|
||||
if(intersectionInside) {
|
||||
myRefIndex = 1.0/clossurf->getRefracIndex();
|
||||
} else {
|
||||
myRefIndex = clossurf->getRefracIndex();
|
||||
}
|
||||
|
||||
refractedDir = refractVector(mDirection, normal, myRefIndex , (gfxReal)(1.0) /* global ref index */, refRefl);
|
||||
}
|
||||
|
||||
/* calculate fresnel? */
|
||||
if(clossurf->getFresnel()) {
|
||||
// for total reflection, just set trans to 0
|
||||
if(refRefl) {
|
||||
currRefl = 1.0; currTrans = 0.0;
|
||||
} else {
|
||||
// calculate fresnel coefficients
|
||||
clossurf->calculateFresnel( mDirection, normal, myRefIndex, currRefl,currTrans );
|
||||
}
|
||||
}
|
||||
|
||||
ntlRay reflectedRay(intersectionPosition, reflectedDir, mDepth+1, mContribution*currRefl, mpGlob);
|
||||
reflectedRay.setNormal( normal );
|
||||
ntlColor currentColor(0.0);
|
||||
ntlColor highlightColor(0.0);
|
||||
|
||||
/* first add reflected ambient color */
|
||||
currentColor += (clossurf->getAmbientRefl() * mpGlob->getAmbientLight() );
|
||||
|
||||
/* calculate lighting, not on the insides of objects... */
|
||||
if(!intersectionInside) {
|
||||
for (vector<ntlLightObject*>::iterator iter = lightlist->begin();
|
||||
iter != lightlist->end();
|
||||
iter++) {
|
||||
|
||||
/* let light illuminate point */
|
||||
currentColor += (*iter)->illuminatePoint( reflectedRay, closest, highlightColor );
|
||||
|
||||
} // for all lights
|
||||
}
|
||||
|
||||
// recurse ?
|
||||
if ((mDepth < mpGlob->getRayMaxDepth() )&&(currRefl>RAY_THRESHOLD)) {
|
||||
|
||||
if(badRefl) {
|
||||
ntlVec3Gfx intersectionPosition2;
|
||||
ntlGeometryObject *closest2 = NULL;
|
||||
gfxReal minT2 = GFX_REAL_MAX;
|
||||
ntlTriangle *tri2 = NULL;
|
||||
ntlVec3Gfx normal2;
|
||||
|
||||
ntlVec3Gfx refractionPosition2(mOrigin + (mDirection * minT) );
|
||||
refractionPosition2 -= (triangleNormal*getVecEpsilon() );
|
||||
|
||||
ntlRay reflectedRay2 = ntlRay(refractionPosition2, reflectedDir, mDepth+1, mContribution*currRefl, mpGlob);
|
||||
mpGlob->getScene()->intersectScene(reflectedRay2, minT2, normal2, tri2, 0);
|
||||
if(minT2>0) {
|
||||
closest2 = mpGlob->getScene()->getObject( tri2->getObjectId() );
|
||||
}
|
||||
|
||||
/* object hit... */
|
||||
if (closest2 != NULL) {
|
||||
ntlVec3Gfx triangleNormal2 = tri2->getNormal();
|
||||
gfxReal valDN2;
|
||||
valDN2 = dot(reflectedDir, triangleNormal2);
|
||||
if( valDN2 > 0.0) {
|
||||
triangleNormal2 = triangleNormal2 * -1.0;
|
||||
intersectionPosition2 = ntlVec3Gfx(intersectionPosition + (reflectedDir * (minT2)) );
|
||||
/* correct intersection position and create new reflected ray */
|
||||
intersectionPosition2 += ( triangleNormal2*getVecEpsilon() );
|
||||
reflectedRay = ntlRay(intersectionPosition2, reflectedDir, mDepth+1, mContribution*currRefl, mpGlob);
|
||||
} else {
|
||||
/*exit(-1);*/
|
||||
// ray seems to work, continue normally ?
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// add mirror color multiplied by mirror factor of surface
|
||||
if(mpGlob->getDebugOut() > 5) errorOut("Reflected ray from depth "<<mDepth<<", dir "<<reflectedDir );
|
||||
ntlColor reflectedColor = reflectedRay.shade() * currRefl;
|
||||
currentColor += reflectedColor;
|
||||
}
|
||||
|
||||
/* Trace another ray on for transparent objects */
|
||||
if(currTrans > RAY_THRESHOLD) {
|
||||
|
||||
//gfxReal refrac_dn = mDirection | normal;
|
||||
/* position at the other side of the surface, along ray */
|
||||
ntlVec3Gfx refraction_position(mOrigin + (mDirection * minT) );
|
||||
refraction_position += (mDirection * getVecEpsilon());
|
||||
refraction_position -= (triangleNormal*getVecEpsilon() );
|
||||
|
||||
ntlColor refracCol(0.0); /* refracted color */
|
||||
|
||||
|
||||
/* trace refracted ray */
|
||||
ntlRay transRay(refraction_position, refractedDir, mDepth+1, mContribution*currTrans, mpGlob);
|
||||
transRay.setRefracted(1);
|
||||
transRay.setNormal( normal );
|
||||
if(mDepth < mpGlob->getRayMaxDepth() ) {
|
||||
if(!refRefl) {
|
||||
if(mpGlob->getDebugOut() > 5) errorOut("Refracted ray from depth "<<mDepth<<", dir "<<refractedDir );
|
||||
refracCol = transRay.shade();
|
||||
} else {
|
||||
//we shouldnt reach this!
|
||||
if(mpGlob->getDebugOut() > 5) errorOut("Fully reflected ray from depth "<<mDepth<<", dir "<<reflectedDir );
|
||||
refracCol = reflectedRay.shade();
|
||||
}
|
||||
}
|
||||
|
||||
/* calculate color */
|
||||
/* additive transparency "light amplification" */
|
||||
ntlColor add_col = currentColor + refracCol * currTrans;
|
||||
/* subtractive transparency, more realistic */
|
||||
ntlColor sub_col = (refracCol * currTrans) +
|
||||
( currentColor * (1.0-currTrans) );
|
||||
|
||||
/* mix additive and subtractive */
|
||||
add_col += sub_col;
|
||||
currentColor += (refracCol * currTrans);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* add highlights (should not be affected by transparence as the diffuse reflections */
|
||||
currentColor += highlightColor;
|
||||
|
||||
/* attentuate as a last step*/
|
||||
//if(currTrans > RAY_THRESHOLD) {
|
||||
/* check if we're on the inside or outside */
|
||||
if(intersectionInside) {
|
||||
gfxReal kr,kg,kb; /* attentuation */
|
||||
/* calculate attentuation */
|
||||
ntlColor attCol = clossurf->getTransAttCol();
|
||||
kr = exp( attCol[0] * minT );
|
||||
kg = exp( attCol[1] * minT );
|
||||
kb = exp( attCol[2] * minT );
|
||||
currentColor = currentColor * ntlColor(kr,kg,kb);
|
||||
}
|
||||
|
||||
/* done... */
|
||||
if(mpGlob->getDebugOut() > 5) { errorOut("Ray "<<mDepth<<" color "<<currentColor ); }
|
||||
return ntlColor(currentColor);
|
||||
}
|
||||
|
||||
/* no object hit -> ray goes to infinity */
|
||||
return mpGlob->getBackgroundCol();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
234
intern/elbeem/intern/ntl_ray.h
Normal file
234
intern/elbeem/intern/ntl_ray.h
Normal file
@ -0,0 +1,234 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* ray class
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef NTL_RAY_HH
|
||||
#define NTL_RAY_HH
|
||||
|
||||
#include "ntl_vector3dim.h"
|
||||
#include "ntl_lightobject.h"
|
||||
#include "ntl_geometryobject.h"
|
||||
#include "ntl_renderglobals.h"
|
||||
|
||||
|
||||
/* Minimum value for refl/refr to be traced */
|
||||
#define RAY_THRESHOLD 0.001
|
||||
|
||||
#if GFX_PRECISION==1
|
||||
// float values
|
||||
//! the minimal triangle determinant length
|
||||
#define RAY_TRIANGLE_EPSILON (1e-08)
|
||||
//! Minimal contribution for rays to be traced on
|
||||
#define RAY_MINCONTRIB (1e-04)
|
||||
|
||||
#else
|
||||
// double values
|
||||
//! the minimal triangle determinant length
|
||||
#define RAY_TRIANGLE_EPSILON (1e-15)
|
||||
//! Minimal contribution for rays to be traced on
|
||||
#define RAY_MINCONTRIB (1e-05)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//! store data for an intersection of a ray and a triangle
|
||||
// NOT YET USED
|
||||
class ntlIntersection {
|
||||
public:
|
||||
|
||||
ntlIntersection() :
|
||||
distance(-1.0), normal(0.0),
|
||||
ray(NULL), tri(NULL), flags(0) { };
|
||||
|
||||
gfxReal distance;
|
||||
ntlVec3Gfx normal;
|
||||
ntlRay *ray;
|
||||
ntlTriangle *tri;
|
||||
char flags;
|
||||
};
|
||||
|
||||
//! the main ray class
|
||||
class ntlRay
|
||||
{
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
//! Initialize ray memebers, prints error message
|
||||
ntlRay();
|
||||
//! Copy constructor, copy all members
|
||||
ntlRay(const ntlRay &r);
|
||||
//! Explicitly init member variables with global render object
|
||||
ntlRay(const ntlVec3Gfx &o, const ntlVec3Gfx &d, unsigned int i, gfxReal contrib, ntlRenderGlobals *glob);
|
||||
//! Destructor
|
||||
~ntlRay();
|
||||
|
||||
//! Set the refraction flag for refracted rays
|
||||
inline void setRefracted(unsigned char set) { mIsRefracted = set; }
|
||||
inline void setReflected(unsigned char set) { mIsReflected = set; }
|
||||
|
||||
//! main ray recursion function
|
||||
/*!
|
||||
* First get closest object intersection, return background color if nothing
|
||||
* was hit, else calculate shading and reflection components
|
||||
* and return mixed color */
|
||||
const ntlColor shade() /*const*/;
|
||||
|
||||
/*! Trace a photon through the scene */
|
||||
void tracePhoton(ntlColor) const;
|
||||
|
||||
//! intersect ray with AABB
|
||||
void intersectFrontAABB(ntlVec3Gfx mStart, ntlVec3Gfx mEnd, gfxReal &t, ntlVec3Gfx &normal, ntlVec3Gfx &retcoord) const;
|
||||
void intersectBackAABB(ntlVec3Gfx mStart, ntlVec3Gfx mEnd, gfxReal &t, ntlVec3Gfx &normal, ntlVec3Gfx &retcoord) const;
|
||||
void intersectCompleteAABB(ntlVec3Gfx mStart, ntlVec3Gfx mEnd, gfxReal &tmin, gfxReal &tmax) const;
|
||||
//! optimized intersect ray with triangle
|
||||
inline void intersectTriangle(vector<ntlVec3Gfx> *mpV, ntlTriangle *tri, gfxReal &t, gfxReal &u, gfxReal &v) const;
|
||||
//! intersect only with front side
|
||||
inline void intersectTriangleFront(vector<ntlVec3Gfx> *mpV, ntlTriangle *tri, gfxReal &t, gfxReal &u, gfxReal &v) const;
|
||||
//! intersect ray only with backsides
|
||||
inline void intersectTriangleBack(vector<ntlVec3Gfx> *mpV, ntlTriangle *tri, gfxReal &t, gfxReal &u, gfxReal &v) const;
|
||||
|
||||
// access methods
|
||||
//! Returns the ray origin
|
||||
inline ntlVec3Gfx getOrigin() const { return ntlVec3Gfx(mOrigin); }
|
||||
//! Returns the ray direction
|
||||
inline ntlVec3Gfx getDirection() const { return ntlVec3Gfx(mDirection); }
|
||||
/*! Returns the ray relfection normal */
|
||||
inline ntlVec3Gfx getNormal() const { return ntlVec3Gfx(mvNormal); }
|
||||
//! Is this ray refracted?
|
||||
inline unsigned char getRefracted() const { return mIsRefracted; }
|
||||
inline unsigned char getReflected() const { return mIsReflected; }
|
||||
/*! Get position along ray */
|
||||
inline ntlVec3Gfx getPositionAt(gfxReal t) const { return (mOrigin+(mDirection*t)); }
|
||||
/*! Get render globals pointer of this ray */
|
||||
inline ntlRenderGlobals *getRenderglobals( void ) const { return mpGlob; }
|
||||
/*! get this ray's ID */
|
||||
inline int getID( void ) const { return mID; }
|
||||
|
||||
/*! Set origin of this ray */
|
||||
inline void setOrigin(ntlVec3Gfx set) { mOrigin = set; }
|
||||
/*! Set direction of this ray */
|
||||
inline void setDirection(ntlVec3Gfx set) { mDirection = set; }
|
||||
/*! Set normal of this ray */
|
||||
inline void setNormal(ntlVec3Gfx set) { mvNormal = set; }
|
||||
|
||||
protected:
|
||||
/* Calulates the Lambertian and Specular color for
|
||||
* the given reflection and returns it */
|
||||
const ntlColor getShadedColor(ntlLightObject *light, const ntlRay &reflectedray,
|
||||
const ntlVec3Gfx &normal, ntlMaterial *surf) const;
|
||||
|
||||
private:
|
||||
/*! Origin of ray */
|
||||
ntlVec3Gfx mOrigin;
|
||||
/*! Normalized direction vector of ray */
|
||||
ntlVec3Gfx mDirection;
|
||||
/*! For reflected/refracted rays, the normal is stored here */
|
||||
ntlVec3Gfx mvNormal;
|
||||
/*! recursion depth */
|
||||
unsigned int mDepth;
|
||||
/*! How much does this ray contribute to the surface color? abort if too small */
|
||||
gfxReal mContribution;
|
||||
|
||||
/*! Global rendering settings */
|
||||
ntlRenderGlobals *mpGlob;
|
||||
|
||||
/*! If this ray is a refracted one, this flag has to be set
|
||||
* This is necessary to for example also give the background color
|
||||
* to refracted rays. Otherwise things may look strange...
|
||||
*/
|
||||
unsigned char mIsRefracted;
|
||||
unsigned char mIsReflected;
|
||||
|
||||
/*! ID of this ray (from renderglobals */
|
||||
int mID;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************************
|
||||
* triangle intersection with triangle pointer,
|
||||
* returns t,u,v by references
|
||||
*/
|
||||
inline void ntlRay::intersectTriangle(vector<ntlVec3Gfx> *mpV, ntlTriangle *tri, gfxReal &t, gfxReal &u, gfxReal &v) const
|
||||
{
|
||||
/* (cf. moeller&haines, page 305) */
|
||||
t = GFX_REAL_MAX;
|
||||
ntlVec3Gfx e0 = (*mpV)[ tri->getPoints()[0] ];
|
||||
ntlVec3Gfx e1 = (*mpV)[ tri->getPoints()[1] ] - e0;
|
||||
ntlVec3Gfx e2 = (*mpV)[ tri->getPoints()[2] ] - e0;
|
||||
ntlVec3Gfx p = cross( mDirection, e2 );
|
||||
gfxReal a = dot(e1, p);
|
||||
if((a > -RAY_TRIANGLE_EPSILON)&&(a < RAY_TRIANGLE_EPSILON)) return;
|
||||
|
||||
gfxReal f = 1/a;
|
||||
ntlVec3Gfx s = mOrigin - e0;
|
||||
u = f * dot(s, p);
|
||||
if( (u<0.0-RAY_TRIANGLE_EPSILON) || (u>1.0+RAY_TRIANGLE_EPSILON) ) return;
|
||||
|
||||
ntlVec3Gfx q = cross( s,e1 );
|
||||
v = f * dot(mDirection, q);
|
||||
if( (v<0.0-RAY_TRIANGLE_EPSILON) || ((u+v)>1.0+RAY_TRIANGLE_EPSILON) ) return;
|
||||
|
||||
t = f * dot(e2, q);
|
||||
}
|
||||
/******************************************************************
|
||||
* intersect only front or backsides
|
||||
*/
|
||||
inline void ntlRay::intersectTriangleFront(vector<ntlVec3Gfx> *mpV, ntlTriangle *tri, gfxReal &t, gfxReal &u, gfxReal &v) const
|
||||
{
|
||||
t = GFX_REAL_MAX;
|
||||
ntlVec3Gfx e0 = (*mpV)[ tri->getPoints()[0] ];
|
||||
ntlVec3Gfx e1 = (*mpV)[ tri->getPoints()[1] ] - e0;
|
||||
ntlVec3Gfx e2 = (*mpV)[ tri->getPoints()[2] ] - e0;
|
||||
ntlVec3Gfx p = cross( mDirection, e2 );
|
||||
gfxReal a = dot(e1, p);
|
||||
//if((a > -RAY_TRIANGLE_EPSILON)&&(a < RAY_TRIANGLE_EPSILON)) return;
|
||||
if(a < RAY_TRIANGLE_EPSILON) return; // cull backsides
|
||||
|
||||
gfxReal f = 1/a;
|
||||
ntlVec3Gfx s = mOrigin - e0;
|
||||
u = f * dot(s, p);
|
||||
if( (u<0.0-RAY_TRIANGLE_EPSILON) || (u>1.0+RAY_TRIANGLE_EPSILON) ) return;
|
||||
|
||||
ntlVec3Gfx q = cross( s,e1 );
|
||||
v = f * dot(mDirection, q);
|
||||
if( (v<0.0-RAY_TRIANGLE_EPSILON) || ((u+v)>1.0+RAY_TRIANGLE_EPSILON) ) return;
|
||||
|
||||
t = f * dot(e2, q);
|
||||
}
|
||||
inline void ntlRay::intersectTriangleBack(vector<ntlVec3Gfx> *mpV, ntlTriangle *tri, gfxReal &t, gfxReal &u, gfxReal &v) const
|
||||
{
|
||||
t = GFX_REAL_MAX;
|
||||
ntlVec3Gfx e0 = (*mpV)[ tri->getPoints()[0] ];
|
||||
ntlVec3Gfx e1 = (*mpV)[ tri->getPoints()[1] ] - e0;
|
||||
ntlVec3Gfx e2 = (*mpV)[ tri->getPoints()[2] ] - e0;
|
||||
ntlVec3Gfx p = cross( mDirection, e2 );
|
||||
gfxReal a = dot(e1, p);
|
||||
//if((a > -RAY_TRIANGLE_EPSILON)&&(a < RAY_TRIANGLE_EPSILON)) return;
|
||||
if(a > -RAY_TRIANGLE_EPSILON) return; // cull frontsides
|
||||
|
||||
gfxReal f = 1/a;
|
||||
ntlVec3Gfx s = mOrigin - e0;
|
||||
u = f * dot(s, p);
|
||||
if( (u<0.0-RAY_TRIANGLE_EPSILON) || (u>1.0+RAY_TRIANGLE_EPSILON) ) return;
|
||||
|
||||
ntlVec3Gfx q = cross( s,e1 );
|
||||
v = f * dot(mDirection, q);
|
||||
if( (v<0.0-RAY_TRIANGLE_EPSILON) || ((u+v)>1.0+RAY_TRIANGLE_EPSILON) ) return;
|
||||
|
||||
t = f * dot(e2, q);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
726
intern/elbeem/intern/ntl_raytracer.cpp
Normal file
726
intern/elbeem/intern/ntl_raytracer.cpp
Normal file
@ -0,0 +1,726 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* Main renderer class
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sstream>
|
||||
#include "utilities.h"
|
||||
#include "ntl_raytracer.h"
|
||||
#include "ntl_scene.h"
|
||||
#include "parametrizer.h"
|
||||
#include "globals.h"
|
||||
|
||||
// for non-threaded renderViz
|
||||
#ifndef NOGUI
|
||||
#include "../gui/ntl_openglrenderer.h"
|
||||
#include "../gui/guifuncs.h"
|
||||
#include "../gui/frame.h"
|
||||
#endif
|
||||
|
||||
|
||||
/* external parser functions from cfgparser.cxx */
|
||||
//#include "cfgparse_functions.h"
|
||||
|
||||
/* parse given file as config file */
|
||||
void parseFile(string filename);
|
||||
|
||||
/* set pointers for parsing */
|
||||
void setPointers( ntlRenderGlobals *setglob);
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Constructor
|
||||
*****************************************************************************/
|
||||
ntlRaytracer::ntlRaytracer(string filename, bool commandlineMode) :
|
||||
mpGlob(NULL),
|
||||
mpLightList(NULL), mpPropList(NULL), mpSims(NULL),
|
||||
mpOpenGLRenderer(NULL),
|
||||
mStopRenderVisualization( false ),
|
||||
mThreadRunning( false ),
|
||||
mSimulationTime(0.0), mFirstSim(-1),
|
||||
mSingleStepDebug( false )
|
||||
{
|
||||
/* create scene storage */
|
||||
mpGlob = new ntlRenderGlobals();
|
||||
mpLightList = new vector<ntlLightObject*>;
|
||||
mpPropList = new vector<ntlMaterial*>;
|
||||
mpSims = new vector<SimulationObject*>;
|
||||
|
||||
mpGlob->setLightList(mpLightList);
|
||||
mpGlob->setMaterials(mpPropList);
|
||||
mpGlob->setSims(mpSims);
|
||||
|
||||
/* init default material */
|
||||
ntlMaterial *def = GET_GLOBAL_DEFAULT_MATERIAL;
|
||||
mpPropList->push_back( def );
|
||||
|
||||
/* init the scene object */
|
||||
ntlScene *scene;
|
||||
scene = new ntlScene( mpGlob );
|
||||
mpGlob->setScene( scene );
|
||||
|
||||
// load config
|
||||
setPointers( getRenderGlobals() );
|
||||
parseFile( filename.c_str() );
|
||||
|
||||
|
||||
// init the scene for the first time
|
||||
long startTime = getTime();
|
||||
scene->buildScene();
|
||||
long stopTime = getTime();
|
||||
debMsgStd("ntlRaytracer::ntlRaytracer",DM_MSG,"Scene build time: "<< getTimeString(stopTime-startTime) <<" ", 10);
|
||||
|
||||
// TODO check simulations, run first steps
|
||||
mFirstSim = -1;
|
||||
if(mpSims->size() > 0) {
|
||||
|
||||
// use values from first simulation as master time scale
|
||||
long startTime = getTime();
|
||||
|
||||
// remember first active sim
|
||||
for(size_t i=0;i<mpSims->size();i++) {
|
||||
if(!(*mpSims)[i]->getVisible()) continue;
|
||||
if((*mpSims)[i]->getPanic()) continue;
|
||||
|
||||
// check largest timestep
|
||||
if(mFirstSim>=0) {
|
||||
if( (*mpSims)[i]->getStepTime() > (*mpSims)[mFirstSim]->getStepTime() ) {
|
||||
mFirstSim = i;
|
||||
debMsgStd("ntlRaytracer::ntlRaytracer",DM_MSG,"First Sim changed: "<<i ,10);
|
||||
}
|
||||
}
|
||||
// check any valid sim
|
||||
if(mFirstSim<0) {
|
||||
mFirstSim = i;
|
||||
debMsgStd("ntlRaytracer::ntlRaytracer",DM_MSG,"First Sim: "<<i ,10);
|
||||
}
|
||||
}
|
||||
|
||||
if(mFirstSim>=0) {
|
||||
debMsgStd("ntlRaytracer::ntlRaytracer",DM_MSG,"Anistart Time: "<<(*mpSims)[mFirstSim]->getStartTime() ,10);
|
||||
while(mSimulationTime < (*mpSims)[mFirstSim]->getStartTime() ) {
|
||||
debMsgStd("ntlRaytracer::ntlRaytracer",DM_MSG,"Anistart Time: "<<(*mpSims)[mFirstSim]->getStartTime()<<" simtime:"<<mSimulationTime ,10);
|
||||
advanceSims();
|
||||
}
|
||||
long stopTime = getTime();
|
||||
|
||||
mSimulationTime += (*mpSims)[mFirstSim]->getStartTime();
|
||||
debMsgStd("ntlRaytracer::ntlRaytracer",DM_MSG,"Time for start simulations times "<<": "<< getTimeString(stopTime-startTime) <<"s ", 1);
|
||||
#ifndef NOGUI
|
||||
guiResetSimulationTimeRange( mSimulationTime );
|
||||
#endif
|
||||
} else {
|
||||
if(!mpGlob->getSingleFrameMode()) debMsgStd("ntlRaytracer::ntlRaytracer",DM_WARNING,"No active simulations!", 1);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NOGUI
|
||||
// setup opengl display, save first animation step for start time
|
||||
if(!commandlineMode) {
|
||||
mpOpenGLRenderer = new ntlOpenGLRenderer( mpGlob, scene );
|
||||
}
|
||||
#else // NOGUI
|
||||
commandlineMode = true; // remove warning...
|
||||
#endif // NOGUI
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Destructor
|
||||
*****************************************************************************/
|
||||
ntlRaytracer::~ntlRaytracer()
|
||||
{
|
||||
delete mpGlob->getScene();
|
||||
delete mpGlob;
|
||||
delete mpLightList;
|
||||
delete mpPropList;
|
||||
delete mpSims;
|
||||
#ifndef NOGUI
|
||||
if(mpOpenGLRenderer) delete mpOpenGLRenderer;
|
||||
#endif // NOGUI
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/*! set single frame rendering to filename */
|
||||
void ntlRaytracer::setSingleFrameOut(string singleframeFilename) {
|
||||
mpGlob->setSingleFrameMode(true);
|
||||
mpGlob->setSingleFrameFilename(singleframeFilename);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* render a whole animation (command line mode)
|
||||
*****************************************************************************/
|
||||
#if ELBEEM_BLENDER==1
|
||||
extern "C" {
|
||||
void simulateThreadIncreaseFrame(void);
|
||||
}
|
||||
#endif // ELBEEM_BLENDER==1
|
||||
int ntlRaytracer::renderAnimation( void )
|
||||
{
|
||||
// only single pic currently
|
||||
//debMsgStd("ntlRaytracer::renderAnimation : Warning only simulating...",1);
|
||||
if(mpGlob->getAniFrames() < 0) {
|
||||
debMsgStd("ntlRaytracer::renderAnimation",DM_NOTIFY,"No frames to render... ",1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(mFirstSim<0) {
|
||||
debMsgStd("ntlRaytracer::renderAnimation",DM_NOTIFY,"No reference animation found...",1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
mThreadRunning = true; // not threaded, but still use the same flags
|
||||
renderScene();
|
||||
for(int i=0; ((i<mpGlob->getAniFrames()) && (!getStopRenderVisualization() )); i++) {
|
||||
advanceSims();
|
||||
renderScene();
|
||||
#if ELBEEM_BLENDER==1
|
||||
// update gui display
|
||||
simulateThreadIncreaseFrame();
|
||||
#endif // ELBEEM_BLENDER==1
|
||||
|
||||
if(mpSims->size() <= 0) {
|
||||
debMsgStd("ntlRaytracer::renderAnimation",DM_NOTIFY,"No simulations found, stopping...",1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
mThreadRunning = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* render a whole animation (visualization mode)
|
||||
* this function is run in another thread, and communicates
|
||||
* with the parent thread via a mutex
|
||||
*****************************************************************************/
|
||||
int ntlRaytracer::renderVisualization( bool multiThreaded )
|
||||
{
|
||||
#ifndef NOGUI
|
||||
//gfxReal deltat = 0.0015;
|
||||
if(multiThreaded) mThreadRunning = true;
|
||||
while(!getStopRenderVisualization()) {
|
||||
|
||||
if(mpSims->size() <= 0) {
|
||||
debMsgStd("ntlRaytracer::renderVisualization",DM_NOTIFY,"No simulations found, stopping...",1);
|
||||
stopSimulationThread();
|
||||
break;
|
||||
}
|
||||
|
||||
// determine stepsize
|
||||
if(!mSingleStepDebug) {
|
||||
long startTime = getTime();
|
||||
advanceSims();
|
||||
long stopTime = getTime();
|
||||
debMsgStd("ntlRaytracer::renderVisualization",DM_MSG,"Time for "<<mSimulationTime<<": "<< getTimeString(stopTime-startTime) <<"s ", 10);
|
||||
} else {
|
||||
double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getStepTime();
|
||||
singleStepSims(targetTime);
|
||||
|
||||
// check paniced sims (normally done by advanceSims
|
||||
bool allPanic = true;
|
||||
for(size_t i=0;i<mpSims->size();i++) {
|
||||
if(!(*mpSims)[i]->getPanic()) allPanic = false;
|
||||
}
|
||||
if(allPanic) {
|
||||
warnMsg("ntlRaytracer::advanceSims","All sims panicked... stopping thread" );
|
||||
setStopRenderVisualization( true );
|
||||
}
|
||||
//? mSimulationTime = (*mpSims)[mFirstSim]->getCurrentTime();
|
||||
//debMsgStd("ntlRaytracer::renderVisualization : single step mode ", 10);
|
||||
//debMsgStd("", 10 );
|
||||
}
|
||||
|
||||
#ifndef NOGUI
|
||||
// save frame
|
||||
if(mpOpenGLRenderer) mpOpenGLRenderer->saveAnimationFrame( mSimulationTime );
|
||||
#endif // NOGUI
|
||||
|
||||
// for non-threaded check events
|
||||
if(!multiThreaded) {
|
||||
//if(gpElbeemFrame->ElbeemWindow->visible()) {
|
||||
//if (!Fl::check()) break; // returns immediately
|
||||
//}
|
||||
Fl::check();
|
||||
//gpElbeemFrame->SceneDisplay->doIdleRedraw();
|
||||
gpElbeemFrame->SceneDisplay->doOnlyForcedRedraw();
|
||||
}
|
||||
|
||||
}
|
||||
mThreadRunning = false;
|
||||
stopSimulationRestoreGui();
|
||||
#else
|
||||
multiThreaded = false; // remove warning
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
/*! render a single step for viz mode */
|
||||
int ntlRaytracer::singleStepVisualization( void )
|
||||
{
|
||||
mThreadRunning = true;
|
||||
double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getStepTime();
|
||||
singleStepSims(targetTime);
|
||||
mSimulationTime = (*mpSims)[0]->getCurrentTime();
|
||||
|
||||
#ifndef NOGUI
|
||||
if(mpOpenGLRenderer) mpOpenGLRenderer->saveAnimationFrame( mSimulationTime );
|
||||
Fl::check();
|
||||
gpElbeemFrame->SceneDisplay->doOnlyForcedRedraw();
|
||||
#endif // NOGUI
|
||||
|
||||
mThreadRunning = false;
|
||||
#ifndef NOGUI
|
||||
stopSimulationRestoreGui();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
// dont use LBM_EPSILON here, time is always double-precision!
|
||||
#define LBM_TIME_EPSILON 1e-10
|
||||
|
||||
/******************************************************************************
|
||||
* advance simulations by time t
|
||||
*****************************************************************************/
|
||||
int ntlRaytracer::advanceSims()
|
||||
{
|
||||
//gfxReal currTime[ mpSims->size() ];
|
||||
|
||||
bool done = false;
|
||||
bool allPanic = true;
|
||||
double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getFrameTime();
|
||||
//debMsgStd("ntlRaytracer::advanceSims",DM_MSG,"Advancing sims to "<<targetTime, 10 ); // timedebug
|
||||
|
||||
while(!done) {
|
||||
double nextTargetTime = (*mpSims)[mFirstSim]->getCurrentTime() + (*mpSims)[mFirstSim]->getStepTime();
|
||||
singleStepSims(nextTargetTime);
|
||||
|
||||
// check target times
|
||||
done = true;
|
||||
allPanic = false;
|
||||
for(size_t i=0;i<mpSims->size();i++) {
|
||||
if(!(*mpSims)[i]->getVisible()) continue;
|
||||
if((*mpSims)[i]->getPanic()) allPanic = true; // do any panic now!?
|
||||
//debMsgStd("ntlRaytracer::advanceSims",DM_MSG, " sim "<<i<<" c"<<(*mpSims)[i]->getCurrentTime()<<" p"<<(*mpSims)[i]->getPanic()<<" t"<<targetTime, 10); // debug // timedebug
|
||||
}
|
||||
//if((*mpSims)[mFirstSim]->getCurrentTime() < targetTime) done = false;
|
||||
if( (targetTime - (*mpSims)[mFirstSim]->getCurrentTime()) > LBM_TIME_EPSILON) done=false;
|
||||
if(allPanic) done = true;
|
||||
}
|
||||
|
||||
if(allPanic) {
|
||||
warnMsg("ntlRaytracer::advanceSims","All sims panicked... stopping thread" );
|
||||
setStopRenderVisualization( true );
|
||||
}
|
||||
for(size_t i=0;i<mpSims->size();i++) {
|
||||
SimulationObject *sim = (*mpSims)[i];
|
||||
if(!sim->getVisible()) continue;
|
||||
if(sim->getPanic()) continue;
|
||||
sim->prepareVisualization();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* advance simulations by a single step */
|
||||
/* dont check target time, if *targetTime==NULL */
|
||||
void ntlRaytracer::singleStepSims(double targetTime) {
|
||||
const bool debugTime = false;
|
||||
//double targetTime = mSimulationTime + (*mpSims)[mFirstSim]->getStepTime();
|
||||
if(debugTime) errMsg("ntlRaytracer::singleStepSims","Target time: "<<targetTime);
|
||||
|
||||
for(size_t i=0;i<mpSims->size();i++) {
|
||||
SimulationObject *sim = (*mpSims)[i];
|
||||
if(!sim->getVisible()) continue;
|
||||
if(sim->getPanic()) continue;
|
||||
bool done = false;
|
||||
while(!done) {
|
||||
// try to prevent round off errs
|
||||
if(debugTime) errMsg("ntlRaytracer::singleStepSims","Test sim "<<i<<" curt:"<< sim->getCurrentTime()<<" target:"<<targetTime<<" delta:"<<(targetTime - sim->getCurrentTime())<<" stept:"<<sim->getStepTime()<<" leps:"<<LBM_TIME_EPSILON ); // timedebug
|
||||
if( (targetTime - sim->getCurrentTime()) > LBM_TIME_EPSILON) {
|
||||
if(debugTime) errMsg("ntlRaytracer::singleStepSims","Stepping sim "<<i<<" t:"<< sim->getCurrentTime()); // timedebug
|
||||
sim->step();
|
||||
} else {
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mSimulationTime = (*mpSims)[mFirstSim]->getCurrentTime();
|
||||
#ifndef NOGUI
|
||||
if(mpOpenGLRenderer) mpOpenGLRenderer->notifyOfNextStep(mSimulationTime);
|
||||
#endif // NOGUI
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Render the current scene
|
||||
* uses the global variables from the parser
|
||||
*****************************************************************************/
|
||||
int ntlRaytracer::renderScene( void )
|
||||
{
|
||||
char nrStr[5]; /* nr conversion */
|
||||
//std::ostringstream outfilename(""); /* ppm file */
|
||||
std::ostringstream outfn_conv(""); /* converted ppm with other suffix */
|
||||
ntlRenderGlobals *glob; /* storage for global rendering parameters */
|
||||
myTime_t timeStart,totalStart,timeEnd; /* measure user running time */
|
||||
myTime_t rendStart,rendEnd; /* measure user rendering time */
|
||||
glob = mpGlob;
|
||||
|
||||
/* check if picture already exists... */
|
||||
if(!glob->getSingleFrameMode() ) {
|
||||
snprintf(nrStr, 5, "%04d", glob->getAniCount() );
|
||||
//outfilename << glob->getOutFilename() <<"_" << nrStr << ".ppm";
|
||||
outfn_conv << glob->getOutFilename() <<"_" << nrStr << ".png";
|
||||
|
||||
//if((mpGlob->getDisplayMode() == DM_RAY)&&(mpGlob->getFrameSkip())) {
|
||||
if(mpGlob->getFrameSkip()) {
|
||||
struct stat statBuf;
|
||||
if(stat(outfn_conv.str().c_str(),&statBuf) == 0) {
|
||||
errorOut("ntlRaytracer::renderscene Warning: file "<<outfn_conv.str()<<" already exists - skipping frame...");
|
||||
glob->setAniCount( glob->getAniCount() +1 );
|
||||
return(2);
|
||||
}
|
||||
} // RAY mode
|
||||
} else {
|
||||
// single frame rendering, overwrite if necessary...
|
||||
outfn_conv << glob->getSingleFrameFilename();
|
||||
}
|
||||
|
||||
/* start program */
|
||||
timeStart = getTime();
|
||||
|
||||
/* build scene geometry */
|
||||
glob->getScene()->prepareScene();
|
||||
|
||||
/* start program */
|
||||
totalStart = getTime();
|
||||
|
||||
|
||||
/* view parameters are currently not animated */
|
||||
/* calculate rays through projection plane */
|
||||
ntlVec3Gfx direction = glob->getLookat() - glob->getEye();
|
||||
/* calculate width of screen using perpendicular triangle diven by
|
||||
* viewing direction and screen plane */
|
||||
gfxReal screenWidth = norm(direction)*tan( (glob->getFovy()*0.5/180.0)*M_PI );
|
||||
|
||||
/* calculate vector orthogonal to up and viewing direction */
|
||||
ntlVec3Gfx upVec = glob->getUpVec();
|
||||
ntlVec3Gfx rightVec( cross(upVec,direction) );
|
||||
normalize(rightVec);
|
||||
|
||||
/* calculate screen plane up vector, perpendicular to viewdir and right vec */
|
||||
upVec = ntlVec3Gfx( cross(rightVec,direction) );
|
||||
normalize(upVec);
|
||||
|
||||
/* check if vectors are valid */
|
||||
if( (equal(upVec,ntlVec3Gfx(0.0))) || (equal(rightVec,ntlVec3Gfx(0.0))) ) {
|
||||
errorOut("NTL ERROR: Invalid viewpoint vectors!\n");
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* length from center to border of screen plane */
|
||||
rightVec *= (screenWidth*glob->getAspect() * -1.0);
|
||||
upVec *= (screenWidth * -1.0);
|
||||
|
||||
/* screen traversal variables */
|
||||
ntlVec3Gfx screenPos; /* current position on virtual screen */
|
||||
int Xres = glob->getResX(); /* X resolution */
|
||||
int Yres = glob->getResY(); /* Y resolution */
|
||||
ntlVec3Gfx rightStep = (rightVec/(Xres/2.0)); /* one step right for a pixel */
|
||||
ntlVec3Gfx upStep = (upVec/(Yres/2.0)); /* one step up for a pixel */
|
||||
|
||||
|
||||
/* anti alias init */
|
||||
char showAAPic = 0;
|
||||
int aaDepth = glob->getAADepth();
|
||||
int aaLength;
|
||||
if(aaDepth>=0) aaLength = (2<<aaDepth);
|
||||
else aaLength = 0;
|
||||
float aaSensRed = 0.1;
|
||||
float aaSensGreen = 0.1;
|
||||
float aaSensBlue = 0.1;
|
||||
int aaArrayX = aaLength*Xres+1;
|
||||
int aaArrayY = ( aaLength+1 );
|
||||
ntlColor *aaCol = new ntlColor[ aaArrayX*aaArrayY ];
|
||||
char *aaUse = new char[ aaArrayX*aaArrayY ];
|
||||
|
||||
/* picture storage */
|
||||
int picX = Xres;
|
||||
int picY = Yres;
|
||||
if(showAAPic) {
|
||||
picX = Xres *aaLength+1;
|
||||
picY = Yres *aaLength+1;
|
||||
}
|
||||
ntlColor *finalPic = new ntlColor[picX * picY];
|
||||
|
||||
|
||||
/* reset picture vars */
|
||||
for(int j=0;j<aaArrayY;j++) {
|
||||
for(int i=0;i<aaArrayX;i++) {
|
||||
aaCol[j*aaArrayX+i] = ntlColor(0.0, 0.0, 0.0);
|
||||
aaUse[j*aaArrayX+i] = 0;
|
||||
}
|
||||
}
|
||||
for(int j=0;j<picY;j++) {
|
||||
for(int i=0;i<picX;i++) {
|
||||
finalPic[j*picX+i] = ntlColor(0.0, 0.0, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
/* loop over all y lines in screen, from bottom to top because
|
||||
* ppm format wants 0,0 top left */
|
||||
rendStart = getTime();
|
||||
glob->setCounterShades(0);
|
||||
glob->setCounterSceneInter(0);
|
||||
for (int scanline=Yres ; scanline > 0 ; --scanline) {
|
||||
|
||||
debugOutInter( "ntlRaytracer::renderScene: Line "<<scanline<<
|
||||
" ("<< ((Yres-scanline)*100/Yres) <<"%) ", 2, 2000 );
|
||||
screenPos = glob->getLookat() + upVec*((2.0*scanline-Yres)/Yres)
|
||||
- rightVec;
|
||||
|
||||
/* loop over all pixels in line */
|
||||
for (int sx=0 ; sx < Xres ; ++sx) {
|
||||
|
||||
if((sx==glob->getDebugPixelX())&&(scanline==(Yres-glob->getDebugPixelY()) )) {
|
||||
// DEBUG!!!
|
||||
glob->setDebugOut(10);
|
||||
} else glob->setDebugOut(0);
|
||||
|
||||
/* compute ray from eye through current pixel into scene... */
|
||||
ntlColor col;
|
||||
if(aaDepth<0) {
|
||||
ntlVec3Gfx dir(screenPos - glob->getEye());
|
||||
ntlRay the_ray(glob->getEye(), getNormalized(dir), 0, 1.0, glob );
|
||||
|
||||
/* ...and trace it */
|
||||
col = the_ray.shade();
|
||||
} else {
|
||||
/* anti alias */
|
||||
int ai,aj; /* position in grid */
|
||||
int aOrg = sx*aaLength; /* grid offset x */
|
||||
int currStep = aaLength; /* step size */
|
||||
char colDiff = 1; /* do colors still differ too much? */
|
||||
ntlColor minCol,maxCol; /* minimum and maximum Color Values */
|
||||
minCol = ntlColor(1.0,1.0,1.0);
|
||||
maxCol = ntlColor(0.0,0.0,0.0);
|
||||
|
||||
while((colDiff) && (currStep>0)) {
|
||||
colDiff = 0;
|
||||
|
||||
for(aj = 0;aj<=aaLength;aj+= currStep) {
|
||||
for(ai = 0;ai<=aaLength;ai+= currStep) {
|
||||
|
||||
/* shade pixel if not done */
|
||||
if(aaUse[aj*aaArrayX +ai +aOrg] == 0) {
|
||||
aaUse[aj*aaArrayX +ai +aOrg] = 1;
|
||||
ntlVec3Gfx aaPos( screenPos +
|
||||
(rightStep * (ai- aaLength/2)/(gfxReal)aaLength ) +
|
||||
(upStep * (aj- aaLength/2)/(gfxReal)aaLength ) );
|
||||
|
||||
ntlVec3Gfx dir(aaPos - glob->getEye());
|
||||
ntlRay the_ray(glob->getEye(), getNormalized(dir), 0, 1.0, glob );
|
||||
|
||||
/* ...and trace it */
|
||||
ntlColor newCol= the_ray.shade();
|
||||
aaCol[aj*aaArrayX +ai +aOrg]= newCol;
|
||||
} /* not used? */
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* check color differences */
|
||||
for(aj = 0;aj<aaLength;aj+= currStep) {
|
||||
for(ai = 0;ai<aaLength;ai+= currStep) {
|
||||
|
||||
char thisColDiff = 0;
|
||||
if(
|
||||
(fabs(aaCol[aj*aaArrayX +ai +aOrg][0] -
|
||||
aaCol[(aj+0)*aaArrayX +(ai+currStep) +aOrg][0])> aaSensRed ) ||
|
||||
(fabs(aaCol[aj*aaArrayX +ai +aOrg][1] -
|
||||
aaCol[(aj+0)*aaArrayX +(ai+currStep) +aOrg][1])> aaSensGreen ) ||
|
||||
(fabs(aaCol[aj*aaArrayX +ai +aOrg][2] -
|
||||
aaCol[(aj+0)*aaArrayX +(ai+currStep) +aOrg][2])> aaSensBlue ) ) {
|
||||
thisColDiff = 1;
|
||||
} else
|
||||
if(
|
||||
(fabs(aaCol[aj*aaArrayX +ai +aOrg][0] -
|
||||
aaCol[(aj+currStep)*aaArrayX +(ai+0) +aOrg][0])> aaSensRed ) ||
|
||||
(fabs(aaCol[aj*aaArrayX +ai +aOrg][1] -
|
||||
aaCol[(aj+currStep)*aaArrayX +(ai+0) +aOrg][1])> aaSensGreen ) ||
|
||||
(fabs(aaCol[aj*aaArrayX +ai +aOrg][2] -
|
||||
aaCol[(aj+currStep)*aaArrayX +(ai+0) +aOrg][2])> aaSensBlue ) ) {
|
||||
thisColDiff = 1;
|
||||
} else
|
||||
if(
|
||||
(fabs(aaCol[aj*aaArrayX +ai +aOrg][0] -
|
||||
aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg][0])> aaSensRed ) ||
|
||||
(fabs(aaCol[aj*aaArrayX +ai +aOrg][1] -
|
||||
aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg][1])> aaSensGreen ) ||
|
||||
(fabs(aaCol[aj*aaArrayX +ai +aOrg][2] -
|
||||
aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg][2])> aaSensBlue ) ) {
|
||||
thisColDiff = 1;
|
||||
}
|
||||
|
||||
//colDiff =1;
|
||||
if(thisColDiff) {
|
||||
/* set diff flag */
|
||||
colDiff = thisColDiff;
|
||||
for(int bj=aj;bj<=aj+currStep;bj++) {
|
||||
for(int bi=ai;bi<=ai+currStep;bi++) {
|
||||
if(aaUse[bj*aaArrayX +bi +aOrg]==2) {
|
||||
//if(showAAPic)
|
||||
aaUse[bj*aaArrayX +bi +aOrg] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* set all values */
|
||||
ntlColor avgCol = (
|
||||
aaCol[(aj+0 )*aaArrayX +(ai+0 ) +aOrg] +
|
||||
aaCol[(aj+0 )*aaArrayX +(ai+currStep) +aOrg] +
|
||||
aaCol[(aj+currStep)*aaArrayX +(ai+0 ) +aOrg] +
|
||||
aaCol[(aj+currStep)*aaArrayX +(ai+currStep) +aOrg] ) *0.25;
|
||||
for(int bj=aj;bj<=aj+currStep;bj++) {
|
||||
for(int bi=ai;bi<=ai+currStep;bi++) {
|
||||
if(aaUse[bj*aaArrayX +bi +aOrg]==0) {
|
||||
aaCol[bj*aaArrayX +bi +aOrg] = avgCol;
|
||||
aaUse[bj*aaArrayX +bi +aOrg] = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
} /* smaller values set */
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* half step size */
|
||||
currStep /= 2;
|
||||
|
||||
} /* repeat until diff not too big */
|
||||
|
||||
/* get average color */
|
||||
gfxReal colNum = 0.0;
|
||||
col = ntlColor(0.0, 0.0, 0.0);
|
||||
for(aj = 0;aj<=aaLength;aj++) {
|
||||
for(ai = 0;ai<=aaLength;ai++) {
|
||||
col += aaCol[aj*aaArrayX +ai +aOrg];
|
||||
colNum += 1.0;
|
||||
}
|
||||
}
|
||||
col /= colNum;
|
||||
|
||||
}
|
||||
|
||||
/* mark pixels with debugging */
|
||||
if( glob->getDebugOut() > 0) col = ntlColor(0,1,0);
|
||||
|
||||
/* store pixel */
|
||||
if(!showAAPic) {
|
||||
finalPic[(scanline-1)*picX+sx] = col;
|
||||
}
|
||||
screenPos += rightStep;
|
||||
|
||||
} /* foreach x */
|
||||
|
||||
/* init aa array */
|
||||
if(showAAPic) {
|
||||
for(int j=0;j<=aaArrayY-1;j++) {
|
||||
for(int i=0;i<=aaArrayX-1;i++) {
|
||||
if(aaUse[j*aaArrayX +i]==1) finalPic[((scanline-1)*aaLength +j)*picX+i][0] = 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0;i<aaArrayX;i++) {
|
||||
aaCol[(aaArrayY-1)*aaArrayX+i] = aaCol[0*aaArrayX+i];
|
||||
aaUse[(aaArrayY-1)*aaArrayX+i] = aaUse[0*aaArrayX+i];
|
||||
}
|
||||
for(int j=0;j<aaArrayY-1;j++) {
|
||||
for(int i=0;i<aaArrayX;i++) {
|
||||
aaCol[j*aaArrayX+i] = ntlColor(0.0, 0.0, 0.0);
|
||||
aaUse[j*aaArrayX+i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} /* foreach y */
|
||||
rendEnd = getTime();
|
||||
|
||||
|
||||
/* write png file */
|
||||
{
|
||||
int w = picX;
|
||||
int h = picY;
|
||||
|
||||
unsigned rowbytes = w*4;
|
||||
unsigned char *screenbuf, **rows;
|
||||
screenbuf = (unsigned char*)malloc( h*rowbytes );
|
||||
rows = (unsigned char**)malloc( h*sizeof(unsigned char*) );
|
||||
unsigned char *filler = screenbuf;
|
||||
|
||||
// cutoff color values 0..1
|
||||
for(int j=0;j<h;j++) {
|
||||
for(int i=0;i<w;i++) {
|
||||
ntlColor col = finalPic[j*w+i];
|
||||
for (unsigned int cc=0; cc<3; cc++) {
|
||||
if(col[cc] <= 0.0) col[cc] = 0.0;
|
||||
if(col[cc] >= 1.0) col[cc] = 1.0;
|
||||
}
|
||||
*filler = (unsigned char)( col[0]*255.0 );
|
||||
filler++;
|
||||
*filler = (unsigned char)( col[1]*255.0 );
|
||||
filler++;
|
||||
*filler = (unsigned char)( col[2]*255.0 );
|
||||
filler++;
|
||||
*filler = (unsigned char)( 255.0 );
|
||||
filler++; // alpha channel
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < h; i++) rows[i] = &screenbuf[ (h - i - 1)*rowbytes ];
|
||||
#ifndef NOPNG
|
||||
writePng(outfn_conv.str().c_str(), rows, w, h);
|
||||
#else // NOPNG
|
||||
debMsgStd("ntlRaytracer::renderScene",DM_NOTIFY, "No PNG linked, no picture...", 1);
|
||||
#endif // NOPNG
|
||||
}
|
||||
|
||||
|
||||
// next frame
|
||||
glob->setAniCount( glob->getAniCount() +1 );
|
||||
|
||||
// done
|
||||
timeEnd = getTime();
|
||||
|
||||
char resout[1024];
|
||||
snprintf(resout,1024, "NTL Done %s, frame %d/%d (%s scene, %s raytracing, %s total, %d shades, %d i.s.'s)!\n",
|
||||
outfn_conv.str().c_str(), (glob->getAniCount()), (glob->getAniFrames()+1),
|
||||
getTimeString(totalStart-timeStart).c_str(), getTimeString(rendEnd-rendStart).c_str(), getTimeString(timeEnd-timeStart).c_str(),
|
||||
glob->getCounterShades(),
|
||||
glob->getCounterSceneInter() );
|
||||
debMsgStd("ntlRaytracer::renderScene",DM_MSG, resout, 1 );
|
||||
|
||||
/* clean stuff up */
|
||||
delete [] aaCol;
|
||||
delete [] aaUse;
|
||||
delete [] finalPic;
|
||||
glob->getScene()->cleanupScene();
|
||||
|
||||
if(mpGlob->getSingleFrameMode() ) {
|
||||
debMsgStd("ntlRaytracer::renderScene",DM_NOTIFY, "Single frame mode done...", 1 );
|
||||
exit(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
105
intern/elbeem/intern/ntl_raytracer.h
Normal file
105
intern/elbeem/intern/ntl_raytracer.h
Normal file
@ -0,0 +1,105 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* Main renderer class
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef NTL_RAYTRACER_HH
|
||||
#define NTL_RAYTRACER_HH
|
||||
|
||||
#include "ntl_vector3dim.h"
|
||||
#include "ntl_ray.h"
|
||||
#include "ntl_geometryobject.h"
|
||||
#include "ntl_lightobject.h"
|
||||
#include "ntl_renderglobals.h"
|
||||
#include "ntl_material.h"
|
||||
#include "simulation_object.h"
|
||||
class ntlOpenGLRenderer;
|
||||
|
||||
class ntlRaytracer
|
||||
{
|
||||
public:
|
||||
/*! Constructor */
|
||||
ntlRaytracer(string filename, bool commandlineMode);
|
||||
/*! Destructor */
|
||||
virtual ~ntlRaytracer( void );
|
||||
|
||||
/*! render a whole animation (command line mode) */
|
||||
int renderAnimation( void );
|
||||
/*! render a whole animation (visualization mode) */
|
||||
int renderVisualization( bool );
|
||||
/*! render a single step for viz mode */
|
||||
int singleStepVisualization( void );
|
||||
/*! advance simulations by time frame time */
|
||||
int advanceSims();
|
||||
/*! advance simulations by a single step */
|
||||
void singleStepSims(double targetTime);
|
||||
|
||||
/*! set stop rend viz flag */
|
||||
void setStopRenderVisualization(bool set) { mStopRenderVisualization = set; }
|
||||
/*! should the rendering viz thread be stopped? */
|
||||
bool getStopRenderVisualization() { return mStopRenderVisualization; }
|
||||
|
||||
/*! render scene (a single pictures) */
|
||||
virtual int renderScene( void );
|
||||
|
||||
/*! display world with opengl */
|
||||
//int draw( void );
|
||||
/*! set single frame rendering to filename */
|
||||
void setSingleFrameOut( string singleframeFilename );
|
||||
|
||||
/* access functions */
|
||||
|
||||
/*! set&get render globals */
|
||||
inline void setRenderGlobals( ntlRenderGlobals *set) { mpGlob = set; }
|
||||
inline ntlRenderGlobals *getRenderGlobals( void ) { return mpGlob; }
|
||||
|
||||
/*! set&get render globals */
|
||||
inline void setSimulationTime( double set) { mSimulationTime = set; }
|
||||
inline double getSimulationTime( void ) { return mSimulationTime; }
|
||||
|
||||
/*! set&get single step debug mode */
|
||||
inline void setSingleStepDebug( bool set) { mSingleStepDebug = set; }
|
||||
inline bool getSingleStepDebug( void ) { return mSingleStepDebug; }
|
||||
|
||||
/*! &get simulation object vector (debugging) */
|
||||
inline vector<SimulationObject*> *getSimulations( void ) { return mpSims; }
|
||||
|
||||
/*! get opengl renderer */
|
||||
inline ntlOpenGLRenderer *getOpenGLRenderer() { return mpOpenGLRenderer; }
|
||||
|
||||
private:
|
||||
|
||||
protected:
|
||||
|
||||
/*! global render settings needed almost everywhere */
|
||||
ntlRenderGlobals *mpGlob;
|
||||
|
||||
/*! a list of lights in the scene (geometry is store in ntl_scene) */
|
||||
vector<ntlLightObject*> *mpLightList;
|
||||
/*! surface materials */
|
||||
vector<ntlMaterial*> *mpPropList;
|
||||
/*! sims list */
|
||||
vector<SimulationObject*> *mpSims;
|
||||
|
||||
/*! opengl display */
|
||||
ntlOpenGLRenderer *mpOpenGLRenderer;
|
||||
|
||||
/*! stop rend viz? */
|
||||
bool mStopRenderVisualization;
|
||||
|
||||
/*! rend viz thread currently running? */
|
||||
bool mThreadRunning;
|
||||
|
||||
/*! remember the current simulation time */
|
||||
double mSimulationTime;
|
||||
/*! first simulation that is valid */
|
||||
int mFirstSim;
|
||||
|
||||
/*! single step mode for debugging */
|
||||
bool mSingleStepDebug;
|
||||
};
|
||||
|
||||
#endif
|
371
intern/elbeem/intern/ntl_renderglobals.h
Normal file
371
intern/elbeem/intern/ntl_renderglobals.h
Normal file
@ -0,0 +1,371 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* main renderer class
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef NTL_RENDERGLOBALS_HH
|
||||
#define NTL_RENDERGLOBALS_HH
|
||||
|
||||
|
||||
#include "ntl_vector3dim.h"
|
||||
#include "ntl_rndstream.h"
|
||||
#include "ntl_geometryobject.h"
|
||||
#include "ntl_material.h"
|
||||
#include "ntl_lightobject.h"
|
||||
class ntlScene;
|
||||
class SimulationObject;
|
||||
|
||||
|
||||
|
||||
//! Display mode
|
||||
#define DM_VIZ 0
|
||||
#define DM_RAY 1
|
||||
#define DM_LBM 2
|
||||
|
||||
|
||||
|
||||
//! Class that handles global rendering parameters
|
||||
class ntlRenderGlobals
|
||||
{
|
||||
public:
|
||||
//! Standard constructor
|
||||
inline ntlRenderGlobals();
|
||||
//! Destructor
|
||||
~ntlRenderGlobals();
|
||||
|
||||
//! Returns the scene manager
|
||||
inline ntlScene *getScene(void) { return mpScene; }
|
||||
//! Set the scene manager
|
||||
inline void setScene(ntlScene *set) { mpScene = set;}
|
||||
|
||||
//! Returns the object list
|
||||
//inline vector<ntlGeometryObject*> *getObjectList(void) { return mpObjList; }
|
||||
//! Set the object list
|
||||
//inline void setObjectList(vector<ntlGeometryObject*> *set) { mpObjList = set;}
|
||||
|
||||
//! Returns the light object list
|
||||
inline vector<ntlLightObject*> *getLightList(void) { return mpLightList; }
|
||||
//! Set the light list
|
||||
inline void setLightList(vector<ntlLightObject*> *set) { mpLightList = set;}
|
||||
|
||||
//! Returns the property object list
|
||||
inline vector<ntlMaterial*> *getMaterials(void) { return mpMaterials; }
|
||||
//! Set the property list
|
||||
inline void setMaterials(vector<ntlMaterial*> *set) { mpMaterials = set;}
|
||||
|
||||
//! Returns the list of simulations
|
||||
inline vector<SimulationObject*> *getSims(void) { return mpSims; }
|
||||
//! Set the pointer to the list of simulations
|
||||
inline void setSims(vector<SimulationObject*> *set) { mpSims = set;}
|
||||
|
||||
//! Set the x resolution
|
||||
inline void setResX(unsigned int set) { mResX = set; }
|
||||
//! Set the y resolution
|
||||
inline void setResY(unsigned int set) { mResY = set; }
|
||||
//! Set the anti-aliasing depth
|
||||
inline void setAADepth(int set) { mAADepth = set; }
|
||||
//! Set the max color value
|
||||
inline void setMaxColVal(unsigned int set) { mMaxColVal = set; }
|
||||
//! Set the maximum ray recursion
|
||||
inline void setRayMaxDepth(unsigned int set) { mRayMaxDepth = set; }
|
||||
//! Set the eye point
|
||||
inline void setEye(ntlVec3Gfx set) { mvEye = set; }
|
||||
//! Set the look at vector
|
||||
inline void setLookat(ntlVec3Gfx set) { mvLookat = set; }
|
||||
//! Set the up vector
|
||||
inline void setUpVec(ntlVec3Gfx set) { mvUpvec = set; }
|
||||
//! Set the image aspect
|
||||
inline void setAspect(float set) { mAspect = set; }
|
||||
//! Set the field of view
|
||||
inline void setFovy(float set) { mFovy = set; }
|
||||
//! Set the background color
|
||||
inline void setBackgroundCol(ntlColor set) { mcBackgr = set; }
|
||||
//! Set the ambient lighting color
|
||||
inline void setAmbientLight(ntlColor set) { mcAmbientLight = set; }
|
||||
//! Set the debug output var
|
||||
inline void setDebugOut(int set) { mDebugOut = set; }
|
||||
|
||||
//! Set the animation start time
|
||||
inline void setAniStart(int set) { mAniStart = set; }
|
||||
//! Set the animation number of frames
|
||||
inline void setAniFrames(int set) { mAniFrames = set; }
|
||||
//! Set the animation
|
||||
inline void setAniCount(int set) { mAniCount = set; }
|
||||
//! Set the lbmsolver animation step size
|
||||
inline void setAniFrameTime(int set) { mAniFrameTime=set; }
|
||||
//! Set the ray counter
|
||||
inline void setCounterRays(int set) { mCounterRays = set; }
|
||||
//! Set the ray shades counter
|
||||
inline void setCounterShades(int set) { mCounterShades = set; }
|
||||
//! Set the scenen intersection counter
|
||||
inline void setCounterSceneInter(int set) { mCounterSceneInter = set; }
|
||||
//! Set if existing frames should be skipped
|
||||
inline void setFrameSkip(int set) { mFrameSkip = set; }
|
||||
|
||||
//! Set the outfilename
|
||||
inline void setOutFilename(string set) { mOutFilename = set; }
|
||||
|
||||
//! get Maximum depth for BSP tree
|
||||
inline void setTreeMaxDepth( int set ) { mTreeMaxDepth = set; }
|
||||
//! get Maxmimum nr of triangles per BSP tree node
|
||||
inline void setTreeMaxTriangles( int set ) { mTreeMaxTriangles = set; }
|
||||
|
||||
//! set the enable flag of the test sphere
|
||||
inline void setTestSphereEnabled( bool set ) { mTestSphereEnabled = set; }
|
||||
//! set the center of the test sphere
|
||||
inline void setTestSphereCenter( ntlVec3Gfx set ) { mTestSphereCenter = set; }
|
||||
//! set the radius of the test sphere
|
||||
inline void setTestSphereRadius( gfxReal set ) { mTestSphereRadius = set; }
|
||||
//! set the material name of the test sphere
|
||||
inline void setTestSphereMaterialName( char* set ) { mTestSphereMaterialName = set; }
|
||||
//! set debugging pixel coordinates
|
||||
inline void setDebugPixel( int setx, int sety ) { mDebugPixelX = setx; mDebugPixelY = sety; }
|
||||
//! set test mode flag
|
||||
inline void setTestMode( bool set ) { mTestMode = set; }
|
||||
//! set single frame mode flag
|
||||
inline void setSingleFrameMode(bool set) {mSingleFrameMode = set; };
|
||||
//! set single frame mode filename
|
||||
inline void setSingleFrameFilename(string set) {mSingleFrameFilename = set; };
|
||||
|
||||
|
||||
//! Return the x resolution
|
||||
inline unsigned int getResX(void) { return mResX; }
|
||||
//! Return the y resolution
|
||||
inline unsigned int getResY(void) { return mResY; }
|
||||
//! Return the anti-aliasing depth
|
||||
inline int getAADepth(void) { return mAADepth; }
|
||||
//! Return the max color value for ppm
|
||||
inline unsigned int getMaxColVal(void) { return mMaxColVal; }
|
||||
//! Return the maximum ray recursion
|
||||
inline unsigned int getRayMaxDepth(void) { return mRayMaxDepth; }
|
||||
//! Return the eye point
|
||||
inline ntlVec3Gfx getEye(void) { return mvEye; }
|
||||
//! Return the look at vector
|
||||
inline ntlVec3Gfx getLookat(void) { return mvLookat; }
|
||||
//! Return the up vector
|
||||
inline ntlVec3Gfx getUpVec(void) { return mvUpvec; }
|
||||
//! Return the image aspect
|
||||
inline float getAspect(void) { return mAspect; }
|
||||
//! Return the field of view
|
||||
inline float getFovy(void) { return mFovy; }
|
||||
//! Return the background color
|
||||
inline ntlColor getBackgroundCol(void) { return mcBackgr; }
|
||||
//! Return the ambient color
|
||||
inline ntlColor getAmbientLight(void) { return mcAmbientLight; }
|
||||
//! Return the debug mode setting
|
||||
inline int getDebugOut(void) { return mDebugOut; }
|
||||
|
||||
//! Return the animation start time
|
||||
inline int getAniStart(void) { return mAniStart; }
|
||||
//! Return the animation frame number
|
||||
inline int getAniFrames(void) { return mAniFrames; }
|
||||
//! Return the animation counter
|
||||
inline int getAniCount(void) { return mAniCount; }
|
||||
//! Return the ray counter
|
||||
inline int getCounterRays(void) { return mCounterRays; }
|
||||
//! Return the ray shades counter
|
||||
inline int getCounterShades(void) { return mCounterShades; }
|
||||
//! Return the scene intersection counter
|
||||
inline int getCounterSceneInter(void) { return mCounterSceneInter; }
|
||||
/*! Get auto run time variable */
|
||||
inline int getAniFrameTime( void ) { return mAniFrameTime; }
|
||||
//! Check if existing frames should be skipped
|
||||
inline int getFrameSkip( void ) { return mFrameSkip; }
|
||||
|
||||
|
||||
//! Return the outfilename
|
||||
inline string getOutFilename(void) { return mOutFilename; }
|
||||
|
||||
//! get Maximum depth for BSP tree
|
||||
inline int getTreeMaxDepth( void ) { return mTreeMaxDepth; }
|
||||
//! get Maxmimum nr of triangles per BSP tree node
|
||||
inline int getTreeMaxTriangles( void ) { return mTreeMaxTriangles; }
|
||||
|
||||
//! get open gl attribute list
|
||||
inline AttributeList* getOpenGlAttributes( void ) { return mpOpenGlAttr; }
|
||||
//! get blender output attribute list
|
||||
inline AttributeList* getBlenderAttributes( void ) { return mpBlenderAttr; }
|
||||
|
||||
//! is the test sphere enabled?
|
||||
inline bool getTestSphereEnabled( void ) { return mTestSphereEnabled; }
|
||||
//! get the center of the test sphere
|
||||
inline ntlVec3Gfx getTestSphereCenter( void ) { return mTestSphereCenter; }
|
||||
//! get the radius of the test sphere
|
||||
inline gfxReal getTestSphereRadius( void) { return mTestSphereRadius; }
|
||||
//! get the materialname of the test sphere
|
||||
inline char *getTestSphereMaterialName( void) { return mTestSphereMaterialName; }
|
||||
//! get the debug pixel coordinate
|
||||
inline int getDebugPixelX( void ) { return mDebugPixelX; }
|
||||
//! get the debug pixel coordinate
|
||||
inline int getDebugPixelY( void ) { return mDebugPixelY; }
|
||||
//! get test mode flag
|
||||
inline bool getTestMode( void ) { return mTestMode; }
|
||||
//! set single frame mode flag
|
||||
inline bool getSingleFrameMode() { return mSingleFrameMode; };
|
||||
//! set single frame mode filename
|
||||
inline string getSingleFrameFilename() { return mSingleFrameFilename; };
|
||||
|
||||
|
||||
// random number functions
|
||||
//! init random numbers for photon directions
|
||||
inline void initRandomDirections( int seed ) { if(mpRndDirections) delete mpRndDirections; mpRndDirections = new ntlRandomStream( seed ); }
|
||||
//! get the next random photon direction
|
||||
inline ntlVec3Gfx getRandomDirection( void );
|
||||
//! init random numbers for russian roulette
|
||||
inline void initRandomRoulette( int seed ) { if(mpRndRoulette) delete mpRndRoulette; mpRndRoulette = new ntlRandomStream( seed ); }
|
||||
//! get the next random number for russion roulette
|
||||
inline gfxReal getRandomRoulette( void ) { return mpRndRoulette->getGfxReal(); }
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
|
||||
/*! Scene storage */
|
||||
ntlScene *mpScene;
|
||||
|
||||
//! List of geometry objects
|
||||
//vector<ntlGeometryObject*> *mpObjList;
|
||||
//! List of light objects
|
||||
vector<ntlLightObject*> *mpLightList;
|
||||
//! List of surface properties
|
||||
vector<ntlMaterial*> *mpMaterials;
|
||||
/*! storage for simulations */
|
||||
vector<SimulationObject*> *mpSims;
|
||||
|
||||
//! resolution of the picture
|
||||
unsigned int mResX, mResY;
|
||||
//! Anti-Aliasing depth
|
||||
int mAADepth;
|
||||
//! max color value for ppm
|
||||
unsigned int mMaxColVal;
|
||||
/* Maximal ray recursion depth */
|
||||
int mRayMaxDepth;
|
||||
//! The eye point
|
||||
ntlVec3Gfx mvEye;
|
||||
//! The look at point
|
||||
ntlVec3Gfx mvLookat;
|
||||
//! The up vector
|
||||
ntlVec3Gfx mvUpvec;
|
||||
//! The image aspect = Xres/Yres
|
||||
float mAspect;
|
||||
//! The horizontal field of view
|
||||
float mFovy;
|
||||
//! The background color
|
||||
ntlColor mcBackgr;
|
||||
//! The ambient color
|
||||
ntlColor mcAmbientLight;
|
||||
//! how much debug output is needed? off by default
|
||||
char mDebugOut;
|
||||
|
||||
|
||||
//! animation properties, start time
|
||||
int mAniStart;
|
||||
//! animation properties, number of frames to render
|
||||
int mAniFrames;
|
||||
//! animation status, current frame number
|
||||
int mAniCount;
|
||||
/*! no. of steps for auto run (lbmsolver steps) */
|
||||
int mAniFrameTime;
|
||||
/*! Should existing picture frames be skipped? */
|
||||
int mFrameSkip;
|
||||
|
||||
|
||||
//! count the total number of rays created (also used for ray ID's)
|
||||
int mCounterRays;
|
||||
//! count the total number of rays shaded
|
||||
int mCounterShades;
|
||||
//! count the total number of scene intersections
|
||||
int mCounterSceneInter;
|
||||
|
||||
/*! filename of output pictures (without suffix or numbers) */
|
||||
string mOutFilename;
|
||||
|
||||
//! get Maximum depth for BSP tree
|
||||
int mTreeMaxDepth;
|
||||
//! get Maxmimum nr of triangles per BSP tree node
|
||||
int mTreeMaxTriangles;
|
||||
|
||||
//! attribute list for opengl renderer
|
||||
AttributeList *mpOpenGlAttr;
|
||||
//! attribute list for blender output
|
||||
AttributeList *mpBlenderAttr;
|
||||
|
||||
|
||||
//! Enable test sphere?
|
||||
bool mTestSphereEnabled;
|
||||
//! Center of the test sphere
|
||||
ntlVec3Gfx mTestSphereCenter;
|
||||
//! Radius of the test sphere
|
||||
gfxReal mTestSphereRadius;
|
||||
//! Materialname of the test sphere
|
||||
char *mTestSphereMaterialName;
|
||||
//! coordinates of the debugging pixel
|
||||
int mDebugPixelX, mDebugPixelY;
|
||||
|
||||
//! test mode for quick rendering activated?, inited in ntl_scene::buildScene
|
||||
bool mTestMode;
|
||||
|
||||
//! single frame flag
|
||||
bool mSingleFrameMode;
|
||||
//! filename for single frame mode
|
||||
string mSingleFrameFilename;
|
||||
|
||||
/*! Two random number streams for photon generation (one for the directions, the other for russion roulette) */
|
||||
ntlRandomStream *mpRndDirections, *mpRndRoulette;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Constructor with standard value init */
|
||||
inline ntlRenderGlobals::ntlRenderGlobals() :
|
||||
mpLightList( NULL ), mpMaterials( NULL ), mpSims( NULL ),
|
||||
mResX(320), mResY(200), mAADepth(-1), mMaxColVal(255),
|
||||
mRayMaxDepth( 5 ),
|
||||
mvEye(0.0,0.0,5.0), mvLookat(0.0,0.0,0.0), mvUpvec(0.0,1.0,0.0),
|
||||
mAspect(320.0/200.0),
|
||||
mFovy(45), mcBackgr(0.0,0.0,0.0), mcAmbientLight(0.0,0.0,0.0),
|
||||
mDebugOut( 0 ),
|
||||
mAniStart(0), mAniFrames( -1 ), mAniCount( 0 ),
|
||||
mAniFrameTime(10), mFrameSkip( 0 ),
|
||||
mCounterRays( 0 ), mCounterShades( 0 ), mCounterSceneInter( 0 ),
|
||||
mOutFilename( "pic" ),
|
||||
mTreeMaxDepth( 30 ), mTreeMaxTriangles( 30 ),
|
||||
mpOpenGlAttr(NULL),
|
||||
mpBlenderAttr(NULL),
|
||||
mTestSphereEnabled( false ),
|
||||
mDebugPixelX( -1 ), mDebugPixelY( -1 ), mTestMode(false),
|
||||
mSingleFrameMode(false), mSingleFrameFilename(""),
|
||||
mpRndDirections( NULL ), mpRndRoulette( NULL )
|
||||
{
|
||||
// create internal attribute list for opengl renderer
|
||||
mpOpenGlAttr = new AttributeList("__ntlOpenGLRenderer");
|
||||
mpBlenderAttr = new AttributeList("__ntlBlenderAttr");
|
||||
};
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Destructor */
|
||||
inline ntlRenderGlobals::~ntlRenderGlobals() {
|
||||
if(mpOpenGlAttr) delete mpOpenGlAttr;
|
||||
if(mpBlenderAttr) delete mpBlenderAttr;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
//! get the next random photon direction
|
||||
inline ntlVec3Gfx ntlRenderGlobals::getRandomDirection( void ) {
|
||||
return ntlVec3Gfx(
|
||||
(mpRndDirections->getGfxReal()-0.5),
|
||||
(mpRndDirections->getGfxReal()-0.5),
|
||||
(mpRndDirections->getGfxReal()-0.5) );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
127
intern/elbeem/intern/ntl_rndstream.h
Normal file
127
intern/elbeem/intern/ntl_rndstream.h
Normal file
@ -0,0 +1,127 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* A seperate random number stream (e.g. for photon tracing)
|
||||
* (cf. Numerical recipes in C, sec. ed., p 283, Knuth method)
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef NTL_RANDOMSTREAM_H
|
||||
|
||||
|
||||
//! some big number
|
||||
#define MBIG 1000000000
|
||||
|
||||
//! modify initial seed
|
||||
#define MSEED 161803398
|
||||
|
||||
//! minimum value - no idea why this is a define?
|
||||
#define MZ 0
|
||||
|
||||
//! for normalization to 0..1
|
||||
#define FAC (1.0/MBIG)
|
||||
|
||||
|
||||
/*! a stream of random numbers using Knuth's portable method */
|
||||
class ntlRandomStream
|
||||
{
|
||||
public:
|
||||
/*! Default constructor */
|
||||
inline ntlRandomStream(long seed);
|
||||
/*! Destructor */
|
||||
~ntlRandomStream() {}
|
||||
|
||||
/*! get a random number from the stream */
|
||||
inline double getDouble( void );
|
||||
|
||||
#ifdef HAVE_GFXTYPES
|
||||
//! gfx random functions
|
||||
|
||||
/*! get a random number from the stream */
|
||||
inline gfxReal getGfxReal( void );
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
/*! random number state */
|
||||
long idnum;
|
||||
|
||||
/*! pointers into number table */
|
||||
int inext, inextp;
|
||||
/*! store seed and number for subtraction */
|
||||
long ma[56];
|
||||
|
||||
};
|
||||
|
||||
|
||||
/* init random stream tables */
|
||||
inline ntlRandomStream::ntlRandomStream(long seed)
|
||||
{
|
||||
idnum = seed;
|
||||
|
||||
long mj = MSEED - (idnum < 0 ? -idnum : idnum);
|
||||
mj %= MBIG;
|
||||
ma[55] = mj;
|
||||
long mk = 1;
|
||||
|
||||
// init table once, otherwise strange results...
|
||||
for(int i=0;i<=55;i++) ma[i] = (i*i+seed);
|
||||
|
||||
// init table in random order
|
||||
for(int i=1;i<=54;i++) {
|
||||
int ii = (21*i) % 56;
|
||||
ma[ii] = mk;
|
||||
mk = mj - mk;
|
||||
if(mk < MZ) mk += MBIG;
|
||||
mj = ma[ii];
|
||||
}
|
||||
|
||||
// "warm up" generator
|
||||
for(int k=1;k<=4;k++)
|
||||
for(int i=1;i<=55;i++) {
|
||||
ma[i] -= ma[1+ (i+30) % 55];
|
||||
if(ma[i] < MZ) ma[i] += MBIG;
|
||||
}
|
||||
|
||||
inext = 0;
|
||||
inextp = 31; // the special "31"
|
||||
idnum = 1;
|
||||
}
|
||||
|
||||
|
||||
/* return one random value */
|
||||
inline double ntlRandomStream::getDouble( void )
|
||||
{
|
||||
if( ++inext == 56) inext = 1;
|
||||
if( ++inextp == 56) inextp = 1;
|
||||
|
||||
// generate by subtaction
|
||||
long mj = ma[inext] - ma[inextp];
|
||||
|
||||
// check range
|
||||
if(mj < MZ) mj += MBIG;
|
||||
ma[ inext ] = mj;
|
||||
return (double)(mj * FAC);
|
||||
}
|
||||
|
||||
#ifdef HAVE_GFXTYPES
|
||||
/* return one random value */
|
||||
inline gfxReal ntlRandomStream::getGfxReal( void )
|
||||
{
|
||||
if( ++inext == 56) inext = 1;
|
||||
if( ++inextp == 56) inextp = 1;
|
||||
|
||||
// generate by subtaction
|
||||
long mj = ma[inext] - ma[inextp];
|
||||
|
||||
// check range
|
||||
if(mj < MZ) mj += MBIG;
|
||||
ma[ inext ] = mj;
|
||||
return (gfxReal)(mj * FAC);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define NTL_RANDOMSTREAM_H
|
||||
#endif
|
||||
|
239
intern/elbeem/intern/ntl_scene.cpp
Normal file
239
intern/elbeem/intern/ntl_scene.cpp
Normal file
@ -0,0 +1,239 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* Scene object, that contains and manages all geometry objects
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "utilities.h"
|
||||
#include "ntl_scene.h"
|
||||
#include "ntl_geometryobject.h"
|
||||
#include "ntl_geometryshader.h"
|
||||
//#include <sys/times.h>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Constructor
|
||||
*****************************************************************************/
|
||||
ntlScene::ntlScene( ntlRenderGlobals *glob ) :
|
||||
mpGlob( glob ),
|
||||
mpTree( NULL ),
|
||||
mDisplayListId( -1 ),
|
||||
mSceneBuilt( false ), mFirstInitDone( false )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Destructor
|
||||
*****************************************************************************/
|
||||
ntlScene::~ntlScene()
|
||||
{
|
||||
cleanupScene();
|
||||
|
||||
// cleanup lists
|
||||
for (vector<ntlGeometryClass*>::iterator iter = mGeos.begin();
|
||||
iter != mGeos.end(); iter++) {
|
||||
delete (*iter);
|
||||
}
|
||||
for (vector<ntlLightObject*>::iterator iter = mpGlob->getLightList()->begin();
|
||||
iter != mpGlob->getLightList()->end(); iter++) {
|
||||
delete (*iter);
|
||||
}
|
||||
for (vector<ntlMaterial*>::iterator iter = mpGlob->getMaterials()->begin();
|
||||
iter != mpGlob->getMaterials()->end(); iter++) {
|
||||
delete (*iter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Build the scene arrays (obj, tris etc.)
|
||||
*****************************************************************************/
|
||||
void ntlScene::buildScene( void )
|
||||
{
|
||||
const bool buildInfo=false;
|
||||
mObjects.clear();
|
||||
/* init geometry array, first all standard objects */
|
||||
for (vector<ntlGeometryClass*>::iterator iter = mGeos.begin();
|
||||
iter != mGeos.end(); iter++) {
|
||||
bool geoinit = false;
|
||||
int tid = (*iter)->getTypeId();
|
||||
if(tid & GEOCLASSTID_OBJECT) {
|
||||
ntlGeometryObject *geoobj = (ntlGeometryObject*)(*iter);
|
||||
geoinit = true;
|
||||
mObjects.push_back( geoobj );
|
||||
if(buildInfo) debMsgStd("ntlScene::BuildScene",DM_MSG,"added GeoObj "<<geoobj->getName(), 5 );
|
||||
}
|
||||
//if(geoshad) {
|
||||
if(tid & GEOCLASSTID_SHADER) {
|
||||
ntlGeometryShader *geoshad = (ntlGeometryShader*)(*iter);
|
||||
geoinit = true;
|
||||
if(!mFirstInitDone) {
|
||||
// only on first init
|
||||
geoshad->initializeShader();
|
||||
}
|
||||
for (vector<ntlGeometryObject*>::iterator siter = geoshad->getObjectsBegin();
|
||||
siter != geoshad->getObjectsEnd();
|
||||
siter++) {
|
||||
if(buildInfo) debMsgStd("ntlScene::BuildScene",DM_MSG,"added shader geometry "<<(*siter)->getName(), 5 );
|
||||
mObjects.push_back( (*siter) );
|
||||
}
|
||||
}
|
||||
|
||||
if(!geoinit) {
|
||||
errMsg("ntlScene::BuildScene","Invalid geometry class!");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// collect triangles
|
||||
mTriangles.clear();
|
||||
mVertices.clear();
|
||||
mVertNormals.clear();
|
||||
|
||||
/* for test mode deactivate transparencies etc. */
|
||||
if( mpGlob->getTestMode() ) {
|
||||
debugOut("ntlScene::buildScene : Test Mode activated!", 2);
|
||||
// assign random colors to dark materials
|
||||
int matCounter = 0;
|
||||
ntlColor stdCols[] = { ntlColor(0,0,1.0), ntlColor(0,1.0,0), ntlColor(1.0,0.7,0) , ntlColor(0.7,0,0.6) };
|
||||
int stdColNum = 4;
|
||||
for (vector<ntlMaterial*>::iterator iter = mpGlob->getMaterials()->begin();
|
||||
iter != mpGlob->getMaterials()->end(); iter++) {
|
||||
(*iter)->setTransparence(0.0);
|
||||
(*iter)->setMirror(0.0);
|
||||
(*iter)->setFresnel(false);
|
||||
// too dark?
|
||||
if( norm((*iter)->getDiffuseRefl()) <0.01) {
|
||||
(*iter)->setDiffuseRefl( stdCols[matCounter] );
|
||||
matCounter ++;
|
||||
matCounter = matCounter%stdColNum;
|
||||
}
|
||||
}
|
||||
|
||||
// restrict output file size to 400
|
||||
float downscale = 1.0;
|
||||
if(mpGlob->getResX() > 400){ downscale = 400.0/(float)mpGlob->getResX(); }
|
||||
if(mpGlob->getResY() > 400){
|
||||
float downscale2 = 400.0/(float)mpGlob->getResY();
|
||||
if(downscale2<downscale) downscale=downscale2;
|
||||
}
|
||||
mpGlob->setResX( (int)(mpGlob->getResX() * downscale) );
|
||||
mpGlob->setResY( (int)(mpGlob->getResY() * downscale) );
|
||||
|
||||
}
|
||||
|
||||
/* collect triangles from objects */
|
||||
int idCnt = 0; // give IDs to objects
|
||||
for (vector<ntlGeometryObject*>::iterator iter = mObjects.begin();
|
||||
iter != mObjects.end();
|
||||
iter++) {
|
||||
/* only add visible objects */
|
||||
(*iter)->initialize( mpGlob );
|
||||
(*iter)->getTriangles(&mTriangles, &mVertices, &mVertNormals, idCnt);
|
||||
idCnt ++;
|
||||
}
|
||||
|
||||
|
||||
/* calculate triangle normals, and initialize flags */
|
||||
for (vector<ntlTriangle>::iterator iter = mTriangles.begin();
|
||||
iter != mTriangles.end();
|
||||
iter++) {
|
||||
|
||||
// calculate normal from triangle points
|
||||
ntlVec3Gfx normal =
|
||||
cross( (ntlVec3Gfx)( (mVertices[(*iter).getPoints()[2]] - mVertices[(*iter).getPoints()[0]]) *-1.0), // BLITZ minus sign right??
|
||||
(ntlVec3Gfx)(mVertices[(*iter).getPoints()[1]] - mVertices[(*iter).getPoints()[0]]) );
|
||||
normalize(normal);
|
||||
(*iter).setNormal( normal );
|
||||
}
|
||||
|
||||
|
||||
|
||||
// scene geometry built
|
||||
mSceneBuilt = true;
|
||||
|
||||
// init shaders that require complete geometry
|
||||
if(!mFirstInitDone) {
|
||||
// only on first init
|
||||
for (vector<ntlGeometryClass*>::iterator iter = mGeos.begin();
|
||||
iter != mGeos.end(); iter++) {
|
||||
if( (*iter)->getTypeId() & GEOCLASSTID_SHADER ) {
|
||||
ntlGeometryShader *geoshad = (ntlGeometryShader*)(*iter);
|
||||
geoshad->postGeoConstrInit( mpGlob );
|
||||
}
|
||||
}
|
||||
mFirstInitDone = true;
|
||||
}
|
||||
|
||||
// check unused attributes (for classes and objects!)
|
||||
for (vector<ntlGeometryObject*>::iterator iter = mObjects.begin(); iter != mObjects.end(); iter++) {
|
||||
if((*iter)->getAttributeList()->checkUnusedParams()) {
|
||||
debMsgStd("ntlScene::buildScene",DM_WARNING,"Unused params for object '"<< (*iter)->getName() <<"' !", 1 );
|
||||
(*iter)->getAttributeList()->print(); // DEBUG
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
for (vector<ntlGeometryClass*>::iterator iter = mGeos.begin(); iter != mGeos.end(); iter++) {
|
||||
if((*iter)->getAttributeList()->checkUnusedParams()) {
|
||||
debMsgStd("ntlScene::buildScene",DM_WARNING,"Unused params for object '"<< (*iter)->getName() <<"' !", 1 );
|
||||
(*iter)->getAttributeList()->print(); // DEBUG
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Prepare the scene triangles and maps for raytracing
|
||||
*****************************************************************************/
|
||||
void ntlScene::prepareScene( void )
|
||||
{
|
||||
/* init triangles... */
|
||||
buildScene();
|
||||
// what for currently not used ???
|
||||
if(mpTree != NULL) delete mpTree;
|
||||
mpTree = new ntlTree( mpGlob->getTreeMaxDepth(), mpGlob->getTreeMaxTriangles(),
|
||||
this, TRI_GEOMETRY );
|
||||
|
||||
//debMsgStd("ntlScene::prepareScene",DM_MSG,"Stats - tris:"<< (int)mTriangles.size()<<" verts:"<<mVertices.size()<<" vnorms:"<<mVertNormals.size(), 5 );
|
||||
}
|
||||
/******************************************************************************
|
||||
* Do some memory cleaning, when frame is finished
|
||||
*****************************************************************************/
|
||||
void ntlScene::cleanupScene( void )
|
||||
{
|
||||
mObjects.clear();
|
||||
mTriangles.clear();
|
||||
mVertices.clear();
|
||||
mVertNormals.clear();
|
||||
|
||||
if(mpTree != NULL) delete mpTree;
|
||||
mpTree = NULL;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Intersect a ray with the scene triangles
|
||||
*****************************************************************************/
|
||||
void ntlScene::intersectScene(const ntlRay &r, gfxReal &distance, ntlVec3Gfx &normal, ntlTriangle *&tri,int flags) const
|
||||
{
|
||||
distance = -1.0;
|
||||
mpGlob->setCounterSceneInter( mpGlob->getCounterSceneInter()+1 );
|
||||
mpTree->intersect(r, distance, normal, tri, flags, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
186
intern/elbeem/intern/ntl_scene.h
Normal file
186
intern/elbeem/intern/ntl_scene.h
Normal file
@ -0,0 +1,186 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* Scene object, that contains and manages all geometry objects
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef NTL_SCENE_HH
|
||||
#define NTL_SCENE_HH
|
||||
|
||||
#include <sstream>
|
||||
#include "ntl_vector3dim.h"
|
||||
#include "ntl_material.h"
|
||||
#include "ntl_geometryclass.h"
|
||||
#include "ntl_triangle.h"
|
||||
#include "ntl_bsptree.h"
|
||||
class ntlRay;
|
||||
class ntlGeometryObject;
|
||||
|
||||
/*! fluid geometry init types */
|
||||
#define FGI_FLAGSTART 16
|
||||
#define FGI_FLUID (1<<(FGI_FLAGSTART+0))
|
||||
#define FGI_NO_FLUID (1<<(FGI_FLAGSTART+1))
|
||||
#define FGI_BNDNO (1<<(FGI_FLAGSTART+2))
|
||||
#define FGI_BNDFREE (1<<(FGI_FLAGSTART+3))
|
||||
#define FGI_NO_BND (1<<(FGI_FLAGSTART+4))
|
||||
#define FGI_ACC (1<<(FGI_FLAGSTART+5))
|
||||
#define FGI_NO_ACC (1<<(FGI_FLAGSTART+6))
|
||||
#define FGI_SPEEDSET (1<<(FGI_FLAGSTART+7))
|
||||
#define FGI_NO_SPEEDSET (1<<(FGI_FLAGSTART+8))
|
||||
|
||||
#define FGI_ALLBOUNDS (FGI_BNDNO | FGI_BNDFREE)
|
||||
|
||||
#define FGI_REFP1 (1<<(FGI_FLAGSTART+0))
|
||||
#define FGI_REFP2 (1<<(FGI_FLAGSTART+1))
|
||||
#define FGI_REFP3 (1<<(FGI_FLAGSTART+2))
|
||||
|
||||
#define FGI_ALLREFS (FGI_REFP1 | FGI_REFP2 | FGI_REFP3)
|
||||
|
||||
|
||||
//! convenience macro for adding triangles
|
||||
#define sceneAddTriangle(p1,p2,p3, pn1,pn2,pn3, trin, smooth) {\
|
||||
\
|
||||
ntlTriangle tri;\
|
||||
int tempVert;\
|
||||
\
|
||||
if(normals->size() != vertices->size()) {\
|
||||
errorOut("getTriangles Error for '"<<mName<<"': Vertices and normals sizes to not match!!!");\
|
||||
exit(1); }\
|
||||
\
|
||||
vertices->push_back( p1 ); \
|
||||
normals->push_back( pn1 ); \
|
||||
tempVert = normals->size()-1;\
|
||||
tri.getPoints()[0] = tempVert;\
|
||||
\
|
||||
vertices->push_back( p2 ); \
|
||||
normals->push_back( pn2 ); \
|
||||
tempVert = normals->size()-1;\
|
||||
tri.getPoints()[1] = tempVert;\
|
||||
\
|
||||
vertices->push_back( p3 ); \
|
||||
normals->push_back( pn3 ); \
|
||||
tempVert = normals->size()-1;\
|
||||
tri.getPoints()[2] = tempVert;\
|
||||
\
|
||||
\
|
||||
/* init flags */\
|
||||
int flag = 0; \
|
||||
if(getVisible()){ flag |= TRI_GEOMETRY; }\
|
||||
if(getCastShadows() ) { \
|
||||
flag |= TRI_CASTSHADOWS; } \
|
||||
if( (getMaterial()->getMirror()>0.0) || \
|
||||
(getMaterial()->getTransparence()>0.0) || \
|
||||
(getMaterial()->getFresnel()>0.0) ) { \
|
||||
flag |= TRI_MAKECAUSTICS; } \
|
||||
else { \
|
||||
flag |= TRI_NOCAUSTICS; } \
|
||||
\
|
||||
/* init geo init id */\
|
||||
int geoiId = getGeoInitId(); \
|
||||
if(geoiId > 0) { \
|
||||
flag |= (1<< (geoiId+4)); \
|
||||
flag |= mGeoInitType; \
|
||||
} \
|
||||
\
|
||||
tri.setFlags( flag );\
|
||||
\
|
||||
/* triangle normal missing */\
|
||||
tri.setNormal( trin );\
|
||||
tri.setSmoothNormals( smooth );\
|
||||
tri.setObjectId( objectId );\
|
||||
triangles->push_back( tri ); \
|
||||
}\
|
||||
|
||||
|
||||
|
||||
class ntlScene
|
||||
{
|
||||
public:
|
||||
/* CONSTRUCTORS */
|
||||
/*! Default constructor */
|
||||
ntlScene( ntlRenderGlobals *glob );
|
||||
/*! Default destructor */
|
||||
~ntlScene();
|
||||
|
||||
/*! Add an object to the scene */
|
||||
inline void addGeoClass(ntlGeometryClass *geo) { mGeos.push_back( geo ); }
|
||||
|
||||
/*! Acces a certain object */
|
||||
inline ntlGeometryObject *getObject(int id) {
|
||||
if(!mSceneBuilt) { errMsg("ntlScene::getObject","Scene not inited!"); exit(1); }
|
||||
return mObjects[id]; }
|
||||
|
||||
/*! Acces object array */
|
||||
inline vector<ntlGeometryObject*> *getObjects() {
|
||||
if(!mSceneBuilt) { errMsg("ntlScene::getObjects[]","Scene not inited!"); exit(1); }
|
||||
return &mObjects; }
|
||||
|
||||
/*! Acces geo class array */
|
||||
inline vector<ntlGeometryClass*> *getGeoClasses() {
|
||||
if(!mSceneBuilt) { errMsg("ntlScene::getGeoClasses[]","Scene not inited!"); exit(1); }
|
||||
return &mGeos; }
|
||||
|
||||
/*! draw scene with opengl */
|
||||
//void draw();
|
||||
|
||||
/*! Build the scene arrays */
|
||||
void buildScene( void );
|
||||
|
||||
//! Prepare the scene triangles and maps for raytracing
|
||||
void prepareScene( void );
|
||||
//! Do some memory cleaning, when frame is finished
|
||||
void cleanupScene( void );
|
||||
|
||||
/*! Intersect a ray with the scene triangles */
|
||||
void intersectScene(const ntlRay &r, gfxReal &distance, ntlVec3Gfx &normal, ntlTriangle *&tri, int flags) const;
|
||||
|
||||
/*! return a vertex */
|
||||
ntlVec3Gfx getVertex(int index) { return mVertices[index]; }
|
||||
|
||||
// for tree generation
|
||||
/*! return pointer to vertices vector */
|
||||
vector<ntlVec3Gfx> *getVertexPointer( void ) { return &mVertices; }
|
||||
/*! return pointer to vertices vector */
|
||||
vector<ntlVec3Gfx> *getVertexNormalPointer( void ) { return &mVertNormals; }
|
||||
/*! return pointer to vertices vector */
|
||||
vector<ntlTriangle> *getTrianglePointer( void ) { return &mTriangles; }
|
||||
|
||||
private:
|
||||
|
||||
/*! Global settings */
|
||||
ntlRenderGlobals *mpGlob;
|
||||
|
||||
/*! List of geometry classes */
|
||||
vector<ntlGeometryClass *> mGeos;
|
||||
|
||||
/*! List of geometry objects */
|
||||
vector<ntlGeometryObject *> mObjects;
|
||||
|
||||
/*! List of triangles */
|
||||
vector<ntlTriangle> mTriangles;
|
||||
/*! List of vertices */
|
||||
vector<ntlVec3Gfx> mVertices;
|
||||
/*! List of normals */
|
||||
vector<ntlVec3Gfx> mVertNormals;
|
||||
/*! List of triangle normals */
|
||||
vector<ntlVec3Gfx> mTriangleNormals;
|
||||
|
||||
/*! Tree to store quickly intersect triangles */
|
||||
ntlTree *mpTree;
|
||||
|
||||
/*! id of dislpay list for raytracer stuff */
|
||||
int mDisplayListId;
|
||||
|
||||
/*! was the scene successfully built? only then getObject(i) requests are valid */
|
||||
bool mSceneBuilt;
|
||||
|
||||
/*! shader/obj initializations are only done on first init */
|
||||
bool mFirstInitDone;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
183
intern/elbeem/intern/ntl_triangle.h
Normal file
183
intern/elbeem/intern/ntl_triangle.h
Normal file
@ -0,0 +1,183 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* a single triangle
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef NTL_TRIANGLE_HH
|
||||
#define NTL_TRIANGLE_HH
|
||||
|
||||
|
||||
#include "ntl_vector3dim.h"
|
||||
#include "ntl_material.h"
|
||||
class ntlRay;
|
||||
|
||||
|
||||
/*! Triangle flag defines */
|
||||
#define TRI_GEOMETRY (1<<0)
|
||||
#define TRI_CASTSHADOWS (1<<1)
|
||||
#define TRI_MAKECAUSTICS (1<<2)
|
||||
#define TRI_NOCAUSTICS (1<<3)
|
||||
|
||||
|
||||
class ntlTriangle
|
||||
{
|
||||
public:
|
||||
/* CONSTRUCTORS */
|
||||
/*! Default constructor */
|
||||
inline ntlTriangle( void );
|
||||
/*! Constructor with parameters */
|
||||
inline ntlTriangle(int *p, bool smooth, int obj, ntlVec3Gfx norm, int setflags);
|
||||
/*! Copy - Constructor */
|
||||
inline ntlTriangle(const ntlTriangle &tri);
|
||||
/*! Destructor */
|
||||
inline ~ntlTriangle() {}
|
||||
|
||||
/* Access methods */
|
||||
|
||||
/*! Acces to points of triangle */
|
||||
inline int *getPoints( void ) { return mPoints; }
|
||||
/*! Acces normal smoothing */
|
||||
inline bool getSmoothNormals( void ) const { return mSmoothNormals; }
|
||||
inline void setSmoothNormals( bool set){ mSmoothNormals = set; }
|
||||
/*! Access object */
|
||||
inline int getObjectId( void ) const { return mObjectId; }
|
||||
inline void setObjectId( int set) { mObjectId = set; }
|
||||
/*! Acces normal index */
|
||||
inline ntlVec3Gfx getNormal( void ) const { return mNormal; }
|
||||
inline void setNormal( ntlVec3Gfx set ) { mNormal = set; }
|
||||
/*! Acces flags */
|
||||
inline int getFlags( void ) const { return mFlags; }
|
||||
inline void setFlags( int set ) { mFlags = set; }
|
||||
/*! Access last intersection ray ID */
|
||||
inline int getLastRay( void ) const { return mLastRay; }
|
||||
inline void setLastRay( int set ) { mLastRay = set; }
|
||||
/*! Acces bbox id */
|
||||
inline int getBBoxId( void ) const { return mBBoxId; }
|
||||
inline void setBBoxId( int set ) { mBBoxId = set; }
|
||||
|
||||
/*! Get average of the three points for this axis */
|
||||
inline gfxReal getAverage( int axis ) const;
|
||||
|
||||
/*! operator < for sorting, uses global sorting axis */
|
||||
inline friend bool operator<(const ntlTriangle &lhs, const ntlTriangle &rhs);
|
||||
/*! operator > for sorting, uses global sorting axis */
|
||||
inline friend bool operator>(const ntlTriangle &lhs, const ntlTriangle &rhs);
|
||||
|
||||
protected:
|
||||
|
||||
private:
|
||||
|
||||
/*! indices to the three points of the triangle */
|
||||
int mPoints[3];
|
||||
|
||||
/*! bounding box id (for tree generation), -1 if invalid */
|
||||
int mBBoxId;
|
||||
|
||||
/*! Should the normals of this triangle get smoothed? */
|
||||
bool mSmoothNormals;
|
||||
|
||||
/*! Id of parent object */
|
||||
int mObjectId;
|
||||
|
||||
/*! Index to normal (for not smooth triangles) */
|
||||
//int mNormalIndex; ??
|
||||
ntlVec3Gfx mNormal;
|
||||
|
||||
/*! Flags for object attributes cast shadows, make caustics etc. */
|
||||
int mFlags;
|
||||
|
||||
/*! ID of last ray that an intersection was calculated for */
|
||||
int mLastRay;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Default Constructor
|
||||
*****************************************************************************/
|
||||
ntlTriangle::ntlTriangle( void ) :
|
||||
mBBoxId(-1),
|
||||
mLastRay( 0 )
|
||||
{
|
||||
mPoints[0] = mPoints[1] = mPoints[2] = 0;
|
||||
mSmoothNormals = 0;
|
||||
mObjectId = 0;
|
||||
mNormal = ntlVec3Gfx(0.0);
|
||||
mFlags = 0;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Constructor
|
||||
*****************************************************************************/
|
||||
ntlTriangle::ntlTriangle(int *p, bool smooth, int obj, ntlVec3Gfx norm, int setflags) :
|
||||
mBBoxId(-1),
|
||||
mLastRay( 0 )
|
||||
{
|
||||
mPoints[0] = p[0];
|
||||
mPoints[1] = p[1];
|
||||
mPoints[2] = p[2];
|
||||
mSmoothNormals = smooth;
|
||||
mObjectId = obj;
|
||||
mNormal = norm;
|
||||
mFlags = setflags;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Copy Constructor
|
||||
*****************************************************************************/
|
||||
ntlTriangle::ntlTriangle(const ntlTriangle &tri) :
|
||||
mBBoxId(-1),
|
||||
mLastRay( 0 )
|
||||
{
|
||||
mPoints[0] = tri.mPoints[0];
|
||||
mPoints[1] = tri.mPoints[1];
|
||||
mPoints[2] = tri.mPoints[2];
|
||||
mSmoothNormals = tri.mSmoothNormals;
|
||||
mObjectId = tri.mObjectId;
|
||||
mNormal = tri.mNormal;
|
||||
mFlags = tri.mFlags;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Triangle sorting functions
|
||||
*****************************************************************************/
|
||||
|
||||
/* variables imported from ntl_bsptree.cc, necessary for using the stl sort funtion */
|
||||
/* Static global variable for sorting direction */
|
||||
extern int globalSortingAxis;
|
||||
/* Access to points array for sorting */
|
||||
extern vector<ntlVec3Gfx> *globalSortingPoints;
|
||||
|
||||
|
||||
gfxReal ntlTriangle::getAverage( int axis ) const
|
||||
{
|
||||
return ( ( (*globalSortingPoints)[ mPoints[0] ][axis] +
|
||||
(*globalSortingPoints)[ mPoints[1] ][axis] +
|
||||
(*globalSortingPoints)[ mPoints[2] ][axis] )/3.0);
|
||||
}
|
||||
|
||||
bool operator<(const ntlTriangle &lhs,const ntlTriangle &rhs)
|
||||
{
|
||||
return ( lhs.getAverage(globalSortingAxis) <
|
||||
rhs.getAverage(globalSortingAxis) );
|
||||
}
|
||||
|
||||
bool operator>(const ntlTriangle &lhs,const ntlTriangle &rhs)
|
||||
{
|
||||
return ( lhs.getAverage(globalSortingAxis) >
|
||||
rhs.getAverage(globalSortingAxis) );
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
1032
intern/elbeem/intern/ntl_vector3dim.h
Normal file
1032
intern/elbeem/intern/ntl_vector3dim.h
Normal file
File diff suppressed because it is too large
Load Diff
501
intern/elbeem/intern/parametrizer.cpp
Normal file
501
intern/elbeem/intern/parametrizer.cpp
Normal file
@ -0,0 +1,501 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* Parameter calculator for the LBM Solver class
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <sstream>
|
||||
#include "parametrizer.h"
|
||||
|
||||
/*! param seen debug string array */
|
||||
char *ParamStrings[] = {
|
||||
"RelaxTime",
|
||||
"Reynolds",
|
||||
"Viscosity",
|
||||
"SoundSpeed",
|
||||
"DomainSize",
|
||||
"GravityForce",
|
||||
"TimeLength",
|
||||
"StepTime",
|
||||
"Size",
|
||||
"TimeFactor",
|
||||
"AniFrames",
|
||||
"AniFrameTime",
|
||||
"AniStart",
|
||||
"SurfaceTension",
|
||||
"Density",
|
||||
"CellSize",
|
||||
"GStar",
|
||||
"MaxSpeed",
|
||||
"SimMaxSpeed",
|
||||
"FluidVolHeight",
|
||||
"NormalizedGStar",
|
||||
"PSERR", "PSERR", "PSERR", "PSERR"
|
||||
};
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Default constructor
|
||||
*****************************************************************************/
|
||||
Parametrizer::Parametrizer( void ) :
|
||||
mSetupType("caro"),
|
||||
mRelaxTime( 1.0 ), mReynolds( 0.0 ),
|
||||
mViscosity( 8.94e-7 ), mSoundSpeed( 1500 ),
|
||||
mDomainSize( 0.1 ), mCellSize( 0.01 ),
|
||||
mGravity(0.0, 0.0, 0.0), mLatticeGravity(0.0, 0.0, 0.0),
|
||||
mStepTime(0.01), mDesiredStepTime(-1.0),
|
||||
mSizex(50), mSizey(50), mSizez(50),
|
||||
mTimeFactor( 1.0 ),
|
||||
mAniFrames(0), mAniFrameTime(0.0), mAniStart(0.0),
|
||||
mExtent(1.0, 1.0, 1.0), mSurfaceTension( 0.0 ),
|
||||
mDensity(1000.0), mGStar(0.0001), mFluidVolumeHeight(0.0),
|
||||
mMaxSpeed(0.0), mSimulationMaxSpeed(0.0),
|
||||
mTadapMaxOmega(1.95), mTadapMaxSpeed(0.1), mTadapLevels(1),
|
||||
mSeenValues( 0 ), mCalculatedValues( 0 )
|
||||
//mActive( false )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Destructor
|
||||
*****************************************************************************/
|
||||
Parametrizer::~Parametrizer()
|
||||
{
|
||||
/* not much to do... */
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Init from attr list
|
||||
*****************************************************************************/
|
||||
void Parametrizer::parseAttrList()
|
||||
{
|
||||
if(!mpAttrs) {
|
||||
errMsg("Parametrizer::parseAttrList", "mpAttrs pointer not initialized!");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
//mActive = mpAttrs->readBool("p_active",mActive, "Parametrizer","mActive", false);
|
||||
mSetupType = mpAttrs->readString("p_setup",mSetupType, "Parametrizer","mSetupType", false);
|
||||
mRelaxTime = mpAttrs->readFloat("p_relaxtime",mRelaxTime, "Parametrizer","mRelaxTime", false);
|
||||
if(getAttributeList()->exists("p_relaxtime")) seenThis( PARAM_RELAXTIME );
|
||||
|
||||
mReynolds = mpAttrs->readFloat("p_reynolds",mReynolds, "Parametrizer","mReynolds", false);
|
||||
if(getAttributeList()->exists("p_reynolds")) seenThis( PARAM_REYNOLDS );
|
||||
|
||||
mViscosity = mpAttrs->readFloat("p_viscosity",mViscosity, "Parametrizer","mViscosity", false);
|
||||
if(getAttributeList()->exists("p_viscosity")) seenThis( PARAM_VISCOSITY );
|
||||
|
||||
mSoundSpeed = mpAttrs->readFloat("p_soundspeed",mSoundSpeed, "Parametrizer","mSoundSpeed", false);
|
||||
if(getAttributeList()->exists("p_soundspeed")) seenThis( PARAM_SOUNDSPEED );
|
||||
|
||||
mDomainSize = mpAttrs->readFloat("p_domainsize",mDomainSize, "Parametrizer","mDomainSize", false);
|
||||
if(getAttributeList()->exists("p_domainsize")) seenThis( PARAM_DOMAINSIZE );
|
||||
|
||||
mGravity = mpAttrs->readVec3d("p_gravity",mGravity, "Parametrizer","mGravity", false);
|
||||
if(getAttributeList()->exists("p_gravity")) seenThis( PARAM_GRAVITY );
|
||||
|
||||
//mTimeLength = mpAttrs->readFloat("p_timelength",mTimeLength, "Parametrizer","mTimeLength", false);
|
||||
//if(getAttributeList()->exists("p_timelength")) seenThis( PARAM_TIMELENGTH );
|
||||
|
||||
mStepTime = mpAttrs->readFloat("p_steptime",mStepTime, "Parametrizer","mStepTime", false);
|
||||
if(getAttributeList()->exists("p_steptime")) seenThis( PARAM_STEPTIME );
|
||||
|
||||
mTimeFactor = mpAttrs->readFloat("p_timefactor",mTimeFactor, "Parametrizer","mTimeFactor", false);
|
||||
if(getAttributeList()->exists("p_timefactor")) seenThis( PARAM_TIMEFACTOR );
|
||||
|
||||
mAniFrames = mpAttrs->readInt("p_aniframes",mAniFrames, "Parametrizer","mAniFrames", false);
|
||||
if(getAttributeList()->exists("p_aniframes")) seenThis( PARAM_ANIFRAMES );
|
||||
|
||||
mAniFrameTime = mpAttrs->readFloat("p_aniframetime",mAniFrameTime, "Parametrizer","mAniFrameTime", false);
|
||||
if(getAttributeList()->exists("p_aniframetime")) seenThis( PARAM_ANIFRAMETIME );
|
||||
if(mAniFrameTime<=0.0) {
|
||||
errMsg("Parametrizer::parseAttrList","Invalid frame time:"<<mAniFrameTime<<", resetting to 0.0001");
|
||||
mAniFrameTime = 0.0001;
|
||||
}
|
||||
|
||||
mAniStart = mpAttrs->readFloat("p_anistart",mAniStart, "Parametrizer","mAniStart", false);
|
||||
if(getAttributeList()->exists("p_anistart")) seenThis( PARAM_ANISTART );
|
||||
if(mAniStart<0.0) {
|
||||
errMsg("Parametrizer::parseAttrList","Invalid start time:"<<mAniStart<<", resetting to 0.0");
|
||||
mAniStart = 0.0;
|
||||
}
|
||||
|
||||
mSurfaceTension = mpAttrs->readFloat("p_surfacetension",mSurfaceTension, "Parametrizer","mSurfaceTension", false);
|
||||
if(getAttributeList()->exists("p_surfacetension")) seenThis( PARAM_SURFACETENSION );
|
||||
|
||||
mDensity = mpAttrs->readFloat("p_density",mDensity, "Parametrizer","mDensity", false);
|
||||
if(getAttributeList()->exists("p_density")) seenThis( PARAM_DENSITY );
|
||||
|
||||
mCellSize = mpAttrs->readFloat("p_cellsize",mCellSize, "Parametrizer","mCellSize", false);
|
||||
if(getAttributeList()->exists("p_cellsize")) seenThis( PARAM_CELLSIZE );
|
||||
|
||||
mGStar = mpAttrs->readFloat("p_gstar",mGStar, "Parametrizer","mGStar", false);
|
||||
if(getAttributeList()->exists("p_gstar")) seenThis( PARAM_GSTAR );
|
||||
|
||||
mNormalizedGStar = mpAttrs->readFloat("p_normgstar",mNormalizedGStar, "Parametrizer","mNormalizedGStar", false);
|
||||
if(getAttributeList()->exists("p_normgstar")) seenThis( PARAM_NORMALIZEDGSTAR );
|
||||
|
||||
mMaxSpeed = mpAttrs->readFloat("p_maxspeed",mMaxSpeed, "Parametrizer","mMaxSpeed", false);
|
||||
if(getAttributeList()->exists("p_maxspeed")) seenThis( PARAM_MAXSPEED );
|
||||
|
||||
mTadapMaxOmega = mpAttrs->readFloat("p_tadapmaxomega",mTadapMaxOmega, "Parametrizer","mTadapMaxOmega", false);
|
||||
mTadapMaxSpeed = mpAttrs->readFloat("p_tadapmaxspeed",mTadapMaxSpeed, "Parametrizer","mTadapMaxSpeed", false);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* scale a given speed vector in m/s to lattice values
|
||||
*****************************************************************************/
|
||||
ParamVec Parametrizer::calculateAddForce(ParamVec vec, string usage)
|
||||
{
|
||||
ParamVec ret = vec * (mStepTime*mStepTime) /mCellSize;
|
||||
debMsgStd("Parametrizer::calculateVector", DM_MSG, "scaled vector = "<<ret<<" for '"<<usage<<"', org = "<<vec<<" dt="<<mStepTime ,10);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* calculate size of a single cell
|
||||
*****************************************************************************/
|
||||
ParamFloat Parametrizer::calculateCellSize(void)
|
||||
{
|
||||
int maxsize = mSizex; // get max size
|
||||
if(mSizey>maxsize) maxsize = mSizey;
|
||||
if(mSizez>maxsize) maxsize = mSizez;
|
||||
ParamFloat cellSize = 1.0 / (ParamFloat)maxsize;
|
||||
return cellSize;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* simple calulation functions */
|
||||
/*****************************************************************************/
|
||||
|
||||
/*! get omega for LBM */
|
||||
ParamFloat Parametrizer::calculateOmega( void ) {
|
||||
//return (mTimeFactor/mRelaxTime);
|
||||
return (1.0/mRelaxTime);
|
||||
}
|
||||
|
||||
/*! get no. of timesteps for LBM */
|
||||
//int calculateNoOfSteps( void ) {
|
||||
int Parametrizer::calculateNoOfSteps( ParamFloat timelen ) {
|
||||
return (int)(timelen/mStepTime);
|
||||
}
|
||||
|
||||
/*! get external force x component */
|
||||
ParamVec Parametrizer::calculateGravity( void ) {
|
||||
return mLatticeGravity;
|
||||
}
|
||||
|
||||
/*! get no of steps for the given length in seconds */
|
||||
int Parametrizer::calculateStepsForSecs( ParamFloat s ) {
|
||||
return (int)(s/mStepTime);
|
||||
}
|
||||
|
||||
/*! get start time of animation */
|
||||
int Parametrizer::calculateAniStart( void ) {
|
||||
return (int)(mAniStart/mStepTime);
|
||||
}
|
||||
|
||||
/*! get no of steps for a singel animation frame */
|
||||
int Parametrizer::calculateAniStepsPerFrame( void ) {
|
||||
if(!checkSeenValues(PARAM_ANIFRAMETIME)) {
|
||||
errMsg("Parametrizer::calculateAniStepsPerFrame", " Missing ani frame time argument!");
|
||||
exit(1);
|
||||
}
|
||||
return (int)(mAniFrameTime/mStepTime);
|
||||
}
|
||||
|
||||
/*! get extent of the domain = (1,1,1) if parametrizer not used, (x,y,z) [m] otherwise */
|
||||
ParamVec Parametrizer::calculateExtent( void ) {
|
||||
return mExtent;
|
||||
}
|
||||
|
||||
/*! get (scaled) surface tension */
|
||||
ParamFloat Parametrizer::calculateSurfaceTension( void ) {
|
||||
return mSurfaceTension;
|
||||
}
|
||||
|
||||
/*! calculate lattice velocity from real world value [m/s] */
|
||||
ParamVec Parametrizer::calculateLattVelocityFromRw( ParamVec ivel ) {
|
||||
ParamVec velvec = ivel;
|
||||
velvec /= mCellSize;
|
||||
velvec *= mStepTime;
|
||||
return velvec;
|
||||
}
|
||||
/*! calculate real world [m/s] velocity from lattice value */
|
||||
ParamVec Parametrizer::calculateRwVelocityFromLatt( ParamVec ivel ) {
|
||||
ParamVec velvec = ivel;
|
||||
velvec *= mCellSize;
|
||||
velvec /= mStepTime;
|
||||
return velvec;
|
||||
}
|
||||
|
||||
|
||||
/*! get the length of a single time step */
|
||||
// explicity scaled by time factor for refinement
|
||||
// testing purposes (e.g. fsgr solver)
|
||||
// not working... done manually in solver
|
||||
ParamFloat Parametrizer::getStepTime( void ) {
|
||||
//return mTimeFactor * mStepTime;
|
||||
return mStepTime;
|
||||
}
|
||||
|
||||
/*! calculate the lattice viscosity */
|
||||
ParamFloat Parametrizer::calculateLatticeViscosity( void ) {
|
||||
// check seen values
|
||||
int reqValues = PARAM_VISCOSITY | PARAM_STEPTIME; // |PARAM_CELLSIZE | PARAM_GRAVITY;
|
||||
if(!checkSeenValues( reqValues ) ){
|
||||
errMsg("Parametrizer::calculateLatticeViscosity"," Missing arguments!");
|
||||
}
|
||||
ParamFloat viscStar = mViscosity * mStepTime / (mCellSize*mCellSize);
|
||||
return viscStar;
|
||||
}
|
||||
|
||||
/*! get g star value with fhvol calculations */
|
||||
ParamFloat Parametrizer::getCurrentGStar( void ) {
|
||||
ParamFloat gStar = mGStar; // check? TODO get from mNormalizedGStar?
|
||||
if(mFluidVolumeHeight>0.0) {
|
||||
gStar = mGStar/mFluidVolumeHeight;
|
||||
}
|
||||
return gStar;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* function that tries to calculate all the missing values from the given ones
|
||||
* prints errors and returns false if thats not possible
|
||||
*****************************************************************************/
|
||||
bool Parametrizer::calculateAllMissingValues( bool silent )
|
||||
{
|
||||
bool init = false; // did we init correctly?
|
||||
int valuesChecked = 0;
|
||||
int reqValues;
|
||||
|
||||
// are we active anyway?
|
||||
//if(!mActive) {
|
||||
// not active - so there's nothing to calculate
|
||||
//return true;
|
||||
//}
|
||||
|
||||
// we always need the sizes
|
||||
reqValues = PARAM_SIZE;
|
||||
valuesChecked |= reqValues;
|
||||
if(!checkSeenValues(reqValues)) {
|
||||
errMsg("Parametrizer::calculateAllMissingValues"," Missing size argument!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(checkSeenValues(PARAM_CELLSIZE)) {
|
||||
errMsg("Parametrizer::calculateAllMissingValues"," Dont explicitly set cell size (use domain size instead)");
|
||||
return false;
|
||||
}
|
||||
if(!checkSeenValues(PARAM_DOMAINSIZE)) {
|
||||
errMsg("Parametrizer::calculateAllMissingValues"," Missing domain size argument!");
|
||||
return false;
|
||||
}
|
||||
int maxsize = mSizex; // get max size
|
||||
if(mSizey>maxsize) maxsize = mSizey;
|
||||
if(mSizez>maxsize) maxsize = mSizez;
|
||||
mCellSize = ( mDomainSize * calculateCellSize() ); // sets mCellSize
|
||||
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," max domain resolution="<<(maxsize)<<" cells , cellsize="<<mCellSize ,10);
|
||||
|
||||
|
||||
/* Carolin init , see DA for details */
|
||||
//ParamFloat viscMax = 0.7600; // max lattice viscosity
|
||||
//ParamFloat viscMin = 0.0033; // min lattice viscosity
|
||||
ParamFloat maxDeltaT = 0.0;
|
||||
ParamFloat maxSpeed = 0.1; // for reynolds approx
|
||||
|
||||
/* normalized gstar init */
|
||||
reqValues = PARAM_NORMALIZEDGSTAR;
|
||||
valuesChecked |= reqValues;
|
||||
if(checkSeenValues( reqValues ) ){
|
||||
//if(checkSeenValues( PARAM_GSTAR ) ){ if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_WARNING," g star value override by normalizedGStar!",1); }
|
||||
mGStar = mNormalizedGStar/maxsize;
|
||||
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," g star set to "<<mGStar<<" from normalizedGStar="<<mNormalizedGStar ,1);
|
||||
seenThis(PARAM_GSTAR);
|
||||
}
|
||||
|
||||
reqValues = PARAM_GSTAR | PARAM_VISCOSITY;
|
||||
if((checkSeenValues(PARAM_SURFACETENSION))) reqValues |= PARAM_DENSITY; // surface tension optional now...
|
||||
valuesChecked |= reqValues;
|
||||
if(checkSeenValues( reqValues ) ){
|
||||
const ParamFloat gstarReset = 0.0005;
|
||||
if(getCurrentGStar()<=0.0) {
|
||||
errMsg("Parametrizer::calculateAllMissingValues","Invalid Gstar: "<<getCurrentGStar()<<" (set to "<<mGStar<<") ... resetting to "<<gstarReset);
|
||||
mGStar = gstarReset;
|
||||
}
|
||||
|
||||
ParamFloat gStar = getCurrentGStar();
|
||||
if(mFluidVolumeHeight>0.0) {
|
||||
debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," height"<<mFluidVolumeHeight<<" resGStar = "<<gStar, 10);
|
||||
}
|
||||
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," g star = "<<gStar, 10);
|
||||
|
||||
if(mSetupType=="caro") {
|
||||
if(!checkSeenValues(PARAM_GRAVITY)) {
|
||||
errMsg("Parametrizer::calculateAllMissingValues","Setup type '"<<mSetupType<<"' requires gravity force!");
|
||||
goto failure;
|
||||
}
|
||||
ParamFloat forceStrength = norm(mGravity);
|
||||
if(forceStrength<=0) {
|
||||
errMsg("Parametrizer::calculateAllMissingValues"," Init failed - forceStrength = "<<forceStrength);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
// determine max. delta density per timestep trough gravity force
|
||||
maxDeltaT = sqrt( gStar*mCellSize/forceStrength );
|
||||
} else if(mSetupType=="maxspeed") {
|
||||
// determine max. delta t from maximum speed (explicity set)
|
||||
if((!checkSeenValues(PARAM_MAXSPEED))||(mMaxSpeed<=0.0)) {
|
||||
errMsg("Parametrizer::calculateAllMissingValues","Setup type '"<<mSetupType<<"' requires maximum speed ("<<mMaxSpeed<<") !");
|
||||
goto failure;
|
||||
}
|
||||
ParamFloat maxLatticeSpeed = 0.0333333; //?
|
||||
maxDeltaT = ( maxLatticeSpeed * mCellSize) / mMaxSpeed;
|
||||
maxSpeed = mMaxSpeed;
|
||||
} else if(mSetupType=="falling") {
|
||||
// determine max. delta t from maximum speed that can be caused by falling through the domain
|
||||
errMsg("Parametrizer::calculateAllMissingValues"," NYI setup falling");
|
||||
} else {
|
||||
errMsg("Parametrizer::calculateAllMissingValues","Setup type '"<<mSetupType<<"' unknown!");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," targeted step time = "<<maxDeltaT, 10);
|
||||
|
||||
ParamFloat viscStarFac = mViscosity/(mCellSize*mCellSize);
|
||||
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," viscStarFac = "<<viscStarFac, 10);
|
||||
|
||||
// FIXME remove for LES?
|
||||
//if( (viscStarFac*maxDeltaT>=viscMin) && (viscStarFac*maxDeltaT<=viscMax) ) {
|
||||
//if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," delta t: "<<viscMin<<" <? "<<maxDeltaT*viscStarFac<<" <? "<<viscMax, 1);
|
||||
//} else {
|
||||
//if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_WARNING," delta t not in valid range: "<<viscMin<<" <? "<<maxDeltaT*viscStarFac<<" <? "<<viscMax, 1);
|
||||
//}
|
||||
|
||||
// time step adaptivty, only for caro with max sim speed
|
||||
ParamFloat setDeltaT = maxDeltaT;
|
||||
if(mDesiredStepTime>0.0) {
|
||||
setDeltaT = mDesiredStepTime;
|
||||
mDesiredStepTime = -1.0;
|
||||
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," desired step time = "<<setDeltaT, 10);
|
||||
} else if((mSetupType=="caro") && (checkSeenValues( PARAM_SIMMAXSPEED )) ) {
|
||||
// determine minimal delta t by omega max.
|
||||
ParamFloat minDeltaT;
|
||||
ParamFloat maxOmega = mTadapMaxOmega;
|
||||
ParamFloat minRelaxTime = 1.0/maxOmega;
|
||||
for(int lev=1; lev<mTadapLevels; lev++) {
|
||||
// make minRelaxTime larger for each level that exists...
|
||||
minRelaxTime = 2.0 * (minRelaxTime-0.5) + 0.5;
|
||||
}
|
||||
maxOmega = 1.0/minRelaxTime;
|
||||
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," maxOmega="<<maxOmega<<" minRelaxTime="<<minRelaxTime<<" levels="<<mTadapLevels, 1);
|
||||
// visc-star for min relax time to calculate min delta ta
|
||||
if(mViscosity>0.0) {
|
||||
minDeltaT = ((2.0*minRelaxTime-1.0)/6.0) * mCellSize * mCellSize / mViscosity;
|
||||
} else {
|
||||
// visc=0, this is not physical, but might happen
|
||||
minDeltaT = 0.0;
|
||||
}
|
||||
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," min delta t = "<<minDeltaT<<" , range = " << (maxDeltaT/minDeltaT) ,1);
|
||||
|
||||
// sim speed + accel shouldnt exceed 0.1?
|
||||
//if(mSimulationMaxSpeed + norm(mGravity*)) { ParamFloat nextmax = 0.1-mSimulationMaxSpeed }
|
||||
mMaxStepTime = maxDeltaT;
|
||||
mMinStepTime = minDeltaT;
|
||||
// only use once...
|
||||
} else {
|
||||
debMsgStd("Parametrizer::calculateAllMissingValues",DM_WARNING,"Warning - setup type set to '"<<mSetupType<<"' ",1);
|
||||
mMaxStepTime = mMinStepTime = setDeltaT;
|
||||
}
|
||||
|
||||
setStepTime( setDeltaT ); // set mStepTime to new value
|
||||
|
||||
//ParamFloat viscStar = mViscosity * mStepTime / (mCellSize*mCellSize);
|
||||
ParamFloat viscStar = calculateLatticeViscosity();
|
||||
mRelaxTime = (6.0 * viscStar + 1) * 0.5;
|
||||
init = true;
|
||||
|
||||
}
|
||||
|
||||
// finish init
|
||||
if(init) {
|
||||
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," omega = "<<calculateOmega()<<", relax time = "<<mRelaxTime<<", delt="<<mStepTime,1);
|
||||
//debMsgStd("Parametrizer::calculateAllMissingValues: lbm steps = "<<calculateNoOfSteps()<<" ",1);
|
||||
|
||||
if(checkSeenValues(PARAM_GRAVITY)) {
|
||||
ParamFloat forceFactor = (mStepTime *mStepTime)/mCellSize;
|
||||
//if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," given force = "<<PRINT_NTLVEC(mGravity),1);
|
||||
mLatticeGravity = mGravity * forceFactor;
|
||||
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," gravity force = "<<PRINT_NTLVEC(mGravity)<<", scaled with "<<forceFactor<<" to "<<mLatticeGravity,1);
|
||||
}
|
||||
|
||||
if((checkSeenValues(PARAM_SURFACETENSION))&&(mSurfaceTension>0.0)) {
|
||||
ParamFloat massDelta = 1.0;
|
||||
ParamFloat densityStar = 1.0;
|
||||
massDelta = mDensity / densityStar *mCellSize*mCellSize*mCellSize;
|
||||
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," massDelta = "<<massDelta, 10);
|
||||
|
||||
mSurfaceTension = mSurfaceTension*mStepTime*mStepTime/massDelta;
|
||||
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," surface tension = "<<mSurfaceTension<<" ",1);
|
||||
}
|
||||
|
||||
mExtent = ParamVec( mCellSize*mSizex, mCellSize*mSizey, mCellSize*mSizez );
|
||||
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," domain extent = "<<PRINT_NTLVEC(mExtent)<<"m ",1);
|
||||
|
||||
if(checkSeenValues(PARAM_ANIFRAMETIME)) {
|
||||
if(checkSeenValues(PARAM_ANIFRAMES)) {
|
||||
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," Warning - ani frame time and ani frames given!", 1);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
mAniFrameTime = mAniFrames * mStepTime;
|
||||
}
|
||||
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," ani frame steps = "<<calculateAniStepsPerFrame()<<" ", 1);
|
||||
|
||||
if((checkSeenValues(PARAM_ANISTART))&&(calculateAniStart()>0)) {
|
||||
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," ani start steps = "<<calculateAniStart()<<" ",1);
|
||||
}
|
||||
|
||||
// calculate reynolds number
|
||||
ParamFloat reynoldsApprox = -1.0;
|
||||
ParamFloat gridSpeed = (maxSpeed*mCellSize/mStepTime);
|
||||
reynoldsApprox = (mDomainSize*gridSpeed) / mViscosity;
|
||||
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues",DM_MSG," reynolds number (D="<<mDomainSize<<", assuming V="<<gridSpeed<<")= "<<reynoldsApprox<<" ", 1);
|
||||
|
||||
// everything ok
|
||||
return true;
|
||||
}
|
||||
|
||||
failure:
|
||||
errMsg("Parametrizer::calculateAllMissingValues "," invalid configuration!");
|
||||
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues ",DM_WARNING, " values seen:", 1);
|
||||
for(int i=0;i<PARAM_NUMIDS;i++) {
|
||||
if(checkSeenValues( 1<<i )) {
|
||||
if(!silent) debMsgStd(" ",DM_NOTIFY, ParamStrings[i], 1);
|
||||
}
|
||||
}
|
||||
if(!silent) debMsgStd("Parametrizer::calculateAllMissingValues ",DM_WARNING, "values checked but missing:", 1);
|
||||
for(int i=0;i<PARAM_NUMIDS;i++) {
|
||||
if((!checkSeenValues( 1<<i ))&&
|
||||
( (valuesChecked&(1<<i))==(1<<i)) ) {
|
||||
debMsgStd(" ",DM_IMPORTANT, ParamStrings[i], 1);
|
||||
}
|
||||
}
|
||||
|
||||
// print values?
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
369
intern/elbeem/intern/parametrizer.h
Normal file
369
intern/elbeem/intern/parametrizer.h
Normal file
@ -0,0 +1,369 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* Parameter calculator for the LBM Solver class
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef MFFSLBM_PARAMETRIZER
|
||||
#define MFFSLBM_PARAMETRIZER
|
||||
|
||||
|
||||
/* LBM Files */
|
||||
#include "utilities.h"
|
||||
#include "attributes.h"
|
||||
|
||||
/* parametrizer accuracy */
|
||||
typedef double ParamFloat;
|
||||
typedef ntlVec3d ParamVec;
|
||||
|
||||
/*! flags to check which values are known */
|
||||
#define PARAM_RELAXTIME (1<< 0)
|
||||
#define PARAM_REYNOLDS (1<< 1)
|
||||
#define PARAM_VISCOSITY (1<< 2)
|
||||
#define PARAM_SOUNDSPEED (1<< 3)
|
||||
#define PARAM_DOMAINSIZE (1<< 4)
|
||||
#define PARAM_GRAVITY (1<< 5)
|
||||
#define PARAM_TIMELENGTH (1<< 6)
|
||||
#define PARAM_STEPTIME (1<< 7)
|
||||
#define PARAM_SIZE (1<< 8)
|
||||
#define PARAM_TIMEFACTOR (1<< 9)
|
||||
#define PARAM_ANIFRAMES (1<<10)
|
||||
#define PARAM_ANIFRAMETIME (1<<11)
|
||||
#define PARAM_ANISTART (1<<12)
|
||||
#define PARAM_SURFACETENSION (1<<13)
|
||||
#define PARAM_DENSITY (1<<14)
|
||||
#define PARAM_CELLSIZE (1<<15)
|
||||
#define PARAM_GSTAR (1<<16)
|
||||
#define PARAM_MAXSPEED (1<<17)
|
||||
#define PARAM_SIMMAXSPEED (1<<18)
|
||||
#define PARAM_FLUIDVOLHEIGHT (1<<19)
|
||||
#define PARAM_NORMALIZEDGSTAR (1<<20)
|
||||
#define PARAM_NUMIDS 21
|
||||
|
||||
//! parameters to ignore for parametrizer activation
|
||||
#define PARAM_IGNORE (~(PARAM_ANIFRAMES|PARAM_SIZE))
|
||||
|
||||
//! output parameter debug message?
|
||||
//#define PARAM_DEBUG 1
|
||||
|
||||
|
||||
|
||||
/*! Parameter calculator for the LBM Solver class */
|
||||
class Parametrizer {
|
||||
|
||||
public:
|
||||
/*! default contructor */
|
||||
Parametrizer();
|
||||
|
||||
/*! destructor */
|
||||
~Parametrizer();
|
||||
|
||||
/*! Initilize variables fom attribute list */
|
||||
void parseAttrList( void );
|
||||
|
||||
/*! function that tries to calculate all the missing values from the given ones
|
||||
* prints errors and returns false if thats not possible */
|
||||
bool calculateAllMissingValues( bool silent = false );
|
||||
bool oldCalculateAllMissingValues( void );
|
||||
/*! is the parametrizer used at all? */
|
||||
//bool isUsed() { if(!mActive){ return false; } return(mSeenValues!=(~PARAM_IGNORE)); }
|
||||
bool isUsed() { return true; }
|
||||
|
||||
/*! add this flag to the seen values */
|
||||
void seenThis(int seen) { mSeenValues = (mSeenValues | seen);
|
||||
#ifdef PARAM_DEBUG
|
||||
errorOut(" seen "<<seen<<endl);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*! set the flags integer */
|
||||
void setSeenValues(int set) { mSeenValues = set; }
|
||||
/*! check if the flags are set in the values int */
|
||||
bool checkSeenValues(int check) { /*errorOut( " b"<<((mSeenValues&check)==check) );*/ return ((mSeenValues&check)==check); }
|
||||
|
||||
/*! add this flag to the calculated values */
|
||||
void calculatedThis(int cac) { mCalculatedValues = (mCalculatedValues | cac); /*errorOut(" a "<<seen);*/ }
|
||||
/*! set the calculated flags integer */
|
||||
void setCalculatedValues(int set) { mCalculatedValues = set; }
|
||||
/*! check if the calculated flags are set in the values int */
|
||||
bool checkCalculatedValues(int check) { /*errorOut( " b"<<((mSeenValues&check)==check) );*/ return ((mCalculatedValues&check)==check); }
|
||||
|
||||
/*! scale a given speed vector in m/s to lattice values
|
||||
* usage string is only needed for debugging */
|
||||
ParamVec calculateAddForce(ParamVec vec, string usage);
|
||||
|
||||
/* simple calulation functions */
|
||||
/*! get omega for LBM */
|
||||
ParamFloat calculateOmega( void );
|
||||
/*! get no. of timesteps for LBM */
|
||||
//int calculateNoOfSteps( void ) { return (int)(mTimeLength/mStepTime); }
|
||||
int calculateNoOfSteps( ParamFloat timelen );
|
||||
/*! get external force x component */
|
||||
ParamVec calculateGravity( void );
|
||||
/*! get no of steps for the given length in seconds */
|
||||
int calculateStepsForSecs( ParamFloat s );
|
||||
/*! get start time of animation */
|
||||
int calculateAniStart( void );
|
||||
/*! get no of steps for a singel animation frame */
|
||||
int calculateAniStepsPerFrame( void );
|
||||
/*! get extent of the domain = (1,1,1) if parametrizer not used, (x,y,z) [m] otherwise */
|
||||
ParamVec calculateExtent( void );
|
||||
/*! get (scaled) surface tension */
|
||||
ParamFloat calculateSurfaceTension( void );
|
||||
/*! get time step size for lbm (equals mTimeFactor) */
|
||||
// unused ParamFloat calculateTimestep( void );
|
||||
/*! calculate size of a single cell */
|
||||
ParamFloat calculateCellSize(void);
|
||||
/*! calculate the lattice viscosity */
|
||||
ParamFloat calculateLatticeViscosity(void);
|
||||
|
||||
/*! calculate lattice velocity from real world value [m/s] */
|
||||
ParamVec calculateLattVelocityFromRw( ParamVec ivel );
|
||||
/*! calculate real world [m/s] velocity from lattice value */
|
||||
ParamVec calculateRwVelocityFromLatt( ParamVec ivel );
|
||||
|
||||
|
||||
/*! set relaxation time */
|
||||
void setRelaxTime(ParamFloat set) { mRelaxTime = set; seenThis( PARAM_RELAXTIME ); }
|
||||
/*! get relaxation time */
|
||||
ParamFloat getRelaxTime( void ) { return mRelaxTime; }
|
||||
|
||||
/*! set reynolds number */
|
||||
void setReynolds(ParamFloat set) { mReynolds = set; seenThis( PARAM_REYNOLDS ); }
|
||||
/*! get reynolds number */
|
||||
ParamFloat getReynolds( void ) { return mReynolds; }
|
||||
|
||||
/*! set kinematic viscosity */
|
||||
void setViscosity(ParamFloat set) { mViscosity = set; seenThis( PARAM_VISCOSITY ); }
|
||||
/*! get kinematic viscosity */
|
||||
ParamFloat getViscosity( void ) { return mViscosity; }
|
||||
|
||||
/*! set speed of sound */
|
||||
void setSoundSpeed(ParamFloat set) { mSoundSpeed = set; seenThis( PARAM_SOUNDSPEED ); }
|
||||
/*! get speed of sound */
|
||||
ParamFloat getSoundSpeed( void ) { return mSoundSpeed; }
|
||||
|
||||
/*! set the external force */
|
||||
void setGravity(ParamFloat setx, ParamFloat sety, ParamFloat setz) { mGravity = ParamVec(setx,sety,setz); seenThis( PARAM_GRAVITY ); }
|
||||
void setGravity(ParamVec set) { mGravity = set; seenThis( PARAM_GRAVITY ); }
|
||||
|
||||
/*! set the length of the simulation */
|
||||
//void setTimeLength(ParamFloat set) { mTimeLength = set; seenThis( PARAM_TIMELENGTH ); }
|
||||
/*! get the length of the simulation */
|
||||
//ParamFloat getTimeLength( void ) { return mTimeLength; }
|
||||
|
||||
/*! set the length of a single time step */
|
||||
void setStepTime(ParamFloat set) { mStepTime = set; seenThis( PARAM_STEPTIME ); }
|
||||
/*! get the length of a single time step */
|
||||
ParamFloat getStepTime( void);
|
||||
/*! set a desired step time for rescaling/adaptive timestepping */
|
||||
void setDesiredStepTime(ParamFloat set) { mDesiredStepTime = set; }
|
||||
/*! get the length of a single time step */
|
||||
ParamFloat getMaxStepTime( void ) { return mMaxStepTime; }
|
||||
/*! get the length of a single time step */
|
||||
ParamFloat getMinStepTime( void ) { return mMinStepTime; }
|
||||
|
||||
/*! set the time scaling factor */
|
||||
void setTimeFactor(ParamFloat set) { mTimeFactor = set; seenThis( PARAM_TIMEFACTOR ); }
|
||||
/*! get the time scaling factor */
|
||||
ParamFloat getTimeFactor( void ) { return mTimeFactor; }
|
||||
|
||||
/*! init domain resoultion */
|
||||
void setSize(int ijk) { mSizex = ijk; mSizey = ijk; mSizez = ijk; seenThis( PARAM_SIZE ); }
|
||||
void setSize(int i,int j, int k) { mSizex = i; mSizey = j; mSizez = k; seenThis( PARAM_SIZE ); }
|
||||
|
||||
/*! set no of animation steps (renderer) */
|
||||
void setAniFrames(int set) { mAniFrames = set; seenThis( PARAM_ANIFRAMES ); }
|
||||
/*! get no of animation steps (renderer) */
|
||||
int getAniFrames( void ) { return mAniFrames; }
|
||||
|
||||
/*! set time of an animation frame (renderer) */
|
||||
void setAniFrameTime(ParamFloat set) { mAniFrameTime = set; seenThis( PARAM_ANIFRAMETIME ); }
|
||||
/*! get time of an animation frame (renderer) */
|
||||
ParamFloat getAniFrameTime( void ) { return mAniFrameTime; }
|
||||
|
||||
/*! set starting time of the animation (renderer) */
|
||||
void setAniStart(ParamFloat set) { mAniStart = set; seenThis( PARAM_ANISTART ); }
|
||||
/*! get starting time of the animation (renderer) */
|
||||
ParamFloat getAniStart( void ) { return mAniStart; }
|
||||
|
||||
/*! set starting time of the animation (renderer) */
|
||||
void setSurfaceTension(ParamFloat set) { mSurfaceTension = set; seenThis( PARAM_SURFACETENSION ); }
|
||||
/*! get starting time of the animation (renderer) */
|
||||
ParamFloat getSurfaceTension( void ) { return mSurfaceTension; }
|
||||
|
||||
/*! set fluid density */
|
||||
void setDensity(ParamFloat set) { mDensity = set; seenThis( PARAM_DENSITY ); }
|
||||
/*! get fluid density */
|
||||
ParamFloat getDensity( void ) { return mDensity; }
|
||||
|
||||
/*! set g star value */
|
||||
void setGStar(ParamFloat set) { mGStar = set; seenThis( PARAM_GSTAR ); }
|
||||
/*! get g star value */
|
||||
ParamFloat getGStar( void ) { return mGStar; }
|
||||
/*! get g star value with fhvol calculations */
|
||||
ParamFloat getCurrentGStar( void );
|
||||
/*! set normalized g star value */
|
||||
void setNormalizedGStar(ParamFloat set) { mNormalizedGStar = set; seenThis( PARAM_NORMALIZEDGSTAR ); }
|
||||
/*! get normalized g star value */
|
||||
ParamFloat getNormalizedGStar( void ) { return mNormalizedGStar; }
|
||||
|
||||
/*! set g star value */
|
||||
void setFluidVolumeHeight(ParamFloat set) { mFluidVolumeHeight = set; seenThis( PARAM_FLUIDVOLHEIGHT ); }
|
||||
/*! get g star value */
|
||||
ParamFloat getFluidVolumeHeight( void ) { return mFluidVolumeHeight; }
|
||||
|
||||
/*! set the size of a single lbm cell */
|
||||
void setDomainSize(ParamFloat set) { mDomainSize = set; seenThis( PARAM_DOMAINSIZE ); }
|
||||
/*! get the size of a single lbm cell */
|
||||
ParamFloat getDomainSize( void ) { return mDomainSize; }
|
||||
|
||||
/*! set the size of a single lbm cell */
|
||||
void setCellSize(ParamFloat set) { mCellSize = set; seenThis( PARAM_CELLSIZE ); }
|
||||
/*! get the size of a single lbm cell */
|
||||
ParamFloat getCellSize( void ) { return mCellSize; }
|
||||
|
||||
/*! set active flag for parametrizer */
|
||||
//void setActive(bool set) { mActive = set; }
|
||||
|
||||
/*! set attr list pointer */
|
||||
void setAttrList(AttributeList *set) { mpAttrs = set; }
|
||||
/*! Returns the attribute list pointer */
|
||||
inline AttributeList *getAttributeList() { return mpAttrs; }
|
||||
|
||||
/*! set maximum allowed speed for maxspeed setup */
|
||||
void setMaxSpeed(ParamFloat set) { mMaxSpeed = set; seenThis( PARAM_MAXSPEED ); }
|
||||
/*! get maximum allowed speed for maxspeed setup */
|
||||
ParamFloat getMaxSpeed( void ) { return mMaxSpeed; }
|
||||
|
||||
/*! set maximum allowed speed for maxspeed setup */
|
||||
void setSimulationMaxSpeed(ParamFloat set) { mSimulationMaxSpeed = set; seenThis( PARAM_SIMMAXSPEED ); }
|
||||
/*! get maximum allowed speed for maxspeed setup */
|
||||
ParamFloat getSimulationMaxSpeed( void ) { return mSimulationMaxSpeed; }
|
||||
|
||||
/*! set maximum allowed omega for time adaptivity */
|
||||
void setTadapMaxOmega(ParamFloat set) { mTadapMaxOmega = set; }
|
||||
/*! get maximum allowed omega for time adaptivity */
|
||||
ParamFloat getTadapMaxOmega( void ) { return mTadapMaxOmega; }
|
||||
|
||||
/*! set maximum allowed speed for time adaptivity */
|
||||
void setTadapMaxSpeed(ParamFloat set) { mTadapMaxSpeed = set; }
|
||||
/*! get maximum allowed speed for time adaptivity */
|
||||
ParamFloat getTadapMaxSpeed( void ) { return mTadapMaxSpeed; }
|
||||
|
||||
/*! set maximum allowed omega for time adaptivity */
|
||||
void setTadapLevels(int set) { mTadapLevels = set; }
|
||||
/*! get maximum allowed omega for time adaptivity */
|
||||
int getTadapLevels( void ) { return mTadapLevels; }
|
||||
|
||||
|
||||
/*! set */
|
||||
// void set(ParamFloat set) { m = set; seenThis( PARAM_ ); }
|
||||
/*! get */
|
||||
// ParamFloat get( void ) { return m; }
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/*! type of parameter setup to use */
|
||||
string mSetupType;
|
||||
|
||||
/*! relaxation time [s] */
|
||||
ParamFloat mRelaxTime;
|
||||
|
||||
/*! reynolds number (calculated from domain length and max. speed [dimensionless] */
|
||||
ParamFloat mReynolds;
|
||||
|
||||
/*! kinematic viscosity of the fluid [m^2/s] */
|
||||
ParamFloat mViscosity;
|
||||
|
||||
/*! speed of sound of the fluid [m/s] */
|
||||
ParamFloat mSoundSpeed;
|
||||
|
||||
/*! size of the domain [m] */
|
||||
ParamFloat mDomainSize;
|
||||
|
||||
/*! size of a single cell in the grid [m] */
|
||||
ParamFloat mCellSize;
|
||||
|
||||
/*! time step length [s] */
|
||||
ParamFloat mTimeStep;
|
||||
|
||||
/*! external force as acceleration [m/s^2] */
|
||||
ParamVec mGravity;
|
||||
/*! force converted to lattice units (returned by calc gravity) */
|
||||
ParamVec mLatticeGravity;
|
||||
|
||||
/*! lenth of the simulation [s] */
|
||||
//ParamFloat mTimeLength;
|
||||
|
||||
/*! length of one time step in the simulation */
|
||||
ParamFloat mStepTime;
|
||||
/*! desired step time for rescaling/adaptive timestepping, only regarded if >0.0, reset after usage */
|
||||
ParamFloat mDesiredStepTime;
|
||||
/*! minimal and maximal step times for current setup */
|
||||
ParamFloat mMaxStepTime, mMinStepTime;
|
||||
|
||||
/*! domain resoultion, the same values as in lbmsolver */
|
||||
int mSizex, mSizey, mSizez;
|
||||
|
||||
/*! time scaling factor (auto calc from accel, or set), equals the delta t in LBM */
|
||||
ParamFloat mTimeFactor;
|
||||
|
||||
/*! from renderer - no of animation frames for the animation (same as mpglob mAniFrames) */
|
||||
int mAniFrames;
|
||||
|
||||
/*! for renderer - length of an animation step [s] */
|
||||
ParamFloat mAniFrameTime;
|
||||
|
||||
/*! for renderer - start time of the animation [s] */
|
||||
ParamFloat mAniStart;
|
||||
|
||||
/*! extent of the domain in meters */
|
||||
ParamVec mExtent;
|
||||
|
||||
/*! surface tension, [kg/s^2] */
|
||||
ParamFloat mSurfaceTension;
|
||||
|
||||
/*! fluid density [kg/m^3], default 1.0 g/cm^3 */
|
||||
ParamFloat mDensity;
|
||||
|
||||
/*! max difference due to gravity (for caro setup) */
|
||||
ParamFloat mGStar;
|
||||
/*! set gstar normalized! */
|
||||
ParamFloat mNormalizedGStar;
|
||||
/*! fluid volume/height multiplier for GStar */
|
||||
ParamFloat mFluidVolumeHeight;
|
||||
|
||||
/*! max speed (for maxspeed setup) */
|
||||
ParamFloat mMaxSpeed;
|
||||
|
||||
/*! current max speed of the simulation (for adaptive time steps) */
|
||||
ParamFloat mSimulationMaxSpeed;
|
||||
/*! maximum omega (for adaptive time steps) */
|
||||
ParamFloat mTadapMaxOmega;
|
||||
/*! maximum allowed speed in lattice units e.g. 0.1 (for adaptive time steps, not directly used in parametrizer) */
|
||||
ParamFloat mTadapMaxSpeed;
|
||||
/*! no. of levels for max omega (set by fsgr, not in cfg file) */
|
||||
int mTadapLevels;
|
||||
|
||||
|
||||
/*! values that are seen for this simulation */
|
||||
int mSeenValues;
|
||||
|
||||
/*! values that are calculated from the seen ones for this simulation */
|
||||
int mCalculatedValues;
|
||||
|
||||
/*! is the parametrizer active? */
|
||||
//bool mActive;
|
||||
|
||||
/*! pointer to the attribute list */
|
||||
AttributeList *mpAttrs;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
270
intern/elbeem/intern/particletracer.cpp
Normal file
270
intern/elbeem/intern/particletracer.cpp
Normal file
@ -0,0 +1,270 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* Particle Viewer/Tracer
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
//#include "../libs/my_gl.h"
|
||||
//#include "../libs/my_glu.h"
|
||||
|
||||
/* own lib's */
|
||||
#include "particletracer.h"
|
||||
#include "ntl_matrices.h"
|
||||
#include "ntl_ray.h"
|
||||
#include "ntl_scene.h"
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Standard constructor
|
||||
*****************************************************************************/
|
||||
ParticleTracer::ParticleTracer() :
|
||||
ntlGeometryObject(),
|
||||
mParts(1),
|
||||
mNumParticles(0), mTrailLength(1), mTrailInterval(1),mTrailIntervalCounter(0),
|
||||
mPartSize(0.01), mTrailScale(1.0),
|
||||
mStart(-1.0), mEnd(1.0),
|
||||
mSimStart(-1.0), mSimEnd(1.0),
|
||||
mPartScale(1.0) , mPartHeadDist( 0.5 ), mPartTailDist( -4.5 ), mPartSegments( 4 ),
|
||||
mValueScale(0),
|
||||
mValueCutoffTop(0.0), mValueCutoffBottom(0.0)
|
||||
{
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
//! parse settings from attributes (dont use own list!)
|
||||
/*****************************************************************************/
|
||||
void ParticleTracer::parseAttrList(AttributeList *att)
|
||||
{
|
||||
AttributeList *tempAtt = mpAttrs;
|
||||
mpAttrs = att;
|
||||
mNumParticles = mpAttrs->readInt("particles",mNumParticles, "ParticleTracer","mNumParticles", false);
|
||||
mTrailLength = mpAttrs->readInt("traillength",mTrailLength, "ParticleTracer","mTrailLength", false);
|
||||
mTrailInterval= mpAttrs->readInt("trailinterval",mTrailInterval, "ParticleTracer","mTrailInterval", false);
|
||||
|
||||
mPartScale = mpAttrs->readFloat("part_scale",mPartScale, "ParticleTracer","mPartScale", false);
|
||||
mPartHeadDist = mpAttrs->readFloat("part_headdist",mPartHeadDist, "ParticleTracer","mPartHeadDist", false);
|
||||
mPartTailDist = mpAttrs->readFloat("part_taildist",mPartTailDist, "ParticleTracer","mPartTailDist", false);
|
||||
mPartSegments = mpAttrs->readInt ("part_segments",mPartSegments, "ParticleTracer","mPartSegments", false);
|
||||
mValueScale = mpAttrs->readInt ("part_valscale",mValueScale, "ParticleTracer","mValueScale", false);
|
||||
mValueCutoffTop = mpAttrs->readFloat("part_valcutofftop",mValueCutoffTop, "ParticleTracer","mValueCutoffTop", false);
|
||||
mValueCutoffBottom = mpAttrs->readFloat("part_valcutoffbottom",mValueCutoffBottom, "ParticleTracer","mValueCutoffBottom", false);
|
||||
|
||||
mTrailScale = mpAttrs->readFloat("trail_scale",mTrailScale, "ParticleTracer","mTrailScale", false);
|
||||
|
||||
string matPart;
|
||||
matPart = mpAttrs->readString("material_part", "default", "ParticleTracer","material", false);
|
||||
setMaterialName( matPart );
|
||||
// trail length has to be at least one, if anything should be displayed
|
||||
if((mNumParticles>0)&&(mTrailLength<2)) mTrailLength = 2;
|
||||
|
||||
// restore old list
|
||||
mpAttrs = tempAtt;
|
||||
mParts.resize(mTrailLength*mTrailInterval);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* draw the particle array
|
||||
*****************************************************************************/
|
||||
void ParticleTracer::draw()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* set the number of timesteps to trace
|
||||
*****************************************************************************/
|
||||
void ParticleTracer::setTimesteps(int steps)
|
||||
{
|
||||
steps=0; // remove warning...
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* add a particle at this position
|
||||
*****************************************************************************/
|
||||
void ParticleTracer::addParticle(double x, double y, double z)
|
||||
{
|
||||
ntlVec3Gfx p(x,y,z);
|
||||
ParticleObject part( p );
|
||||
//mParts[0].push_back( part );
|
||||
// TODO handle other arrays?
|
||||
//part.setActive( false );
|
||||
for(size_t l=0; l<mParts.size(); l++) {
|
||||
// add deactivated particles to other arrays
|
||||
mParts[l].push_back( part );
|
||||
// deactivate further particles
|
||||
if(l>1) {
|
||||
//mParts[l][ mParts.size()-1 ].setActive( false );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* save particle positions before adding a new timestep
|
||||
* copy "one index up", newest has to remain unmodified, it will be
|
||||
* advanced after the next smiulation step
|
||||
*****************************************************************************/
|
||||
void ParticleTracer::savePreviousPositions()
|
||||
{
|
||||
//debugOut(" PARTS SIZE "<<mParts.size() ,10);
|
||||
if(mTrailIntervalCounter==0) {
|
||||
//errMsg("spp"," PARTS SIZE "<<mParts.size() );
|
||||
for(size_t l=mParts.size()-1; l>0; l--) {
|
||||
if( mParts[l].size() != mParts[l-1].size() ) {
|
||||
errorOut("ParticleTracer::savePreviousPositions error: Invalid array sizes ["<<l<<"]="<<mParts[l].size()<<
|
||||
" ["<<(l+1)<<"]="<<mParts[l+1].size() <<" , total "<< mParts.size() );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for(size_t i=0; i<mParts[l].size(); i++) {
|
||||
mParts[l][i] = mParts[l-1][i];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
mTrailIntervalCounter++;
|
||||
if(mTrailIntervalCounter>=mTrailInterval) mTrailIntervalCounter = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Get triangles for rendering
|
||||
*****************************************************************************/
|
||||
void ParticleTracer::getTriangles( vector<ntlTriangle> *triangles,
|
||||
vector<ntlVec3Gfx> *vertices,
|
||||
vector<ntlVec3Gfx> *normals, int objectId )
|
||||
{
|
||||
int tris = 0;
|
||||
gfxReal partNormSize = 0.01 * mPartScale;
|
||||
ntlVec3Gfx pScale = ntlVec3Gfx(
|
||||
(mEnd[0]-mStart[0])/(mSimEnd[0]-mSimStart[0]),
|
||||
(mEnd[1]-mStart[1])/(mSimEnd[1]-mSimStart[1]),
|
||||
(mEnd[2]-mStart[2])/(mSimEnd[2]-mSimStart[2])
|
||||
);
|
||||
//errMsg(" PS ", " S "<<pScale );
|
||||
ntlVec3Gfx org = mStart;
|
||||
int segments = mPartSegments;
|
||||
|
||||
int lnewst = mTrailLength-1;
|
||||
int loldst = mTrailLength-2;
|
||||
// trails gehen nicht so richtig mit der
|
||||
// richtung der partikel...
|
||||
//for(int l=0; l<mTrailLength-2; l++) {
|
||||
//int lnewst = l+1;
|
||||
//int loldst = l;
|
||||
|
||||
for(size_t i=0; i<mParts[lnewst].size(); i++) {
|
||||
|
||||
//mParts[0][i].setActive(true);
|
||||
|
||||
if( mParts[lnewst][i].getActive()==false ) continue;
|
||||
if( mParts[loldst][i].getActive()==false ) continue;
|
||||
|
||||
ntlVec3Gfx pnew = mParts[lnewst][i].getPos();
|
||||
ntlVec3Gfx pold = mParts[loldst][i].getPos();
|
||||
ntlVec3Gfx pdir = pnew - pold;
|
||||
gfxReal plen = normalize( pdir );
|
||||
if( plen < 1e-05) pdir = ntlVec3Gfx(-1.0 ,0.0 ,0.0);
|
||||
ntlVec3Gfx p = org + pnew*pScale;
|
||||
gfxReal partsize = 0.0;
|
||||
//errMsg("pp"," "<<l<<" i"<<i<<" new"<<pnew<<" old"<<pold );
|
||||
|
||||
// value length scaling?
|
||||
if(mValueScale==1) {
|
||||
partsize = mPartScale * plen;
|
||||
} else if(mValueScale==2) {
|
||||
// cut off scaling
|
||||
if(plen > mValueCutoffTop) continue;
|
||||
if(plen < mValueCutoffBottom) continue;
|
||||
partsize = mPartScale * plen;
|
||||
} else {
|
||||
partsize = mPartScale; // no length scaling
|
||||
}
|
||||
|
||||
ntlVec3Gfx pstart( mPartHeadDist *partsize, 0.0, 0.0 );
|
||||
ntlVec3Gfx pend ( mPartTailDist *partsize, 0.0, 0.0 );
|
||||
gfxReal phi = 0.0;
|
||||
gfxReal phiD = 2.0*M_PI / (gfxReal)segments;
|
||||
|
||||
ntlMat4Gfx cvmat;
|
||||
cvmat.initId();
|
||||
pdir *= -1.0;
|
||||
ntlVec3Gfx cv1 = pdir;
|
||||
ntlVec3Gfx cv2 = ntlVec3Gfx(pdir[1], -pdir[0], 0.0);
|
||||
ntlVec3Gfx cv3 = cross( cv1, cv2);
|
||||
for(int l=0; l<3; l++) {
|
||||
cvmat.value[l][0] = cv1[l];
|
||||
cvmat.value[l][1] = cv2[l];
|
||||
cvmat.value[l][2] = cv3[l];
|
||||
}
|
||||
pstart = (cvmat * pstart);
|
||||
pend = (cvmat * pend);
|
||||
|
||||
for(int s=0; s<segments; s++) {
|
||||
ntlVec3Gfx p1( 0.0 );
|
||||
ntlVec3Gfx p2( 0.0 );
|
||||
|
||||
gfxReal radscale = partNormSize;
|
||||
radscale = (partsize+partNormSize)*0.5;
|
||||
p1[1] += cos(phi) * radscale;
|
||||
p1[2] += sin(phi) * radscale;
|
||||
p2[1] += cos(phi + phiD) * radscale;
|
||||
p2[2] += sin(phi + phiD) * radscale;
|
||||
ntlVec3Gfx n1 = ntlVec3Gfx( 0.0, cos(phi), sin(phi) );
|
||||
ntlVec3Gfx n2 = ntlVec3Gfx( 0.0, cos(phi + phiD), sin(phi + phiD) );
|
||||
ntlVec3Gfx ns = n1*0.5 + n2*0.5;
|
||||
|
||||
p1 = (cvmat * p1);
|
||||
p2 = (cvmat * p2);
|
||||
|
||||
sceneAddTriangle( p+pstart, p+p1, p+p2,
|
||||
ns,n1,n2, ntlVec3Gfx(0.0), 1 );
|
||||
sceneAddTriangle( p+pend , p+p2, p+p1,
|
||||
ns,n2,n1, ntlVec3Gfx(0.0), 1 );
|
||||
|
||||
phi += phiD;
|
||||
tris += 2;
|
||||
}
|
||||
}
|
||||
|
||||
//} // trail
|
||||
return; // DEBUG
|
||||
|
||||
|
||||
// add trails
|
||||
//double tScale = 0.01 * mPartScale * mTrailScale;
|
||||
double trails = 0.01 * mPartScale * mTrailScale;
|
||||
//for(int l=0; l<mParts.size()-1; l++) {
|
||||
for(int l=0; l<mTrailLength-2; l++) {
|
||||
for(size_t i=0; i<mParts[0].size(); i++) {
|
||||
int tl1 = l*mTrailInterval;
|
||||
int tl2 = (l+1)*mTrailInterval;
|
||||
if( mParts[tl1][i].getActive()==false ) continue;
|
||||
if( mParts[tl2][i].getActive()==false ) continue;
|
||||
ntlVec3Gfx p1 = org+mParts[tl1][i].getPos()*pScale;
|
||||
ntlVec3Gfx p2 = org+mParts[tl2][i].getPos()*pScale;
|
||||
ntlVec3Gfx n = ntlVec3Gfx(0,0,-1);
|
||||
sceneAddTriangle( p1+ntlVec3Gfx(0,trails,0), p1+ntlVec3Gfx(0,-trails,0), p2,
|
||||
n,n,n, ntlVec3Gfx(0.0), 1 );
|
||||
sceneAddTriangle( p2, p1+ntlVec3Gfx(0,-trails,0), p1+ntlVec3Gfx(0,trails,0),
|
||||
n,n,n, ntlVec3Gfx(0.0), 1 );
|
||||
tris += 2;
|
||||
}
|
||||
}
|
||||
debugOut("ParticleTracer::getTriangles "<<mName<<" : Triangulated "<< (mParts[0].size()) <<" particles (triangles: "<<tris<<") ", 10);
|
||||
//debugOut(" s"<<mStart<<" e"<<mEnd<<" ss"<<mSimStart<<" se"<<mSimEnd , 10);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
165
intern/elbeem/intern/particletracer.h
Normal file
165
intern/elbeem/intern/particletracer.h
Normal file
@ -0,0 +1,165 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* Particle Viewer/Tracer
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef NTL_PARTICLETRACER_H
|
||||
|
||||
#include "ntl_geometryobject.h"
|
||||
|
||||
|
||||
//! A single particle
|
||||
class ParticleObject
|
||||
{
|
||||
public:
|
||||
//! Standard constructor
|
||||
inline ParticleObject(ntlVec3Gfx mp) :
|
||||
mPos(mp), mActive( true ) { };
|
||||
//! Copy constructor
|
||||
inline ParticleObject(const ParticleObject &a) :
|
||||
mPos(a.mPos), mActive(a.mActive) { };
|
||||
//! Destructor
|
||||
inline ~ParticleObject() { /* empty */ };
|
||||
|
||||
//! add vector to position
|
||||
inline void advance(double vx, double vy, double vz) {
|
||||
mPos[0] += vx; mPos[1] += vy; mPos[2] += vz; }
|
||||
|
||||
//! add vector to position
|
||||
inline ntlVec3Gfx getPos() { return mPos; }
|
||||
|
||||
//! get active flag
|
||||
inline bool getActive() { return mActive; }
|
||||
//! set active flag
|
||||
inline void setActive(bool set) { mActive = set; }
|
||||
|
||||
protected:
|
||||
|
||||
/*! the particle position */
|
||||
ntlVec3Gfx mPos;
|
||||
|
||||
/*! particle active? */
|
||||
bool mActive;
|
||||
};
|
||||
|
||||
|
||||
//! A whole particle array
|
||||
class ParticleTracer :
|
||||
public ntlGeometryObject
|
||||
{
|
||||
public:
|
||||
//! Standard constructor
|
||||
ParticleTracer();
|
||||
//! Destructor
|
||||
~ParticleTracer() { /* empty */ };
|
||||
|
||||
//! add a particle at this position
|
||||
void addParticle(double x, double y, double z);
|
||||
|
||||
//! save particle positions before adding a new timestep
|
||||
void savePreviousPositions();
|
||||
|
||||
//! draw the particle array
|
||||
void draw();
|
||||
|
||||
//! parse settings from attributes (dont use own list!)
|
||||
void parseAttrList( AttributeList *att );
|
||||
|
||||
|
||||
// access funcs
|
||||
|
||||
//! set the number of timesteps to trace
|
||||
void setTimesteps(int steps);
|
||||
|
||||
//! set the number of particles
|
||||
inline void setNumParticles(int set) { mNumParticles = set; }
|
||||
//! get the number of particles
|
||||
inline int getNumParticles() { return mNumParticles; }
|
||||
|
||||
//! set the number of timesteps to trace
|
||||
inline void setTrailLength(int set) { mTrailLength = set; mParts.resize(mTrailLength*mTrailInterval); }
|
||||
//! get the number of timesteps to trace
|
||||
inline int getTrailLength() { return mTrailLength; }
|
||||
//! set the number of timesteps between each anim step saving
|
||||
inline void setTrailInterval(int set) { mTrailInterval = set; mParts.resize(mTrailLength*mTrailInterval); }
|
||||
|
||||
//! get the no. of particles in the current array
|
||||
inline int getPartArraySize() { return mParts[0].size(); }
|
||||
|
||||
//! iterate over all newest particles (for advancing positions)
|
||||
inline vector<ParticleObject>::iterator getParticlesBegin() { return mParts[0].begin(); }
|
||||
//! end iterator for newest particles
|
||||
inline vector<ParticleObject>::iterator getParticlesEnd() { return mParts[0].end(); }
|
||||
|
||||
/*! set geometry start (for renderer) */
|
||||
inline void setStart(ntlVec3Gfx set) { mStart = set; }
|
||||
/*! set geometry end (for renderer) */
|
||||
inline void setEnd(ntlVec3Gfx set) { mEnd = set; }
|
||||
|
||||
/*! set simulation domain start */
|
||||
inline void setSimStart(ntlVec3Gfx set) { mSimStart = set; }
|
||||
/*! set simulation domain end */
|
||||
inline void setSimEnd(ntlVec3Gfx set) { mSimEnd = set; }
|
||||
|
||||
//! set the particle scaling factor
|
||||
inline void setPartScale(double set) { mPartScale = set; }
|
||||
//! set the trail scaling factor
|
||||
inline void setTrailScale(double set) { mTrailScale = set; }
|
||||
|
||||
|
||||
// NTL geometry implementation
|
||||
|
||||
/*! Get the triangles from this object */
|
||||
virtual void getTriangles( vector<ntlTriangle> *triangles,
|
||||
vector<ntlVec3Gfx> *vertices,
|
||||
vector<ntlVec3Gfx> *normals, int objectId );
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
/*! the particle array (for multiple timesteps) */
|
||||
vector< vector<ParticleObject> > mParts;
|
||||
|
||||
/*! desired number of particles */
|
||||
int mNumParticles;
|
||||
|
||||
/*! number of particle positions to trace */
|
||||
int mTrailLength;
|
||||
|
||||
/*! number of timesteps to between saving particle positions */
|
||||
int mTrailInterval;
|
||||
int mTrailIntervalCounter;
|
||||
|
||||
/*! size of the particles to display */
|
||||
double mPartSize;
|
||||
|
||||
/*! size of the particle trail */
|
||||
double mTrailScale;
|
||||
|
||||
/*! start and end vectors for the triangulation region to create particles in */
|
||||
ntlVec3Gfx mStart, mEnd;
|
||||
|
||||
/*! start and end vectors of the simulation domain */
|
||||
ntlVec3Gfx mSimStart, mSimEnd;
|
||||
|
||||
/*! scaling param for particles */
|
||||
double mPartScale;
|
||||
/*! head and tail distance for particle shapes */
|
||||
double mPartHeadDist, mPartTailDist;
|
||||
/*! no of segments for particle cone */
|
||||
int mPartSegments;
|
||||
/*! use length/absval of values to scale particles? */
|
||||
int mValueScale;
|
||||
/*! value length maximal cutoff value, for mValueScale==2 */
|
||||
double mValueCutoffTop;
|
||||
/*! value length minimal cutoff value, for mValueScale==2 */
|
||||
double mValueCutoffBottom;
|
||||
|
||||
};
|
||||
|
||||
#define NTL_PARTICLETRACER_H
|
||||
#endif
|
||||
|
355
intern/elbeem/intern/simulation_object.cpp
Normal file
355
intern/elbeem/intern/simulation_object.cpp
Normal file
@ -0,0 +1,355 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* Basic interface for all simulation modules
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "simulation_object.h"
|
||||
#include "ntl_bsptree.h"
|
||||
#include "ntl_scene.h"
|
||||
#include "factory_lbm.h"
|
||||
#include "lbmfunctions.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Constructor
|
||||
*****************************************************************************/
|
||||
SimulationObject::SimulationObject() :
|
||||
ntlGeometryShader(),
|
||||
mGeoStart(-100.0), mGeoEnd(100.0),
|
||||
mGeoInitId(-1), mpGiTree(NULL), mpGiObjects(NULL),
|
||||
mpGlob(NULL),
|
||||
mPanic( false ),
|
||||
mDebugType( 1 /* =FLUIDDISPNothing*/ ),
|
||||
mSolverType("-"), mStepsPerFrame( 10 ),
|
||||
mpLbm(NULL),
|
||||
mpParam( NULL ),
|
||||
mShowSurface(true), mShowParticles(false),
|
||||
mSelectedCid( NULL ),
|
||||
|
||||
stnOld("opt"),
|
||||
stnFsgr("fsgr")
|
||||
{
|
||||
mpParam = new Parametrizer();
|
||||
|
||||
for(int i=0; i<MAX_DEBDISPSET; i++) {
|
||||
mDebDispSet[i].type = (i);
|
||||
mDebDispSet[i].on = false;
|
||||
mDebDispSet[i].scale = 1.0;
|
||||
}
|
||||
|
||||
// reset time
|
||||
mTime = 0.0;
|
||||
mDisplayTime = 0.0;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Destructor
|
||||
*****************************************************************************/
|
||||
SimulationObject::~SimulationObject()
|
||||
{
|
||||
if(mpGiTree != NULL) delete mpGiTree;
|
||||
delete mpLbm;
|
||||
delete mpParam;
|
||||
debMsgStd("SimulationObject",DM_MSG,"El'Beem Done!\n",10);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/*! init tree for certain geometry init */
|
||||
/*****************************************************************************/
|
||||
void SimulationObject::initGeoTree(int id) {
|
||||
if(mpGlob == NULL) { errorOut("SimulationObject::initGeoTree error: Requires globals!"); exit(1); }
|
||||
mGeoInitId = id;
|
||||
ntlScene *scene = mpGlob->getScene();
|
||||
mpGiObjects = scene->getObjects();
|
||||
|
||||
if(mpGiTree != NULL) delete mpGiTree;
|
||||
char treeFlag = (1<<(mGeoInitId+4));
|
||||
mpGiTree = new ntlTree( 20, 4, // warning - fixed values for depth & maxtriangles here...
|
||||
scene, treeFlag );
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*! destroy tree etc. when geometry init done */
|
||||
/*****************************************************************************/
|
||||
void SimulationObject::freeGeoTree() {
|
||||
if(mpGiTree != NULL) delete mpGiTree;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* simluation interface: initialize simulation using the given configuration file
|
||||
*****************************************************************************/
|
||||
int SimulationObject::initializeLbmSimulation(ntlRenderGlobals *glob)
|
||||
{
|
||||
mpGlob = glob;
|
||||
if(!getVisible()) {
|
||||
mpAttrs->setAllUsed();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//mDimension is deprecated
|
||||
mSolverType = mpAttrs->readString("solver", mSolverType, "SimulationObject","mSolverType", false );
|
||||
if(mSolverType == stnFsgr) {
|
||||
mpLbm = createSolverLbmFsgr();
|
||||
} else if(mSolverType == stnOld) {
|
||||
#ifdef LBM_INCLUDE_TESTSOLVERS
|
||||
// old solver for gfx demo
|
||||
mpLbm = createSolverOld();
|
||||
#endif // LBM_TESTSOLVER
|
||||
} else {
|
||||
errorOut("SimulationObject::initializeLbmSimulation : Invalid solver type - note that mDimension is deprecated, use the 'solver' keyword instead");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/* check lbm pointer */
|
||||
if(mpLbm == NULL) {
|
||||
errorOut("SimulationObject::initializeLbmSimulation : Unable to init dim"<<mSolverType<<" LBM solver! ");
|
||||
exit(1);
|
||||
}
|
||||
debugOut("SimulationObject::initialized "<< mpLbm->getIdString() <<" LBM solver! ", 2);
|
||||
|
||||
// for non-param simulations
|
||||
mpLbm->setParametrizer( mpParam );
|
||||
mpParam->setAttrList( getAttributeList() );
|
||||
mpParam->setSize( mpLbm->getSizeX(), mpLbm->getSizeY(), mpLbm->getSizeZ() );
|
||||
mpParam->parseAttrList();
|
||||
|
||||
mpLbm->setAttrList( getAttributeList() );
|
||||
mpLbm->parseAttrList();
|
||||
mParts.parseAttrList( getAttributeList() );
|
||||
mParts.setName( getName() + "_part" );
|
||||
mParts.initialize( glob );
|
||||
|
||||
// init material settings
|
||||
string matMc("default");
|
||||
matMc = mpAttrs->readString("material_surf", matMc, "SimulationObject","matMc", false );
|
||||
mShowSurface = mpAttrs->readInt("showsurface", mShowSurface, "SimulationObject","mShowSurface", false );
|
||||
mShowParticles = mpAttrs->readInt("showparticles", mShowParticles, "SimulationObject","mShowParticles", false );
|
||||
|
||||
checkBoundingBox( mGeoStart, mGeoEnd, "SimulationObject::initializeSimulation" );
|
||||
mpLbm->setGeoStart( mGeoStart );
|
||||
mpLbm->setGeoEnd( mGeoEnd );
|
||||
mpLbm->setRenderGlobals( mpGlob );
|
||||
mpLbm->setName( getName() + "_lbm" );
|
||||
mpLbm->initialize( NULL, mpGlob->getScene()->getObjects() );
|
||||
|
||||
// print cell type stats
|
||||
const int jmax = sizeof(CellFlagType)*8;
|
||||
int totalCells = 0;
|
||||
int flagCount[jmax];
|
||||
for(int j=0; j<jmax ; j++) flagCount[j] = 0;
|
||||
int diffInits = 0;
|
||||
LbmSolverInterface::CellIdentifier cid = mpLbm->getFirstCell();
|
||||
for(; mpLbm->noEndCell( cid );
|
||||
mpLbm->advanceCell( cid ) ) {
|
||||
int flag = mpLbm->getCellFlag(cid,0);
|
||||
int flag2 = mpLbm->getCellFlag(cid,1);
|
||||
if(flag != flag2) {
|
||||
diffInits++;
|
||||
}
|
||||
for(int j=0; j<jmax ; j++) {
|
||||
if( flag&(1<<j) ) flagCount[j]++;
|
||||
}
|
||||
totalCells++;
|
||||
}
|
||||
mpLbm->deleteCellIterator( &cid );
|
||||
|
||||
#if ELBEEM_BLENDER!=1
|
||||
char charNl = '\n';
|
||||
debugOutNnl("SimulationObject::initializeLbmSimulation celltype stats: " <<charNl, 5);
|
||||
debugOutNnl("no. of cells = "<<totalCells<<", "<<charNl ,5);
|
||||
for(int j=0; j<jmax ; j++) {
|
||||
std::ostringstream out;
|
||||
if(flagCount[j]>0) {
|
||||
out<<"\t" << flagCount[j] <<" x "<< convertCellFlagType2String( (CellFlagType)(1<<j) ) <<", " << charNl;
|
||||
debugOutNnl(out.str(), 5);
|
||||
}
|
||||
}
|
||||
// compute dist. of empty/bnd - fluid - if
|
||||
// cfEmpty = (1<<0), cfBnd = (1<< 2), cfFluid = (1<<10), cfInter = (1<<11),
|
||||
{
|
||||
std::ostringstream out;
|
||||
out.precision(2); out.width(4);
|
||||
int totNum = flagCount[0]+flagCount[2]+flagCount[10]+flagCount[11];
|
||||
double ebFrac = (double)(flagCount[0]+flagCount[2]) / totNum;
|
||||
double flFrac = (double)(flagCount[10]) / totNum;
|
||||
double ifFrac = (double)(flagCount[11]) / totNum;
|
||||
double eifFrac = (double)(flagCount[11]+flagCount[26]+flagCount[27]) / totNum;
|
||||
//???
|
||||
out<<"\tFractions: [empty/bnd - fluid - interface - ext. if] = [" << ebFrac<<" - " << flFrac<<" - " << ifFrac<<" - " << eifFrac <<"] "<< charNl;
|
||||
|
||||
if(diffInits > 0) {
|
||||
debugOut("SimulationObject::initializeLbmSimulation celltype Warning: Diffinits="<<diffInits<<" !!!!!!!!!" , 5);
|
||||
}
|
||||
debugOutNnl(out.str(), 5);
|
||||
}
|
||||
#endif // ELBEEM_BLENDER==1
|
||||
|
||||
mpLbm->initParticles( &mParts );
|
||||
|
||||
// this has to be inited here - before, the values might be unknown
|
||||
ntlGeometryObject *surf = mpLbm->getSurfaceGeoObj();
|
||||
if(surf) {
|
||||
surf->setName( "final" ); // final surface mesh
|
||||
// warning - this might cause overwriting effects for multiple sims and geom dump...
|
||||
surf->setCastShadows( true );
|
||||
surf->setReceiveShadows( false );
|
||||
surf->searchMaterial( glob->getMaterials() );
|
||||
if(mShowSurface) mObjects.push_back( surf );
|
||||
}
|
||||
|
||||
mParts.setStart( mGeoStart );
|
||||
mParts.setEnd( mGeoEnd );
|
||||
mParts.setCastShadows( false );
|
||||
mParts.setReceiveShadows( false );
|
||||
mParts.searchMaterial( glob->getMaterials() );
|
||||
if(mShowParticles) mObjects.push_back( &mParts );
|
||||
|
||||
// add objects to display for debugging (e.g. levelset particles)
|
||||
vector<ntlGeometryObject *> debugObjs = mpLbm->getDebugObjects();
|
||||
for(size_t i=0;i<debugObjs.size(); i++) {
|
||||
debugObjs[i]->setCastShadows( false );
|
||||
debugObjs[i]->setReceiveShadows( false );
|
||||
debugObjs[i]->searchMaterial( glob->getMaterials() );
|
||||
mObjects.push_back( debugObjs[i] );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* simluation interface: advance simulation another step (whatever delta time that might be)
|
||||
*****************************************************************************/
|
||||
void SimulationObject::step( void )
|
||||
{
|
||||
mpLbm->step();
|
||||
|
||||
mParts.savePreviousPositions();
|
||||
mpLbm->advanceParticles( &mParts );
|
||||
mTime += mpParam->getStepTime();
|
||||
if(mpLbm->getPanic()) mPanic = true;
|
||||
|
||||
//debMsgStd("SimulationObject::step",DM_MSG," Sim '"<<mName<<"' stepped to "<<mTime<<" (stept="<<(mpParam->getStepTime())<<", framet="<<getFrameTime()<<") ", 10);
|
||||
}
|
||||
/*! prepare visualization of simulation for e.g. raytracing */
|
||||
void SimulationObject::prepareVisualization( void ) {
|
||||
if(mPanic) return;
|
||||
mpLbm->prepareVisualization();
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* get current start simulation time */
|
||||
double SimulationObject::getStartTime( void ) {
|
||||
//return mpParam->calculateAniStart();
|
||||
return mpParam->getAniStart();
|
||||
}
|
||||
/* get time for a single animation frame */
|
||||
double SimulationObject::getFrameTime( void ) {
|
||||
return mpParam->getAniFrameTime();
|
||||
}
|
||||
/* get time for a single time step */
|
||||
double SimulationObject::getStepTime( void ) {
|
||||
return mpParam->getStepTime();
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* return a pointer to the geometry object of this simulation
|
||||
*****************************************************************************/
|
||||
//ntlGeometryObject *SimulationObject::getGeometry() { return mpMC; }
|
||||
vector<ntlGeometryObject *>::iterator
|
||||
SimulationObject::getObjectsBegin()
|
||||
{
|
||||
return mObjects.begin();
|
||||
}
|
||||
vector<ntlGeometryObject *>::iterator
|
||||
SimulationObject::getObjectsEnd()
|
||||
{
|
||||
return mObjects.end();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* GUI - display debug info
|
||||
*****************************************************************************/
|
||||
|
||||
void SimulationObject::drawDebugDisplay() {
|
||||
#ifndef NOGUI
|
||||
//debugOut(" SD: "<<mDebugType<<" v"<<getVisible()<<" don"<< (mDebDispSet[mDebugType].on) , 10);
|
||||
if(!getVisible()) return;
|
||||
|
||||
if( mDebugType > (MAX_DEBDISPSET-1) ){
|
||||
errorOut("SimulationObject::drawDebugDisplay : Invalid debug type!");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
mDebDispSet[ mDebugType ].on = true;
|
||||
//errorOut( mDebugType <<"//"<< mDebDispSet[mDebugType].type );
|
||||
mpLbm->debugDisplay( &mDebDispSet[ mDebugType ] );
|
||||
|
||||
::lbmMarkedCellDisplay<>( mpLbm );
|
||||
#endif
|
||||
}
|
||||
|
||||
/* GUI - display interactive info */
|
||||
void SimulationObject::drawInteractiveDisplay()
|
||||
{
|
||||
#ifndef NOGUI
|
||||
if(!getVisible()) return;
|
||||
if(mSelectedCid) {
|
||||
// in debugDisplayNode if dispset is on is ignored...
|
||||
::debugDisplayNode<>( &mDebDispSet[ FLUIDDISPGrid ], mpLbm, mSelectedCid );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************/
|
||||
// GUI - handle mouse movement for selection
|
||||
/*******************************************************************************/
|
||||
void SimulationObject::setMousePos(int x,int y, ntlVec3Gfx org, ntlVec3Gfx dir)
|
||||
{
|
||||
normalize( dir );
|
||||
// assume 2D sim is in XY plane...
|
||||
|
||||
double zplane = (mGeoEnd[2]-mGeoStart[2])*0.5;
|
||||
double zt = (zplane-org[2]) / dir[2];
|
||||
ntlVec3Gfx pos(
|
||||
org[0]+ dir[0] * zt,
|
||||
org[1]+ dir[1] * zt, 0.0);
|
||||
|
||||
mSelectedCid = mpLbm->getCellAt( pos );
|
||||
//errMsg("SMP ", mName<< x<<" "<<y<<" - "<<dir );
|
||||
x = y = 0; // remove warning
|
||||
}
|
||||
|
||||
|
||||
void SimulationObject::setMouseClick()
|
||||
{
|
||||
if(mSelectedCid) {
|
||||
::debugPrintNodeInfo<>( mpLbm, mSelectedCid, mpLbm->getNodeInfoString() );
|
||||
}
|
||||
}
|
||||
|
||||
|
202
intern/elbeem/intern/simulation_object.h
Normal file
202
intern/elbeem/intern/simulation_object.h
Normal file
@ -0,0 +1,202 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* Basic interface for all simulation modules
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef ELBEEM_SIMINTERFACE
|
||||
#define ELBEEM_SIMINTERFACE
|
||||
|
||||
|
||||
#define USE_GLUTILITIES
|
||||
#include "ntl_geometryshader.h"
|
||||
#include "lbmdimensions.h"
|
||||
#include "parametrizer.h"
|
||||
#include "particletracer.h"
|
||||
|
||||
class ntlTree;
|
||||
class ntlRenderGlobals;
|
||||
class ntlRenderGlobals;
|
||||
|
||||
|
||||
//! type fluid geometry init
|
||||
// warning : should match typeslbm.h values!
|
||||
const int cFgiFlagstart = 16;
|
||||
typedef enum {
|
||||
fgiFluid = (1<<(cFgiFlagstart+0)),
|
||||
fgiNoFluid = (1<<(cFgiFlagstart+1)),
|
||||
fgiSlipNo = (1<<(cFgiFlagstart+2)),
|
||||
fgiSlipFree = (1<<(cFgiFlagstart+3)),
|
||||
fgiNoBnd = (1<<(cFgiFlagstart+4)),
|
||||
fgiAcc = (1<<(cFgiFlagstart+5)),
|
||||
fgiNoAcc = (1<<(cFgiFlagstart+6)),
|
||||
|
||||
fgiBndAll = (fgiSlipNo | fgiSlipFree)
|
||||
} FgiFlagType;
|
||||
|
||||
|
||||
/*! interface for different simluation models to visualize */
|
||||
class SimulationObject :
|
||||
public ntlGeometryShader {
|
||||
|
||||
public:
|
||||
|
||||
/*! Constructor */
|
||||
SimulationObject();
|
||||
/*! Destructor */
|
||||
virtual ~SimulationObject();
|
||||
|
||||
|
||||
/*! init tree for certain geometry init */
|
||||
void initGeoTree(int id);
|
||||
/*! destroy tree etc. when geometry init done */
|
||||
void freeGeoTree();
|
||||
/*! get fluid init type at certain position */
|
||||
int geoInitGetPointType(ntlVec3Gfx org, int &OId);
|
||||
/*! check for a certain flag type at position org */
|
||||
bool geoInitCheckPointInside(ntlVec3Gfx org, int flags, int &OId);
|
||||
|
||||
// access functions
|
||||
|
||||
/*! get current (max) simulation time */
|
||||
double getCurrentTime( void ) { return mTime; }
|
||||
|
||||
/*! set time to display */
|
||||
void setDisplayTime(double set) { mDisplayTime = set; }
|
||||
|
||||
/*! set geometry generation start point */
|
||||
virtual void setGeoStart(ntlVec3Gfx set) { mGeoStart = set; }
|
||||
/*! set geometry generation end point */
|
||||
virtual void setGeoEnd(ntlVec3Gfx set) { mGeoEnd = set; }
|
||||
|
||||
/*! set sim panic flag */
|
||||
void setPanic(bool set) { mPanic = set; }
|
||||
/*! get sim panic flag */
|
||||
bool getPanic( void ) { return mPanic; }
|
||||
|
||||
/*! simluation interface: initialize simulation */
|
||||
int initializeLbmSimulation(ntlRenderGlobals *glob);
|
||||
|
||||
/*! Do geo etc. init */
|
||||
virtual int postGeoConstrInit(ntlRenderGlobals *glob) { return initializeLbmSimulation(glob); };
|
||||
virtual int initializeShader() { /* ... */ return true; };
|
||||
/*! simluation interface: draw the simulation with OpenGL */
|
||||
virtual void draw( void ) {};
|
||||
virtual vector<ntlGeometryObject *>::iterator getObjectsBegin();
|
||||
virtual vector<ntlGeometryObject *>::iterator getObjectsEnd();
|
||||
|
||||
|
||||
/*! simluation interface: advance simulation another step (whatever delta time that might be) */
|
||||
virtual void step( void );
|
||||
/*! prepare visualization of simulation for e.g. raytracing */
|
||||
virtual void prepareVisualization( void );
|
||||
|
||||
/*! get current start simulation time */
|
||||
virtual double getStartTime( void );
|
||||
/*! get time for a single animation frame */
|
||||
virtual double getFrameTime( void );
|
||||
/*! get time for a single time step in the simulation */
|
||||
virtual double getStepTime( void );
|
||||
|
||||
/*! GUI - display debug info */
|
||||
virtual void drawDebugDisplay();
|
||||
/*! GUI - display interactive info */
|
||||
virtual void drawInteractiveDisplay();
|
||||
/*! GUI - handle mouse movement for selection */
|
||||
virtual void setMousePos(int x,int y, ntlVec3Gfx org, ntlVec3Gfx dir);
|
||||
virtual void setMouseClick();
|
||||
|
||||
//! access solver
|
||||
LbmSolverInterface *getSolver(){ return mpLbm; }
|
||||
|
||||
protected:
|
||||
|
||||
/*! current time in the simulation */
|
||||
double mTime;
|
||||
|
||||
/*! time to display in the visualizer */
|
||||
double mDisplayTime;
|
||||
|
||||
/*! for display - start and end vectors for geometry */
|
||||
ntlVec3Gfx mGeoStart, mGeoEnd;
|
||||
|
||||
/*! geometry init id */
|
||||
int mGeoInitId;
|
||||
/*! tree object for geomerty initialization */
|
||||
ntlTree *mpGiTree;
|
||||
/*! object vector for geo init */
|
||||
vector<ntlGeometryObject*> *mpGiObjects;
|
||||
/*! remember globals */
|
||||
ntlRenderGlobals *mpGlob;
|
||||
|
||||
/*! simulation panic on/off */
|
||||
bool mPanic;
|
||||
|
||||
/*! debug info to display */
|
||||
int mDebugType;
|
||||
|
||||
//! dimension of the simulation - now given by LBMDIM define globally
|
||||
//! solver type
|
||||
string mSolverType;
|
||||
|
||||
/*! when no parametrizer, use this as no. of steps per frame */
|
||||
int mStepsPerFrame;
|
||||
|
||||
/*! pointer to the lbm solver */
|
||||
LbmSolverInterface *mpLbm;
|
||||
|
||||
/*! marching cubes object */
|
||||
//mCubes *mpMC;
|
||||
|
||||
/*! parametrizer for lbm solver */
|
||||
Parametrizer *mpParam;
|
||||
|
||||
/*! particle tracing object */
|
||||
ParticleTracer mParts;
|
||||
|
||||
/*! show parts of the simulation toggles */
|
||||
bool mShowSurface;
|
||||
bool mShowParticles;
|
||||
|
||||
/*! debug display settings */
|
||||
static const int MAX_DEBDISPSET = 10;
|
||||
fluidDispSettings mDebDispSet[ MAX_DEBDISPSET ];
|
||||
|
||||
/*! pointer to identifier of selected node */
|
||||
CellIdentifierInterface *mSelectedCid;
|
||||
|
||||
public:
|
||||
|
||||
// debug display setting funtions
|
||||
|
||||
/*! set type of info to display */
|
||||
inline void setDebugDisplay(int disp) { mDebugType = disp; }
|
||||
|
||||
/* miscelleanous access functions */
|
||||
|
||||
/*! init parametrizer for anim step length */
|
||||
void initParametrizer(Parametrizer *set) { mpParam = set; }
|
||||
/*! init parametrizer for anim step length */
|
||||
Parametrizer *getParametrizer() { return mpParam; }
|
||||
|
||||
/*! Access marching cubes object */
|
||||
//mCubes *getMCubes( void ) { return mpMC; }
|
||||
|
||||
/*! get bounding box of fluid for GUI */
|
||||
virtual inline ntlVec3Gfx *getBBStart() { return &mGeoStart; }
|
||||
virtual inline ntlVec3Gfx *getBBEnd() { return &mGeoEnd; }
|
||||
|
||||
/*! solver dimension constants */
|
||||
const string stnOld;
|
||||
const string stnFsgr;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
260
intern/elbeem/intern/typeslbm.h
Normal file
260
intern/elbeem/intern/typeslbm.h
Normal file
@ -0,0 +1,260 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* Lattice-Boltzmann defines...
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef TYPES_LBM_H
|
||||
|
||||
/* standard precision for LBM solver */
|
||||
typedef double LBM_Float;
|
||||
//typedef float LBM_Float;
|
||||
|
||||
typedef double LBM2D_Float;
|
||||
//typedef float LBM2D_Float; // FLAGS might not work!!!!
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* 2D
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
//! use incompressible LGBK model?
|
||||
#define LBM2D_INCOMPBGK 1
|
||||
|
||||
|
||||
/*! size of a single set of distribution functions */
|
||||
#define LBM2D_DISTFUNCSIZE 9
|
||||
/*! size of a single set for a cell (+cell flags, mass, bubble id) */
|
||||
#define LBM2D_SETSIZE 12
|
||||
/*! floats per LBM cell */
|
||||
#define LBM2D_FLOATSPERCELL (LBM2D_SETSIZE +LBM2D_SETSIZE )
|
||||
|
||||
|
||||
/*! sphere init full or empty */
|
||||
#define LBM2D_FILLED true
|
||||
#define LBM2D_EMPTY false
|
||||
|
||||
/*! distribution functions directions */
|
||||
#define WC 0
|
||||
#define WN 1
|
||||
#define WS 2
|
||||
#define WE 3
|
||||
#define WW 4
|
||||
#define WNE 5
|
||||
#define WNW 6
|
||||
#define WSE 7
|
||||
#define WSW 8
|
||||
#define FLAG2D_BND (9)
|
||||
#define FLAG2D_MASS (10)
|
||||
#define FLAG2D_BUBBLE (11)
|
||||
|
||||
/* Wi factors for collide step */
|
||||
#define LBM2D_COLLEN_ZERO (4.0/9.0)
|
||||
#define LBM2D_COLLEN_ONE (1.0/9.0)
|
||||
#define LBM2D_COLLEN_SQRTWO (1.0/36.0)
|
||||
|
||||
|
||||
/* calculate equlibrium function for a single direction at cell i,j
|
||||
* pass 0 for the u_ terms that are not needed
|
||||
*/
|
||||
#define LBM2D_VELVEC(l, ux,uy) ((ux)*DF2DdvecX[l]+(uy)*DF2DdvecY[l])
|
||||
#if LBM2D_INCOMPBGK!=1
|
||||
#define LBM2D_COLLIDE_EQ(target, l,Rho, ux,uy) \
|
||||
{\
|
||||
LBM2D_Float tmp = LBM2D_VELVEC(l,ux,uy); \
|
||||
target = ( (DF2Dlength[l]*Rho) *( \
|
||||
+ 1.0 - (3.0/2.0*(ux*ux + uy*uy)) \
|
||||
+ 3.0 *tmp \
|
||||
+ 9.0/2.0 *(tmp*tmp) ) \
|
||||
);\
|
||||
}
|
||||
#endif
|
||||
|
||||
/* incompressible LBGK model?? */
|
||||
#if LBM2D_INCOMPBGK==1
|
||||
#define LBM2D_COLLIDE_EQ(target, l,Rho, ux,uy) \
|
||||
{\
|
||||
LBM2D_Float tmp = LBM2D_VELVEC(l,ux,uy); \
|
||||
target = ( (DF2Dlength[l]) *( \
|
||||
+ Rho - (3.0/2.0*(ux*ux + uy*uy )) \
|
||||
+ 3.0 *tmp \
|
||||
+ 9.0/2.0 *(tmp*tmp) ) \
|
||||
);\
|
||||
}
|
||||
#endif
|
||||
|
||||
/* calculate new distribution function for cell i,j
|
||||
* Now also includes gravity
|
||||
*/
|
||||
#define LBM2D_COLLIDE(l,omega, Rho, ux,uy ) \
|
||||
{\
|
||||
LBM2D_Float collideTempVar; \
|
||||
LBM2D_COLLIDE_EQ(collideTempVar, l,Rho, (ux), (uy) ); \
|
||||
m[l] = (1.0-omega) * m[l] + \
|
||||
omega* collideTempVar \
|
||||
; \
|
||||
}\
|
||||
|
||||
|
||||
#ifdef LBM2D_IMPORT
|
||||
extern char *DF2Dstring[LBM2D_DISTFUNCSIZE];
|
||||
extern int DF2Dnorm[LBM2D_DISTFUNCSIZE];
|
||||
extern int DF2Dinv[LBM2D_DISTFUNCSIZE];
|
||||
extern int DF2DrefX[LBM2D_DISTFUNCSIZE];
|
||||
extern int DF2DrefY[LBM2D_DISTFUNCSIZE];
|
||||
extern LBM2D_Float DF2Dequil[ LBM2D_DISTFUNCSIZE ];
|
||||
extern int DF2DvecX[LBM2D_DISTFUNCSIZE];
|
||||
extern int DF2DvecY[LBM2D_DISTFUNCSIZE];
|
||||
extern LBM2D_Float DF2DdvecX[LBM2D_DISTFUNCSIZE];
|
||||
extern LBM2D_Float DF2DdvecY[LBM2D_DISTFUNCSIZE];
|
||||
extern LBM2D_Float DF2Dlength[LBM2D_DISTFUNCSIZE];
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* 3D
|
||||
*****************************************************************************/
|
||||
|
||||
// use incompressible LGBK model?
|
||||
#define LBM_INCOMPBGK 1
|
||||
|
||||
|
||||
|
||||
/*! size of a single set of distribution functions */
|
||||
#define LBM_DISTFUNCSIZE 19
|
||||
/*! size of a single set for a cell (+cell flags, mass, bubble id) */
|
||||
#define LBM_SETSIZE 22
|
||||
/*! floats per LBM cell */
|
||||
#define LBM_FLOATSPERCELL (LBM_SETSIZE +LBM_SETSIZE )
|
||||
|
||||
|
||||
/*! distribution functions directions */
|
||||
#define MC 0
|
||||
#define MN 1
|
||||
#define MS 2
|
||||
#define ME 3
|
||||
#define MW 4
|
||||
#define MT 5
|
||||
#define MB 6
|
||||
#define MNE 7
|
||||
#define MNW 8
|
||||
#define MSE 9
|
||||
#define MSW 10
|
||||
#define MNT 11
|
||||
#define MNB 12
|
||||
#define MST 13
|
||||
#define MSB 14
|
||||
#define MET 15
|
||||
#define MEB 16
|
||||
#define MWT 17
|
||||
#define MWB 18
|
||||
#define FLAG_BND (19)
|
||||
#define FLAG_MASS (20)
|
||||
#define FLAG_BUBBLE (21)
|
||||
|
||||
/* Wi factors for collide step */
|
||||
#define LBM_COLLEN_ZERO (1.0/3.0)
|
||||
#define LBM_COLLEN_ONE (1.0/18.0)
|
||||
#define LBM_COLLEN_SQRTWO (1.0/36.0)
|
||||
|
||||
|
||||
/* calculate equlibrium function for a single direction at cell i,j,k
|
||||
* pass 0 for the u_ terms that are not needed
|
||||
*/
|
||||
#define LBM_VELVEC(l, ux,uy,uz) ((ux)*DFdvecX[l]+(uy)*DFdvecY[l]+(uz)*DFdvecZ[l])
|
||||
#ifndef LBM_INCOMPBGK
|
||||
#define LBM_COLLIDE_EQ(target, l,Rho, ux,uy,uz) \
|
||||
{\
|
||||
LBM_Float tmp = LBM_VELVEC(l,ux,uy,uz); \
|
||||
target = ( (DFlength[l]*Rho) *( \
|
||||
+ 1.0 - (3.0/2.0*(ux*ux + uy*uy + uz*uz)) \
|
||||
+ 3.0 *tmp \
|
||||
+ 9.0/2.0 *(tmp*tmp) ) \
|
||||
);\
|
||||
}
|
||||
#endif
|
||||
|
||||
/* incompressible LBGK model?? */
|
||||
#ifdef LBM_INCOMPBGK
|
||||
#define LBM_COLLIDE_EQ(target, l,Rho, ux,uy,uz) \
|
||||
{\
|
||||
LBM_Float tmp = LBM_VELVEC(l,ux,uy,uz); \
|
||||
target = ( (DFlength[l]) *( \
|
||||
+ Rho - (3.0/2.0*(ux*ux + uy*uy + uz*uz)) \
|
||||
+ 3.0 *tmp \
|
||||
+ 9.0/2.0 *(tmp*tmp) ) \
|
||||
);\
|
||||
}
|
||||
#endif
|
||||
|
||||
/* calculate new distribution function for cell i,j,k
|
||||
* Now also includes gravity
|
||||
*/
|
||||
#define LBM_COLLIDE(l,omega,Rho, ux,uy,uz ) \
|
||||
{\
|
||||
LBM_Float collideTempVar; \
|
||||
LBM_COLLIDE_EQ(collideTempVar, l,Rho, (ux), (uy), (uz) ); \
|
||||
m[l] = (1.0-omega) * m[l] + \
|
||||
omega* collideTempVar \
|
||||
; \
|
||||
}\
|
||||
|
||||
|
||||
#ifdef LBM3D_IMPORT
|
||||
char *DFstring[LBM_DISTFUNCSIZE];
|
||||
int DFnorm[LBM_DISTFUNCSIZE];
|
||||
int DFinv[LBM_DISTFUNCSIZE];
|
||||
int DFrefX[LBM_DISTFUNCSIZE];
|
||||
int DFrefY[LBM_DISTFUNCSIZE];
|
||||
int DFrefZ[LBM_DISTFUNCSIZE];
|
||||
LBM_Float DFequil[ LBM_DISTFUNCSIZE ];
|
||||
int DFvecX[LBM_DISTFUNCSIZE];
|
||||
int DFvecY[LBM_DISTFUNCSIZE];
|
||||
int DFvecZ[LBM_DISTFUNCSIZE];
|
||||
LBM_Float DFdvecX[LBM_DISTFUNCSIZE];
|
||||
LBM_Float DFdvecY[LBM_DISTFUNCSIZE];
|
||||
LBM_Float DFdvecZ[LBM_DISTFUNCSIZE];
|
||||
LBM_Float DFlength[LBM_DISTFUNCSIZE];
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* BOTH
|
||||
*****************************************************************************/
|
||||
|
||||
/*! boundary flags
|
||||
* only 1 should be active for a cell */
|
||||
#define BND (1<< 0)
|
||||
#define ACCX (1<< 1)
|
||||
#define ACCY (1<< 2)
|
||||
#define ACCZ (1<< 3)
|
||||
#define FREESLIP (1<< 4)
|
||||
#define NOSLIP (1<< 5)
|
||||
#define PERIODIC (1<< 6)
|
||||
#define PARTSLIP (1<< 7)
|
||||
/*! surface type, also only 1 should be active (2. flag byte) */
|
||||
#define EMPTY (0)
|
||||
#define FLUID (1<< 8)
|
||||
#define INTER (1<< 9)
|
||||
/*! neighbor flags (3. flag byte) */
|
||||
#define I_NONBFLUID (1<<16)
|
||||
#define I_NONBINTER (1<<17)
|
||||
#define I_NONBEMPTY (1<<18)
|
||||
#define I_NODELETE (1<<19)
|
||||
#define I_NEWCELL (1<<20)
|
||||
#define I_NEWINTERFACE (1<<21)
|
||||
/*! marker only for debugging, this bit is reset each step */
|
||||
#define I_CELLMARKER ((int) (1<<30) )
|
||||
#define I_NOTCELLMARKER ((int) (~(1<<30)) )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define TYPES_LBM_H
|
||||
#endif
|
||||
|
292
intern/elbeem/intern/utilities.cpp
Normal file
292
intern/elbeem/intern/utilities.cpp
Normal file
@ -0,0 +1,292 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* Global C style utility funcions
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#ifdef WIN32
|
||||
// for timing
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/times.h>
|
||||
#endif
|
||||
|
||||
#include "utilities.h"
|
||||
|
||||
#ifndef NOPNG
|
||||
#ifdef WIN32
|
||||
#include "png.h"
|
||||
#else
|
||||
#include <png.h>
|
||||
#endif
|
||||
#endif // NOPNG
|
||||
|
||||
//! for interval debugging output
|
||||
myTime_t globalIntervalTime = 0;
|
||||
//! color output setting for messages (0==off, else on)
|
||||
#ifdef WIN32
|
||||
int globalColorSetting = 0;
|
||||
#else // WIN32
|
||||
int globalColorSetting = 1;
|
||||
#endif // WIN32
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// helper function that converts a string to integer,
|
||||
// and returns an alternative value if the conversion fails
|
||||
int convertString2Int(const char *str, int alt)
|
||||
{
|
||||
int val;
|
||||
char *endptr;
|
||||
bool success=true;
|
||||
|
||||
val = strtol(str, &endptr, 10);
|
||||
if( (str==endptr) ||
|
||||
((str!=endptr) && (*endptr != '\0')) ) success = false;
|
||||
|
||||
if(!success) {
|
||||
return alt;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//! helper function that converts a flag field to a readable integer
|
||||
std::string convertFlags2String(int flags) {
|
||||
std::ostringstream ret;
|
||||
ret <<"(";
|
||||
int max = sizeof(int)*8;
|
||||
for(int i=0; i<max; i++) {
|
||||
if(flags & (1<<31)) ret <<"1";
|
||||
else ret<<"0";
|
||||
if(i<max-1) {
|
||||
//ret << ",";
|
||||
if((i%8)==7) ret << " ";
|
||||
}
|
||||
flags = flags << 1;
|
||||
}
|
||||
ret <<")";
|
||||
return ret.str();
|
||||
}
|
||||
|
||||
#ifndef NOPNG
|
||||
//-----------------------------------------------------------------------------
|
||||
//! write png image
|
||||
int writePng(const char *fileName, unsigned char **rowsp, int w, int h)
|
||||
{
|
||||
// defaults for elbeem
|
||||
const int colortype = PNG_COLOR_TYPE_RGBA;
|
||||
const int bitdepth = 8;
|
||||
png_structp png_ptr = NULL;
|
||||
png_infop info_ptr = NULL;
|
||||
png_bytep *rows = rowsp;
|
||||
|
||||
//FILE *fp = fopen(fileName, "wb");
|
||||
FILE *fp = NULL;
|
||||
char *doing = "open for writing";
|
||||
if (!(fp = fopen(fileName, "wb"))) goto fail;
|
||||
|
||||
if(!png_ptr) {
|
||||
doing = "create png write struct";
|
||||
if (!(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL))) goto fail;
|
||||
}
|
||||
if(!info_ptr) {
|
||||
doing = "create png info struct";
|
||||
if (!(info_ptr = png_create_info_struct(png_ptr))) goto fail;
|
||||
}
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr))) goto fail;
|
||||
doing = "init IO";
|
||||
png_init_io(png_ptr, fp);
|
||||
doing = "write header";
|
||||
png_set_IHDR(png_ptr, info_ptr, w, h, bitdepth, colortype, PNG_INTERLACE_NONE,
|
||||
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
|
||||
doing = "write info";
|
||||
png_write_info(png_ptr, info_ptr);
|
||||
doing = "write image";
|
||||
png_write_image(png_ptr, rows);
|
||||
doing = "write end";
|
||||
png_write_end(png_ptr, NULL);
|
||||
doing = "write destroy structs";
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
|
||||
fclose( fp );
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
errMsg("writePng","Write_png: could not "<<doing<<" !");
|
||||
if(fp) fclose( fp );
|
||||
if(png_ptr || info_ptr) png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
return -1;
|
||||
}
|
||||
#endif // NOPNG
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// helper function to determine current time
|
||||
myTime_t getTime()
|
||||
{
|
||||
myTime_t ret = 0;
|
||||
#ifdef WIN32
|
||||
LARGE_INTEGER liTimerFrequency;
|
||||
QueryPerformanceFrequency(&liTimerFrequency);
|
||||
LARGE_INTEGER liLastTime;
|
||||
QueryPerformanceCounter(&liLastTime);
|
||||
ret = (INT)( ((double)liLastTime.QuadPart / liTimerFrequency.QuadPart)*1000 ); // - mFirstTime;
|
||||
#else
|
||||
//fprintf(stderr, " Tp s%lu us%lu \n", tv.tv_sec, tv.tv_usec );
|
||||
//clock_t ct = clock();
|
||||
//ret = ct*1000/CLOCKS_PER_SEC;
|
||||
//fprintf(stderr, " Tp s%lu cps%lu us%lu \n", ct,CLOCKS_PER_SEC, ret );
|
||||
|
||||
/*struct tms tt;
|
||||
times(&tt);
|
||||
//ret = tt.tms_utime/(CLOCKS_PER_SEC/1000);
|
||||
ret = tt.tms_utime*10;
|
||||
//fprintf(stderr, " Tp s%lu cps%lu us%lu %d %d \n", tt.tms_cutime,CLOCKS_PER_SEC, ret, sizeof(clock_t), tt.tms_cutime );
|
||||
//fprintf(stderr, " Tp s%d cps%d us%d %d %d \n", tt.tms_utime,CLOCKS_PER_SEC, ret, sizeof(clock_t), clock() );
|
||||
// */
|
||||
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
tz.tz_minuteswest = 0;
|
||||
tz.tz_dsttime = 0;
|
||||
gettimeofday(&tv,&tz);
|
||||
ret = (tv.tv_sec*1000)+(tv.tv_usec/1000); //-mFirstTime;
|
||||
//fprintf(stderr, " Tp s%lu us%lu \n", tv.tv_sec, tv.tv_usec );
|
||||
#endif
|
||||
//cout << " Tret " << ret <<endl;
|
||||
return (myTime_t)ret;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// convert time to readable string
|
||||
std::string getTimeString(myTime_t usecs) {
|
||||
std::ostringstream ret;
|
||||
//myTime_t us = usecs % 1000;
|
||||
myTime_t ms = usecs / (60*1000);
|
||||
myTime_t ss = (usecs / 1000) - (ms*60);
|
||||
|
||||
//ret.setf(ios::showpoint|ios::fixed);
|
||||
//ret.precision(5); ret.width(7);
|
||||
|
||||
if(ms>0) {
|
||||
ret << ms<<"m"<< ss<<"s" ;
|
||||
} else {
|
||||
ret << ss<<"s" ;
|
||||
}
|
||||
return ret.str();
|
||||
}
|
||||
|
||||
//! helper to check if a bounding box was specified in the right way
|
||||
bool checkBoundingBox(ntlVec3Gfx s, ntlVec3Gfx e, std::string checker) {
|
||||
if( (s[0]>e[0]) ||
|
||||
(s[1]>e[1]) ||
|
||||
(s[2]>e[2]) ) {
|
||||
errMsg("checkBoundingBox","Check by '"<<checker<<"' for BB "<<s<<":"<<e<<" failed! Aborting...");
|
||||
exit(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// debug message output
|
||||
|
||||
static std::string col_black ( "\033[0;30m");
|
||||
static std::string col_dark_gray ( "\033[1;30m");
|
||||
static std::string col_bright_gray ( "\033[0;37m");
|
||||
static std::string col_red ( "\033[0;31m");
|
||||
static std::string col_bright_red ( "\033[1;31m");
|
||||
static std::string col_green ( "\033[0;32m");
|
||||
static std::string col_bright_green ( "\033[1;32m");
|
||||
static std::string col_bright_yellow ( "\033[1;33m");
|
||||
static std::string col_yellow ( "\033[0;33m");
|
||||
static std::string col_cyan ( "\033[0;36m");
|
||||
static std::string col_bright_cyan ( "\033[1;36m");
|
||||
static std::string col_purple ( "\033[0;35m");
|
||||
static std::string col_bright_purple ( "\033[1;35m");
|
||||
static std::string col_neutral ( "\033[0m");
|
||||
static std::string col_std = col_bright_gray;
|
||||
void messageOutputFunc(std::string from, int id, std::string msg, myTime_t interval) {
|
||||
if(interval>0) {
|
||||
myTime_t currTime = getTime();
|
||||
if((currTime - globalIntervalTime)>interval) {
|
||||
globalIntervalTime = getTime();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// colors off?
|
||||
if(globalColorSetting==0) {
|
||||
// only reset once
|
||||
col_std = col_black = col_dark_gray = col_bright_gray =
|
||||
col_red = col_bright_red = col_green =
|
||||
col_bright_green = col_bright_yellow =
|
||||
col_yellow = col_cyan = col_bright_cyan =
|
||||
col_purple = col_bright_purple = col_neutral = "";
|
||||
globalColorSetting=1;
|
||||
}
|
||||
|
||||
std::ostringstream sout;
|
||||
if(id==DM_DIRECT) {
|
||||
sout << msg;
|
||||
} else {
|
||||
sout << col_cyan<< from;
|
||||
switch(id) {
|
||||
case DM_MSG:
|
||||
sout << col_std << " message:";
|
||||
break;
|
||||
case DM_NOTIFY:
|
||||
sout << col_bright_cyan << " note:" << col_std;
|
||||
break;
|
||||
case DM_IMPORTANT:
|
||||
sout << col_yellow << " important:" << col_std;
|
||||
break;
|
||||
case DM_WARNING:
|
||||
sout << col_bright_red << " warning:" << col_std;
|
||||
break;
|
||||
case DM_ERROR:
|
||||
sout << col_red << " error:" << col_red;
|
||||
break;
|
||||
default:
|
||||
// this shouldnt happen...
|
||||
sout << col_red << " --- messageOutputFunc error: invalid id ("<<id<<") --- aborting... \n\n" << col_std;
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
sout <<" "<< msg << col_std;
|
||||
}
|
||||
#ifdef ELBEEM_BLENDER
|
||||
fprintf(GEN_userstream, "%s",sout.str().c_str() );
|
||||
if(id!=DM_DIRECT) fflush(GEN_userstream);
|
||||
#else
|
||||
fprintf(stdout,"%s", sout.str().c_str());
|
||||
if(id!=DM_DIRECT) fflush(stdout);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
bool debugOutInterTest(myTime_t interval) {
|
||||
myTime_t currTime = getTime();
|
||||
if((currTime - globalIntervalTime)>interval) {
|
||||
globalIntervalTime = getTime();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
170
intern/elbeem/intern/utilities.h
Normal file
170
intern/elbeem/intern/utilities.h
Normal file
@ -0,0 +1,170 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* El'Beem - Free Surface Fluid Simulation with the Lattice Boltzmann Method
|
||||
* Copyright 2003,2004 Nils Thuerey
|
||||
*
|
||||
* Global C style utility funcions
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef UTILITIES_H
|
||||
#include "ntl_vector3dim.h"
|
||||
|
||||
typedef unsigned long myTime_t;
|
||||
|
||||
//! helper function that converts a string to integer
|
||||
int convertString2Int(const char *string, int alt);
|
||||
|
||||
//! helper function that converts a flag field to a readable integer
|
||||
std::string convertFlags2String(int flags);
|
||||
|
||||
//! write png image
|
||||
#ifndef NOPNG
|
||||
//int writePng(const char *fileName, unsigned char **rows, int w, int h, int colortype, int bitdepth);
|
||||
int writePng(const char *fileName, unsigned char **rows, int w, int h);
|
||||
//! write opengl buffer to png
|
||||
void writeOpenglToPng(const char *fileName);
|
||||
#endif// NOPNG
|
||||
|
||||
// output streams
|
||||
#ifdef ELBEEM_BLENDER
|
||||
extern "C" FILE* GEN_errorstream;
|
||||
extern "C" FILE* GEN_userstream;
|
||||
#endif // ELBEEM_BLENDER
|
||||
|
||||
//! get the current system time
|
||||
myTime_t getTime();
|
||||
//! convert time to readable string
|
||||
std::string getTimeString(myTime_t usecs);
|
||||
|
||||
//! helper to check if a bounding box was specified in the right way
|
||||
bool checkBoundingBox(ntlVec3Gfx s, ntlVec3Gfx e, std::string checker);
|
||||
|
||||
// optionally include OpenGL utility functions
|
||||
#ifdef USE_GLUTILITIES
|
||||
|
||||
void drawCubeWire(ntlVec3Gfx s, ntlVec3Gfx e);
|
||||
void drawCubeSolid(ntlVec3Gfx s, ntlVec3Gfx e);
|
||||
|
||||
#endif // USE_GLUTILITIES
|
||||
|
||||
|
||||
/* debugging outputs */
|
||||
//#define DEBUG 10
|
||||
|
||||
/* debug output function */
|
||||
#define DM_MSG 1
|
||||
#define DM_NOTIFY 2
|
||||
#define DM_IMPORTANT 3
|
||||
#define DM_WARNING 4
|
||||
#define DM_ERROR 5
|
||||
#define DM_DIRECT 6
|
||||
void messageOutputFunc(std::string from, int id, std::string msg, myTime_t interval);
|
||||
|
||||
/* debugging messages defines */
|
||||
#if LBM_PRECISION==2
|
||||
#define MSGSTREAM std::ostringstream msg; msg.precision(15); msg.width(17);
|
||||
#else
|
||||
#define MSGSTREAM std::ostringstream msg; msg.precision(7); msg.width(9);
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
# define debMsgDirect(mStr) { std::ostringstream msg; msg << mStr; messageOutputFunc(string(""), DM_DIRECT, msg.str(), 0); }
|
||||
# define debMsgStd(from,id,mStr,level) if(DEBUG>=level){ MSGSTREAM; msg << mStr <<"\n"; messageOutputFunc(from, id, msg.str(), 0); }
|
||||
# define debMsgNnl(from,id,mStr,level) if(DEBUG>=level){ MSGSTREAM; msg << mStr ; messageOutputFunc(from, id, msg.str(), 0); }
|
||||
# define debMsgInter(from,id,mStr,level, interval) if(DEBUG>=level){ MSGSTREAM; msg << mStr <<"\n"; messageOutputFunc(from, id, msg.str(), interval); }
|
||||
# define debugOut(mStr,level) if(DEBUG>=level){ debMsgStd("D",DM_MSG,mStr,level); }
|
||||
# define debugOutNnl(mStr,level) if(DEBUG>=level){ debMsgNnl("D",DM_MSG,mStr,level); }
|
||||
# define debugOutInter(mStr,level, interval) debMsgInter("D",DM_MSG,mStr,level, interval);
|
||||
|
||||
#else
|
||||
|
||||
# define debMsgDirect(mStr)
|
||||
# define debMsgStd(from,id,mStr,level)
|
||||
# define debMsgNnl(from,id,mStr,level)
|
||||
# define debMsgInter(from,id,mStr,level, interval)
|
||||
# define debugOut(mStr,level)
|
||||
# define debugOutNnl(mStr,level)
|
||||
# define debugOutInter(mStr,level, interval)
|
||||
#endif
|
||||
|
||||
/* Error output function */
|
||||
#define errMsg(from,mStr) { MSGSTREAM; msg << mStr <<"\n"; messageOutputFunc(from, DM_ERROR, msg.str(), 0); }
|
||||
#define warnMsg(from,mStr){ MSGSTREAM; msg << mStr <<"\n"; messageOutputFunc(from, DM_WARNING, msg.str(), 0); }
|
||||
#define errorOut(mStr) { errMsg("D",mStr); }
|
||||
// old... #define ...(mStr) { std::cout << mStr << "\n"; fflush(stdout); }
|
||||
|
||||
/*! print some vector from 3 values e.g. for ux,uy,uz */
|
||||
#define PRINT_VEC(x,y,z) " ["<<(x)<<","<<(y)<<","<<(z)<<"] "
|
||||
|
||||
/*! print some vector from 3 values e.g. for ux,uy,uz */
|
||||
#define PRINT_VEC2D(x,y) " ["<<(x)<<","<<(y)<<"] "
|
||||
|
||||
/*! print l'th neighbor of i,j,k as a vector, as we need ijk all the time */
|
||||
#define PRINT_IJK_NBL PRINT_VEC(i+D::dfVecX[l],j+D::dfVecY[l],k+D::dfVecZ[l])
|
||||
|
||||
/*! print i,j,k as a vector, as we need ijk all the time */
|
||||
#define PRINT_IJK PRINT_VEC(i,j,k)
|
||||
|
||||
/*! print i,j,k as a vector, as we need ijk all the time */
|
||||
#define PRINT_IJ PRINT_VEC2D(i,j)
|
||||
|
||||
/*! print some vector from 3 values e.g. for ux,uy,uz */
|
||||
#define PRINT_NTLVEC(v) " ["<<(v)[0]<<","<<(v)[1]<<","<<(v)[2]<<"] "
|
||||
|
||||
/*! print some vector from 3 values e.g. for ux,uy,uz */
|
||||
#define PRINT_NTLVEC2D(v) " ["<<(v)[0]<<","<<(v)[1]<<"] "
|
||||
|
||||
/*! print a triangle */
|
||||
#define PRINT_TRIANGLE(t,mpV) " { "<<PRINT_VEC( (mpV[(t).getPoints()[0]][0]),(mpV[(t).getPoints()[0]][1]),(mpV[(t).getPoints()[0]][2]) )<<\
|
||||
PRINT_VEC( (mpV[(t).getPoints()[1]][0]),(mpV[(t).getPoints()[1]][1]),(mpV[(t).getPoints()[1]][2]) )<<" | "<<\
|
||||
PRINT_VEC( (mpV[(t).getPoints()[2]][0]),(mpV[(t).getPoints()[2]][1]),(mpV[(t).getPoints()[2]][2]) )<<" } "
|
||||
|
||||
|
||||
|
||||
/* some useful templated functions
|
||||
* may require some operators for the classes
|
||||
*/
|
||||
|
||||
/* minimum */
|
||||
template < class T >
|
||||
inline T
|
||||
MIN( T a, T b )
|
||||
{ return (a < b) ? a : b ; }
|
||||
|
||||
/* maximum */
|
||||
template < class T >
|
||||
inline T
|
||||
MAX( T a, T b )
|
||||
{ return (a < b) ? b : a ; }
|
||||
|
||||
/* absolute value */
|
||||
template < class T >
|
||||
inline T
|
||||
ABS( T a )
|
||||
{ return (0 < a) ? a : -a ; }
|
||||
|
||||
/* sign of the value */
|
||||
template < class T >
|
||||
inline T
|
||||
SIGNUM( T a )
|
||||
{ return (0 < a) ? 1 : -1 ; }
|
||||
|
||||
/* sign, returns -1,0,1 depending on sign/value=0 */
|
||||
template < class T >
|
||||
inline T
|
||||
SIGNUM0( T a )
|
||||
{ return (0 < a) ? 1 : ( a < 0 ? -1 : 0 ) ; }
|
||||
|
||||
/* round to nearest integer */
|
||||
inline int
|
||||
ROUND(double d)
|
||||
{ return int(d + 0.5); }
|
||||
|
||||
/* square function */
|
||||
template < class T >
|
||||
inline T
|
||||
SQUARE( T a )
|
||||
{ return a*a; }
|
||||
|
||||
|
||||
#define UTILITIES_H
|
||||
#endif
|
@ -218,6 +218,7 @@ endif
|
||||
|
||||
PULIB = $(NAN_IKSOLVER)/lib/libiksolver.a
|
||||
PULIB += $(NAN_MOTO)/lib/libmoto.a
|
||||
PULIB += $(NAN_ELBEEM)/lib/$(DEBUG_DIR)libelbeem.a
|
||||
PULIB += $(OCGDIR)/blender/readblenfile/$(DEBUG_DIR)libreadblenfile.a
|
||||
PULIB += $(OCGDIR)/blender/src/$(DEBUG_DIR)libsrcpublisher.a
|
||||
|
||||
|
@ -205,5 +205,13 @@ struct Object* modifiers_isDeformedByArmature(struct Object *ob);
|
||||
|
||||
ModifierData* modifiers_getVirtualModifierList (struct Object *ob);
|
||||
|
||||
/* Modifier utility calls, do call through type pointer and return
|
||||
* default values if pointer is optional.
|
||||
*/
|
||||
struct ModifierData* modifier_new (int type);
|
||||
void modifier_free (struct ModifierData *md);
|
||||
|
||||
int modifier_dependsOnTime (struct ModifierData *md);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -56,6 +56,7 @@ blenkernel_env.Append (CPPPATH = ['.',
|
||||
'../../../intern/decimation/extern',
|
||||
'../imbuf',
|
||||
'../avi',
|
||||
'#/intern/elbeem/extern',
|
||||
'#/intern/iksolver/extern',
|
||||
'../blenloader'])
|
||||
|
||||
@ -71,3 +72,4 @@ SConscript(['bad_level_call_stubs/SConscript'])
|
||||
|
||||
blenkernel_env.Append (CPPPATH = user_options_dict['OPENGL_INCLUDE'])
|
||||
blenkernel_env.Append (CPPPATH = user_options_dict['Z_INCLUDE'])
|
||||
blenkernel_env.Append (CPPPATH = user_options_dict['SDL_INCLUDE'])
|
||||
|
@ -36,6 +36,8 @@
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include "PIL_time.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
@ -46,6 +48,8 @@
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_object_force.h"
|
||||
#include "DNA_object_fluidsim.h" // N_T
|
||||
#include "DNA_scene_types.h" // N_T
|
||||
|
||||
#include "BLI_arithb.h"
|
||||
#include "BLI_blenlib.h"
|
||||
@ -60,6 +64,7 @@
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_subsurf.h"
|
||||
#include "LBM_fluidsim.h"
|
||||
#include "BKE_deform.h"
|
||||
#include "BKE_modifier.h"
|
||||
#include "BKE_key.h"
|
||||
@ -531,6 +536,7 @@ static DerivedMesh *getMeshDerivedMesh(Mesh *me, Object *ob, float (*vertCos)[3]
|
||||
mdm->dm.drawFacesSolid = meshDM_drawFacesSolid;
|
||||
mdm->dm.drawFacesColored = meshDM_drawFacesColored;
|
||||
mdm->dm.drawFacesTex = meshDM_drawFacesTex;
|
||||
mdm->dm.drawMappedFaces = meshDM_drawMappedFaces;
|
||||
|
||||
mdm->dm.drawMappedEdges = meshDM_drawMappedEdges;
|
||||
mdm->dm.drawMappedFaces = meshDM_drawMappedFaces;
|
||||
@ -1429,7 +1435,6 @@ DerivedMesh *derivedmesh_from_displistmesh(DispListMesh *dlm, float (*vertexCos)
|
||||
|
||||
/***/
|
||||
|
||||
typedef float vec3f[3];
|
||||
|
||||
DerivedMesh *mesh_create_derived_for_modifier(Object *ob, ModifierData *md)
|
||||
{
|
||||
@ -1468,6 +1473,14 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], DerivedM
|
||||
if (deform_r) *deform_r = NULL;
|
||||
*final_r = NULL;
|
||||
|
||||
// N_T
|
||||
if((G.obedit!=ob) && (ob->fluidsimFlag & OB_FLUIDSIM_ENABLE)) {
|
||||
if(ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN) {
|
||||
*final_r = getFluidsimDerivedMesh(ob,useRenderParams, NULL,NULL);
|
||||
if(*final_r) return;
|
||||
}
|
||||
}
|
||||
|
||||
if (useDeform) {
|
||||
do_mesh_key(me);
|
||||
|
||||
@ -1936,3 +1949,374 @@ DerivedMesh *editmesh_get_derived_base(void)
|
||||
{
|
||||
return getEditMeshDerivedMesh(G.editMesh, NULL);
|
||||
}
|
||||
|
||||
// N_T fluidsim declarations
|
||||
typedef struct {
|
||||
MeshDerivedMesh mdm;
|
||||
|
||||
/* release whole mesh? */
|
||||
char freeMesh;
|
||||
} FluidsimDerivedMesh;
|
||||
|
||||
|
||||
/***/
|
||||
// N_T fluidsim interface
|
||||
#ifdef WIN32
|
||||
#ifndef snprintf
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
static void fluidsimDM_release(DerivedMesh *dm)
|
||||
{
|
||||
FluidsimDerivedMesh *fsdm = (FluidsimDerivedMesh*) dm;
|
||||
if(fsdm->freeMesh) {
|
||||
// similar to free_mesh(fsdm->mdm.me) , but no things like unlink...
|
||||
if(fsdm->mdm.me->mvert) MEM_freeN(fsdm->mdm.me->mvert);
|
||||
if(fsdm->mdm.me->medge) MEM_freeN(fsdm->mdm.me->medge);
|
||||
if(fsdm->mdm.me->mface) MEM_freeN(fsdm->mdm.me->mface);
|
||||
MEM_freeN(fsdm->mdm.me);
|
||||
}
|
||||
|
||||
if (fsdm->mdm.freeNors) MEM_freeN(fsdm->mdm.nors);
|
||||
if (fsdm->mdm.freeVerts) MEM_freeN(fsdm->mdm.verts);
|
||||
MEM_freeN(fsdm);
|
||||
}
|
||||
|
||||
DerivedMesh *getFluidsimDerivedMesh(Object *srcob, int useRenderParams, float *extverts, float *nors) {
|
||||
//fprintf(stderr,"getFluidsimDerivedMesh call (obid '%s', rp %d)\n", srcob->id.name, useRenderParams); // debug
|
||||
int i;
|
||||
Mesh *mesh = NULL; // srcob->ata;
|
||||
FluidsimDerivedMesh *fsdm;
|
||||
MeshDerivedMesh *mdm = NULL;
|
||||
float (*vertCos)[3];
|
||||
int displaymode = 0;
|
||||
int curFrame = G.scene->r.cfra - 1; /* start with 0 */
|
||||
char filename[FILE_MAXFILE],filepath[FILE_MAXFILE+FILE_MAXDIR];
|
||||
char curWd[FILE_MAXDIR];
|
||||
|
||||
if(!useRenderParams) {
|
||||
displaymode = srcob->fluidsimSettings->guiDisplayMode;
|
||||
} else {
|
||||
displaymode = srcob->fluidsimSettings->renderDisplayMode;
|
||||
}
|
||||
|
||||
//fprintf(stderr,"getFluidsimDerivedMesh call (obid '%s', rp %d, dm %d)\n", srcob->id.name, useRenderParams, displaymode); // debug
|
||||
if((displaymode==1) || (G.obedit==srcob)) {
|
||||
mesh = srcob->data;
|
||||
return getMeshDerivedMesh(mesh , srcob, NULL);
|
||||
}
|
||||
|
||||
// init preview frame
|
||||
if(displaymode==2) {
|
||||
// use preview
|
||||
snprintf(filename,FILE_MAXFILE,"%s_surface_preview_%04d.bobj.gz", srcob->fluidsimSettings->surfdataPrefix, curFrame);
|
||||
} else {
|
||||
// load final mesh
|
||||
snprintf(filename,FILE_MAXFILE,"%s_surface_final_%04d.bobj.gz", srcob->fluidsimSettings->surfdataPrefix, curFrame);
|
||||
}
|
||||
BLI_getwdN(curWd);
|
||||
BLI_make_file_string(G.sce, filepath, srcob->fluidsimSettings->surfdataDir, filename);
|
||||
|
||||
//fprintf(stderr,"getFluidsimDerivedMesh call (obid '%s', rp %d, dm %d) %s \n", srcob->id.name, useRenderParams, displaymode, filepath); // debug
|
||||
mesh = readBobjgz(filepath, (Mesh*)(srcob->data) );
|
||||
if(!mesh) {
|
||||
// display org. object upon failure
|
||||
mesh = srcob->data;
|
||||
return getMeshDerivedMesh(mesh , srcob, NULL);
|
||||
}
|
||||
if((mesh)&&(mesh->totvert>0)) {
|
||||
make_edges(mesh);
|
||||
for(i=0;i<mesh->totedge;i++) {
|
||||
// force all edge draw
|
||||
mesh->medge[i].flag |= ME_EDGEDRAW;
|
||||
//fprintf(stderr,"INI %d a%d f%d\n",fsdm->fsmesh->totedge,i, (fsdm->fsmesh->medge[i].flag & ME_EDGEDRAW) );
|
||||
}
|
||||
}
|
||||
|
||||
// WARNING copied from getMeshDerivedMesh
|
||||
fsdm = MEM_callocN(sizeof(*fsdm), "getFluidsimDerivedMesh_fsdm");
|
||||
fsdm->freeMesh = 1;
|
||||
mdm = &fsdm->mdm;
|
||||
vertCos = NULL;
|
||||
|
||||
mdm->dm.getMinMax = meshDM_getMinMax;
|
||||
mdm->dm.convertToDispListMesh = meshDM_convertToDispListMesh;
|
||||
mdm->dm.getNumVerts = meshDM_getNumVerts;
|
||||
mdm->dm.getNumFaces = meshDM_getNumFaces;
|
||||
mdm->dm.getVertCos = meshDM_getVertCos;
|
||||
mdm->dm.getVertCo = meshDM_getVertCo;
|
||||
mdm->dm.getVertNo = meshDM_getVertNo;
|
||||
mdm->dm.drawVerts = meshDM_drawVerts;
|
||||
mdm->dm.drawUVEdges = meshDM_drawUVEdges;
|
||||
mdm->dm.drawEdges = meshDM_drawEdges;
|
||||
mdm->dm.drawLooseEdges = meshDM_drawLooseEdges;
|
||||
mdm->dm.drawFacesSolid = meshDM_drawFacesSolid;
|
||||
mdm->dm.drawFacesColored = meshDM_drawFacesColored;
|
||||
mdm->dm.drawFacesTex = meshDM_drawFacesTex;
|
||||
mdm->dm.drawMappedFaces = meshDM_drawMappedFaces;
|
||||
mdm->dm.drawMappedEdges = meshDM_drawMappedEdges;
|
||||
mdm->dm.drawMappedFaces = meshDM_drawMappedFaces;
|
||||
|
||||
// use own release function
|
||||
mdm->dm.release = fluidsimDM_release;
|
||||
|
||||
mdm->ob = srcob;
|
||||
mdm->me = mesh;
|
||||
mdm->verts = mesh->mvert;
|
||||
mdm->nors = NULL;
|
||||
mdm->freeNors = 0;
|
||||
mdm->freeVerts = 0;
|
||||
|
||||
//fprintf(stderr,"fsdm loc %f,%f,%f; size %f,%f,%f; rot %f,%f,%f \n",
|
||||
//mesh->loc[0], mesh->loc[1], mesh->loc[2],
|
||||
//mesh->size[0], mesh->size[1], mesh->size[2],
|
||||
//mesh->rot[0], mesh->rot[1], mesh->rot[2]);
|
||||
|
||||
if (vertCos) {
|
||||
int i;
|
||||
|
||||
mdm->verts = MEM_mallocN(sizeof(*mdm->verts)*mdm->me->totvert, "deformedVerts");
|
||||
for (i=0; i<mdm->me->totvert; i++) {
|
||||
mdm->verts[i].co[0] = vertCos[i][0];
|
||||
mdm->verts[i].co[1] = vertCos[i][1];
|
||||
mdm->verts[i].co[2] = vertCos[i][2];
|
||||
}
|
||||
mesh_calc_normals(mdm->verts, mdm->me->totvert, mdm->me->mface, mdm->me->totface, &mdm->nors);
|
||||
mdm->freeNors = 1;
|
||||
mdm->freeVerts = 1;
|
||||
} else {
|
||||
// XXX this is kinda ... see getMeshDerivedMesh
|
||||
mesh_calc_normals(mdm->verts, mdm->me->totvert, mdm->me->mface, mdm->me->totface, &mdm->nors);
|
||||
mdm->freeNors = 1;
|
||||
}
|
||||
|
||||
return (DerivedMesh*) mdm;
|
||||
}
|
||||
|
||||
|
||||
/* ***************************** bobj file handling ***************************** */
|
||||
|
||||
/* write .bobj.gz file for a mesh object */
|
||||
|
||||
void writeBobjgz(char *filename, struct Object *ob)
|
||||
{
|
||||
int wri,i,j;
|
||||
float wrf;
|
||||
gzFile gzf;
|
||||
DispListMesh *dlm = NULL;
|
||||
DerivedMesh *dm;
|
||||
float vec[3];
|
||||
float rotmat[3][3];
|
||||
MFace *mface = NULL;
|
||||
|
||||
if(!ob->data || (ob->type!=OB_MESH)) {
|
||||
fprintf(stderr,"Writing GZ_BOBJ Invalid object %s ...\n", ob->id.name);
|
||||
return;
|
||||
}
|
||||
if((ob->size[0]<0.0) || (ob->size[0]<0.0) || (ob->size[0]<0.0) ) {
|
||||
fprintf(stderr,"\nfluidSim::writeBobjgz:: Warning object %s has negative scaling - check triangle ordering...?\n\n", ob->id.name);
|
||||
}
|
||||
|
||||
fprintf(stderr,"Writing GZ_BOBJ '%s' ... ",filename);
|
||||
gzf = gzopen(filename, "wb9");
|
||||
if (!gzf) {
|
||||
fprintf(stderr,"writeBobjgz::error - Unable to open file for writing '%s'\n", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
dm = mesh_create_derived_render(ob);
|
||||
dlm = dm->convertToDispListMesh(dm, 1);
|
||||
mface = dlm->mface;
|
||||
|
||||
if(sizeof(wri)!=4) { fprintf(stderr,"Writing GZ_BOBJ, Invalid int size %d...\n", wri); return; } // paranoia check
|
||||
wri = dlm->totvert;
|
||||
gzwrite(gzf, &wri, sizeof(wri));
|
||||
for(i=0; i<wri;i++) {
|
||||
VECCOPY(vec, dlm->mvert[i].co); /* get transformed point */
|
||||
Mat4MulVecfl(ob->obmat, vec);
|
||||
//fprintf(stderr,"VTEST %d = %f,%f,%f\n",i,vec[0],vec[1],vec[2]); // DEBUG
|
||||
for(j=0; j<3; j++) {
|
||||
wrf = vec[j];
|
||||
gzwrite(gzf, &wrf, sizeof( wrf ));
|
||||
}
|
||||
}
|
||||
|
||||
// should be the same as Vertices.size
|
||||
wri = dlm->totvert;
|
||||
gzwrite(gzf, &wri, sizeof(wri));
|
||||
EulToMat3(ob->rot, rotmat);
|
||||
for(i=0; i<wri;i++) {
|
||||
VECCOPY(vec, dlm->mvert[i].no);
|
||||
// FIXME divide? mv->no[0]= (short)(no[0]*32767.0);
|
||||
Mat3MulVecfl(rotmat, vec);
|
||||
Normalise(vec);
|
||||
//fprintf(stderr, "N %s normrot %d %f %f %f\n",ob->id.name, i,vec[0],vec[1],vec[2]); // DEBUG
|
||||
for(j=0; j<3; j++) {
|
||||
wrf = vec[j]; //dlm->normals[i][j];
|
||||
gzwrite(gzf, &wrf, sizeof( wrf ));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* compute no. of triangles */
|
||||
wri = 0;
|
||||
for(i=0; i<dlm->totface; i++) {
|
||||
wri++;
|
||||
if(mface[i].v4) { wri++; }
|
||||
}
|
||||
gzwrite(gzf, &wri, sizeof(wri));
|
||||
for(i=0; i<dlm->totface; i++) {
|
||||
|
||||
int face[4];
|
||||
face[0] = mface[i].v1;
|
||||
face[1] = mface[i].v2;
|
||||
face[2] = mface[i].v3;
|
||||
face[3] = mface[i].v4;
|
||||
//fprintf(stderr,"F %s %d = %d,%d,%d,%d \n",ob->id.name, i, face[0],face[1],face[2],face[3] );
|
||||
|
||||
gzwrite(gzf, &(face[0]), sizeof( face[0] ));
|
||||
gzwrite(gzf, &(face[1]), sizeof( face[1] ));
|
||||
gzwrite(gzf, &(face[2]), sizeof( face[2] ));
|
||||
if(face[3]) {
|
||||
gzwrite(gzf, &(face[0]), sizeof( face[0] ));
|
||||
gzwrite(gzf, &(face[2]), sizeof( face[2] ));
|
||||
gzwrite(gzf, &(face[3]), sizeof( face[3] ));
|
||||
}
|
||||
}
|
||||
|
||||
gzclose( gzf );
|
||||
if(dlm) displistmesh_free(dlm);
|
||||
dm->release(dm);
|
||||
|
||||
//fprintf(stderr,"done. #Vertices: %d, #Normals: %d, #Triangles: %d\n", dlm->vertices.size(), dlm->normals.size(), dlm->faces.size() );
|
||||
}
|
||||
|
||||
/* security macro for readgin bobjs */
|
||||
#define CHECK_GOTBYTES(b,s) \
|
||||
if((b)!=4) { \
|
||||
if(newmesh->mvert) MEM_freeN(newmesh->mvert); \
|
||||
if(newmesh->mface) MEM_freeN(newmesh->mface); \
|
||||
if(newmesh) MEM_freeN(newmesh); \
|
||||
return NULL; \
|
||||
}
|
||||
/* read .bobj.gz file into a fluidsimDerivedMesh struct */
|
||||
Mesh* readBobjgz(char *filename, Mesh *orgmesh) //, fluidsimDerivedMesh *fsdm)
|
||||
{
|
||||
int wri,i,j;
|
||||
float wrf;
|
||||
gzFile gzf;
|
||||
Mesh *newmesh;
|
||||
const int debugOutput = 0;
|
||||
// init data from old mesh (materials,flags)
|
||||
MFace *origMFace = &((MFace*) orgmesh->mface)[0];
|
||||
int mat_nr = origMFace->mat_nr;
|
||||
int flag = origMFace->flag;
|
||||
MFace *fsface = NULL;
|
||||
int gotBytes;
|
||||
|
||||
if(!orgmesh) return NULL;
|
||||
|
||||
// similar to copy_mesh
|
||||
newmesh = MEM_dupallocN(orgmesh);
|
||||
newmesh->mat= orgmesh->mat; //MEM_dupallocN(orgmesh->mat); // use original?
|
||||
|
||||
newmesh->mvert= NULL;
|
||||
newmesh->medge= NULL;
|
||||
newmesh->mface= NULL;
|
||||
newmesh->tface= NULL;
|
||||
newmesh->dface= NULL;
|
||||
|
||||
newmesh->dvert = NULL; //MEM_mallocN (sizeof (MDeformVert)*orgmesh->totvert, "MDeformVert");
|
||||
|
||||
newmesh->mcol= NULL; //MEM_dupallocN(orgmesh->mcol);
|
||||
newmesh->msticky= NULL; //MEM_dupallocN(orgmesh->msticky);
|
||||
newmesh->texcomesh= NULL;
|
||||
|
||||
newmesh->key= NULL; //copy_key(orgmesh->key);
|
||||
newmesh->totface = 0;
|
||||
newmesh->totvert = 0;
|
||||
newmesh->totedge = 0;
|
||||
newmesh->medge = NULL; //? MEM_mallocN(sizeof(MEdge)*fsdm->fstotedge, "fluidsimDerivedMesh_edges");
|
||||
|
||||
|
||||
if(debugOutput) fprintf(stderr,"Reading '%s' GZ_BOBJ... ",filename);
|
||||
gzf = gzopen(filename, "rb");
|
||||
if (!gzf) {
|
||||
//fprintf(stderr,"readBobjgz::error - Unable to open file for reading '%s'\n", filename); // DEBUG
|
||||
MEM_freeN(newmesh);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//if(sizeof(wri)!=4) { fprintf(stderr,"Reading GZ_BOBJ, Invalid int size %d...\n", wri); return NULL; } // paranoia check
|
||||
|
||||
gotBytes = gzread(gzf, &wri, sizeof(wri));
|
||||
CHECK_GOTBYTES(gotBytes, "numverts");
|
||||
newmesh->totvert = wri;
|
||||
newmesh->mvert = MEM_mallocN(sizeof(MVert)*newmesh->totvert, "fluidsimDerivedMesh_bobjvertices");
|
||||
if(debugOutput) fprintf(stderr,"#vertices %d ", newmesh->totvert); //DEBUG
|
||||
for(i=0; i<newmesh->totvert;i++) {
|
||||
for(j=0; j<3; j++) {
|
||||
gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
|
||||
CHECK_GOTBYTES(gotBytes, "vert");
|
||||
newmesh->mvert[i].co[j] = wrf;
|
||||
}
|
||||
//fprintf(stderr,"VTEST %d = %f,%f,%f\n",i,newmesh->mvert[i].co[0],newmesh->mvert[i].co[1],newmesh->mvert[i].co[2]); // DEBUG
|
||||
}
|
||||
|
||||
// should be the same as Vertices.size
|
||||
gotBytes = gzread(gzf, &wri, sizeof(wri));
|
||||
CHECK_GOTBYTES(gotBytes, "numnorms");
|
||||
if(wri != newmesh->totvert) {
|
||||
// complain #vertices has to be equal to #normals, reset&abort
|
||||
MEM_freeN(newmesh->mvert);
|
||||
MEM_freeN(newmesh);
|
||||
fprintf(stderr,"Reading GZ_BOBJ, #normals=%d, #vertices=%d, aborting...\n", wri,newmesh->totvert );
|
||||
return NULL;
|
||||
}
|
||||
for(i=0; i<newmesh->totvert;i++) {
|
||||
for(j=0; j<3; j++) {
|
||||
gotBytes = gzread(gzf, &wrf, sizeof( wrf ));
|
||||
CHECK_GOTBYTES(gotBytes, "norm");
|
||||
newmesh->mvert[i].no[j] = wrf*32767.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* compute no. of triangles */
|
||||
gotBytes = gzread(gzf, &wri, sizeof(wri));
|
||||
CHECK_GOTBYTES(gotBytes, "numfaces");
|
||||
newmesh->totface = wri;
|
||||
newmesh->mface = MEM_mallocN(sizeof(MFace)*newmesh->totface, "fluidsimDerivedMesh_bobjfaces");
|
||||
if(debugOutput) fprintf(stderr,"#faces %d ", newmesh->totface); // DEBUG
|
||||
fsface = newmesh->mface;
|
||||
for(i=0; i<newmesh->totface; i++) {
|
||||
int face[4];
|
||||
|
||||
gotBytes = gzread(gzf, &(face[0]), sizeof( face[0] ));
|
||||
CHECK_GOTBYTES(gotBytes, "f1");
|
||||
gotBytes = gzread(gzf, &(face[1]), sizeof( face[1] ));
|
||||
CHECK_GOTBYTES(gotBytes, "f2");
|
||||
gotBytes = gzread(gzf, &(face[2]), sizeof( face[2] ));
|
||||
CHECK_GOTBYTES(gotBytes, "f3");
|
||||
face[3] = 0;
|
||||
|
||||
fsface[i].v1 = face[0];
|
||||
fsface[i].v2 = face[1];
|
||||
fsface[i].v3 = face[2];
|
||||
fsface[i].v4 = face[3];
|
||||
//fprintf(stderr,"F %s %d = %d,%d,%d,%d \n",newmesh->ob->id.name, i, face[0],face[1],face[2],face[3] );
|
||||
}
|
||||
|
||||
gzclose( gzf );
|
||||
|
||||
for(i=0;i<newmesh->totface;i++) {
|
||||
fsface[i].mat_nr = mat_nr;
|
||||
fsface[i].flag = flag;
|
||||
}
|
||||
|
||||
// if(debugOutput) fprintf(stderr," done\n");
|
||||
return newmesh;
|
||||
}
|
||||
|
||||
|
@ -69,6 +69,7 @@ CPPFLAGS += -I../../render/extern/include
|
||||
|
||||
CPPFLAGS += -I$(NAN_IKSOLVER)/include
|
||||
CPPFLAGS += -I$(NAN_DECIMATION)/include
|
||||
CPPFLAGS += -I$(NAN_ELBEEM)/include
|
||||
|
||||
# path to zlib
|
||||
CPPFLAGS += -I$(NAN_ZLIB)/include
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_object_force.h"
|
||||
#include "DNA_object_fluidsim.h"
|
||||
#include "DNA_oops_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
@ -1437,6 +1438,16 @@ void DAG_scene_update_flags(Scene *sce, unsigned int lay)
|
||||
case OB_MESH:
|
||||
me= ob->data;
|
||||
if(me->key) ob->recalc |= OB_RECALC_DATA;
|
||||
else if(ob->effect.first) {
|
||||
Effect *eff= ob->effect.first;
|
||||
if(eff->type==EFF_WAVE) ob->recalc |= OB_RECALC_DATA;
|
||||
}
|
||||
if((ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) && (ob->fluidsimSettings)) {
|
||||
// fluidsimSettings might not be initialized during load...
|
||||
if(ob->fluidsimSettings->type & OB_FLUIDSIM_DOMAIN) {
|
||||
ob->recalc |= OB_RECALC_DATA; // NT
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OB_CURVE:
|
||||
case OB_SURF:
|
||||
|
@ -216,6 +216,7 @@ void free_object(Object *ob)
|
||||
|
||||
if(ob->pd) MEM_freeN(ob->pd);
|
||||
if(ob->soft) sbFree(ob->soft);
|
||||
if(ob->fluidsimSettings) MEM_freeN(ob->fluidsimSettings); /* NT */
|
||||
}
|
||||
|
||||
static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Object **obpoin)
|
||||
@ -730,6 +731,10 @@ Object *add_object(int type)
|
||||
ob->anisotropicFriction[1] = 1.0f;
|
||||
ob->anisotropicFriction[2] = 1.0f;
|
||||
ob->gameflag= OB_PROP;
|
||||
|
||||
/* NT fluid sim defaults */
|
||||
ob->fluidsimFlag = 0;
|
||||
ob->fluidsimSettings = NULL;
|
||||
|
||||
ob->data= add_obdata_from_type(type);
|
||||
|
||||
@ -832,6 +837,10 @@ Object *copy_object(Object *ob)
|
||||
|
||||
if(ob->pd) obn->pd= MEM_dupallocN(ob->pd);
|
||||
obn->soft= copy_softbody(ob->soft);
|
||||
|
||||
/* NT copy fluid sim setting memory */
|
||||
if(ob->fluidsimSettings) ob->fluidsimSettings = MEM_dupallocN(ob->fluidsimSettings);
|
||||
else ob->fluidsimSettings = NULL;
|
||||
|
||||
ob->derivedDeform = NULL;
|
||||
ob->derivedFinal = NULL;
|
||||
|
@ -85,6 +85,7 @@
|
||||
#include "DNA_nla_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_object_force.h"
|
||||
#include "DNA_object_fluidsim.h" // NT
|
||||
#include "DNA_oops_types.h"
|
||||
#include "DNA_object_force.h"
|
||||
#include "DNA_packedFile_types.h"
|
||||
@ -2385,6 +2386,11 @@ static void direct_link_object(FileData *fd, Object *ob)
|
||||
}
|
||||
}
|
||||
}
|
||||
ob->fluidsimSettings= newdataadr(fd, ob->fluidsimSettings); /* NT */
|
||||
if(ob->fluidsimSettings) {
|
||||
// not much to do for now... fprintf(stderr, "FLUIDSIMT newdataadr\n");
|
||||
ob->fluidsimSettings->orgMesh = NULL;
|
||||
}
|
||||
|
||||
link_list(fd, &ob->prop);
|
||||
prop= ob->prop.first;
|
||||
|
@ -712,6 +712,7 @@ static void write_objects(WriteData *wd, ListBase *idbase)
|
||||
}
|
||||
}
|
||||
}
|
||||
writestruct(wd, DATA, "FluidsimSettings", 1, ob->fluidsimSettings); // NT
|
||||
|
||||
write_modifiers(wd, &ob->modifiers);
|
||||
}
|
||||
|
@ -234,6 +234,10 @@ void test_idbutton_cb(void *namev, void *arg2_unused);
|
||||
/* this has MAX_EFFECT settings! Next free define is 1450... */
|
||||
#define B_SELEFFECT 1430
|
||||
|
||||
/* Fluidsim button defines */
|
||||
#define B_FLUIDSIM_BAKE 1450
|
||||
#define B_FLUIDSIM_SELDIR 1451
|
||||
|
||||
|
||||
/* *********************** */
|
||||
#define B_WORLDBUTS 1600
|
||||
|
@ -53,6 +53,7 @@ struct Material;
|
||||
struct bConstraintChannel;
|
||||
struct PartDeflect;
|
||||
struct SoftBody;
|
||||
struct FluidsimSettings;
|
||||
struct DerivedMesh;
|
||||
|
||||
typedef struct bDeformGroup {
|
||||
@ -190,6 +191,10 @@ typedef struct Object {
|
||||
LBuf port;
|
||||
|
||||
float pad3, smoothresh; /* smoothresh is phong interpolation ray_shadow correction in render */
|
||||
|
||||
short fluidsimFlag; /* NT toggle fluidsim participation on/off */
|
||||
short dnapadFluidsimDummy1, dnapadFluidsimDummy2, dnapadFluidsimDummy3; /* 8byte align */
|
||||
struct FluidsimSettings *fluidsimSettings; /* if fluidsim enabled, store additional settings */
|
||||
|
||||
struct DerivedMesh *derivedDeform, *derivedFinal;
|
||||
} Object;
|
||||
|
@ -97,6 +97,7 @@ char *includefiles[] = {
|
||||
"DNA_lattice_types.h",
|
||||
"DNA_object_types.h",
|
||||
"DNA_object_force.h",
|
||||
"DNA_object_fluidsim.h",
|
||||
"DNA_world_types.h",
|
||||
"DNA_radio_types.h",
|
||||
"DNA_scene_types.h",
|
||||
@ -1104,6 +1105,7 @@ int main(int argc, char ** argv)
|
||||
#include "DNA_lattice_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_object_force.h"
|
||||
#include "DNA_object_fluidsim.h",
|
||||
#include "DNA_world_types.h"
|
||||
#include "DNA_radio_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
@ -59,6 +59,7 @@ endif
|
||||
CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION)
|
||||
CPPFLAGS += -I$(NAN_GHOST)/include
|
||||
CPPFLAGS += -I$(NAN_BMFONT)/include
|
||||
CPPFLAGS += -I$(NAN_ELBEEM)/include
|
||||
CPPFLAGS += -I$(NAN_SOUNDSYSTEM)/include $(NAN_SDLCFLAGS)
|
||||
|
||||
# External interfaces of modules:
|
||||
|
@ -23,7 +23,7 @@ source_files = ['B.blend.c',
|
||||
'cmovie.tga.c',
|
||||
'cursors.c',
|
||||
'drawaction.c',
|
||||
'drawarmature.c',
|
||||
'drawarmature.c',
|
||||
'drawdeps.c',
|
||||
'drawimage.c',
|
||||
'drawimasel.c',
|
||||
@ -71,6 +71,7 @@ source_files = ['B.blend.c',
|
||||
'editview.c',
|
||||
'eventdebug.c',
|
||||
'filesel.c',
|
||||
'fluidsim.c',
|
||||
'ghostwinlay.c',
|
||||
'glutil.c',
|
||||
'headerbuttons.c',
|
||||
@ -150,6 +151,7 @@ src_env.Append (CPPPATH = ['#/intern/guardedalloc',
|
||||
'../readstreamglue',
|
||||
'../img',
|
||||
'../quicktime',
|
||||
'#/intern/elbeem/extern',
|
||||
'#/intern/ghost',
|
||||
'#/intern/opennl/extern'])
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* $Id:
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
||||
*
|
||||
@ -50,6 +50,7 @@
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_library.h"
|
||||
#include "BKE_softbody.h"
|
||||
#include "BKE_utildefines.h"
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_arithb.h"
|
||||
@ -97,6 +98,7 @@
|
||||
#include "DNA_modifier_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_object_force.h"
|
||||
#include "DNA_object_fluidsim.h"
|
||||
#include "DNA_radio_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_sound_types.h"
|
||||
@ -126,6 +128,7 @@
|
||||
#include "BKE_texture.h"
|
||||
#include "BKE_utildefines.h"
|
||||
#include "BKE_DerivedMesh.h"
|
||||
#include "LBM_fluidsim.h"
|
||||
|
||||
#include "BIF_editconstraint.h"
|
||||
#include "BSE_editipo.h"
|
||||
@ -1182,6 +1185,57 @@ static void softbody_bake(Object *ob)
|
||||
}
|
||||
|
||||
|
||||
// NT store processed path & file prefix for fluidsim bake directory
|
||||
void fluidsimFilesel(char *selection)
|
||||
{
|
||||
Object *ob = OBACT;
|
||||
char srcDir[FILE_MAXDIR], srcFile[FILE_MAXFILE];
|
||||
char prefix[FILE_MAXFILE];
|
||||
char *srch, *srchSub, *srchExt, *lastFound;
|
||||
int isElbeemSurf = 0;
|
||||
|
||||
strcpy(srcDir, selection);
|
||||
BLI_splitdirstring(srcDir, srcFile);
|
||||
|
||||
// make prefix
|
||||
strcpy(prefix, srcFile);
|
||||
// check if this is a previously generated surface mesh file
|
||||
srch = strstr(prefix, "_surface_");
|
||||
if(srch) {
|
||||
srchSub = strstr(prefix,"_preview_");
|
||||
if(!srchSub) srchSub = strstr(prefix,"_final_");
|
||||
srchExt = strstr(prefix,".gz.bobj");
|
||||
if(!srchExt) srchExt = strstr(prefix,".bobj");
|
||||
if(srchSub && srchExt) {
|
||||
*srch = '\0';
|
||||
isElbeemSurf = 1;
|
||||
}
|
||||
}
|
||||
if(!isElbeemSurf) {
|
||||
// try to remove suffix
|
||||
lastFound = NULL;
|
||||
srch = strchr(prefix, '.'); // search last . from extension
|
||||
while(srch) {
|
||||
lastFound = srch;
|
||||
if(srch) {
|
||||
srch++;
|
||||
srch = strchr(srch, '.');
|
||||
}
|
||||
}
|
||||
if(lastFound) {
|
||||
*lastFound = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
// TODO check srcDir for file path from sce?
|
||||
|
||||
|
||||
strcpy(ob->fluidsimSettings->surfdataDir, srcDir);
|
||||
strcpy(ob->fluidsimSettings->surfdataPrefix, prefix);
|
||||
//fprintf(stderr,"fluidsimFilesel: Using surfdata path '%s', prefix '%s' \n", ob->fluidsimSettings->surfdataDir,ob->fluidsimSettings->surfdataPrefix); // DEBUG
|
||||
|
||||
}
|
||||
|
||||
void do_object_panels(unsigned short event)
|
||||
{
|
||||
Object *ob;
|
||||
@ -1261,6 +1315,22 @@ void do_object_panels(unsigned short event)
|
||||
allqueue(REDRAWBUTSOBJECT, 0);
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
break;
|
||||
|
||||
case B_FLUIDSIM_BAKE:
|
||||
ob= OBACT;
|
||||
/* write config files (currently no simulation) */
|
||||
fluidsimBake(ob);
|
||||
break;
|
||||
case B_FLUIDSIM_SELDIR: {
|
||||
char str[FILE_MAXDIR+FILE_MAXFILE];
|
||||
ScrArea *sa = closest_bigger_area();
|
||||
strcpy(str,"//");
|
||||
ob= OBACT;
|
||||
/* chosse dir for surface files */
|
||||
areawinset(sa->win);
|
||||
activate_fileselect(FILE_SPECIAL, "Select Directory", str, fluidsimFilesel);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if(event>=B_SELEFFECT && event<B_SELEFFECT+MAX_EFFECT) {
|
||||
@ -1800,6 +1870,119 @@ static void object_panel_effects(Object *ob)
|
||||
}
|
||||
}
|
||||
|
||||
/* NT - Panel for fluidsim settings */
|
||||
static void object_panel_fluidsim(Object *ob)
|
||||
{
|
||||
uiBlock *block;
|
||||
int yline = 160;
|
||||
const int lineHeight = 20;
|
||||
const int objHeight = 20;
|
||||
|
||||
block= uiNewBlock(&curarea->uiblocks, "object_fluidsim", UI_EMBOSS, UI_HELV, curarea->win);
|
||||
uiNewPanelTabbed("Constraints", "Object");
|
||||
if(uiNewPanel(curarea, block, "Fluidsim", "Object", 640, 0, 318, 204)==0) return;
|
||||
|
||||
uiDefButBitS(block, TOG, OB_FLUIDSIM_ENABLE, REDRAWBUTSOBJECT, "Enable", 0,yline, 75,objHeight,
|
||||
&ob->fluidsimFlag, 0, 0, 0, 0, "Sets object to participate in fluid simulation");
|
||||
|
||||
if(ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) {
|
||||
FluidsimSettings *fss= ob->fluidsimSettings;
|
||||
|
||||
if(fss==NULL) {
|
||||
fss = ob->fluidsimSettings = fluidsimSettingsNew(ob); // sbNew();
|
||||
}
|
||||
|
||||
if(ob->type==OB_MESH) {
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButS(block, ROW, REDRAWBUTSOBJECT ,"Domain", 90, yline, 70,objHeight, &fss->type, 15.0, OB_FLUIDSIM_DOMAIN, 0.0, 0.0, "Bounding box of this object represents the computational domain of the fluid simulation.");
|
||||
uiDefButS(block, ROW, REDRAWBUTSOBJECT ,"Fluid", 160, yline, 70,objHeight, &fss->type, 15.0, OB_FLUIDSIM_FLUID, 0.0, 0.0, "Object represents a volume of fluid in the simulation.");
|
||||
uiDefButS(block, ROW, REDRAWBUTSOBJECT ,"Obstacle", 230, yline, 70,objHeight, &fss->type, 15.0, OB_FLUIDSIM_OBSTACLE, 0.0, 0.0, "Object is a fixed obstacle.");
|
||||
yline -= lineHeight;
|
||||
yline -= 5;
|
||||
|
||||
/* display specific settings for each type */
|
||||
if(fss->type == OB_FLUIDSIM_DOMAIN) {
|
||||
const int maxRes = 200;
|
||||
|
||||
uiDefButS(block, NUM, B_DIFF, "Resolution:", 0, yline,150,objHeight, &fss->resolutionxyz, 1, maxRes, 10, 0, "Domain resolution in X,Y and Z direction");
|
||||
uiDefButS(block, NUM, B_DIFF, "Preview-Res.:", 150, yline,150,objHeight, &fss->previewresxyz, 1, 100, 10, 0, "Resolution of the preview meshes to generate, also in X,Y and Z direction");
|
||||
yline -= lineHeight;
|
||||
uiDefButF(block, NUM, B_DIFF, "Real-size:", 0, yline,150,objHeight, &fss->realsize, 0.0, 1.0, 10, 0, "Size of the simulation domain in meters.");
|
||||
yline -= lineHeight;
|
||||
|
||||
uiDefButF(block, NUM, B_DIFF, "GravX:", 0, yline, 100,objHeight, &fss->gravx, -1000.1, 1000.1, 10, 0, "Gravity in X direction");
|
||||
uiDefButF(block, NUM, B_DIFF, "GravY:", 100, yline, 100,objHeight, &fss->gravy, -1000.1, 1000.1, 10, 0, "Gravity in Y direction");
|
||||
uiDefButF(block, NUM, B_DIFF, "GravZ:", 200, yline, 100,objHeight, &fss->gravz, -1000.1, 1000.1, 10, 0, "Gravity in Z direction");
|
||||
yline -= lineHeight;
|
||||
uiDefButF(block, NUM, B_DIFF, "Start time:", 0, yline,150,objHeight, &fss->animStart, 0.0, 100.0, 10, 0, "Simulation time of the first blender frame.");
|
||||
uiDefButF(block, NUM, B_DIFF, "End time:", 150, yline,150,objHeight, &fss->animEnd , 0.0, 100.0, 10, 0, "Simulation time of the last blender frame.");
|
||||
yline -= lineHeight;
|
||||
|
||||
/* "advanced" settings */
|
||||
yline -= 5;
|
||||
|
||||
/* could also be char? */
|
||||
uiDefButS(block, MENU, REDRAWVIEW3D, "Viscosity%t|Manual %x1|Water %x2|Oil %x3|Honey %x4",
|
||||
0,yline,100,objHeight, &fss->viscosityMode, 0, 0, 0, 0, "Set viscosity of the fluid to a preset value, or use manual input.");
|
||||
if(fss->viscosityMode==1) {
|
||||
uiDefButF(block, NUM, B_DIFF, "Value:", 100, yline, 100,objHeight, &fss->viscosityValue, 0.0, 1.0, 10, 0, "Viscosity setting, value that is multiplied by 10 to the power of (exponent*-1).");
|
||||
uiDefButS(block, NUM, B_DIFF, "Neg-Exp.:", 200, yline, 100,objHeight, &fss->viscosityExponent, 0, 10, 10, 0, "Negative exponent for the viscosity value (to simplify entering small values e.g. 5*10^-6.");
|
||||
} else {
|
||||
// display preset values
|
||||
uiDefBut(block, LABEL, 0, fluidsimViscosityPresetString[fss->viscosityMode], 100,yline,200,objHeight, NULL, 0.0, 0, 0, 0, "");
|
||||
}
|
||||
yline -= lineHeight;
|
||||
|
||||
uiDefBut(block, LABEL, 0, "Gui:", 0,yline,50,objHeight, NULL, 0.0, 0, 0, 0, "");
|
||||
uiDefButS(block, MENU, REDRAWVIEW3D, "GuiDisplayMode%t|Geometry %x1|Preview %x2|Final %x3",
|
||||
50,yline,100,objHeight, &fss->guiDisplayMode, 0, 0, 0, 0, "How to display the fluid mesh in the blender gui.");
|
||||
uiDefBut(block, LABEL, 0, "Rend:", 150,yline,50,objHeight, NULL, 0.0, 0, 0, 0, "");
|
||||
uiDefButS(block, MENU, REDRAWVIEW3D, "RenderDisplayMode%t|Geometry %x1|Preview %x2|Final %x3",
|
||||
200,yline,100,objHeight, &fss->renderDisplayMode, 0, 0, 0, 0, "How to display the fluid mesh for rendering.");
|
||||
yline -= lineHeight;
|
||||
|
||||
uiDefBut(block, BUT, B_FLUIDSIM_SELDIR, "Select Output Directory", 0, yline,100,objHeight, NULL, 0.0, 0.0, 10, 0, "Select Directory (and/or filenames) to store baked fluid simulation files in");
|
||||
uiDefBut(block, LABEL, 0, fss->surfdataDir, 100,yline,100,objHeight, NULL, 0.0, 0, 0, 0, "");
|
||||
uiDefBut(block, LABEL, 0, fss->surfdataPrefix, 200,yline,100,objHeight, NULL, 0.0, 0, 0, 0, "");
|
||||
yline -= lineHeight;
|
||||
|
||||
uiDefBut(block, BUT, B_FLUIDSIM_BAKE, "BAKE", 0, yline,300,objHeight, NULL, 0.0, 0.0, 10, 0, "Perform simulation and output and surface&preview meshes for each frame.");
|
||||
}
|
||||
else if(fss->type == OB_FLUIDSIM_FLUID) {
|
||||
yline -= lineHeight + 5;
|
||||
uiDefBut(block, LABEL, 0, "Initial velocity:", 0,yline,300,objHeight, NULL, 0.0, 0, 0, 0, "");
|
||||
yline -= lineHeight;
|
||||
uiDefButF(block, NUM, B_DIFF, "X:", 0, yline, 100,objHeight, &fss->iniVelx, -1000.1, 1000.1, 10, 0, "Initial fluid velocity in X direction");
|
||||
uiDefButF(block, NUM, B_DIFF, "Y:", 100, yline, 100,objHeight, &fss->iniVely, -1000.1, 1000.1, 10, 0, "Initial fluid velocity in Y direction");
|
||||
uiDefButF(block, NUM, B_DIFF, "Z:", 200, yline, 100,objHeight, &fss->iniVelz, -1000.1, 1000.1, 10, 0, "Initial fluid velocity in Z direction");
|
||||
yline -= lineHeight;
|
||||
}
|
||||
else if(fss->type == OB_FLUIDSIM_OBSTACLE) {
|
||||
yline -= lineHeight + 5;
|
||||
uiDefBut(block, LABEL, 0, "No additional settings as of now...", 0,yline,300,objHeight, NULL, 0.0, 0, 0, 0, "");
|
||||
yline -= lineHeight;
|
||||
}
|
||||
else {
|
||||
yline -= lineHeight + 5;
|
||||
/* not yet set */
|
||||
uiDefBut(block, LABEL, 0, "Select object type for simulation", 0,yline,300,objHeight, NULL, 0.0, 0, 0, 0, "");
|
||||
yline -= lineHeight;
|
||||
}
|
||||
|
||||
} else {
|
||||
yline -= lineHeight + 5;
|
||||
uiDefBut(block, LABEL, 0, "Sorry - only meshes supported", 0,yline,300,objHeight, NULL, 0.0, 0, 0, 0, "");
|
||||
yline -= lineHeight;
|
||||
}
|
||||
} else {
|
||||
yline -= lineHeight + 5;
|
||||
uiDefBut(block, LABEL, 0, "Object not enabled for fluid simulation...", 0,yline,300,objHeight, NULL, 0.0, 0, 0, 0, "");
|
||||
yline -= lineHeight;
|
||||
}
|
||||
uiBlockEndAlign(block);
|
||||
}
|
||||
|
||||
void object_panels()
|
||||
{
|
||||
Object *ob;
|
||||
@ -1817,6 +2000,7 @@ void object_panels()
|
||||
}
|
||||
object_panel_deflectors(ob);
|
||||
object_softbodies(ob);
|
||||
object_panel_fluidsim(ob);
|
||||
|
||||
uiClearButLock();
|
||||
}
|
||||
|
@ -85,6 +85,7 @@ endif
|
||||
export NAN_TEST_VERBOSITY ?= 1
|
||||
export NAN_BMFONT ?= $(LCGDIR)/bmfont
|
||||
export NAN_OPENNL ?= $(LCGDIR)/opennl
|
||||
export NAN_ELBEEM ?= $(LCGDIR)/elbeem
|
||||
export NAN_SUPERLU ?= $(LCGDIR)/superlu
|
||||
ifeq ($(FREE_WINDOWS), true)
|
||||
export NAN_FTGL ?= $(LCGDIR)/gcc/ftgl
|
||||
|
@ -62,7 +62,8 @@ def blender_libs(env):
|
||||
'blender_blenkernel',
|
||||
'blender_LOD',
|
||||
'blender_IK',
|
||||
'blender_ONL'])
|
||||
'blender_ONL',
|
||||
'blender_elbeem' ])
|
||||
|
||||
def ketsji_libs(env):
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user