diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:30:19 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:30:19 +0000 |
commit | 5c1676dfe6d2f3c837a5e074117b45613fd29a72 (patch) | |
tree | cbffb45144febf451e54061db2b21395faf94bfe /plug-ins/map-object | |
parent | Initial commit. (diff) | |
download | gimp-upstream.tar.xz gimp-upstream.zip |
Adding upstream version 2.10.34.upstream/2.10.34upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | plug-ins/map-object/Makefile.am | 65 | ||||
-rw-r--r-- | plug-ins/map-object/Makefile.in | 1046 | ||||
-rw-r--r-- | plug-ins/map-object/README | 61 | ||||
-rw-r--r-- | plug-ins/map-object/TODO | 18 | ||||
-rw-r--r-- | plug-ins/map-object/arcball.c | 515 | ||||
-rw-r--r-- | plug-ins/map-object/arcball.h | 50 | ||||
-rw-r--r-- | plug-ins/map-object/map-object-apply.c | 328 | ||||
-rw-r--r-- | plug-ins/map-object/map-object-apply.h | 10 | ||||
-rw-r--r-- | plug-ins/map-object/map-object-image.c | 352 | ||||
-rw-r--r-- | plug-ins/map-object/map-object-image.h | 62 | ||||
-rw-r--r-- | plug-ins/map-object/map-object-main.c | 334 | ||||
-rw-r--r-- | plug-ins/map-object/map-object-main.h | 90 | ||||
-rw-r--r-- | plug-ins/map-object/map-object-preview.c | 745 | ||||
-rw-r--r-- | plug-ins/map-object/map-object-preview.h | 26 | ||||
-rw-r--r-- | plug-ins/map-object/map-object-shade.c | 1254 | ||||
-rw-r--r-- | plug-ins/map-object/map-object-shade.h | 26 | ||||
-rw-r--r-- | plug-ins/map-object/map-object-stock.c | 110 | ||||
-rw-r--r-- | plug-ins/map-object/map-object-stock.h | 37 | ||||
-rw-r--r-- | plug-ins/map-object/map-object-ui.c | 1462 | ||||
-rw-r--r-- | plug-ins/map-object/map-object-ui.h | 14 |
20 files changed, 6605 insertions, 0 deletions
diff --git a/plug-ins/map-object/Makefile.am b/plug-ins/map-object/Makefile.am new file mode 100644 index 0000000..b78b18b --- /dev/null +++ b/plug-ins/map-object/Makefile.am @@ -0,0 +1,65 @@ +## Process this file with automake to produce Makefile.in + +if OS_WIN32 +mwindows = -mwindows +else +libm = -lm +endif + +libgimpui = $(top_builddir)/libgimp/libgimpui-$(GIMP_API_VERSION).la +libgimpconfig = $(top_builddir)/libgimpconfig/libgimpconfig-$(GIMP_API_VERSION).la +libgimpwidgets = $(top_builddir)/libgimpwidgets/libgimpwidgets-$(GIMP_API_VERSION).la +libgimp = $(top_builddir)/libgimp/libgimp-$(GIMP_API_VERSION).la +libgimpcolor = $(top_builddir)/libgimpcolor/libgimpcolor-$(GIMP_API_VERSION).la +libgimpmath = $(top_builddir)/libgimpmath/libgimpmath-$(GIMP_API_VERSION).la +libgimpbase = $(top_builddir)/libgimpbase/libgimpbase-$(GIMP_API_VERSION).la + +if HAVE_WINDRES +include $(top_srcdir)/build/windows/gimprc-plug-ins.rule +map_object_RC = map-object.rc.o +endif + +AM_LDFLAGS = $(mwindows) + +libexecdir = $(gimpplugindir)/plug-ins/map-object + +libexec_PROGRAMS = map-object + +map_object_SOURCES = \ + arcball.c \ + arcball.h \ + map-object-apply.c \ + map-object-apply.h \ + map-object-image.c \ + map-object-image.h \ + map-object-main.c \ + map-object-main.h \ + map-object-preview.c \ + map-object-preview.h \ + map-object-shade.c \ + map-object-shade.h \ + map-object-stock.c \ + map-object-stock.h \ + map-object-ui.c \ + map-object-ui.h + +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + $(GTK_CFLAGS) \ + $(GEGL_CFLAGS) \ + -I$(includedir) + +LDADD = \ + $(libm) \ + $(libgimpui) \ + $(libgimpwidgets) \ + $(libgimpconfig) \ + $(libgimp) \ + $(libgimpcolor) \ + $(libgimpmath) \ + $(libgimpbase) \ + $(GTK_LIBS) \ + $(GEGL_LIBS) \ + $(RT_LIBS) \ + $(INTLLIBS) \ + $(map_object_RC) diff --git a/plug-ins/map-object/Makefile.in b/plug-ins/map-object/Makefile.in new file mode 100644 index 0000000..b006121 --- /dev/null +++ b/plug-ins/map-object/Makefile.in @@ -0,0 +1,1046 @@ +# Makefile.in generated by automake 1.16.3 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2020 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +# Version resources for Microsoft Windows + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +libexec_PROGRAMS = map-object$(EXEEXT) +subdir = plug-ins/map-object +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/m4macros/alsa.m4 \ + $(top_srcdir)/m4macros/ax_compare_version.m4 \ + $(top_srcdir)/m4macros/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4macros/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/m4macros/ax_prog_cc_for_build.m4 \ + $(top_srcdir)/m4macros/ax_prog_perl_version.m4 \ + $(top_srcdir)/m4macros/detectcflags.m4 \ + $(top_srcdir)/m4macros/pythondev.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(libexecdir)" +PROGRAMS = $(libexec_PROGRAMS) +am_map_object_OBJECTS = arcball.$(OBJEXT) map-object-apply.$(OBJEXT) \ + map-object-image.$(OBJEXT) map-object-main.$(OBJEXT) \ + map-object-preview.$(OBJEXT) map-object-shade.$(OBJEXT) \ + map-object-stock.$(OBJEXT) map-object-ui.$(OBJEXT) +map_object_OBJECTS = $(am_map_object_OBJECTS) +map_object_LDADD = $(LDADD) +am__DEPENDENCIES_1 = +map_object_DEPENDENCIES = $(am__DEPENDENCIES_1) $(libgimpui) \ + $(libgimpwidgets) $(libgimpconfig) $(libgimp) $(libgimpcolor) \ + $(libgimpmath) $(libgimpbase) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(map_object_RC) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/arcball.Po \ + ./$(DEPDIR)/map-object-apply.Po \ + ./$(DEPDIR)/map-object-image.Po ./$(DEPDIR)/map-object-main.Po \ + ./$(DEPDIR)/map-object-preview.Po \ + ./$(DEPDIR)/map-object-shade.Po \ + ./$(DEPDIR)/map-object-stock.Po ./$(DEPDIR)/map-object-ui.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(map_object_SOURCES) +DIST_SOURCES = $(map_object_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build/windows/gimprc-plug-ins.rule \ + $(top_srcdir)/depcomp README TODO +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +AA_LIBS = @AA_LIBS@ +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +ALL_LINGUAS = @ALL_LINGUAS@ +ALSA_CFLAGS = @ALSA_CFLAGS@ +ALSA_LIBS = @ALSA_LIBS@ +ALTIVEC_EXTRA_CFLAGS = @ALTIVEC_EXTRA_CFLAGS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +APPSTREAM_UTIL = @APPSTREAM_UTIL@ +AR = @AR@ +AS = @AS@ +ATK_CFLAGS = @ATK_CFLAGS@ +ATK_LIBS = @ATK_LIBS@ +ATK_REQUIRED_VERSION = @ATK_REQUIRED_VERSION@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BABL_CFLAGS = @BABL_CFLAGS@ +BABL_LIBS = @BABL_LIBS@ +BABL_REQUIRED_VERSION = @BABL_REQUIRED_VERSION@ +BUG_REPORT_URL = @BUG_REPORT_URL@ +BUILD_EXEEXT = @BUILD_EXEEXT@ +BUILD_OBJEXT = @BUILD_OBJEXT@ +BZIP2_LIBS = @BZIP2_LIBS@ +CAIRO_CFLAGS = @CAIRO_CFLAGS@ +CAIRO_LIBS = @CAIRO_LIBS@ +CAIRO_PDF_CFLAGS = @CAIRO_PDF_CFLAGS@ +CAIRO_PDF_LIBS = @CAIRO_PDF_LIBS@ +CAIRO_PDF_REQUIRED_VERSION = @CAIRO_PDF_REQUIRED_VERSION@ +CAIRO_REQUIRED_VERSION = @CAIRO_REQUIRED_VERSION@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CC_VERSION = @CC_VERSION@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CPP_FOR_BUILD = @CPP_FOR_BUILD@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DESKTOP_DATADIR = @DESKTOP_DATADIR@ +DESKTOP_FILE_VALIDATE = @DESKTOP_FILE_VALIDATE@ +DLLTOOL = @DLLTOOL@ +DOC_SHOOTER = @DOC_SHOOTER@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILE_AA = @FILE_AA@ +FILE_EXR = @FILE_EXR@ +FILE_HEIF = @FILE_HEIF@ +FILE_JP2_LOAD = @FILE_JP2_LOAD@ +FILE_JPEGXL = @FILE_JPEGXL@ +FILE_MNG = @FILE_MNG@ +FILE_PDF_SAVE = @FILE_PDF_SAVE@ +FILE_PS = @FILE_PS@ +FILE_WMF = @FILE_WMF@ +FILE_XMC = @FILE_XMC@ +FILE_XPM = @FILE_XPM@ +FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ +FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ +FONTCONFIG_REQUIRED_VERSION = @FONTCONFIG_REQUIRED_VERSION@ +FREETYPE2_REQUIRED_VERSION = @FREETYPE2_REQUIRED_VERSION@ +FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ +FREETYPE_LIBS = @FREETYPE_LIBS@ +GDBUS_CODEGEN = @GDBUS_CODEGEN@ +GDK_PIXBUF_CFLAGS = @GDK_PIXBUF_CFLAGS@ +GDK_PIXBUF_CSOURCE = @GDK_PIXBUF_CSOURCE@ +GDK_PIXBUF_LIBS = @GDK_PIXBUF_LIBS@ +GDK_PIXBUF_REQUIRED_VERSION = @GDK_PIXBUF_REQUIRED_VERSION@ +GEGL = @GEGL@ +GEGL_CFLAGS = @GEGL_CFLAGS@ +GEGL_LIBS = @GEGL_LIBS@ +GEGL_MAJOR_MINOR_VERSION = @GEGL_MAJOR_MINOR_VERSION@ +GEGL_REQUIRED_VERSION = @GEGL_REQUIRED_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GEXIV2_CFLAGS = @GEXIV2_CFLAGS@ +GEXIV2_LIBS = @GEXIV2_LIBS@ +GEXIV2_REQUIRED_VERSION = @GEXIV2_REQUIRED_VERSION@ +GIMP_API_VERSION = @GIMP_API_VERSION@ +GIMP_APP_VERSION = @GIMP_APP_VERSION@ +GIMP_BINARY_AGE = @GIMP_BINARY_AGE@ +GIMP_COMMAND = @GIMP_COMMAND@ +GIMP_DATA_VERSION = @GIMP_DATA_VERSION@ +GIMP_FULL_NAME = @GIMP_FULL_NAME@ +GIMP_INTERFACE_AGE = @GIMP_INTERFACE_AGE@ +GIMP_MAJOR_VERSION = @GIMP_MAJOR_VERSION@ +GIMP_MICRO_VERSION = @GIMP_MICRO_VERSION@ +GIMP_MINOR_VERSION = @GIMP_MINOR_VERSION@ +GIMP_MKENUMS = @GIMP_MKENUMS@ +GIMP_MODULES = @GIMP_MODULES@ +GIMP_PACKAGE_REVISION = @GIMP_PACKAGE_REVISION@ +GIMP_PKGCONFIG_VERSION = @GIMP_PKGCONFIG_VERSION@ +GIMP_PLUGINS = @GIMP_PLUGINS@ +GIMP_PLUGIN_VERSION = @GIMP_PLUGIN_VERSION@ +GIMP_REAL_VERSION = @GIMP_REAL_VERSION@ +GIMP_RELEASE = @GIMP_RELEASE@ +GIMP_SYSCONF_VERSION = @GIMP_SYSCONF_VERSION@ +GIMP_TOOL_VERSION = @GIMP_TOOL_VERSION@ +GIMP_UNSTABLE = @GIMP_UNSTABLE@ +GIMP_USER_VERSION = @GIMP_USER_VERSION@ +GIMP_VERSION = @GIMP_VERSION@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GIO_UNIX_CFLAGS = @GIO_UNIX_CFLAGS@ +GIO_UNIX_LIBS = @GIO_UNIX_LIBS@ +GIO_WINDOWS_CFLAGS = @GIO_WINDOWS_CFLAGS@ +GIO_WINDOWS_LIBS = @GIO_WINDOWS_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GLIB_REQUIRED_VERSION = @GLIB_REQUIRED_VERSION@ +GMODULE_NO_EXPORT_CFLAGS = @GMODULE_NO_EXPORT_CFLAGS@ +GMODULE_NO_EXPORT_LIBS = @GMODULE_NO_EXPORT_LIBS@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +GOBJECT_QUERY = @GOBJECT_QUERY@ +GREP = @GREP@ +GS_LIBS = @GS_LIBS@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GTK_CFLAGS = @GTK_CFLAGS@ +GTK_LIBS = @GTK_LIBS@ +GTK_MAC_INTEGRATION_CFLAGS = @GTK_MAC_INTEGRATION_CFLAGS@ +GTK_MAC_INTEGRATION_LIBS = @GTK_MAC_INTEGRATION_LIBS@ +GTK_REQUIRED_VERSION = @GTK_REQUIRED_VERSION@ +GTK_UPDATE_ICON_CACHE = @GTK_UPDATE_ICON_CACHE@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@ +HARFBUZZ_LIBS = @HARFBUZZ_LIBS@ +HARFBUZZ_REQUIRED_VERSION = @HARFBUZZ_REQUIRED_VERSION@ +HAVE_CXX14 = @HAVE_CXX14@ +HAVE_FINITE = @HAVE_FINITE@ +HAVE_ISFINITE = @HAVE_ISFINITE@ +HAVE_VFORK = @HAVE_VFORK@ +HOST_GLIB_COMPILE_RESOURCES = @HOST_GLIB_COMPILE_RESOURCES@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_REQUIRED_VERSION = @INTLTOOL_REQUIRED_VERSION@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +ISO_CODES_LOCALEDIR = @ISO_CODES_LOCALEDIR@ +ISO_CODES_LOCATION = @ISO_CODES_LOCATION@ +JPEG_LIBS = @JPEG_LIBS@ +JSON_GLIB_CFLAGS = @JSON_GLIB_CFLAGS@ +JSON_GLIB_LIBS = @JSON_GLIB_LIBS@ +JXL_CFLAGS = @JXL_CFLAGS@ +JXL_LIBS = @JXL_LIBS@ +JXL_THREADS_CFLAGS = @JXL_THREADS_CFLAGS@ +JXL_THREADS_LIBS = @JXL_THREADS_LIBS@ +LCMS_CFLAGS = @LCMS_CFLAGS@ +LCMS_LIBS = @LCMS_LIBS@ +LCMS_REQUIRED_VERSION = @LCMS_REQUIRED_VERSION@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBBACKTRACE_LIBS = @LIBBACKTRACE_LIBS@ +LIBHEIF_CFLAGS = @LIBHEIF_CFLAGS@ +LIBHEIF_LIBS = @LIBHEIF_LIBS@ +LIBHEIF_REQUIRED_VERSION = @LIBHEIF_REQUIRED_VERSION@ +LIBJXL_REQUIRED_VERSION = @LIBJXL_REQUIRED_VERSION@ +LIBLZMA_REQUIRED_VERSION = @LIBLZMA_REQUIRED_VERSION@ +LIBMYPAINT_CFLAGS = @LIBMYPAINT_CFLAGS@ +LIBMYPAINT_LIBS = @LIBMYPAINT_LIBS@ +LIBMYPAINT_REQUIRED_VERSION = @LIBMYPAINT_REQUIRED_VERSION@ +LIBOBJS = @LIBOBJS@ +LIBPNG_REQUIRED_VERSION = @LIBPNG_REQUIRED_VERSION@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBUNWIND_CFLAGS = @LIBUNWIND_CFLAGS@ +LIBUNWIND_LIBS = @LIBUNWIND_LIBS@ +LIBUNWIND_REQUIRED_VERSION = @LIBUNWIND_REQUIRED_VERSION@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_CURRENT_MINUS_AGE = @LT_CURRENT_MINUS_AGE@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LT_VERSION_INFO = @LT_VERSION_INFO@ +LZMA_CFLAGS = @LZMA_CFLAGS@ +LZMA_LIBS = @LZMA_LIBS@ +MAIL = @MAIL@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MIME_INFO_CFLAGS = @MIME_INFO_CFLAGS@ +MIME_INFO_LIBS = @MIME_INFO_LIBS@ +MIME_TYPES = @MIME_TYPES@ +MKDIR_P = @MKDIR_P@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MMX_EXTRA_CFLAGS = @MMX_EXTRA_CFLAGS@ +MNG_CFLAGS = @MNG_CFLAGS@ +MNG_LIBS = @MNG_LIBS@ +MSGFMT = @MSGFMT@ +MSGFMT_OPTS = @MSGFMT_OPTS@ +MSGMERGE = @MSGMERGE@ +MYPAINT_BRUSHES_CFLAGS = @MYPAINT_BRUSHES_CFLAGS@ +MYPAINT_BRUSHES_LIBS = @MYPAINT_BRUSHES_LIBS@ +NATIVE_GLIB_CFLAGS = @NATIVE_GLIB_CFLAGS@ +NATIVE_GLIB_LIBS = @NATIVE_GLIB_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OPENEXR_CFLAGS = @OPENEXR_CFLAGS@ +OPENEXR_LIBS = @OPENEXR_LIBS@ +OPENEXR_REQUIRED_VERSION = @OPENEXR_REQUIRED_VERSION@ +OPENJPEG_CFLAGS = @OPENJPEG_CFLAGS@ +OPENJPEG_LIBS = @OPENJPEG_LIBS@ +OPENJPEG_REQUIRED_VERSION = @OPENJPEG_REQUIRED_VERSION@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PANGOCAIRO_CFLAGS = @PANGOCAIRO_CFLAGS@ +PANGOCAIRO_LIBS = @PANGOCAIRO_LIBS@ +PANGOCAIRO_REQUIRED_VERSION = @PANGOCAIRO_REQUIRED_VERSION@ +PATHSEP = @PATHSEP@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_REQUIRED_VERSION = @PERL_REQUIRED_VERSION@ +PERL_VERSION = @PERL_VERSION@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +PNG_CFLAGS = @PNG_CFLAGS@ +PNG_LIBS = @PNG_LIBS@ +POFILES = @POFILES@ +POPPLER_CFLAGS = @POPPLER_CFLAGS@ +POPPLER_DATA_CFLAGS = @POPPLER_DATA_CFLAGS@ +POPPLER_DATA_LIBS = @POPPLER_DATA_LIBS@ +POPPLER_DATA_REQUIRED_VERSION = @POPPLER_DATA_REQUIRED_VERSION@ +POPPLER_LIBS = @POPPLER_LIBS@ +POPPLER_REQUIRED_VERSION = @POPPLER_REQUIRED_VERSION@ +POSUB = @POSUB@ +PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ +PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ +PYBIN_PATH = @PYBIN_PATH@ +PYCAIRO_CFLAGS = @PYCAIRO_CFLAGS@ +PYCAIRO_LIBS = @PYCAIRO_LIBS@ +PYGIMP_EXTRA_CFLAGS = @PYGIMP_EXTRA_CFLAGS@ +PYGTK_CFLAGS = @PYGTK_CFLAGS@ +PYGTK_CODEGEN = @PYGTK_CODEGEN@ +PYGTK_DEFSDIR = @PYGTK_DEFSDIR@ +PYGTK_LIBS = @PYGTK_LIBS@ +PYLINK_LIBS = @PYLINK_LIBS@ +PYTHON = @PYTHON@ +PYTHON2_REQUIRED_VERSION = @PYTHON2_REQUIRED_VERSION@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_INCLUDES = @PYTHON_INCLUDES@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +RSVG_REQUIRED_VERSION = @RSVG_REQUIRED_VERSION@ +RT_LIBS = @RT_LIBS@ +SCREENSHOT_LIBS = @SCREENSHOT_LIBS@ +SED = @SED@ +SENDMAIL = @SENDMAIL@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SOCKET_LIBS = @SOCKET_LIBS@ +SSE2_EXTRA_CFLAGS = @SSE2_EXTRA_CFLAGS@ +SSE4_1_EXTRA_CFLAGS = @SSE4_1_EXTRA_CFLAGS@ +SSE_EXTRA_CFLAGS = @SSE_EXTRA_CFLAGS@ +STRIP = @STRIP@ +SVG_CFLAGS = @SVG_CFLAGS@ +SVG_LIBS = @SVG_LIBS@ +SYMPREFIX = @SYMPREFIX@ +TIFF_LIBS = @TIFF_LIBS@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +WEBKIT_CFLAGS = @WEBKIT_CFLAGS@ +WEBKIT_LIBS = @WEBKIT_LIBS@ +WEBKIT_REQUIRED_VERSION = @WEBKIT_REQUIRED_VERSION@ +WEBPDEMUX_CFLAGS = @WEBPDEMUX_CFLAGS@ +WEBPDEMUX_LIBS = @WEBPDEMUX_LIBS@ +WEBPMUX_CFLAGS = @WEBPMUX_CFLAGS@ +WEBPMUX_LIBS = @WEBPMUX_LIBS@ +WEBP_CFLAGS = @WEBP_CFLAGS@ +WEBP_LIBS = @WEBP_LIBS@ +WEBP_REQUIRED_VERSION = @WEBP_REQUIRED_VERSION@ +WEB_PAGE = @WEB_PAGE@ +WIN32_LARGE_ADDRESS_AWARE = @WIN32_LARGE_ADDRESS_AWARE@ +WINDRES = @WINDRES@ +WMF_CFLAGS = @WMF_CFLAGS@ +WMF_CONFIG = @WMF_CONFIG@ +WMF_LIBS = @WMF_LIBS@ +WMF_REQUIRED_VERSION = @WMF_REQUIRED_VERSION@ +XDG_EMAIL = @XDG_EMAIL@ +XFIXES_CFLAGS = @XFIXES_CFLAGS@ +XFIXES_LIBS = @XFIXES_LIBS@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_REQUIRED_VERSION = @XGETTEXT_REQUIRED_VERSION@ +XMC_CFLAGS = @XMC_CFLAGS@ +XMC_LIBS = @XMC_LIBS@ +XMKMF = @XMKMF@ +XMLLINT = @XMLLINT@ +XMU_LIBS = @XMU_LIBS@ +XPM_LIBS = @XPM_LIBS@ +XSLTPROC = @XSLTPROC@ +XVFB_RUN = @XVFB_RUN@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +Z_LIBS = @Z_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +gimpdatadir = @gimpdatadir@ +gimpdir = @gimpdir@ +gimplocaledir = @gimplocaledir@ +gimpplugindir = @gimpplugindir@ +gimpsysconfdir = @gimpsysconfdir@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = $(gimpplugindir)/plug-ins/map-object +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +manpage_gimpdir = @manpage_gimpdir@ +mkdir_p = @mkdir_p@ +ms_librarian = @ms_librarian@ +mypaint_brushes_dir = @mypaint_brushes_dir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +@OS_WIN32_TRUE@mwindows = -mwindows +@OS_WIN32_FALSE@libm = -lm +libgimpui = $(top_builddir)/libgimp/libgimpui-$(GIMP_API_VERSION).la +libgimpconfig = $(top_builddir)/libgimpconfig/libgimpconfig-$(GIMP_API_VERSION).la +libgimpwidgets = $(top_builddir)/libgimpwidgets/libgimpwidgets-$(GIMP_API_VERSION).la +libgimp = $(top_builddir)/libgimp/libgimp-$(GIMP_API_VERSION).la +libgimpcolor = $(top_builddir)/libgimpcolor/libgimpcolor-$(GIMP_API_VERSION).la +libgimpmath = $(top_builddir)/libgimpmath/libgimpmath-$(GIMP_API_VERSION).la +libgimpbase = $(top_builddir)/libgimpbase/libgimpbase-$(GIMP_API_VERSION).la +@HAVE_WINDRES_TRUE@GIMPPLUGINRC = $(top_builddir)/build/windows/gimp-plug-ins.rc +@HAVE_WINDRES_TRUE@map_object_RC = map-object.rc.o +AM_LDFLAGS = $(mwindows) +map_object_SOURCES = \ + arcball.c \ + arcball.h \ + map-object-apply.c \ + map-object-apply.h \ + map-object-image.c \ + map-object-image.h \ + map-object-main.c \ + map-object-main.h \ + map-object-preview.c \ + map-object-preview.h \ + map-object-shade.c \ + map-object-shade.h \ + map-object-stock.c \ + map-object-stock.h \ + map-object-ui.c \ + map-object-ui.h + +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + $(GTK_CFLAGS) \ + $(GEGL_CFLAGS) \ + -I$(includedir) + +LDADD = \ + $(libm) \ + $(libgimpui) \ + $(libgimpwidgets) \ + $(libgimpconfig) \ + $(libgimp) \ + $(libgimpcolor) \ + $(libgimpmath) \ + $(libgimpbase) \ + $(GTK_LIBS) \ + $(GEGL_LIBS) \ + $(RT_LIBS) \ + $(INTLLIBS) \ + $(map_object_RC) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/build/windows/gimprc-plug-ins.rule $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu plug-ins/map-object/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu plug-ins/map-object/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; +$(top_srcdir)/build/windows/gimprc-plug-ins.rule $(am__empty): + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-libexecPROGRAMS: $(libexec_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(libexecdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libexecdir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(libexecdir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(libexecdir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-libexecPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(libexec_PROGRAMS)'; test -n "$(libexecdir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(libexecdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(libexecdir)" && rm -f $$files + +clean-libexecPROGRAMS: + @list='$(libexec_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +map-object$(EXEEXT): $(map_object_OBJECTS) $(map_object_DEPENDENCIES) $(EXTRA_map_object_DEPENDENCIES) + @rm -f map-object$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(map_object_OBJECTS) $(map_object_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arcball.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map-object-apply.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map-object-image.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map-object-main.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map-object-preview.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map-object-shade.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map-object-stock.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map-object-ui.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(libexecdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libexecPROGRAMS clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/arcball.Po + -rm -f ./$(DEPDIR)/map-object-apply.Po + -rm -f ./$(DEPDIR)/map-object-image.Po + -rm -f ./$(DEPDIR)/map-object-main.Po + -rm -f ./$(DEPDIR)/map-object-preview.Po + -rm -f ./$(DEPDIR)/map-object-shade.Po + -rm -f ./$(DEPDIR)/map-object-stock.Po + -rm -f ./$(DEPDIR)/map-object-ui.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libexecPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/arcball.Po + -rm -f ./$(DEPDIR)/map-object-apply.Po + -rm -f ./$(DEPDIR)/map-object-image.Po + -rm -f ./$(DEPDIR)/map-object-main.Po + -rm -f ./$(DEPDIR)/map-object-preview.Po + -rm -f ./$(DEPDIR)/map-object-shade.Po + -rm -f ./$(DEPDIR)/map-object-stock.Po + -rm -f ./$(DEPDIR)/map-object-ui.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libexecPROGRAMS + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libexecPROGRAMS clean-libtool \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-libexecPROGRAMS \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-libexecPROGRAMS + +.PRECIOUS: Makefile + + +# `windres` seems a very stupid tool and it breaks with double shlashes +# in parameter paths. Strengthen the rule a little. +@HAVE_WINDRES_TRUE@%.rc.o: +@HAVE_WINDRES_TRUE@ $(WINDRES) --define ORIGINALFILENAME_STR="$*$(EXEEXT)" \ +@HAVE_WINDRES_TRUE@ --define INTERNALNAME_STR="$*" \ +@HAVE_WINDRES_TRUE@ --define TOP_SRCDIR="`echo $(top_srcdir) | sed 's*//*/*'`" \ +@HAVE_WINDRES_TRUE@ -I"`echo $(top_srcdir)/app | sed 's%/\+%/%'`" \ +@HAVE_WINDRES_TRUE@ -I"`echo $(top_builddir)/app | sed 's%/\+%/%'`"\ +@HAVE_WINDRES_TRUE@ -I"`echo $(top_builddir) | sed 's%/\+%/%'`"\ +@HAVE_WINDRES_TRUE@ $(GIMPPLUGINRC) $@ + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/plug-ins/map-object/README b/plug-ins/map-object/README new file mode 100644 index 0000000..6c6e228 --- /dev/null +++ b/plug-ins/map-object/README @@ -0,0 +1,61 @@ + +MapObject 1.2.0 -- image filter plug-in for GIMP +=========================================================== + +Copyright (C) 1996-98 Tom Bech +Copyright (C) 1996-98 Federico Mena Quintero + +Released 16th of July, 1998 + +You can reach the author(s) via E-mail: +tomb@gimp.org (Tom) or quartic@gimp.org (Federico). + +GIMP was developed by Peter Mattis and Spencer Kimball. +You can contact them at gimp@xcf.berkeley.edu. + +There's more GIMP stuff on our home pages: +http://www.ii.uib.no/~tomb/gimp.html (Tom's page) +http://www.nuclecu.unam.mx/~federico/gimp/index.html (Quartic's page) + +Legal stuff +=========== + +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 3 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, see <https://www.gnu.org/licenses/>. + +In other words, you can't sue us for whatever happens while using this ;) + +Compiling +========= + +To compile you'll need GIMP 1.0 and GTK+ 1.0.4 or later. +You'll also need GCK 1.00 (http://www.ii.uib.no/~tomb/gck.html) + +1) Edit the Makefile to reflect your system setup. + +2) Type "make" and then "make install" + +You should now be ready to run. "make install" puts the executable "MapObject" +in the standard plug-in directory. + +Documentation +============= + +Ahem.. right.. ;) ..I'll get around to it eventually. + +Please send me a mail if you find any bugs. + +Have fun, + +Tom + diff --git a/plug-ins/map-object/TODO b/plug-ins/map-object/TODO new file mode 100644 index 0000000..fc9b41c --- /dev/null +++ b/plug-ins/map-object/TODO @@ -0,0 +1,18 @@ + +The MapObject plug-in "todo"-list: +================================= + +* Interactive positioning of directional light +* Rotation by mouse (doesn't work correctly yet and is disabled). +* Faster mapping code +* Multiple light-sources +* More objects? +* Presets (including save/load) +* Gray-scale/channels support +* Documentation +* Autoconf/automake stuff? + +If there's anything you would like to add, feel free +to send me any suggestions for new stuff or improvements. + +Tom diff --git a/plug-ins/map-object/arcball.c b/plug-ins/map-object/arcball.c new file mode 100644 index 0000000..1f509d4 --- /dev/null +++ b/plug-ins/map-object/arcball.c @@ -0,0 +1,515 @@ +/************************************/ +/* ArcBall.c (c) Ken Shoemake, 1993 */ +/* Modified by Tom Bech, 1996 */ +/************************************/ + +#include "config.h" + +#include <libgimp/gimp.h> + +#include "arcball.h" + +/* Global variables */ +/* ================ */ + +Quat qOne = { 0, 0, 0, 1 }; + +static HVect center; +static double radius; +static Quat qNow, qDown, qDrag; +static HVect vNow, vDown, vFrom, vTo, vrFrom, vrTo; +static HMatrix mNow, mDown; +static unsigned int showResult, dragging; +static ConstraintSet sets[NSets]; +static int setSizes[NSets]; +static AxisSet axisSet; +static int axisIndex; + +static HMatrix mId = +{ + { 1, 0, 0, 0 }, + { 0, 1, 0, 0 }, + { 0, 0, 1, 0 }, + { 0, 0, 0, 1 } +}; + +static double otherAxis[][4] = +{ + {-0.48, 0.80, 0.36, 1} +}; + +/* Internal methods */ +/* ================ */ + +static void Qt_ToMatrix(Quat q,HMatrix out); +static Quat Qt_Conj(Quat q); +static Quat Qt_Mul(Quat qL, Quat qR); +static Quat Qt_FromBallPoints(HVect from, HVect to); +static void Qt_ToBallPoints(Quat q, HVect *arcFrom, HVect *arcTo); + +static HVect V3_(double x, double y, double z); +static double V3_Norm(HVect v); +static HVect V3_Unit(HVect v); +static HVect V3_Scale(HVect v, double s); +static HVect V3_Negate(HVect v); +/* +static HVect V3_Add(HVect v1, HVect v2); +*/ +static HVect V3_Sub(HVect v1, HVect v2); +static double V3_Dot(HVect v1, HVect v2); +/* +static HVect V3_Cross(HVect v1, HVect v2); +static HVect V3_Bisect(HVect v0, HVect v1); +*/ + +static HVect MouseOnSphere(HVect mouse, HVect ballCenter, double ballRadius); +static HVect ConstrainToAxis(HVect loose, HVect axis); +static int NearestConstraintAxis(HVect loose, HVect *axes, int nAxes); + +/* Establish reasonable initial values for controller. */ +/* =================================================== */ + +void +ArcBall_Init (void) +{ + int i; + + center = qOne; + radius = 1.0; + vDown = vNow = qOne; + qDown = qNow = qOne; + for (i=15; i>=0; i--) + ((double *)mNow)[i] = ((double *)mDown)[i] = ((double *)mId)[i]; + + showResult = dragging = FALSE; + axisSet = NoAxes; + sets[CameraAxes] = mId[X]; + setSizes[CameraAxes] = 3; + sets[BodyAxes] = mDown[X]; + setSizes[BodyAxes] = 3; + sets[OtherAxes] = otherAxis[X]; + setSizes[OtherAxes] = 1; +} + +/* Set the center and size of the controller. */ +/* ========================================== */ + +void +ArcBall_Place (HVect Center, + double Radius) +{ + center = Center; + radius = Radius; +} + +/* Incorporate new mouse position. */ +/* =============================== */ + +void +ArcBall_Mouse (HVect v_Now) +{ + vNow = v_Now; +} + +/* Choose a constraint set, or none. */ +/* ================================= */ + +void +ArcBall_UseSet (AxisSet axis_Set) +{ + if (!dragging) axisSet = axis_Set; +} + +/* Using vDown, vNow, dragging, and axisSet, compute rotation etc. */ +/* =============================================================== */ + +void +ArcBall_Update (void) +{ + int setSize = setSizes[axisSet]; + HVect *set = (HVect *)(sets[axisSet]); + + vFrom = MouseOnSphere(vDown, center, radius); + vTo = MouseOnSphere(vNow, center, radius); + if (dragging) + { + if (axisSet!=NoAxes) + { + vFrom = ConstrainToAxis(vFrom, set[axisIndex]); + vTo = ConstrainToAxis(vTo, set[axisIndex]); + } + qDrag = Qt_FromBallPoints(vFrom, vTo); + qNow = Qt_Mul(qDrag, qDown); + } + else + { + if (axisSet!=NoAxes) axisIndex = NearestConstraintAxis(vTo, set, setSize); + } + Qt_ToBallPoints(qDown, &vrFrom, &vrTo); + Qt_ToMatrix(Qt_Conj(qNow), mNow); /* Gives transpose for GL. */ +} + +/* Return rotation matrix defined by controller use. */ +/* ================================================= */ + +void +ArcBall_Value (HMatrix m_Now) +{ + ArcBall_CopyMat (mNow, m_Now); +} + +/* Extract rotation angles from matrix */ +/* =================================== */ + +void +ArcBall_Values (double *alpha, + double *beta, + double *gamma) +{ + if ((*beta=asin(-mNow[0][2]))!=0.0) + { + *gamma=atan2(mNow[1][2],mNow[2][2]); + *alpha=atan2(mNow[0][1],mNow[0][0]); + } + else + { + *gamma=atan2(mNow[1][0],mNow[1][1]); + *alpha=0.0; + } +} + +/* Begin drag sequence. */ +/* ==================== */ + +void +ArcBall_BeginDrag (void) +{ + dragging = TRUE; + vDown = vNow; +} + +/* Stop drag sequence. */ +/* =================== */ + +void +ArcBall_EndDrag (void) +{ + dragging = FALSE; + qDown = qNow; + + ArcBall_CopyMat (mNow, mDown); +} + +/*===================*/ +/***** BallAux.c *****/ +/*===================*/ + +/* Return quaternion product qL * qR. Note: order is important! */ +/* To combine rotations, use the product Mul(qSecond, qFirst), */ +/* which gives the effect of rotating by qFirst then qSecond. */ +/* ============================================================= */ + +static Quat +Qt_Mul (Quat qL, + Quat qR) +{ + Quat qq; + qq.w = qL.w*qR.w - qL.x*qR.x - qL.y*qR.y - qL.z*qR.z; + qq.x = qL.w*qR.x + qL.x*qR.w + qL.y*qR.z - qL.z*qR.y; + qq.y = qL.w*qR.y + qL.y*qR.w + qL.z*qR.x - qL.x*qR.z; + qq.z = qL.w*qR.z + qL.z*qR.w + qL.x*qR.y - qL.y*qR.x; + return (qq); +} + +/* Construct rotation matrix from (possibly non-unit) quaternion. */ +/* Assumes matrix is used to multiply column vector on the left: */ +/* vnew = mat vold. Works correctly for right-handed coordinate */ +/* system and right-handed rotations. */ +/* ============================================================== */ + +static void +Qt_ToMatrix (Quat q, + HMatrix out) +{ + double Nq = q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w; + double s = (Nq > 0.0) ? (2.0 / Nq) : 0.0; + double xs = q.x*s, ys = q.y*s, zs = q.z*s; + double wx = q.w*xs, wy = q.w*ys, wz = q.w*zs; + double xx = q.x*xs, xy = q.x*ys, xz = q.x*zs; + double yy = q.y*ys, yz = q.y*zs, zz = q.z*zs; + out[X][X] = 1.0 - (yy + zz); out[Y][X] = xy + wz; out[Z][X] = xz - wy; + out[X][Y] = xy - wz; out[Y][Y] = 1.0 - (xx + zz); out[Z][Y] = yz + wx; + out[X][Z] = xz + wy; out[Y][Z] = yz - wx; out[Z][Z] = 1.0 - (xx + yy); + out[X][W] = out[Y][W] = out[Z][W] = out[W][X] = out[W][Y] = out[W][Z] = 0.0; + out[W][W] = 1.0; +} + +/* Return conjugate of quaternion. */ +/* =============================== */ + +static Quat +Qt_Conj (Quat q) +{ + Quat qq; + qq.x = -q.x; qq.y = -q.y; qq.z = -q.z; qq.w = q.w; + return (qq); +} + +/* Return vector formed from components */ +/* ==================================== */ + +static HVect +V3_ (double x, + double y, + double z) +{ + HVect v; + v.x = x; v.y = y; v.z = z; v.w = 0; + return (v); +} + +/* Return norm of v, defined as sum of squares of components */ +/* ========================================================= */ + +static double +V3_Norm (HVect v) +{ + return ( v.x*v.x + v.y*v.y + v.z*v.z ); +} + +/* Return unit magnitude vector in direction of v */ +/* ============================================== */ + +static HVect +V3_Unit (HVect v) +{ + static HVect u = {0, 0, 0, 0}; + double vlen = sqrt(V3_Norm(v)); + + if (vlen != 0.0) + { + u.x = v.x/vlen; + u.y = v.y/vlen; + u.z = v.z/vlen; + } + return (u); +} + +/* Return version of v scaled by s */ +/* =============================== */ + +static HVect +V3_Scale (HVect v, + double s) +{ + HVect u; + u.x = s*v.x; u.y = s*v.y; u.z = s*v.z; u.w = v.w; + return (u); +} + +/* Return negative of v */ +/* ==================== */ + +static HVect +V3_Negate (HVect v) +{ + static HVect u = {0, 0, 0, 0}; + u.x = -v.x; u.y = -v.y; u.z = -v.z; + return (u); +} + +/* Return sum of v1 and v2 */ +/* ======================= */ +/* +static HVect +V3_Add (HVect v1, + HVect v2) +{ + static HVect v = {0, 0, 0, 0}; + v.x = v1.x+v2.x; v.y = v1.y+v2.y; v.z = v1.z+v2.z; + return (v); +} +*/ +/* Return difference of v1 minus v2 */ +/* ================================ */ + +static HVect +V3_Sub (HVect v1, + HVect v2) +{ + static HVect v = {0, 0, 0, 0}; + v.x = v1.x-v2.x; v.y = v1.y-v2.y; v.z = v1.z-v2.z; + return (v); +} + +/* Halve arc between unit vectors v0 and v1. */ +/* ========================================= */ +/* +static HVect +V3_Bisect (HVect v0, + HVect v1) +{ + HVect v = {0, 0, 0, 0}; + double Nv; + + v = V3_Add(v0, v1); + Nv = V3_Norm(v); + if (Nv < 1.0e-5) v = V3_(0, 0, 1); + else v = V3_Scale(v, 1/sqrt(Nv)); + return (v); +} +*/ + +/* Return dot product of v1 and v2 */ +/* =============================== */ + +static double +V3_Dot (HVect v1, + HVect v2) +{ + return (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z); +} + + +/* Return cross product, v1 x v2 */ +/* ============================= */ +/* +static HVect +V3_Cross (HVect v1, + HVect v2) +{ + static HVect v = {0, 0, 0, 0}; + v.x = v1.y*v2.z-v1.z*v2.y; + v.y = v1.z*v2.x-v1.x*v2.z; + v.z = v1.x*v2.y-v1.y*v2.x; + return (v); +} +*/ + +void +ArcBall_CopyMat (HMatrix inm, + HMatrix outm) +{ + int x=0,y=0; + + for (x=0;x<4;x++) + { + for (y=0;y<4;y++) + { + outm[y][x]=inm[y][x]; + } + } +} + +/*=====================================================*/ +/**** BallMath.c - Essential routines for ArcBall. ****/ +/*=====================================================*/ + +/* Convert window coordinates to sphere coordinates. */ +/* ================================================= */ + +static HVect +MouseOnSphere (HVect mouse, + HVect ballCenter, + double ballRadius) +{ + HVect ballMouse; + register double mag; + + ballMouse.x = (mouse.x - ballCenter.x) / ballRadius; + ballMouse.y = (mouse.y - ballCenter.y) / ballRadius; + mag = ballMouse.x*ballMouse.x + ballMouse.y*ballMouse.y; + if (mag > 1.0) + { + register double scale = 1.0/sqrt(mag); + ballMouse.x *= scale; ballMouse.y *= scale; + ballMouse.z = 0.0; + } + else ballMouse.z = sqrt(1 - mag); + ballMouse.w = 0.0; + return (ballMouse); +} + +/* Construct a unit quaternion from two points on unit sphere */ +/* ========================================================== */ + +static Quat +Qt_FromBallPoints (HVect from, + HVect to) +{ + Quat qu; + qu.x = from.y*to.z - from.z*to.y; + qu.y = from.z*to.x - from.x*to.z; + qu.z = from.x*to.y - from.y*to.x; + qu.w = from.x*to.x + from.y*to.y + from.z*to.z; + return (qu); +} + +/* Convert a unit quaternion to two points on unit sphere */ +/* ====================================================== */ + +static void +Qt_ToBallPoints (Quat q, + HVect *arcFrom, + HVect *arcTo) +{ + double s; + + s = sqrt(q.x*q.x + q.y*q.y); + if (s == 0.0) *arcFrom = V3_(0.0, 1.0, 0.0); + else *arcFrom = V3_(-q.y/s, q.x/s, 0.0); + arcTo->x = q.w*arcFrom->x - q.z*arcFrom->y; + arcTo->y = q.w*arcFrom->y + q.z*arcFrom->x; + arcTo->z = q.x*arcFrom->y - q.y*arcFrom->x; + if (q.w < 0.0) *arcFrom = V3_(-arcFrom->x, -arcFrom->y, 0.0); +} + +/* Force sphere point to be perpendicular to axis. */ +/* =============================================== */ + +static HVect +ConstrainToAxis (HVect loose, + HVect axis) +{ + HVect onPlane; + register double norm; + + onPlane = V3_Sub(loose, V3_Scale(axis, V3_Dot(axis, loose))); + norm = V3_Norm(onPlane); + if (norm > 0.0) + { + if (onPlane.z < 0.0) onPlane = V3_Negate(onPlane); + return ( V3_Scale(onPlane, 1/sqrt(norm)) ); + } + /* else drop through */ + /* ================= */ + + if (axis.z == 1) onPlane = V3_(1.0, 0.0, 0.0); + else onPlane = V3_Unit(V3_(-axis.y, axis.x, 0.0)); + return (onPlane); +} + +/* Find the index of nearest arc of axis set. */ +/* ========================================== */ + +static int +NearestConstraintAxis (HVect loose, + HVect *axes, + int nAxes) +{ + HVect onPlane; + register double max, dot; + register int i, nearest; + max = -1; nearest = 0; + + for (i=0; i<nAxes; i++) + { + onPlane = ConstrainToAxis(loose, axes[i]); + dot = V3_Dot(onPlane, loose); + if (dot>max) + { + max = dot; nearest = i; + } + } + return (nearest); +} diff --git a/plug-ins/map-object/arcball.h b/plug-ins/map-object/arcball.h new file mode 100644 index 0000000..f0b56ce --- /dev/null +++ b/plug-ins/map-object/arcball.h @@ -0,0 +1,50 @@ +#ifndef __ARCBALL_H__ +#define __ARCBALL_H__ + +typedef struct +{ + double x, y, z, w; +} Quat; + +enum QuatPart +{ + X, + Y, + Z, + W, + QuatLen +}; + +typedef Quat HVect; + +typedef double HMatrix[QuatLen][QuatLen]; + +typedef enum AxisSet +{ + NoAxes, + CameraAxes, + BodyAxes, + OtherAxes, + NSets +} AxisSet; + +typedef double *ConstraintSet; + +extern Quat qOne; + +void ArcBall_Init (void); +void ArcBall_Place (HVect Center, + double Radius); +void ArcBall_UseSet (AxisSet axis_Set); +void ArcBall_Update (void); +void ArcBall_Value (HMatrix m_Now); +void ArcBall_Values (double *alpha, + double *beta, + double *gamma); +void ArcBall_BeginDrag (void); +void ArcBall_EndDrag (void); +void ArcBall_Mouse (HVect v_Now); +void ArcBall_CopyMat (HMatrix inm, + HMatrix outm); + +#endif /* __ARCBALL_H__ */ diff --git a/plug-ins/map-object/map-object-apply.c b/plug-ins/map-object/map-object-apply.c new file mode 100644 index 0000000..0a2fb9b --- /dev/null +++ b/plug-ins/map-object/map-object-apply.c @@ -0,0 +1,328 @@ +/******************************************************/ +/* Apply mapping and shading on the whole input image */ +/******************************************************/ + +#include "config.h" + +#include <string.h> + +#include <gtk/gtk.h> + +#include <libgimp/gimp.h> +#include <libgimp/gimpui.h> + +#include "map-object-main.h" +#include "map-object-image.h" +#include "map-object-shade.h" +#include "map-object-apply.h" + +#include "libgimp/stdplugins-intl.h" + + +/*************/ +/* Main loop */ +/*************/ + +gdouble imat[4][4]; +gfloat rotmat[16]; +static gfloat a[16], b[16]; + +void +init_compute (void) +{ + gint i; + + switch (mapvals.maptype) + { + case MAP_SPHERE: + + /* Rotate the equator/northpole axis */ + /* ================================= */ + + gimp_vector3_set (&mapvals.firstaxis, 0.0, 0.0, -1.0); + gimp_vector3_set (&mapvals.secondaxis, 0.0, 1.0, 0.0); + + gimp_vector3_rotate (&mapvals.firstaxis, + gimp_deg_to_rad (mapvals.alpha), + gimp_deg_to_rad (mapvals.beta), + gimp_deg_to_rad (mapvals.gamma)); + gimp_vector3_rotate (&mapvals.secondaxis, + gimp_deg_to_rad (mapvals.alpha), + gimp_deg_to_rad (mapvals.beta), + gimp_deg_to_rad (mapvals.gamma)); + + /* Compute the 2D bounding box of the sphere spanned by the axis */ + /* ============================================================= */ + + compute_bounding_box (); + + get_ray_color = get_ray_color_sphere; + + break; + + case MAP_PLANE: + + /* Rotate the plane axis */ + /* ===================== */ + + gimp_vector3_set (&mapvals.firstaxis, 1.0, 0.0, 0.0); + gimp_vector3_set (&mapvals.secondaxis, 0.0, 1.0, 0.0); + gimp_vector3_set (&mapvals.normal, 0.0, 0.0, 1.0); + + gimp_vector3_rotate (&mapvals.firstaxis, + gimp_deg_to_rad (mapvals.alpha), + gimp_deg_to_rad (mapvals.beta), + gimp_deg_to_rad (mapvals.gamma)); + gimp_vector3_rotate (&mapvals.secondaxis, + gimp_deg_to_rad (mapvals.alpha), + gimp_deg_to_rad (mapvals.beta), + gimp_deg_to_rad (mapvals.gamma)); + + mapvals.normal = gimp_vector3_cross_product (&mapvals.firstaxis, + &mapvals.secondaxis); + + if (mapvals.normal.z < 0.0) + gimp_vector3_mul (&mapvals.normal, -1.0); + + /* Initialize intersection matrix */ + /* ============================== */ + + imat[0][1] = -mapvals.firstaxis.x; + imat[1][1] = -mapvals.firstaxis.y; + imat[2][1] = -mapvals.firstaxis.z; + + imat[0][2] = -mapvals.secondaxis.x; + imat[1][2] = -mapvals.secondaxis.y; + imat[2][2] = -mapvals.secondaxis.z; + + imat[0][3] = mapvals.position.x - mapvals.viewpoint.x; + imat[1][3] = mapvals.position.y - mapvals.viewpoint.y; + imat[2][3] = mapvals.position.z - mapvals.viewpoint.z; + + get_ray_color = get_ray_color_plane; + + break; + + case MAP_BOX: + get_ray_color = get_ray_color_box; + + gimp_vector3_set (&mapvals.firstaxis, 1.0, 0.0, 0.0); + gimp_vector3_set (&mapvals.secondaxis, 0.0, 1.0, 0.0); + gimp_vector3_set (&mapvals.normal, 0.0, 0.0, 1.0); + + ident_mat (rotmat); + + rotatemat (mapvals.alpha, &mapvals.firstaxis, a); + + matmul (a, rotmat, b); + + memcpy (rotmat, b, sizeof (gfloat) * 16); + + rotatemat (mapvals.beta, &mapvals.secondaxis, a); + matmul (a, rotmat, b); + + memcpy (rotmat, b, sizeof (gfloat) * 16); + + rotatemat (mapvals.gamma, &mapvals.normal, a); + matmul (a, rotmat, b); + + memcpy (rotmat, b, sizeof (gfloat) * 16); + + /* Set up pixel regions for the box face images */ + /* ============================================ */ + + for (i = 0; i < 6; i++) + { + box_drawable_ids[i] = mapvals.boxmap_id[i]; + + box_buffers[i] = gimp_drawable_get_buffer (box_drawable_ids[i]); + } + + break; + + case MAP_CYLINDER: + get_ray_color = get_ray_color_cylinder; + + gimp_vector3_set (&mapvals.firstaxis, 1.0, 0.0, 0.0); + gimp_vector3_set (&mapvals.secondaxis, 0.0, 1.0, 0.0); + gimp_vector3_set (&mapvals.normal, 0.0, 0.0, 1.0); + + ident_mat (rotmat); + + rotatemat (mapvals.alpha, &mapvals.firstaxis, a); + + matmul (a, rotmat, b); + + memcpy (rotmat, b, sizeof (gfloat) * 16); + + rotatemat (mapvals.beta, &mapvals.secondaxis, a); + matmul (a, rotmat, b); + + memcpy (rotmat, b, sizeof (gfloat) * 16); + + rotatemat (mapvals.gamma, &mapvals.normal, a); + matmul (a, rotmat, b); + + memcpy (rotmat, b, sizeof (gfloat) * 16); + + /* Set up pixel regions for the cylinder cap images */ + /* ================================================ */ + + for (i = 0; i < 2; i++) + { + cylinder_drawable_ids[i] = mapvals.cylindermap_id[i]; + + cylinder_buffers[i] = gimp_drawable_get_buffer (cylinder_drawable_ids[i]); + } + break; + } + + max_depth = (gint) mapvals.maxdepth; +} + +static void +render (gdouble x, + gdouble y, + GimpRGB *col, + gpointer data) +{ + GimpVector3 pos; + + pos.x = x / (gdouble) width; + pos.y = y / (gdouble) height; + pos.z = 0.0; + + *col = get_ray_color (&pos); +} + +static void +show_progress (gint min, + gint max, + gint curr, + gpointer data) +{ + gimp_progress_update ((gdouble) curr / (gdouble) max); +} + +/**************************************************/ +/* Performs map-to-sphere on the whole input image */ +/* and updates or creates a new GIMP image. */ +/**************************************************/ + +void +compute_image (void) +{ + gint xcount, ycount; + GimpRGB color; + glong progress_counter = 0; + GimpVector3 p; + gint32 new_image_id = -1; + gint32 new_layer_id = -1; + gboolean insert_layer = FALSE; + + init_compute (); + + if (mapvals.create_new_image) + { + new_image_id = gimp_image_new (width, height, GIMP_RGB); + } + else + { + new_image_id = image_id; + } + + gimp_image_undo_group_start (new_image_id); + + if (mapvals.create_new_image || + mapvals.create_new_layer || + (mapvals.transparent_background && + ! gimp_drawable_has_alpha (output_drawable_id))) + { + gchar *layername[] = {_("Map to plane"), + _("Map to sphere"), + _("Map to box"), + _("Map to cylinder"), + _("Background")}; + + new_layer_id = gimp_layer_new (new_image_id, + layername[mapvals.create_new_image ? 4 : + mapvals.maptype], + width, height, + mapvals.transparent_background ? + GIMP_RGBA_IMAGE : + GIMP_RGB_IMAGE, + 100.0, + gimp_image_get_default_new_layer_mode (new_image_id)); + + insert_layer = TRUE; + output_drawable_id = new_layer_id; + } + + dest_buffer = gimp_drawable_get_shadow_buffer (output_drawable_id); + + switch (mapvals.maptype) + { + case MAP_PLANE: + gimp_progress_init (_("Map to plane")); + break; + case MAP_SPHERE: + gimp_progress_init (_("Map to sphere")); + break; + case MAP_BOX: + gimp_progress_init (_("Map to box")); + break; + case MAP_CYLINDER: + gimp_progress_init (_("Map to cylinder")); + break; + } + + if (! mapvals.antialiasing) + { + for (ycount = 0; ycount < height; ycount++) + { + for (xcount = 0; xcount < width; xcount++) + { + p = int_to_pos (xcount, ycount); + color = (* get_ray_color) (&p); + poke (xcount, ycount, &color, NULL); + + progress_counter++; + } + + gimp_progress_update ((gdouble) progress_counter / + (gdouble) maxcounter); + } + } + else + { + gimp_adaptive_supersample_area (0, 0, + width - 1, height - 1, + max_depth, + mapvals.pixelthreshold, + render, + NULL, + poke, + NULL, + show_progress, + NULL); + } + + gimp_progress_update (1.0); + + g_object_unref (source_buffer); + g_object_unref (dest_buffer); + + if (insert_layer) + gimp_image_insert_layer (new_image_id, new_layer_id, -1, 0); + + gimp_drawable_merge_shadow (output_drawable_id, TRUE); + gimp_drawable_update (output_drawable_id, 0, 0, width, height); + + if (new_image_id != image_id) + { + gimp_display_new (new_image_id); + gimp_displays_flush (); + } + + gimp_image_undo_group_end (new_image_id); +} diff --git a/plug-ins/map-object/map-object-apply.h b/plug-ins/map-object/map-object-apply.h new file mode 100644 index 0000000..7b06eda --- /dev/null +++ b/plug-ins/map-object/map-object-apply.h @@ -0,0 +1,10 @@ +#ifndef __MAPOBJECT_APPLY_H__ +#define __MAPOBJECT_APPLY_H__ + +extern gdouble imat[4][4]; +extern gfloat rotmat[16]; + +void init_compute (void); +void compute_image (void); + +#endif /* __MAPOBJECT_APPLY_H__ */ diff --git a/plug-ins/map-object/map-object-image.c b/plug-ins/map-object/map-object-image.c new file mode 100644 index 0000000..1f16279 --- /dev/null +++ b/plug-ins/map-object/map-object-image.c @@ -0,0 +1,352 @@ +/*********************************************************/ +/* Image manipulation routines. Calls mapobject_shade.c */ +/* functions to compute the shading of the image at each */ +/* pixel. These routines are used by the functions in */ +/* mapobject_preview.c and mapobject_apply.c */ +/*********************************************************/ + +#include "config.h" + +#include <string.h> + +#include <sys/types.h> + +#include <gtk/gtk.h> + +#include <libgimp/gimp.h> +#include <libgimp/gimpui.h> + +#include "map-object-main.h" +#include "map-object-preview.h" +#include "map-object-shade.h" +#include "map-object-ui.h" +#include "map-object-image.h" + + +gint32 input_drawable_id; +gint32 output_drawable_id; +GeglBuffer *source_buffer; +GeglBuffer *dest_buffer; + +gint32 box_drawable_ids[6]; +GeglBuffer *box_buffers[6]; + +gint32 cylinder_drawable_ids[2]; +GeglBuffer *cylinder_buffers[2]; + +guchar *preview_rgb_data = NULL; +gint preview_rgb_stride; +cairo_surface_t *preview_surface = NULL; + +glong maxcounter, old_depth, max_depth; +gint width, height, image_id; +GimpRGB background; + +gint border_x, border_y, border_w, border_h; + +/******************/ +/* Implementation */ +/******************/ + +GimpRGB +peek (gint x, + gint y) +{ + GimpRGB color; + + gegl_buffer_sample (source_buffer, x, y, NULL, + &color, babl_format ("R'G'B'A double"), + GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); + + if (! babl_format_has_alpha (gegl_buffer_get_format (source_buffer))) + color.a = 1.0; + + return color; +} + +static GimpRGB +peek_box_image (gint image, + gint x, + gint y) +{ + GimpRGB color; + + gegl_buffer_sample (box_buffers[image], x, y, NULL, + &color, babl_format ("R'G'B'A double"), + GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); + + if (! babl_format_has_alpha (gegl_buffer_get_format (box_buffers[image]))) + color.a = 1.0; + + return color; +} + +static GimpRGB +peek_cylinder_image (gint image, + gint x, + gint y) +{ + GimpRGB color; + + gegl_buffer_sample (cylinder_buffers[image], x, y, NULL, + &color, babl_format ("R'G'B'A double"), + GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); + + if (! babl_format_has_alpha (gegl_buffer_get_format (cylinder_buffers[image]))) + color.a = 1.0; + + return color; +} + +void +poke (gint x, + gint y, + GimpRGB *color, + gpointer user_data) +{ + gegl_buffer_set (dest_buffer, GEGL_RECTANGLE (x, y, 1, 1), 0, + babl_format ("R'G'B'A double"), color, + GEGL_AUTO_ROWSTRIDE); +} + +gint +checkbounds (gint x, + gint y) +{ + if (x < border_x || + y < border_y || + x >= border_x + border_w || + y >= border_y + border_h) + return FALSE; + else + return TRUE; +} + +static gint +checkbounds_box_image (gint image, + gint x, + gint y) +{ + gint w, h; + + w = gegl_buffer_get_width (box_buffers[image]); + h = gegl_buffer_get_height (box_buffers[image]); + + if (x < 0 || y < 0 || x >= w || y >= h) + return FALSE ; + else + return TRUE ; +} + +static gint +checkbounds_cylinder_image (gint image, + gint x, + gint y) +{ + gint w, h; + + w = gegl_buffer_get_width (cylinder_buffers[image]); + h = gegl_buffer_get_height (cylinder_buffers[image]); + + if (x < 0 || y < 0 || x >= w || y >= h) + return FALSE; + else + return TRUE; +} + +GimpVector3 +int_to_pos (gint x, + gint y) +{ + GimpVector3 pos; + + pos.x = (gdouble) x / (gdouble) width; + pos.y = (gdouble) y / (gdouble) height; + pos.z = 0.0; + + return pos; +} + +void +pos_to_int (gdouble x, + gdouble y, + gint *scr_x, + gint *scr_y) +{ + *scr_x = (gint) ((x * (gdouble) width)); + *scr_y = (gint) ((y * (gdouble) height)); +} + +/**********************************************/ +/* Compute the image color at pos (u,v) using */ +/* Quartics bilinear interpolation stuff. */ +/**********************************************/ + +GimpRGB +get_image_color (gdouble u, + gdouble v, + gint *inside) +{ + gint x1, y1, x2, y2; + GimpRGB p[4]; + + pos_to_int (u, v, &x1, &y1); + + if (mapvals.tiled == TRUE) + { + *inside = TRUE; + + if (x1 < 0) x1 = (width-1) - (-x1 % width); + else x1 = x1 % width; + + if (y1 < 0) y1 = (height-1) - (-y1 % height); + else y1 = y1 % height; + + x2 = (x1 + 1) % width; + y2 = (y1 + 1) % height; + + p[0] = peek (x1, y1); + p[1] = peek (x2, y1); + p[2] = peek (x1, y2); + p[3] = peek (x2, y2); + + return gimp_bilinear_rgba (u * width, v * height, p); + } + + if (checkbounds (x1, y1) == FALSE) + { + *inside =FALSE; + + return background; + } + + x2 = (x1 + 1); + y2 = (y1 + 1); + + if (checkbounds (x2, y2) == FALSE) + { + *inside = TRUE; + + return peek (x1, y1); + } + + *inside=TRUE; + + p[0] = peek (x1, y1); + p[1] = peek (x2, y1); + p[2] = peek (x1, y2); + p[3] = peek (x2, y2); + + return gimp_bilinear_rgba (u * width, v * height, p); +} + +GimpRGB +get_box_image_color (gint image, + gdouble u, + gdouble v) +{ + gint w, h; + gint x1, y1, x2, y2; + GimpRGB p[4]; + + w = gegl_buffer_get_width (box_buffers[image]); + h = gegl_buffer_get_height (box_buffers[image]); + + x1 = (gint) ((u * (gdouble) w)); + y1 = (gint) ((v * (gdouble) h)); + + if (checkbounds_box_image (image, x1, y1) == FALSE) + return background; + + x2 = (x1 + 1); + y2 = (y1 + 1); + + if (checkbounds_box_image (image, x2, y2) == FALSE) + return peek_box_image (image, x1,y1); + + p[0] = peek_box_image (image, x1, y1); + p[1] = peek_box_image (image, x2, y1); + p[2] = peek_box_image (image, x1, y2); + p[3] = peek_box_image (image, x2, y2); + + return gimp_bilinear_rgba (u * w, v * h, p); +} + +GimpRGB +get_cylinder_image_color (gint image, + gdouble u, + gdouble v) +{ + gint w, h; + gint x1, y1, x2, y2; + GimpRGB p[4]; + + w = gegl_buffer_get_width (cylinder_buffers[image]); + h = gegl_buffer_get_height (cylinder_buffers[image]); + + x1 = (gint) ((u * (gdouble) w)); + y1 = (gint) ((v * (gdouble) h)); + + if (checkbounds_cylinder_image (image, x1, y1) == FALSE) + return background; + + x2 = (x1 + 1); + y2 = (y1 + 1); + + if (checkbounds_cylinder_image (image, x2, y2) == FALSE) + return peek_cylinder_image (image, x1,y1); + + p[0] = peek_cylinder_image (image, x1, y1); + p[1] = peek_cylinder_image (image, x2, y1); + p[2] = peek_cylinder_image (image, x1, y2); + p[3] = peek_cylinder_image (image, x2, y2); + + return gimp_bilinear_rgba (u * w, v * h, p); +} + +/****************************************/ +/* Allocate memory for temporary images */ +/****************************************/ + +gint +image_setup (gint32 drawable_id, + gint interactive) +{ + input_drawable_id = drawable_id; + output_drawable_id = drawable_id; + + if (! gimp_drawable_mask_intersect (drawable_id, &border_x, &border_y, + &border_w, &border_h)) + return FALSE; + + width = gimp_drawable_width (input_drawable_id); + height = gimp_drawable_height (input_drawable_id); + + source_buffer = gimp_drawable_get_buffer (input_drawable_id); + + maxcounter = (glong) width * (glong) height; + + if (mapvals.transparent_background == TRUE) + { + gimp_rgba_set (&background, 0.0, 0.0, 0.0, 0.0); + } + else + { + gimp_context_get_background (&background); + gimp_rgb_set_alpha (&background, 1.0); + } + + if (interactive == TRUE) + { + preview_rgb_stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, + PREVIEW_WIDTH); + preview_rgb_data = g_new0 (guchar, preview_rgb_stride * PREVIEW_HEIGHT); + preview_surface = cairo_image_surface_create_for_data (preview_rgb_data, + CAIRO_FORMAT_RGB24, + PREVIEW_WIDTH, + PREVIEW_HEIGHT, + preview_rgb_stride); + } + + return TRUE; +} diff --git a/plug-ins/map-object/map-object-image.h b/plug-ins/map-object/map-object-image.h new file mode 100644 index 0000000..189204b --- /dev/null +++ b/plug-ins/map-object/map-object-image.h @@ -0,0 +1,62 @@ +#ifndef __MAPOBJECT_IMAGE_H__ +#define __MAPOBJECT_IMAGE_H__ + +/* Externally visible variables */ +/* ============================ */ + +extern gint32 input_drawable_id; +extern gint32 output_drawable_id; +extern GeglBuffer *source_buffer; +extern GeglBuffer *dest_buffer; + +extern gint32 box_drawable_ids[6]; +extern GeglBuffer *box_buffers[6]; + +extern gint32 cylinder_drawable_ids[2]; +extern GeglBuffer *cylinder_buffers[2]; + +extern guchar *preview_rgb_data; +extern gint preview_rgb_stride; +extern cairo_surface_t *preview_surface; + +extern glong maxcounter, old_depth, max_depth; +extern gint width, height, image_id; +extern GimpRGB background; + +extern gint border_x1, border_y1, border_x2, border_y2; + +/* Externally visible functions */ +/* ============================ */ + +extern gint image_setup (gint32 drawable_id, + gint interactive); +extern glong in_xy_to_index (gint x, + gint y); +extern glong out_xy_to_index (gint x, + gint y); +extern gint checkbounds (gint x, + gint y); +extern GimpRGB peek (gint x, + gint y); +extern void poke (gint x, + gint y, + GimpRGB *color, + gpointer user_data); +extern GimpVector3 int_to_pos (gint x, + gint y); +extern void pos_to_int (gdouble x, + gdouble y, + gint *scr_x, + gint *scr_y); + +extern GimpRGB get_image_color (gdouble u, + gdouble v, + gint *inside); +extern GimpRGB get_box_image_color (gint image, + gdouble u, + gdouble v); +extern GimpRGB get_cylinder_image_color (gint image, + gdouble u, + gdouble v); + +#endif /* __MAPOBJECT_IMAGE_H__ */ diff --git a/plug-ins/map-object/map-object-main.c b/plug-ins/map-object/map-object-main.c new file mode 100644 index 0000000..c2f6a82 --- /dev/null +++ b/plug-ins/map-object/map-object-main.c @@ -0,0 +1,334 @@ +/* MapObject 1.2.0 -- image filter plug-in for GIMP + * + * Copyright (C) 1996-98 Tom Bech + * Copyright (C) 1996-98 Federico Mena Quintero + * + * E-mail: tomb@gimp.org (Tom) or quartic@gimp.org (Federico) + * + * 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 3 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, see <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <gtk/gtk.h> + +#include <libgimp/gimp.h> +#include <libgimp/gimpui.h> + +#include "map-object-ui.h" +#include "map-object-image.h" +#include "map-object-apply.h" +#include "map-object-preview.h" +#include "map-object-main.h" + +#include "libgimp/stdplugins-intl.h" + + +/* Global variables */ +/* ================ */ + +MapObjectValues mapvals; + +/******************/ +/* Implementation */ +/******************/ + +/*************************************/ +/* Set parameters to standard values */ +/*************************************/ + +static void +set_default_settings (void) +{ + gint i; + + gimp_vector3_set (&mapvals.viewpoint, 0.5, 0.5, 2.0); + gimp_vector3_set (&mapvals.firstaxis, 1.0, 0.0, 0.0); + gimp_vector3_set (&mapvals.secondaxis, 0.0, 1.0, 0.0); + gimp_vector3_set (&mapvals.normal, 0.0, 0.0, 1.0); + gimp_vector3_set (&mapvals.position, 0.5, 0.5, 0.0); + gimp_vector3_set (&mapvals.lightsource.position, -0.5, -0.5, 2.0); + gimp_vector3_set (&mapvals.lightsource.direction, -1.0, -1.0, 1.0); + gimp_vector3_set (&mapvals.scale, 0.5, 0.5, 0.5); + + mapvals.maptype = MAP_PLANE; + + mapvals.pixelthreshold = 0.25; + mapvals.alpha = 0.0; + mapvals.beta = 0.0; + mapvals.gamma = 0.0; + mapvals.maxdepth = 3.0; + mapvals.radius = 0.25; + mapvals.cylinder_radius = 0.25; + mapvals.cylinder_length = 1.0; + + mapvals.zoom = 1.0; + mapvals.lightsource.type = POINT_LIGHT; + + mapvals.antialiasing = TRUE; + mapvals.create_new_image = FALSE; + mapvals.create_new_layer = FALSE; + mapvals.transparent_background = FALSE; + mapvals.tiled = FALSE; + mapvals.livepreview = FALSE; + mapvals.showgrid = TRUE; + + mapvals.lightsource.intensity = 1.0; + gimp_rgba_set (&mapvals.lightsource.color, 1.0, 1.0, 1.0, 1.0); + + mapvals.material.ambient_int = 0.3; + mapvals.material.diffuse_int = 1.0; + mapvals.material.diffuse_ref = 0.5; + mapvals.material.specular_ref = 0.5; + mapvals.material.highlight = 27.0; + + for (i = 0; i < 6; i++) + mapvals.boxmap_id[i] = -1; + + for (i = 0; i < 2; i++) + mapvals.cylindermap_id[i] = -1; +} + +static void +check_drawables (gint32 drawable_id) +{ + gint i; + + /* Check that boxmap images are valid */ + /* ================================== */ + + for (i = 0; i < 6; i++) + { + if (mapvals.boxmap_id[i] == -1 || + !gimp_item_is_valid (mapvals.boxmap_id[i]) || + gimp_drawable_is_gray (mapvals.boxmap_id[i])) + mapvals.boxmap_id[i] = drawable_id; + } + + /* Check that cylindermap images are valid */ + /* ======================================= */ + + for (i = 0; i < 2; i++) + { + if (mapvals.cylindermap_id[i] == -1 || + !gimp_item_is_valid (mapvals.cylindermap_id[i]) || + gimp_drawable_is_gray (mapvals.cylindermap_id[i])) + mapvals.cylindermap_id[i] = drawable_id; + } +} + +static void +query (void) +{ + static const GimpParamDef args[] = + { + { GIMP_PDB_INT32, "run-mode", "The run mode { RUN-INTERACTIVE (0), RUN-NONINTERACTIVE (1) }" }, + { GIMP_PDB_IMAGE, "image", "Input image" }, + { GIMP_PDB_DRAWABLE, "drawable", "Input drawable" }, + { GIMP_PDB_INT32, "maptype", "Type of mapping (0=plane,1=sphere,2=box,3=cylinder)" }, + { GIMP_PDB_FLOAT, "viewpoint-x", "Position of viewpoint (x,y,z)" }, + { GIMP_PDB_FLOAT, "viewpoint-y", "Position of viewpoint (x,y,z)" }, + { GIMP_PDB_FLOAT, "viewpoint-z", "Position of viewpoint (x,y,z)" }, + { GIMP_PDB_FLOAT, "position-x", "Object position (x,y,z)" }, + { GIMP_PDB_FLOAT, "position-y", "Object position (x,y,z)" }, + { GIMP_PDB_FLOAT, "position-z", "Object position (x,y,z)" }, + { GIMP_PDB_FLOAT, "firstaxis-x", "First axis of object [x,y,z]" }, + { GIMP_PDB_FLOAT, "firstaxis-y", "First axis of object [x,y,z]" }, + { GIMP_PDB_FLOAT, "firstaxis-z", "First axis of object [x,y,z]" }, + { GIMP_PDB_FLOAT, "secondaxis-x", "Second axis of object [x,y,z]" }, + { GIMP_PDB_FLOAT, "secondaxis-y", "Second axis of object [x,y,z]" }, + { GIMP_PDB_FLOAT, "secondaxis-z", "Second axis of object [x,y,z]" }, + { GIMP_PDB_FLOAT, "rotationangle-x", "Rotation about X axis in degrees" }, + { GIMP_PDB_FLOAT, "rotationangle-y", "Rotation about Y axis in degrees" }, + { GIMP_PDB_FLOAT, "rotationangle-z", "Rotation about Z axis in degrees" }, + { GIMP_PDB_INT32, "lighttype", "Type of lightsource (0=point,1=directional,2=none)" }, + { GIMP_PDB_COLOR, "lightcolor", "Lightsource color (r,g,b)" }, + { GIMP_PDB_FLOAT, "lightposition-x", "Lightsource position (x,y,z)" }, + { GIMP_PDB_FLOAT, "lightposition-y", "Lightsource position (x,y,z)" }, + { GIMP_PDB_FLOAT, "lightposition-z", "Lightsource position (x,y,z)" }, + { GIMP_PDB_FLOAT, "lightdirection-x", "Lightsource direction [x,y,z]" }, + { GIMP_PDB_FLOAT, "lightdirection-y", "Lightsource direction [x,y,z]" }, + { GIMP_PDB_FLOAT, "lightdirection-z", "Lightsource direction [x,y,z]" }, + { GIMP_PDB_FLOAT, "ambient_intensity", "Material ambient intensity (0..1)" }, + { GIMP_PDB_FLOAT, "diffuse_intensity", "Material diffuse intensity (0..1)" }, + { GIMP_PDB_FLOAT, "diffuse_reflectivity", "Material diffuse reflectivity (0..1)" }, + { GIMP_PDB_FLOAT, "specular_reflectivity", "Material specular reflectivity (0..1)" }, + { GIMP_PDB_FLOAT, "highlight", "Material highlight (0..->), note: it's exponential" }, + { GIMP_PDB_INT32, "antialiasing", "Apply antialiasing (TRUE/FALSE)" }, + { GIMP_PDB_INT32, "tiled", "Tile source image (TRUE/FALSE)" }, + { GIMP_PDB_INT32, "newimage", "Create a new image (TRUE/FALSE)" }, + { GIMP_PDB_INT32, "transparentbackground", "Make background transparent (TRUE/FALSE)" }, + { GIMP_PDB_FLOAT, "radius", "Sphere/cylinder radius (only used when maptype=1 or 3)" }, + { GIMP_PDB_FLOAT, "x-scale", "Box x size (0..->)" }, + { GIMP_PDB_FLOAT, "y-scale", "Box y size (0..->)" }, + { GIMP_PDB_FLOAT, "z-scale", "Box z size (0..->)"}, + { GIMP_PDB_FLOAT, "cylinder-length", "Cylinder length (0..->)"}, + { GIMP_PDB_DRAWABLE, "box-front-drawable", "Box front face (set these to -1 if not used)" }, + { GIMP_PDB_DRAWABLE, "box-back-drawable", "Box back face" }, + { GIMP_PDB_DRAWABLE, "box-top-drawable", "Box top face" }, + { GIMP_PDB_DRAWABLE, "box-bottom-drawable", "Box bottom face" }, + { GIMP_PDB_DRAWABLE, "box-left-drawable", "Box left face" }, + { GIMP_PDB_DRAWABLE, "box-right-drawable", "Box right face" }, + { GIMP_PDB_DRAWABLE, "cyl-top-drawable", "Cylinder top face (set these to -1 if not used)" }, + { GIMP_PDB_DRAWABLE, "cyl-bottom-drawable", "Cylinder bottom face" } + }; + + gimp_install_procedure (PLUG_IN_PROC, + N_("Map the image to an object (plane, sphere, box or cylinder)"), + "No help yet", + "Tom Bech & Federico Mena Quintero", + "Tom Bech & Federico Mena Quintero", + "Version 1.2.0, July 16 1998", + N_("Map _Object..."), + "RGB*", + GIMP_PLUGIN, + G_N_ELEMENTS (args), 0, + args, NULL); + + gimp_plugin_menu_register (PLUG_IN_PROC, "<Image>/Filters/Map"); +} + +static void +run (const gchar *name, + gint nparams, + const GimpParam *param, + gint *nreturn_vals, + GimpParam **return_vals) +{ + static GimpParam values[1]; + GimpRunMode run_mode; + gint32 drawable_id; + GimpPDBStatusType status = GIMP_PDB_SUCCESS; + gint i; + + INIT_I18N (); + gegl_init (NULL, NULL); + + values[0].type = GIMP_PDB_STATUS; + values[0].data.d_status = status; + + *nreturn_vals = 1; + *return_vals = values; + + /* Set default values */ + /* ================== */ + + set_default_settings (); + + /* Get the specified drawable */ + /* ========================== */ + + run_mode = param[0].data.d_int32; + image_id = param[1].data.d_int32; + drawable_id = param[2].data.d_int32; + + switch (run_mode) + { + case GIMP_RUN_INTERACTIVE: + + /* Possibly retrieve data */ + /* ====================== */ + + gimp_get_data (PLUG_IN_PROC, &mapvals); + check_drawables (drawable_id); + if (main_dialog (drawable_id)) + { + compute_image (); + + gimp_set_data (PLUG_IN_PROC, &mapvals, sizeof (MapObjectValues)); + } + break; + + case GIMP_RUN_WITH_LAST_VALS: + gimp_get_data (PLUG_IN_PROC, &mapvals); + check_drawables (drawable_id); + if (image_setup (drawable_id, FALSE)) + compute_image (); + break; + + case GIMP_RUN_NONINTERACTIVE: + if (nparams != 49) + { + status = GIMP_PDB_CALLING_ERROR; + } + else + { + mapvals.maptype = (MapType) param[3].data.d_int32; + mapvals.viewpoint.x = param[4].data.d_float; + mapvals.viewpoint.y = param[5].data.d_float; + mapvals.viewpoint.z = param[6].data.d_float; + mapvals.position.x = param[7].data.d_float; + mapvals.position.y = param[8].data.d_float; + mapvals.position.z = param[9].data.d_float; + mapvals.firstaxis.x = param[10].data.d_float; + mapvals.firstaxis.y = param[11].data.d_float; + mapvals.firstaxis.z = param[12].data.d_float; + mapvals.secondaxis.x = param[13].data.d_float; + mapvals.secondaxis.y = param[14].data.d_float; + mapvals.secondaxis.z = param[15].data.d_float; + mapvals.alpha = param[16].data.d_float; + mapvals.beta = param[17].data.d_float; + mapvals.gamma = param[18].data.d_float; + mapvals.lightsource.type = (LightType) param[19].data.d_int32; + mapvals.lightsource.color = param[20].data.d_color; + mapvals.lightsource.position.x = param[21].data.d_float; + mapvals.lightsource.position.y = param[22].data.d_float; + mapvals.lightsource.position.z = param[23].data.d_float; + mapvals.lightsource.direction.x = param[24].data.d_float; + mapvals.lightsource.direction.y = param[25].data.d_float; + mapvals.lightsource.direction.z = param[26].data.d_float; + mapvals.material.ambient_int = param[27].data.d_float; + mapvals.material.diffuse_int = param[28].data.d_float; + mapvals.material.diffuse_ref = param[29].data.d_float; + mapvals.material.specular_ref = param[30].data.d_float; + mapvals.material.highlight = param[31].data.d_float; + mapvals.antialiasing = (gint) param[32].data.d_int32; + mapvals.tiled = (gint) param[33].data.d_int32; + mapvals.create_new_image = (gint) param[34].data.d_int32; + mapvals.transparent_background = (gint) param[35].data.d_int32; + mapvals.radius = param[36].data.d_float; + mapvals.cylinder_radius = param[36].data.d_float; + mapvals.scale.x = param[37].data.d_float; + mapvals.scale.y = param[38].data.d_float; + mapvals.scale.z = param[39].data.d_float; + mapvals.cylinder_length = param[40].data.d_float; + + for (i = 0; i < 6; i++) + mapvals.boxmap_id[i] = param[41+i].data.d_drawable; + + for (i = 0; i < 2; i++) + mapvals.cylindermap_id[i] = param[47+i].data.d_drawable; + + check_drawables (drawable_id); + if (image_setup (drawable_id, FALSE)) + compute_image (); + } + break; + } + + values[0].data.d_status = status; + + if (run_mode != GIMP_RUN_NONINTERACTIVE) + gimp_displays_flush (); +} + +const GimpPlugInInfo PLUG_IN_INFO = +{ + NULL, /* init_proc */ + NULL, /* quit_proc */ + query, /* query_proc */ + run, /* run_proc */ +}; + +MAIN () diff --git a/plug-ins/map-object/map-object-main.h b/plug-ins/map-object/map-object-main.h new file mode 100644 index 0000000..5958c7c --- /dev/null +++ b/plug-ins/map-object/map-object-main.h @@ -0,0 +1,90 @@ +#ifndef __MAPOBJECT_MAIN_H__ +#define __MAPOBJECT_MAIN_H__ + +/* Defines and stuff */ +/* ================= */ + +#define PLUG_IN_PROC "plug-in-map-object" +#define PLUG_IN_BINARY "map-object" +#define PLUG_IN_ROLE "gimp-map-object" + +#define TILE_CACHE_SIZE 16 + +/* Typedefs */ +/* ======== */ + +typedef enum +{ + POINT_LIGHT, + DIRECTIONAL_LIGHT, + NO_LIGHT +} LightType; + +typedef enum +{ + MAP_PLANE, + MAP_SPHERE, + MAP_BOX, + MAP_CYLINDER +} MapType; + +/* Typedefs */ +/* ======== */ + +typedef struct +{ + gdouble ambient_int; + gdouble diffuse_int; + gdouble diffuse_ref; + gdouble specular_ref; + gdouble highlight; + GimpRGB color; +} MaterialSettings; + +typedef struct +{ + LightType type; + GimpVector3 position; + GimpVector3 direction; + GimpRGB color; + gdouble intensity; +} LightSettings; + +typedef struct +{ + GimpVector3 viewpoint,firstaxis,secondaxis,normal,position,scale; + LightSettings lightsource; + + MaterialSettings material; + MaterialSettings refmaterial; + + MapType maptype; + + gint antialiasing; + gint create_new_image; + gint create_new_layer; + gint transparent_background; + gint tiled; + gint livepreview; + gint showgrid; + gint showcaps; + + gdouble zoom; + gdouble alpha,beta,gamma; + gdouble maxdepth; + gdouble pixelthreshold; + gdouble radius; + gdouble cylinder_radius; + gdouble cylinder_length; + + gint32 boxmap_id[6]; + gint32 cylindermap_id[2]; + +} MapObjectValues; + +/* Externally visible variables */ +/* ============================ */ + +extern MapObjectValues mapvals; + +#endif /* __MAPOBJECT_MAIN_H__ */ diff --git a/plug-ins/map-object/map-object-preview.c b/plug-ins/map-object/map-object-preview.c new file mode 100644 index 0000000..afc29b4 --- /dev/null +++ b/plug-ins/map-object/map-object-preview.c @@ -0,0 +1,745 @@ +/*************************************************/ +/* Compute a preview image and preview wireframe */ +/*************************************************/ + +#include "config.h" + +#include <gtk/gtk.h> + +#include <libgimp/gimp.h> +#include <libgimp/gimpui.h> + +#include "map-object-main.h" +#include "map-object-ui.h" +#include "map-object-image.h" +#include "map-object-apply.h" +#include "map-object-shade.h" +#include "map-object-preview.h" + + +gdouble mat[3][4]; +gint lightx, lighty; + +/* Protos */ +/* ====== */ + +static void compute_preview (gint x, + gint y, + gint w, + gint h, + gint pw, + gint ph); +static void draw_light_marker (cairo_t *cr, + gint xpos, + gint ypos); +static void draw_line (cairo_t *cr, + gint startx, + gint starty, + gint pw, + gint ph, + gdouble cx1, + gdouble cy1, + gdouble cx2, + gdouble cy2, + GimpVector3 a, + GimpVector3 b); +static void draw_wireframe (cairo_t *cr, + gint startx, + gint starty, + gint pw, + gint ph); +static void draw_preview_wireframe (cairo_t *cr); +static void draw_wireframe_plane (cairo_t *cr, + gint startx, + gint starty, + gint pw, + gint ph); +static void draw_wireframe_sphere (cairo_t *cr, + gint startx, + gint starty, + gint pw, + gint ph); +static void draw_wireframe_box (cairo_t *cr, + gint startx, + gint starty, + gint pw, + gint ph); +static void draw_wireframe_cylinder (cairo_t *cr, + gint startx, + gint starty, + gint pw, + gint ph); + +/**************************************************************/ +/* Computes a preview of the rectangle starting at (x,y) with */ +/* dimensions (w,h), placing the result in preview_RGB_data. */ +/**************************************************************/ + +static void +compute_preview (gint x, + gint y, + gint w, + gint h, + gint pw, + gint ph) +{ + gdouble xpostab[PREVIEW_WIDTH]; + gdouble ypostab[PREVIEW_HEIGHT]; + gdouble realw; + gdouble realh; + GimpVector3 p1, p2; + GimpRGB color; + GimpRGB lightcheck, darkcheck; + gint xcnt, ycnt, f1, f2; + guchar r, g, b; + glong index = 0; + + init_compute (); + + if (! preview_surface) + return; + + p1 = int_to_pos (x, y); + p2 = int_to_pos (x + w, y + h); + + /* First, compute the linear mapping (x,y,x+w,y+h) to (0,0,pw,ph) */ + /* ============================================================== */ + + realw = (p2.x - p1.x); + realh = (p2.y - p1.y); + + for (xcnt = 0; xcnt < pw; xcnt++) + xpostab[xcnt] = p1.x + realw * ((gdouble) xcnt / (gdouble) pw); + + for (ycnt = 0; ycnt < ph; ycnt++) + ypostab[ycnt] = p1.y + realh * ((gdouble) ycnt / (gdouble) ph); + + /* Compute preview using the offset tables */ + /* ======================================= */ + + if (mapvals.transparent_background == TRUE) + { + gimp_rgba_set (&background, 0.0, 0.0, 0.0, 0.0); + } + else + { + gimp_context_get_background (&background); + gimp_rgb_set_alpha (&background, 1.0); + } + + gimp_rgba_set (&lightcheck, + GIMP_CHECK_LIGHT, GIMP_CHECK_LIGHT, GIMP_CHECK_LIGHT, 1.0); + gimp_rgba_set (&darkcheck, + GIMP_CHECK_DARK, GIMP_CHECK_DARK, GIMP_CHECK_DARK, 1.0); + gimp_vector3_set (&p2, -1.0, -1.0, 0.0); + + cairo_surface_flush (preview_surface); + + for (ycnt = 0; ycnt < ph; ycnt++) + { + index = ycnt * preview_rgb_stride; + for (xcnt = 0; xcnt < pw; xcnt++) + { + p1.x = xpostab[xcnt]; + p1.y = ypostab[ycnt]; + + p2 = p1; + color = (* get_ray_color) (&p1); + + if (color.a < 1.0) + { + f1 = ((xcnt % 32) < 16); + f2 = ((ycnt % 32) < 16); + f1 = f1 ^ f2; + + if (f1) + { + if (color.a == 0.0) + color = lightcheck; + else + gimp_rgb_composite (&color, &lightcheck, + GIMP_RGB_COMPOSITE_BEHIND); + } + else + { + if (color.a == 0.0) + color = darkcheck; + else + gimp_rgb_composite (&color, &darkcheck, + GIMP_RGB_COMPOSITE_BEHIND); + } + } + + gimp_rgb_get_uchar (&color, &r, &g, &b); + GIMP_CAIRO_RGB24_SET_PIXEL((preview_rgb_data + index), r, g, b); + index += 4; + } + } + cairo_surface_mark_dirty (preview_surface); +} + +/*************************************************/ +/* Check if the given position is within the */ +/* light marker. Return TRUE if so, FALSE if not */ +/*************************************************/ + +gint +check_light_hit (gint xpos, + gint ypos) +{ + gdouble dx, dy, r; + + if (mapvals.lightsource.type == POINT_LIGHT) + { + dx = (gdouble) lightx - xpos; + dy = (gdouble) lighty - ypos; + r = sqrt (dx * dx + dy * dy) + 0.5; + + if ((gint) r > 7) + return FALSE; + else + return TRUE; + } + + return FALSE; +} + +/****************************************/ +/* Draw a marker to show light position */ +/****************************************/ + +static void +draw_light_marker (cairo_t *cr, + gint xpos, + gint ypos) +{ + GdkColor color; + + if (mapvals.lightsource.type != POINT_LIGHT) + return; + + cairo_set_line_width (cr, 1.0); + + color.red = 0x0; + color.green = 0x4000; + color.blue = 0xFFFF; + gdk_cairo_set_source_color (cr, &color); + + lightx = xpos; + lighty = ypos; + + cairo_arc (cr, lightx, lighty, 7, 0, 2 * G_PI); + cairo_fill (cr); +} + +static void +draw_lights (cairo_t *cr, + gint startx, + gint starty, + gint pw, + gint ph) +{ + gdouble dxpos, dypos; + gint xpos, ypos; + + gimp_vector_3d_to_2d (startx, starty, pw, ph, + &dxpos, &dypos, &mapvals.viewpoint, + &mapvals.lightsource.position); + xpos = RINT (dxpos); + ypos = RINT (dypos); + + if (xpos >= 0 && xpos <= PREVIEW_WIDTH && + ypos >= 0 && ypos <= PREVIEW_HEIGHT) + { + draw_light_marker (cr, xpos, ypos); + } +} + +/*************************************************/ +/* Update light position given new screen coords */ +/*************************************************/ + +void +update_light (gint xpos, + gint ypos) +{ + gint startx, starty, pw, ph; + + pw = PREVIEW_WIDTH * mapvals.zoom; + ph = PREVIEW_HEIGHT * mapvals.zoom; + startx = (PREVIEW_WIDTH - pw) / 2; + starty = (PREVIEW_HEIGHT - ph) / 2; + + gimp_vector_2d_to_3d (startx, starty, pw, ph, xpos, ypos, + &mapvals.viewpoint, &mapvals.lightsource.position); + + gtk_widget_queue_draw (previewarea); +} + +/**************************/ +/* Compute preview image. */ +/**************************/ + +void +compute_preview_image (void) +{ + GdkDisplay *display = gtk_widget_get_display (previewarea); + GdkCursor *cursor; + gint pw, ph; + + pw = PREVIEW_WIDTH * mapvals.zoom; + ph = PREVIEW_HEIGHT * mapvals.zoom; + + cursor = gdk_cursor_new_for_display (display, GDK_WATCH); + gdk_window_set_cursor (gtk_widget_get_window (previewarea), cursor); + gdk_cursor_unref (cursor); + + compute_preview (0, 0, width - 1, height - 1, pw, ph); + + cursor = gdk_cursor_new_for_display (display, GDK_HAND2); + gdk_window_set_cursor(gtk_widget_get_window (previewarea), cursor); + gdk_cursor_unref (cursor); +} + +gboolean +preview_expose (GtkWidget *widget, + GdkEventExpose *eevent) +{ + gint startx, starty, pw, ph; + cairo_t *cr; + + cr = gdk_cairo_create (eevent->window); + + pw = PREVIEW_WIDTH * mapvals.zoom; + ph = PREVIEW_HEIGHT * mapvals.zoom; + startx = (PREVIEW_WIDTH - pw) / 2; + starty = (PREVIEW_HEIGHT - ph) / 2; + + cairo_set_source_surface (cr, preview_surface, startx, starty); + cairo_rectangle (cr, startx, starty, pw, ph); + cairo_clip (cr); + + cairo_paint (cr); + + cairo_reset_clip (cr); + + if (mapvals.showgrid) + draw_preview_wireframe (cr); + + cairo_reset_clip (cr); + draw_lights (cr, startx, starty, pw, ph); + + cairo_destroy (cr); + + return FALSE; +} + +/**************************/ +/* Draw preview wireframe */ +/**************************/ + +void +draw_preview_wireframe (cairo_t *cr) +{ + gint startx, starty, pw, ph; + + pw = PREVIEW_WIDTH * mapvals.zoom; + ph = PREVIEW_HEIGHT * mapvals.zoom; + startx = (PREVIEW_WIDTH - pw) / 2; + starty = (PREVIEW_HEIGHT - ph) / 2; + + draw_wireframe (cr, startx, starty, pw, ph); +} + +/****************************/ +/* Draw a wireframe preview */ +/****************************/ + +void +draw_wireframe (cairo_t *cr, + gint startx, + gint starty, + gint pw, + gint ph) +{ + cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); + switch (mapvals.maptype) + { + case MAP_PLANE: + draw_wireframe_plane (cr, startx, starty, pw, ph); + break; + case MAP_SPHERE: + draw_wireframe_sphere (cr, startx, starty, pw, ph); + break; + case MAP_BOX: + draw_wireframe_box (cr, startx, starty, pw, ph); + break; + case MAP_CYLINDER: + draw_wireframe_cylinder (cr, startx, starty, pw, ph); + break; + } +} + +static void +draw_wireframe_plane (cairo_t *cr, + gint startx, + gint starty, + gint pw, + gint ph) +{ + GimpVector3 v1, v2, a, b, c, d, dir1, dir2; + gint cnt; + gdouble x1, y1, x2, y2, fac; + + cairo_rectangle (cr, startx, starty, pw, ph); + cairo_clip (cr); + + /* Find rotated box corners */ + /* ======================== */ + + gimp_vector3_set (&v1, 0.5, 0.0, 0.0); + gimp_vector3_set (&v2, 0.0, 0.5, 0.0); + + gimp_vector3_rotate (&v1, + gimp_deg_to_rad (mapvals.alpha), + gimp_deg_to_rad (mapvals.beta), + gimp_deg_to_rad (mapvals.gamma)); + + gimp_vector3_rotate (&v2, + gimp_deg_to_rad (mapvals.alpha), + gimp_deg_to_rad (mapvals.beta), + gimp_deg_to_rad (mapvals.gamma)); + + dir1 = v1; gimp_vector3_normalize (&dir1); + dir2 = v2; gimp_vector3_normalize (&dir2); + + fac = 1.0 / (gdouble) WIRESIZE; + + gimp_vector3_mul (&dir1, fac); + gimp_vector3_mul (&dir2, fac); + + gimp_vector3_add (&a, &mapvals.position, &v1); + gimp_vector3_sub (&b, &a, &v2); + gimp_vector3_add (&a, &a, &v2); + gimp_vector3_sub (&d, &mapvals.position, &v1); + gimp_vector3_sub (&d, &d, &v2); + + c = b; + + for (cnt = 0; cnt <= WIRESIZE; cnt++) + { + gimp_vector_3d_to_2d (startx, starty, pw, ph, + &x1, &y1, &mapvals.viewpoint, &a); + gimp_vector_3d_to_2d (startx, starty, pw, ph, + &x2, &y2, &mapvals.viewpoint, &b); + + cairo_move_to (cr, RINT (x1) + 0.5, RINT (y1) + 0.5); + cairo_line_to (cr, RINT (x2) + 0.5, RINT (y2) + 0.5); + + gimp_vector_3d_to_2d (startx, starty, pw, ph, + &x1, &y1, &mapvals.viewpoint, &c); + gimp_vector_3d_to_2d (startx, starty, pw, ph, + &x2, &y2, &mapvals.viewpoint, &d); + + cairo_move_to (cr, RINT (x1) + 0.5, RINT (y1) + 0.5); + cairo_line_to (cr, RINT (x2) + 0.5, RINT (y2) + 0.5); + + gimp_vector3_sub (&a, &a, &dir1); + gimp_vector3_sub (&b, &b, &dir1); + gimp_vector3_add (&c, &c, &dir2); + gimp_vector3_add (&d, &d, &dir2); + } + + cairo_set_line_width (cr, 3.0); + cairo_stroke_preserve (cr); + cairo_set_line_width (cr, 1.0); + cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); + cairo_stroke (cr); +} + +static void +draw_wireframe_sphere (cairo_t *cr, + gint startx, + gint starty, + gint pw, + gint ph) +{ + GimpVector3 p[2 * (WIRESIZE + 5)]; + gint cnt, cnt2; + gdouble x1, y1, x2, y2, twopifac; + + cairo_rectangle (cr, startx, starty, pw, ph); + cairo_clip (cr); + + /* Compute wireframe points */ + /* ======================== */ + + twopifac = (2.0 * G_PI) / WIRESIZE; + + for (cnt = 0; cnt < WIRESIZE; cnt++) + { + p[cnt].x = mapvals.radius * cos ((gdouble) cnt * twopifac); + p[cnt].y = 0.0; + p[cnt].z = mapvals.radius * sin ((gdouble) cnt * twopifac); + gimp_vector3_rotate (&p[cnt], + gimp_deg_to_rad (mapvals.alpha), + gimp_deg_to_rad (mapvals.beta), + gimp_deg_to_rad (mapvals.gamma)); + gimp_vector3_add (&p[cnt], &p[cnt], &mapvals.position); + } + + p[cnt] = p[0]; + + for (cnt = WIRESIZE + 1; cnt < 2 * WIRESIZE + 1; cnt++) + { + p[cnt].x = mapvals.radius * cos ((gdouble) (cnt-(WIRESIZE+1))*twopifac); + p[cnt].y = mapvals.radius * sin ((gdouble) (cnt-(WIRESIZE+1))*twopifac); + p[cnt].z = 0.0; + gimp_vector3_rotate (&p[cnt], + gimp_deg_to_rad (mapvals.alpha), + gimp_deg_to_rad (mapvals.beta), + gimp_deg_to_rad (mapvals.gamma)); + gimp_vector3_add (&p[cnt], &p[cnt], &mapvals.position); + } + + p[cnt] = p[WIRESIZE+1]; + cnt++; + cnt2 = cnt; + + /* Find rotated axis */ + /* ================= */ + + gimp_vector3_set (&p[cnt], 0.0, -0.35, 0.0); + gimp_vector3_rotate (&p[cnt], + gimp_deg_to_rad (mapvals.alpha), + gimp_deg_to_rad (mapvals.beta), + gimp_deg_to_rad (mapvals.gamma)); + p[cnt+1] = mapvals.position; + + gimp_vector3_set (&p[cnt+2], 0.0, 0.0, -0.35); + gimp_vector3_rotate (&p[cnt+2], + gimp_deg_to_rad (mapvals.alpha), + gimp_deg_to_rad (mapvals.beta), + gimp_deg_to_rad (mapvals.gamma)); + p[cnt+3] = mapvals.position; + + p[cnt + 4] = p[cnt]; + gimp_vector3_mul (&p[cnt + 4], -1.0); + p[cnt + 5] = p[cnt + 1]; + + gimp_vector3_add (&p[cnt], &p[cnt], &mapvals.position); + gimp_vector3_add (&p[cnt + 2], &p[cnt + 2], &mapvals.position); + gimp_vector3_add (&p[cnt + 4], &p[cnt + 4], &mapvals.position); + + /* Draw the circles (equator and zero meridian) */ + /* ============================================ */ + + for (cnt = 0; cnt < cnt2 - 1; cnt++) + { + if (p[cnt].z > mapvals.position.z && p[cnt + 1].z > mapvals.position.z) + { + gimp_vector_3d_to_2d (startx, starty, pw, ph, + &x1, &y1, &mapvals.viewpoint, &p[cnt]); + gimp_vector_3d_to_2d (startx, starty, pw, ph, + &x2, &y2, &mapvals.viewpoint, &p[cnt + 1]); + + cairo_move_to (cr, (gint) (x1 + 0.5) + 0.5, (gint) (y1 + 0.5) + 0.5); + cairo_line_to (cr, (gint) (x2 + 0.5) + 0.5, (gint) (y2 + 0.5) + 0.5); + } + } + + /* Draw the axis (pole to pole and center to zero meridian) */ + /* ======================================================== */ + + for (cnt = 0; cnt < 3; cnt++) + { + gimp_vector_3d_to_2d (startx, starty, pw, ph, + &x1, &y1, &mapvals.viewpoint, &p[cnt2]); + gimp_vector_3d_to_2d (startx, starty, pw, ph, + &x2, &y2, &mapvals.viewpoint, &p[cnt2 + 1]); + + cairo_move_to (cr, RINT (x1) + 0.5, RINT (y1) + 0.5); + cairo_line_to (cr, RINT (x2) + 0.5, RINT (y2) + 0.5); + + cnt2 += 2; + } + + cairo_set_line_width (cr, 3.0); + cairo_stroke_preserve (cr); + cairo_set_line_width (cr, 1.0); + cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); + cairo_stroke (cr); +} + +static void +draw_line (cairo_t *cr, + gint startx, + gint starty, + gint pw, + gint ph, + gdouble cx1, + gdouble cy1, + gdouble cx2, + gdouble cy2, + GimpVector3 a, + GimpVector3 b) +{ + gdouble x1, y1, x2, y2; + + gimp_vector_3d_to_2d (startx, starty, pw, ph, + &x1, &y1, &mapvals.viewpoint, &a); + gimp_vector_3d_to_2d (startx, starty, pw, ph, + &x2, &y2, &mapvals.viewpoint, &b); + + cairo_move_to (cr, RINT (x1) + 0.5, RINT (y1) + 0.5); + cairo_line_to (cr, RINT (x2) + 0.5, RINT (y2) + 0.5); +} + +static void +draw_wireframe_box (cairo_t *cr, + gint startx, + gint starty, + gint pw, + gint ph) +{ + GimpVector3 p[8], tmp, scale; + gint i; + gdouble cx1, cy1, cx2, cy2; + + cairo_rectangle (cr, startx, starty, pw, ph); + cairo_clip (cr); + + /* Compute wireframe points */ + /* ======================== */ + + init_compute (); + + scale = mapvals.scale; + gimp_vector3_mul (&scale, 0.5); + + gimp_vector3_set (&p[0], -scale.x, -scale.y, scale.z); + gimp_vector3_set (&p[1], scale.x, -scale.y, scale.z); + gimp_vector3_set (&p[2], scale.x, scale.y, scale.z); + gimp_vector3_set (&p[3], -scale.x, scale.y, scale.z); + + gimp_vector3_set (&p[4], -scale.x, -scale.y, -scale.z); + gimp_vector3_set (&p[5], scale.x, -scale.y, -scale.z); + gimp_vector3_set (&p[6], scale.x, scale.y, -scale.z); + gimp_vector3_set (&p[7], -scale.x, scale.y, -scale.z); + + /* Rotate and translate points */ + /* =========================== */ + + for (i = 0; i < 8; i++) + { + vecmulmat (&tmp, &p[i], rotmat); + gimp_vector3_add (&p[i], &tmp, &mapvals.position); + } + + /* Draw the box */ + /* ============ */ + + cx1 = (gdouble) startx; + cy1 = (gdouble) starty; + cx2 = cx1 + (gdouble) pw; + cy2 = cy1 + (gdouble) ph; + + draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[0],p[1]); + draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[1],p[2]); + draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[2],p[3]); + draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[3],p[0]); + + draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[4],p[5]); + draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[5],p[6]); + draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[6],p[7]); + draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[7],p[4]); + + draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[0],p[4]); + draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[1],p[5]); + draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[2],p[6]); + draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[3],p[7]); + + cairo_set_line_width (cr, 3.0); + cairo_stroke_preserve (cr); + cairo_set_line_width (cr, 1.0); + cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); + cairo_stroke (cr); +} + +static void +draw_wireframe_cylinder (cairo_t *cr, + gint startx, + gint starty, + gint pw, + gint ph) +{ + GimpVector3 p[2*8], a, axis, scale; + gint i; + gdouble cx1, cy1, cx2, cy2; + gfloat m[16], l, angle; + + cairo_rectangle (cr, startx, starty, pw, ph); + cairo_clip (cr); + + /* Compute wireframe points */ + /* ======================== */ + + init_compute (); + + scale = mapvals.scale; + gimp_vector3_mul (&scale, 0.5); + + l = mapvals.cylinder_length / 2.0; + angle = 0; + + gimp_vector3_set (&axis, 0.0, 1.0, 0.0); + + for (i = 0; i < 8; i++) + { + rotatemat (angle, &axis, m); + + gimp_vector3_set (&a, mapvals.cylinder_radius, 0.0, 0.0); + + vecmulmat (&p[i], &a, m); + + p[i+8] = p[i]; + + p[i].y += l; + p[i+8].y -= l; + + angle += 360.0 / 8.0; + } + + /* Rotate and translate points */ + /* =========================== */ + + for (i = 0; i < 16; i++) + { + vecmulmat (&a, &p[i], rotmat); + gimp_vector3_add (&p[i], &a, &mapvals.position); + } + + /* Draw the box */ + /* ============ */ + + cx1 = (gdouble) startx; + cy1 = (gdouble) starty; + cx2 = cx1 + (gdouble) pw; + cy2 = cy1 + (gdouble) ph; + + for (i = 0; i < 7; i++) + { + draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[i],p[i+1]); + draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[i+8],p[i+9]); + draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[i],p[i+8]); + } + + draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[7],p[0]); + draw_line (cr, startx,starty,pw,ph, cx1,cy1,cx2,cy2, p[15],p[8]); + + cairo_set_line_width (cr, 3.0); + cairo_stroke_preserve (cr); + cairo_set_line_width (cr, 1.0); + cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); + cairo_stroke (cr); +} diff --git a/plug-ins/map-object/map-object-preview.h b/plug-ins/map-object/map-object-preview.h new file mode 100644 index 0000000..400b767 --- /dev/null +++ b/plug-ins/map-object/map-object-preview.h @@ -0,0 +1,26 @@ +#ifndef __MAPOBJECT_PREVIEW_H__ +#define __MAPOBJECT_PREVIEW_H__ + +#define PREVIEW_WIDTH 200 +#define PREVIEW_HEIGHT 200 + +#define WIRESIZE 16 + +/* Externally visible variables */ +/* ============================ */ + +extern gdouble mat[3][4]; +extern gint lightx,lighty; + +/* Externally visible functions */ +/* ============================ */ + +void compute_preview_image (void); +gboolean preview_expose (GtkWidget *widget, + GdkEventExpose *eevent); +gint check_light_hit (gint xpos, + gint ypos); +void update_light (gint xpos, + gint ypos); + +#endif /* __MAPOBJECT_PREVIEW_H__ */ diff --git a/plug-ins/map-object/map-object-shade.c b/plug-ins/map-object/map-object-shade.c new file mode 100644 index 0000000..f91345b --- /dev/null +++ b/plug-ins/map-object/map-object-shade.c @@ -0,0 +1,1254 @@ +/*****************/ +/* Shading stuff */ +/*****************/ + +#include "config.h" + +#include <string.h> + +#include <libgimp/gimp.h> +#include <libgimp/gimpui.h> + +#include "map-object-apply.h" +#include "map-object-main.h" +#include "map-object-image.h" +#include "map-object-shade.h" + + +static gdouble bx1, by1, bx2, by2; +get_ray_color_func get_ray_color; + +typedef struct +{ + gdouble u, v; + gdouble t; + GimpVector3 s; + GimpVector3 n; + gint face; +} FaceIntersectInfo; + +/*****************/ +/* Phong shading */ +/*****************/ + +static GimpRGB +phong_shade (GimpVector3 *pos, + GimpVector3 *viewpoint, + GimpVector3 *normal, + GimpRGB *diff_col, + GimpRGB *spec_col, + LightType type) +{ + GimpRGB ambientcolor, diffusecolor, specularcolor; + gdouble NL, RV, dist; + GimpVector3 L, NN, V, N; + GimpVector3 *light; + + light = mapvals.lightsource.type == DIRECTIONAL_LIGHT + ? &mapvals.lightsource.direction + : &mapvals.lightsource.position, + + /* Compute ambient intensity */ + /* ========================= */ + + N = *normal; + ambientcolor = *diff_col; + gimp_rgb_multiply (&ambientcolor, mapvals.material.ambient_int); + + /* Compute (N*L) term of Phong's equation */ + /* ====================================== */ + + if (type == POINT_LIGHT) + gimp_vector3_sub (&L, light, pos); + else + L = *light; + + dist = gimp_vector3_length (&L); + + if (dist != 0.0) + gimp_vector3_mul (&L, 1.0 / dist); + + NL = 2.0 * gimp_vector3_inner_product (&N, &L); + + if (NL >= 0.0) + { + /* Compute (R*V)^alpha term of Phong's equation */ + /* ============================================ */ + + gimp_vector3_sub (&V, viewpoint, pos); + gimp_vector3_normalize (&V); + + gimp_vector3_mul (&N, NL); + gimp_vector3_sub (&NN, &N, &L); + RV = gimp_vector3_inner_product (&NN, &V); + RV = 0.0 < RV ? pow (RV, mapvals.material.highlight) : 0.0; + + /* Compute diffuse and specular intensity contribution */ + /* =================================================== */ + + diffusecolor = *diff_col; + gimp_rgb_multiply (&diffusecolor, mapvals.material.diffuse_ref); + gimp_rgb_multiply (&diffusecolor, NL); + + specularcolor = *spec_col; + gimp_rgb_multiply (&specularcolor, mapvals.material.specular_ref); + gimp_rgb_multiply (&specularcolor, RV); + + gimp_rgb_add (&diffusecolor, &specularcolor); + gimp_rgb_multiply (&diffusecolor, mapvals.material.diffuse_int); + gimp_rgb_clamp (&diffusecolor); + + gimp_rgb_add (&ambientcolor, &diffusecolor); + } + + return ambientcolor; +} + +static gint +plane_intersect (GimpVector3 *dir, + GimpVector3 *viewp, + GimpVector3 *ipos, + gdouble *u, + gdouble *v) +{ + static gdouble det, det1, det2, det3, t; + + imat[0][0] = dir->x; + imat[1][0] = dir->y; + imat[2][0] = dir->z; + + /* Compute determinant of the first 3x3 sub matrix (denominator) */ + /* ============================================================= */ + + det = (imat[0][0] * imat[1][1] * imat[2][2] + + imat[0][1] * imat[1][2] * imat[2][0] + + imat[0][2] * imat[1][0] * imat[2][1] - + imat[0][2] * imat[1][1] * imat[2][0] - + imat[0][0] * imat[1][2] * imat[2][1] - + imat[2][2] * imat[0][1] * imat[1][0]); + + /* If the determinant is non-zero, a intersection point exists */ + /* =========================================================== */ + + if (det != 0.0) + { + /* Now, lets compute the numerator determinants (wow ;) */ + /* ==================================================== */ + + det1 = (imat[0][3] * imat[1][1] * imat[2][2] + + imat[0][1] * imat[1][2] * imat[2][3] + + imat[0][2] * imat[1][3] * imat[2][1] - + imat[0][2] * imat[1][1] * imat[2][3] - + imat[1][2] * imat[2][1] * imat[0][3] - + imat[2][2] * imat[0][1] * imat[1][3]); + + det2 = (imat[0][0] * imat[1][3] * imat[2][2] + + imat[0][3] * imat[1][2] * imat[2][0] + + imat[0][2] * imat[1][0] * imat[2][3] - + imat[0][2] * imat[1][3] * imat[2][0] - + imat[1][2] * imat[2][3] * imat[0][0] - + imat[2][2] * imat[0][3] * imat[1][0]); + + det3 = (imat[0][0] * imat[1][1] * imat[2][3] + + imat[0][1] * imat[1][3] * imat[2][0] + + imat[0][3] * imat[1][0] * imat[2][1] - + imat[0][3] * imat[1][1] * imat[2][0] - + imat[1][3] * imat[2][1] * imat[0][0] - + imat[2][3] * imat[0][1] * imat[1][0]); + + /* Now we have the simultaneous solutions. Lets compute the unknowns */ + /* (skip u&v if t is <0, this means the intersection is behind us) */ + /* ================================================================ */ + + t = det1 / det; + + if (t > 0.0) + { + *u = 1.0 + ((det2 / det) - 0.5); + *v = 1.0 + ((det3 / det) - 0.5); + + ipos->x = viewp->x + t * dir->x; + ipos->y = viewp->y + t * dir->y; + ipos->z = viewp->z + t * dir->z; + + return TRUE; + } + } + + return FALSE; +} + +/***************************************************************************** + * These routines computes the color of the surface + * of the plane at a given point + *****************************************************************************/ + +GimpRGB +get_ray_color_plane (GimpVector3 *pos) +{ + GimpRGB color = background; + + static gint inside = FALSE; + static GimpVector3 ray, spos; + static gdouble vx, vy; + + /* Construct a line from our VP to the point */ + /* ========================================= */ + + gimp_vector3_sub (&ray, pos, &mapvals.viewpoint); + gimp_vector3_normalize (&ray); + + /* Check for intersection. This is a quasi ray-tracer. */ + /* =================================================== */ + + if (plane_intersect (&ray, &mapvals.viewpoint, &spos, &vx, &vy) == TRUE) + { + color = get_image_color (vx, vy, &inside); + + if (color.a != 0.0 && inside == TRUE && + mapvals.lightsource.type != NO_LIGHT) + { + /* Compute shading at this point */ + /* ============================= */ + + color = phong_shade (&spos, + &mapvals.viewpoint, + &mapvals.normal, + &color, + &mapvals.lightsource.color, + mapvals.lightsource.type); + + gimp_rgb_clamp (&color); + } + } + + if (mapvals.transparent_background == FALSE && color.a < 1.0) + { + gimp_rgb_composite (&color, &background, + GIMP_RGB_COMPOSITE_BEHIND); + } + + return color; +} + +/***********************************************************************/ +/* Given the NorthPole, Equator and a third vector (normal) compute */ +/* the conversion from spherical oordinates to image space coordinates */ +/***********************************************************************/ + +static void +sphere_to_image (GimpVector3 *normal, + gdouble *u, + gdouble *v) +{ + static gdouble alpha, fac; + static GimpVector3 cross_prod; + + alpha = acos (-gimp_vector3_inner_product (&mapvals.secondaxis, normal)); + + *v = alpha / G_PI; + + if (*v == 0.0 || *v == 1.0) + { + *u = 0.0; + } + else + { + fac = (gimp_vector3_inner_product (&mapvals.firstaxis, normal) / + sin (alpha)); + + /* Make sure that we map to -1.0..1.0 (take care of rounding errors) */ + /* ================================================================= */ + + fac = CLAMP (fac, -1.0, 1.0); + + *u = acos (fac) / (2.0 * G_PI); + + cross_prod = gimp_vector3_cross_product (&mapvals.secondaxis, + &mapvals.firstaxis); + + if (gimp_vector3_inner_product (&cross_prod, normal) < 0.0) + *u = 1.0 - *u; + } +} + +/***************************************************/ +/* Compute intersection point with sphere (if any) */ +/***************************************************/ + +static gint +sphere_intersect (GimpVector3 *dir, + GimpVector3 *viewp, + GimpVector3 *spos1, + GimpVector3 *spos2) +{ + static gdouble alpha, beta, tau, s1, s2, tmp; + static GimpVector3 t; + + gimp_vector3_sub (&t, &mapvals.position, viewp); + + alpha = gimp_vector3_inner_product (dir, &t); + beta = gimp_vector3_inner_product (&t, &t); + + tau = alpha * alpha - beta + mapvals.radius * mapvals.radius; + + if (tau >= 0.0) + { + tau = sqrt (tau); + s1 = alpha + tau; + s2 = alpha - tau; + + if (s2 < s1) + { + tmp = s1; + s1 = s2; + s2 = tmp; + } + + spos1->x = viewp->x + s1 * dir->x; + spos1->y = viewp->y + s1 * dir->y; + spos1->z = viewp->z + s1 * dir->z; + spos2->x = viewp->x + s2 * dir->x; + spos2->y = viewp->y + s2 * dir->y; + spos2->z = viewp->z + s2 * dir->z; + + return TRUE; + } + + return FALSE; +} + +/***************************************************************************** + * These routines computes the color of the surface + * of the sphere at a given point + *****************************************************************************/ + +GimpRGB +get_ray_color_sphere (GimpVector3 *pos) +{ + GimpRGB color = background; + + static GimpRGB color2; + static gint inside = FALSE; + static GimpVector3 normal, ray, spos1, spos2; + static gdouble vx, vy; + + /* Check if ray is within the bounding box */ + /* ======================================= */ + + if (pos->x<bx1 || pos->x>bx2 || pos->y<by1 || pos->y>by2) + return color; + + /* Construct a line from our VP to the point */ + /* ========================================= */ + + gimp_vector3_sub (&ray, pos, &mapvals.viewpoint); + gimp_vector3_normalize (&ray); + + /* Check for intersection. This is a quasi ray-tracer. */ + /* =================================================== */ + + if (sphere_intersect (&ray, &mapvals.viewpoint, &spos1, &spos2) == TRUE) + { + /* Compute spherical to rectangular mapping */ + /* ======================================== */ + + gimp_vector3_sub (&normal, &spos1, &mapvals.position); + gimp_vector3_normalize (&normal); + sphere_to_image (&normal, &vx, &vy); + color = get_image_color (vx, vy, &inside); + + /* Check for total transparency... */ + /* =============================== */ + + if (color.a < 1.0) + { + /* Hey, we can see through here! */ + /* Lets see what's on the other side.. */ + /* =================================== */ + + color = phong_shade (&spos1, + &mapvals.viewpoint, + &normal, + &color, + &mapvals.lightsource.color, + mapvals.lightsource.type); + + gimp_rgb_clamp (&color); + + gimp_vector3_sub (&normal, &spos2, &mapvals.position); + gimp_vector3_normalize (&normal); + sphere_to_image (&normal, &vx, &vy); + color2 = get_image_color (vx, vy, &inside); + + /* Make the normal point inwards */ + /* ============================= */ + + gimp_vector3_mul (&normal, -1.0); + + color2 = phong_shade (&spos2, + &mapvals.viewpoint, + &normal, + &color2, + &mapvals.lightsource.color, + mapvals.lightsource.type); + + gimp_rgb_clamp (&color2); + + /* Compute a mix of the first and second colors */ + /* ============================================ */ + + gimp_rgb_composite (&color, &color2, GIMP_RGB_COMPOSITE_NORMAL); + gimp_rgb_clamp (&color); + } + else if (color.a != 0.0 && + inside == TRUE && + mapvals.lightsource.type != NO_LIGHT) + { + /* Compute shading at this point */ + /* ============================= */ + + color = phong_shade (&spos1, + &mapvals.viewpoint, + &normal, + &color, + &mapvals.lightsource.color, + mapvals.lightsource.type); + + gimp_rgb_clamp (&color); + } + } + + if (mapvals.transparent_background == FALSE && color.a < 1.0) + { + gimp_rgb_composite (&color, &background, + GIMP_RGB_COMPOSITE_BEHIND); + } + + return color; +} + +/***************************************************/ +/* Transform the corners of the bounding box to 2D */ +/***************************************************/ + +void +compute_bounding_box (void) +{ + GimpVector3 p1, p2; + gdouble t; + GimpVector3 dir; + + p1 = mapvals.position; + p1.x -= (mapvals.radius + 0.01); + p1.y -= (mapvals.radius + 0.01); + + p2 = mapvals.position; + p2.x += (mapvals.radius + 0.01); + p2.y += (mapvals.radius + 0.01); + + gimp_vector3_sub (&dir, &p1, &mapvals.viewpoint); + gimp_vector3_normalize (&dir); + + if (dir.z != 0.0) + { + t = (-1.0 * mapvals.viewpoint.z) / dir.z; + p1.x = (mapvals.viewpoint.x + t * dir.x); + p1.y = (mapvals.viewpoint.y + t * dir.y); + } + + gimp_vector3_sub (&dir, &p2, &mapvals.viewpoint); + gimp_vector3_normalize (&dir); + + if (dir.z != 0.0) + { + t = (-1.0 * mapvals.viewpoint.z) / dir.z; + p2.x = (mapvals.viewpoint.x + t * dir.x); + p2.y = (mapvals.viewpoint.y + t * dir.y); + } + + bx1 = p1.x; + by1 = p1.y; + bx2 = p2.x; + by2 = p2.y; +} + +/* These two were taken from the Mesa source. Mesa is written */ +/* and is (C) by Brian Paul. vecmulmat() performs a post-mul by */ +/* a 4x4 matrix to a 1x4(3) vector. rotmat() creates a matrix */ +/* that by post-mul will rotate a 1x4(3) vector the given angle */ +/* about the given axis. */ +/* ============================================================ */ + +void +vecmulmat (GimpVector3 *u, + GimpVector3 *v, + gfloat m[16]) +{ + gfloat v0=v->x, v1=v->y, v2=v->z; +#define M(row,col) m[col*4+row] + u->x = v0 * M(0,0) + v1 * M(1,0) + v2 * M(2,0) + M(3,0); + u->y = v0 * M(0,1) + v1 * M(1,1) + v2 * M(2,1) + M(3,1); + u->z = v0 * M(0,2) + v1 * M(1,2) + v2 * M(2,2) + M(3,2); +#undef M +} + +void +rotatemat (gfloat angle, + GimpVector3 *v, + gfloat m[16]) +{ + /* This function contributed by Erich Boleyn (erich@uruk.org) */ + gfloat mag, s, c; + gfloat xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c; + gfloat IdentityMat[16]; + gint cnt; + + s = sin (angle * (G_PI / 180.0)); + c = cos (angle * (G_PI / 180.0)); + + mag = sqrt (v->x*v->x + v->y*v->y + v->z*v->z); + + if (mag == 0.0) + { + /* generate an identity matrix and return */ + + for (cnt = 0; cnt < 16; cnt++) + IdentityMat[cnt] = 0.0; + + IdentityMat[0] = 1.0; + IdentityMat[5] = 1.0; + IdentityMat[10] = 1.0; + IdentityMat[15] = 1.0; + + memcpy (m, IdentityMat, sizeof (gfloat) * 16); + return; + } + + v->x /= mag; + v->y /= mag; + v->z /= mag; + +#define M(row,col) m[col*4+row] + + xx = v->x * v->x; + yy = v->y * v->y; + zz = v->z * v->z; + xy = v->x * v->y; + yz = v->y * v->z; + zx = v->z * v->x; + xs = v->x * s; + ys = v->y * s; + zs = v->z * s; + one_c = 1.0F - c; + + M(0,0) = (one_c * xx) + c; + M(0,1) = (one_c * xy) - zs; + M(0,2) = (one_c * zx) + ys; + M(0,3) = 0.0F; + + M(1,0) = (one_c * xy) + zs; + M(1,1) = (one_c * yy) + c; + M(1,2) = (one_c * yz) - xs; + M(1,3) = 0.0F; + + M(2,0) = (one_c * zx) - ys; + M(2,1) = (one_c * yz) + xs; + M(2,2) = (one_c * zz) + c; + M(2,3) = 0.0F; + + M(3,0) = 0.0F; + M(3,1) = 0.0F; + M(3,2) = 0.0F; + M(3,3) = 1.0F; + +#undef M +} + +/* Transpose the matrix m. If m is orthogonal (like a rotation matrix), */ +/* this is equal to the inverse of the matrix. */ +/* ==================================================================== */ + +void +transpose_mat (gfloat m[16]) +{ + gint i, j; + gfloat t; + + for (i = 0; i < 4; i++) + { + for (j = 0; j < i; j++) + { + t = m[j*4+i]; + m[j*4+i] = m[i*4+j]; + m[i*4+j] = t; + } + } +} + +/* Compute the matrix product c=a*b */ +/* ================================ */ + +void +matmul (gfloat a[16], + gfloat b[16], + gfloat c[16]) +{ + gint i, j, k; + gfloat value; + +#define A(row,col) a[col*4+row] +#define B(row,col) b[col*4+row] +#define C(row,col) c[col*4+row] + + for (i = 0; i < 4; i++) + { + for (j = 0; j < 4; j++) + { + value = 0.0; + + for (k = 0; k < 4; k++) + value += A(i,k) * B(k,j); + + C(i,j) = value; + } + } + +#undef A +#undef B +#undef C +} + +void +ident_mat (gfloat m[16]) +{ + gint i, j; + +#define M(row,col) m[col*4+row] + + for (i = 0; i < 4; i++) + { + for (j = 0; j < 4; j++) + { + if (i == j) + M(i,j) = 1.0; + else + M(i,j) = 0.0; + } + } + +#undef M +} + +static gboolean +intersect_rect (gdouble u, + gdouble v, + gdouble w, + GimpVector3 viewp, + GimpVector3 dir, + FaceIntersectInfo *face_info) +{ + gboolean result = FALSE; + gdouble u2, v2; + + if (dir.z!=0.0) + { + u2 = u / 2.0; + v2 = v / 2.0; + + face_info->t = (w-viewp.z) / dir.z; + face_info->s.x = viewp.x + face_info->t * dir.x; + face_info->s.y = viewp.y + face_info->t * dir.y; + face_info->s.z = w; + + if (face_info->s.x >= -u2 && face_info->s.x <= u2 && + face_info->s.y >= -v2 && face_info->s.y <= v2) + { + face_info->u = (face_info->s.x + u2) / u; + face_info->v = (face_info->s.y + v2) / v; + result = TRUE; + } + } + + return result; +} + +static gboolean +intersect_box (GimpVector3 scale, + GimpVector3 viewp, + GimpVector3 dir, + FaceIntersectInfo *face_intersect) +{ + GimpVector3 v, d, tmp, axis[3]; + FaceIntersectInfo face_tmp; + gboolean result = FALSE; + gfloat m[16]; + gint i = 0; + + gimp_vector3_set (&axis[0], 1.0, 0.0, 0.0); + gimp_vector3_set (&axis[1], 0.0, 1.0, 0.0); + gimp_vector3_set (&axis[2], 0.0, 0.0, 1.0); + + /* Front side */ + /* ========== */ + + if (intersect_rect (scale.x, scale.y, scale.z / 2.0, + viewp, dir, &face_intersect[i]) == TRUE) + { + face_intersect[i].face = 0; + gimp_vector3_set (&face_intersect[i++].n, 0.0, 0.0, 1.0); + result = TRUE; + } + + /* Back side */ + /* ========= */ + + if (intersect_rect (scale.x, scale.y, -scale.z / 2.0, + viewp, dir, &face_intersect[i]) == TRUE) + { + face_intersect[i].face = 1; + face_intersect[i].u = 1.0 - face_intersect[i].u; + gimp_vector3_set (&face_intersect[i++].n, 0.0, 0.0, -1.0); + result = TRUE; + } + + /* Check if we've found the two possible intersection points */ + /* ========================================================= */ + + if (i < 2) + { + /* Top: Rotate viewpoint and direction into rectangle's local coordinate system */ + /* ============================================================================ */ + + rotatemat (90, &axis[0], m); + vecmulmat (&v, &viewp, m); + vecmulmat (&d, &dir, m); + + if (intersect_rect (scale.x, scale.z, scale.y / 2.0, + v, d, &face_intersect[i]) == TRUE) + { + face_intersect[i].face = 2; + + transpose_mat (m); + vecmulmat(&tmp, &face_intersect[i].s, m); + face_intersect[i].s = tmp; + + gimp_vector3_set (&face_intersect[i++].n, 0.0, -1.0, 0.0); + result = TRUE; + } + } + + /* Check if we've found the two possible intersection points */ + /* ========================================================= */ + + if (i < 2) + { + /* Bottom: Rotate viewpoint and direction into rectangle's local coordinate system */ + /* =============================================================================== */ + + rotatemat (90, &axis[0], m); + vecmulmat (&v, &viewp, m); + vecmulmat (&d, &dir, m); + + if (intersect_rect (scale.x, scale.z, -scale.y / 2.0, + v, d, &face_intersect[i]) == TRUE) + { + face_intersect[i].face = 3; + + transpose_mat (m); + + vecmulmat (&tmp, &face_intersect[i].s, m); + face_intersect[i].s = tmp; + + face_intersect[i].v = 1.0 - face_intersect[i].v; + + gimp_vector3_set (&face_intersect[i++].n, 0.0, 1.0, 0.0); + + result = TRUE; + } + } + + /* Check if we've found the two possible intersection points */ + /* ========================================================= */ + + if (i < 2) + { + /* Left side: Rotate viewpoint and direction into rectangle's local coordinate system */ + /* ================================================================================== */ + + rotatemat (90, &axis[1], m); + vecmulmat (&v, &viewp, m); + vecmulmat (&d, &dir, m); + + if (intersect_rect (scale.z, scale.y, scale.x / 2.0, + v, d, &face_intersect[i]) == TRUE) + { + face_intersect[i].face = 4; + + transpose_mat (m); + vecmulmat (&tmp, &face_intersect[i].s, m); + face_intersect[i].s = tmp; + + gimp_vector3_set (&face_intersect[i++].n, 1.0, 0.0, 0.0); + result = TRUE; + } + } + + /* Check if we've found the two possible intersection points */ + /* ========================================================= */ + + if (i < 2) + { + /* Right side: Rotate viewpoint and direction into rectangle's local coordinate system */ + /* =================================================================================== */ + + rotatemat (90, &axis[1], m); + vecmulmat (&v, &viewp, m); + vecmulmat (&d, &dir, m); + + if (intersect_rect (scale.z, scale.y, -scale.x / 2.0, + v, d, &face_intersect[i]) == TRUE) + { + face_intersect[i].face = 5; + + transpose_mat (m); + vecmulmat (&tmp, &face_intersect[i].s, m); + + face_intersect[i].u = 1.0 - face_intersect[i].u; + + gimp_vector3_set (&face_intersect[i++].n, -1.0, 0.0, 0.0); + result = TRUE; + } + } + + /* Sort intersection points */ + /* ======================== */ + + if (face_intersect[0].t > face_intersect[1].t) + { + face_tmp = face_intersect[0]; + face_intersect[0] = face_intersect[1]; + face_intersect[1] = face_tmp; + } + + return result; +} + +GimpRGB +get_ray_color_box (GimpVector3 *pos) +{ + GimpVector3 lvp, ldir, vp, p, dir, ns, nn; + GimpRGB color, color2; + gfloat m[16]; + gint i; + FaceIntersectInfo face_intersect[2]; + + color = background; + vp = mapvals.viewpoint; + p = *pos; + + /* Translate viewpoint so that the box has its origin */ + /* at its lower left corner. */ + /* ================================================== */ + + vp.x = vp.x - mapvals.position.x; + vp.y = vp.y - mapvals.position.y; + vp.z = vp.z - mapvals.position.z; + + p.x = p.x - mapvals.position.x; + p.y = p.y - mapvals.position.y; + p.z = p.z - mapvals.position.z; + + /* Compute direction */ + /* ================= */ + + gimp_vector3_sub (&dir, &p, &vp); + gimp_vector3_normalize (&dir); + + /* Compute inverse of rotation matrix and apply it to */ + /* the viewpoint and direction. This transforms the */ + /* observer into the local coordinate system of the box */ + /* ==================================================== */ + + memcpy (m, rotmat, sizeof (gfloat) * 16); + + transpose_mat (m); + + vecmulmat (&lvp, &vp, m); + vecmulmat (&ldir, &dir, m); + + /* Ok. Now the observer is in the space where the box is located */ + /* with its lower left corner at the origin and its axis aligned */ + /* to the cartesian basis. Check if the transformed ray hits it. */ + /* ============================================================= */ + + face_intersect[0].t = 1000000.0; + face_intersect[1].t = 1000000.0; + + if (intersect_box (mapvals.scale, lvp, ldir, face_intersect) == TRUE) + { + /* We've hit the box. Transform the hit points and */ + /* normals back into the world coordinate system */ + /* =============================================== */ + + for (i = 0; i < 2; i++) + { + vecmulmat (&ns, &face_intersect[i].s, rotmat); + vecmulmat (&nn, &face_intersect[i].n, rotmat); + + ns.x = ns.x + mapvals.position.x; + ns.y = ns.y + mapvals.position.y; + ns.z = ns.z + mapvals.position.z; + + face_intersect[i].s = ns; + face_intersect[i].n = nn; + } + + color = get_box_image_color (face_intersect[0].face, + face_intersect[0].u, + face_intersect[0].v); + + /* Check for total transparency... */ + /* =============================== */ + + if (color.a < 1.0) + { + /* Hey, we can see through here! */ + /* Lets see what's on the other side.. */ + /* =================================== */ + + color = phong_shade (&face_intersect[0].s, + &mapvals.viewpoint, + &face_intersect[0].n, + &color, + &mapvals.lightsource.color, + mapvals.lightsource.type); + + gimp_rgb_clamp (&color); + + color2 = get_box_image_color (face_intersect[1].face, + face_intersect[1].u, + face_intersect[1].v); + + /* Make the normal point inwards */ + /* ============================= */ + + gimp_vector3_mul (&face_intersect[1].n, -1.0); + + color2 = phong_shade (&face_intersect[1].s, + &mapvals.viewpoint, + &face_intersect[1].n, + &color2, + &mapvals.lightsource.color, + mapvals.lightsource.type); + + gimp_rgb_clamp (&color2); + + if (mapvals.transparent_background == FALSE && color2.a < 1.0) + { + gimp_rgb_composite (&color2, &background, + GIMP_RGB_COMPOSITE_BEHIND); + } + + /* Compute a mix of the first and second colors */ + /* ============================================ */ + + gimp_rgb_composite (&color, &color2, GIMP_RGB_COMPOSITE_NORMAL); + gimp_rgb_clamp (&color); + } + else if (color.a != 0.0 && mapvals.lightsource.type != NO_LIGHT) + { + color = phong_shade (&face_intersect[0].s, + &mapvals.viewpoint, + &face_intersect[0].n, + &color, + &mapvals.lightsource.color, + mapvals.lightsource.type); + + gimp_rgb_clamp (&color); + } + } + else + { + if (mapvals.transparent_background == TRUE) + gimp_rgb_set_alpha (&color, 0.0); + } + + return color; +} + +static gboolean +intersect_circle (GimpVector3 vp, + GimpVector3 dir, + gdouble w, + FaceIntersectInfo *face_info) +{ + gboolean result = FALSE; + gdouble r, d; + +#define sqr(a) (a*a) + + if (dir.y != 0.0) + { + face_info->t = (w-vp.y)/dir.y; + face_info->s.x = vp.x + face_info->t*dir.x; + face_info->s.y = w; + face_info->s.z = vp.z + face_info->t*dir.z; + + r = sqrt (sqr (face_info->s.x) + sqr (face_info->s.z)); + + if (r <= mapvals.cylinder_radius) + { + d = 2.0 * mapvals.cylinder_radius; + face_info->u = (face_info->s.x + mapvals.cylinder_radius) / d; + face_info->v = (face_info->s.z + mapvals.cylinder_radius) / d; + result = TRUE; + } + } + +#undef sqr + + return result; +} + +static gboolean +intersect_cylinder (GimpVector3 vp, + GimpVector3 dir, + FaceIntersectInfo *face_intersect) +{ + gdouble a, b, c, d, e, f, tmp, l; + gboolean result = FALSE; + gint i; + +#define sqr(a) (a*a) + + a = sqr (dir.x) + sqr (dir.z); + b = 2.0 * (vp.x * dir.x + vp.z * dir.z); + c = sqr (vp.x) + sqr (vp.z) - sqr (mapvals.cylinder_radius); + + d = sqr (b) - 4.0 * a * c; + + if (d >= 0.0) + { + e = sqrt (d); + f = 2.0 * a; + + if (f != 0.0) + { + result = TRUE; + + face_intersect[0].t = (-b+e)/f; + face_intersect[1].t = (-b-e)/f; + + if (face_intersect[0].t>face_intersect[1].t) + { + tmp = face_intersect[0].t; + face_intersect[0].t = face_intersect[1].t; + face_intersect[1].t = tmp; + } + + for (i = 0; i < 2; i++) + { + face_intersect[i].s.x = vp.x + face_intersect[i].t * dir.x; + face_intersect[i].s.y = vp.y + face_intersect[i].t * dir.y; + face_intersect[i].s.z = vp.z + face_intersect[i].t * dir.z; + + face_intersect[i].n = face_intersect[i].s; + face_intersect[i].n.y = 0.0; + gimp_vector3_normalize(&face_intersect[i].n); + + l = mapvals.cylinder_length/2.0; + + face_intersect[i].u = (atan2(face_intersect[i].s.x,face_intersect[i].s.z)+G_PI)/(2.0*G_PI); + face_intersect[i].v = (face_intersect[i].s.y+l)/mapvals.cylinder_length; + + /* Mark hitpoint as on the cylinder hull */ + /* ===================================== */ + + face_intersect[i].face = 0; + + /* Check if we're completely off the cylinder axis */ + /* =============================================== */ + + if (face_intersect[i].s.y>l || face_intersect[i].s.y<-l) + { + /* Check if we've hit a cap */ + /* ======================== */ + + if (face_intersect[i].s.y>l) + { + if (intersect_circle(vp,dir,l,&face_intersect[i])==FALSE) + result = FALSE; + else + { + face_intersect[i].face = 2; + face_intersect[i].v = 1 - face_intersect[i].v; + gimp_vector3_set(&face_intersect[i].n, 0.0, 1.0, 0.0); + } + } + else + { + if (intersect_circle(vp,dir,-l,&face_intersect[i])==FALSE) + result = FALSE; + else + { + face_intersect[i].face = 1; + gimp_vector3_set(&face_intersect[i].n, 0.0, -1.0, 0.0); + } + } + } + } + } + } + +#undef sqr + + return result; +} + +static GimpRGB +get_cylinder_color (gint face, + gdouble u, + gdouble v) +{ + GimpRGB color; + gint inside; + + if (face == 0) + color = get_image_color (u, v, &inside); + else + color = get_cylinder_image_color (face - 1, u, v); + + return color; +} + +GimpRGB +get_ray_color_cylinder (GimpVector3 *pos) +{ + GimpVector3 lvp, ldir, vp, p, dir, ns, nn; + GimpRGB color, color2; + gfloat m[16]; + gint i; + FaceIntersectInfo face_intersect[2]; + + color = background; + vp = mapvals.viewpoint; + p = *pos; + + vp.x = vp.x - mapvals.position.x; + vp.y = vp.y - mapvals.position.y; + vp.z = vp.z - mapvals.position.z; + + p.x = p.x - mapvals.position.x; + p.y = p.y - mapvals.position.y; + p.z = p.z - mapvals.position.z; + + /* Compute direction */ + /* ================= */ + + gimp_vector3_sub (&dir, &p, &vp); + gimp_vector3_normalize (&dir); + + /* Compute inverse of rotation matrix and apply it to */ + /* the viewpoint and direction. This transforms the */ + /* observer into the local coordinate system of the box */ + /* ==================================================== */ + + memcpy (m, rotmat, sizeof (gfloat) * 16); + + transpose_mat (m); + + vecmulmat (&lvp, &vp, m); + vecmulmat (&ldir, &dir, m); + + if (intersect_cylinder (lvp, ldir, face_intersect) == TRUE) + { + /* We've hit the cylinder. Transform the hit points and */ + /* normals back into the world coordinate system */ + /* ==================================================== */ + + for (i = 0; i < 2; i++) + { + vecmulmat (&ns, &face_intersect[i].s, rotmat); + vecmulmat (&nn, &face_intersect[i].n, rotmat); + + ns.x = ns.x + mapvals.position.x; + ns.y = ns.y + mapvals.position.y; + ns.z = ns.z + mapvals.position.z; + + face_intersect[i].s = ns; + face_intersect[i].n = nn; + } + + color = get_cylinder_color (face_intersect[0].face, + face_intersect[0].u, + face_intersect[0].v); + + /* Check for transparency... */ + /* ========================= */ + + if (color.a < 1.0) + { + /* Hey, we can see through here! */ + /* Lets see what's on the other side.. */ + /* =================================== */ + + color = phong_shade (&face_intersect[0].s, + &mapvals.viewpoint, + &face_intersect[0].n, + &color, + &mapvals.lightsource.color, + mapvals.lightsource.type); + + gimp_rgb_clamp (&color); + + color2 = get_cylinder_color (face_intersect[1].face, + face_intersect[1].u, + face_intersect[1].v); + + /* Make the normal point inwards */ + /* ============================= */ + + gimp_vector3_mul (&face_intersect[1].n, -1.0); + + color2 = phong_shade (&face_intersect[1].s, + &mapvals.viewpoint, + &face_intersect[1].n, + &color2, + &mapvals.lightsource.color, + mapvals.lightsource.type); + + gimp_rgb_clamp (&color2); + + if (mapvals.transparent_background == FALSE && color2.a < 1.0) + { + gimp_rgb_composite (&color2, &background, + GIMP_RGB_COMPOSITE_BEHIND); + } + + /* Compute a mix of the first and second colors */ + /* ============================================ */ + + gimp_rgb_composite (&color, &color2, GIMP_RGB_COMPOSITE_NORMAL); + gimp_rgb_clamp (&color); + } + else if (color.a != 0.0 && mapvals.lightsource.type != NO_LIGHT) + { + color = phong_shade (&face_intersect[0].s, + &mapvals.viewpoint, + &face_intersect[0].n, + &color, + &mapvals.lightsource.color, + mapvals.lightsource.type); + + gimp_rgb_clamp (&color); + } + } + else + { + if (mapvals.transparent_background == TRUE) + gimp_rgb_set_alpha (&color, 0.0); + } + + return color; +} diff --git a/plug-ins/map-object/map-object-shade.h b/plug-ins/map-object/map-object-shade.h new file mode 100644 index 0000000..259e5eb --- /dev/null +++ b/plug-ins/map-object/map-object-shade.h @@ -0,0 +1,26 @@ +#ifndef __MAPOBJECT_SHADE_H__ +#define __MAPOBJECT_SHADE_H__ + +typedef GimpRGB (* get_ray_color_func) (GimpVector3 *pos); + +extern get_ray_color_func get_ray_color; + +GimpRGB get_ray_color_plane (GimpVector3 *pos); +GimpRGB get_ray_color_sphere (GimpVector3 *pos); +GimpRGB get_ray_color_box (GimpVector3 *pos); +GimpRGB get_ray_color_cylinder (GimpVector3 *pos); +void compute_bounding_box (void); + +void vecmulmat (GimpVector3 *u, + GimpVector3 *v, + gfloat m[16]); +void rotatemat (gfloat angle, + GimpVector3 *v, + gfloat m[16]); +void transpose_mat (gfloat m[16]); +void matmul (gfloat a[16], + gfloat b[16], + gfloat c[16]); +void ident_mat (gfloat m[16]); + +#endif /* __MAPOBJECT_SHADE_H__ */ diff --git a/plug-ins/map-object/map-object-stock.c b/plug-ins/map-object/map-object-stock.c new file mode 100644 index 0000000..fc3c153 --- /dev/null +++ b/plug-ins/map-object/map-object-stock.c @@ -0,0 +1,110 @@ +/* + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * 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 3 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, see <https://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <gtk/gtk.h> + +#include "map-object-stock.h" + +#include "../lighting/images/stock-pixbufs.h" + + +static GtkIconFactory *mapobject_icon_factory = NULL; + +static GtkStockItem mapobject_stock_items[] = +{ + { STOCK_INTENSITY_AMBIENT_LOW, NULL, 0, 0, NULL }, + { STOCK_INTENSITY_AMBIENT_HIGH, NULL, 0, 0, NULL }, + { STOCK_INTENSITY_DIFFUSE_LOW, NULL, 0, 0, NULL }, + { STOCK_INTENSITY_DIFFUSE_HIGH, NULL, 0, 0, NULL }, + { STOCK_REFLECTIVITY_DIFFUSE_LOW, NULL, 0, 0, NULL }, + { STOCK_REFLECTIVITY_DIFFUSE_HIGH, NULL, 0, 0, NULL }, + { STOCK_REFLECTIVITY_SPECULAR_LOW, NULL, 0, 0, NULL }, + { STOCK_REFLECTIVITY_SPECULAR_HIGH, NULL, 0, 0, NULL }, + { STOCK_REFLECTIVITY_HIGHLIGHT_LOW, NULL, 0, 0, NULL }, + { STOCK_REFLECTIVITY_HIGHLIGHT_HIGH, NULL, 0, 0, NULL } +}; + + +static void +add_stock_icon (const gchar *stock_id, + GtkIconSize size, + const guint8 *inline_data) +{ + GtkIconSource *source; + GtkIconSet *set; + GdkPixbuf *pixbuf; + + source = gtk_icon_source_new (); + + gtk_icon_source_set_size (source, size); + gtk_icon_source_set_size_wildcarded (source, FALSE); + + pixbuf = gdk_pixbuf_new_from_inline (-1, inline_data, FALSE, NULL); + + gtk_icon_source_set_pixbuf (source, pixbuf); + g_object_unref (pixbuf); + + set = gtk_icon_set_new (); + + gtk_icon_set_add_source (set, source); + gtk_icon_source_free (source); + + gtk_icon_factory_add (mapobject_icon_factory, stock_id, set); + + gtk_icon_set_unref (set); +} + +void +mapobject_stock_init (void) +{ + static gboolean initialized = FALSE; + + if (initialized) + return; + + mapobject_icon_factory = gtk_icon_factory_new (); + + add_stock_icon (STOCK_INTENSITY_AMBIENT_LOW, GTK_ICON_SIZE_BUTTON, + stock_intensity_ambient_low); + add_stock_icon (STOCK_INTENSITY_AMBIENT_HIGH, GTK_ICON_SIZE_BUTTON, + stock_intensity_ambient_high); + add_stock_icon (STOCK_INTENSITY_DIFFUSE_LOW, GTK_ICON_SIZE_BUTTON, + stock_intensity_diffuse_low); + add_stock_icon (STOCK_INTENSITY_DIFFUSE_HIGH, GTK_ICON_SIZE_BUTTON, + stock_intensity_diffuse_high); + add_stock_icon (STOCK_REFLECTIVITY_DIFFUSE_LOW, GTK_ICON_SIZE_BUTTON, + stock_reflectivity_diffuse_low); + add_stock_icon (STOCK_REFLECTIVITY_DIFFUSE_HIGH, GTK_ICON_SIZE_BUTTON, + stock_reflectivity_diffuse_high); + add_stock_icon (STOCK_REFLECTIVITY_SPECULAR_LOW, GTK_ICON_SIZE_BUTTON, + stock_reflectivity_specular_low); + add_stock_icon (STOCK_REFLECTIVITY_SPECULAR_HIGH, GTK_ICON_SIZE_BUTTON, + stock_reflectivity_specular_high); + add_stock_icon (STOCK_REFLECTIVITY_HIGHLIGHT_LOW, GTK_ICON_SIZE_BUTTON, + stock_reflectivity_highlight_low); + add_stock_icon (STOCK_REFLECTIVITY_HIGHLIGHT_HIGH, GTK_ICON_SIZE_BUTTON, + stock_reflectivity_highlight_high); + + gtk_icon_factory_add_default (mapobject_icon_factory); + + gtk_stock_add_static (mapobject_stock_items, + G_N_ELEMENTS (mapobject_stock_items)); + + initialized = TRUE; +} diff --git a/plug-ins/map-object/map-object-stock.h b/plug-ins/map-object/map-object-stock.h new file mode 100644 index 0000000..9226383 --- /dev/null +++ b/plug-ins/map-object/map-object-stock.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 1995 Spencer Kimball and Peter Mattis + * + * 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 3 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, see <https://www.gnu.org/licenses/>. + */ + +#ifndef __MAPOBJECT_STOCK_H__ +#define __MAPOBJECT_STOCK_H__ + + +#define STOCK_INTENSITY_AMBIENT_LOW "intensity-ambient-low" +#define STOCK_INTENSITY_AMBIENT_HIGH "intensity-ambient-high" +#define STOCK_INTENSITY_DIFFUSE_LOW "intensity-diffuse-low" +#define STOCK_INTENSITY_DIFFUSE_HIGH "intensity-diffuse-high" +#define STOCK_REFLECTIVITY_DIFFUSE_LOW "reflectivity-diffuse-low" +#define STOCK_REFLECTIVITY_DIFFUSE_HIGH "reflectivity-diffuse-high" +#define STOCK_REFLECTIVITY_SPECULAR_LOW "reflectivity-specular-low" +#define STOCK_REFLECTIVITY_SPECULAR_HIGH "reflectivity-specular-high" +#define STOCK_REFLECTIVITY_HIGHLIGHT_LOW "reflectivity-highlight-low" +#define STOCK_REFLECTIVITY_HIGHLIGHT_HIGH "reflectivity-highlight-high" + + +void mapobject_stock_init (void); + + +#endif /* __MAPOBJECT_STOCK_H__ */ diff --git a/plug-ins/map-object/map-object-ui.c b/plug-ins/map-object/map-object-ui.c new file mode 100644 index 0000000..7f1d96d --- /dev/null +++ b/plug-ins/map-object/map-object-ui.c @@ -0,0 +1,1462 @@ +/**************************************************************/ +/* Dialog creation and updaters, callbacks and event-handlers */ +/**************************************************************/ + +#include "config.h" + +#include <libgimp/gimp.h> +#include <libgimp/gimpui.h> + +#include "arcball.h" +#include "map-object-ui.h" +#include "map-object-image.h" +#include "map-object-apply.h" +#include "map-object-preview.h" +#include "map-object-main.h" +#include "map-object-stock.h" + +#include "libgimp/stdplugins-intl.h" + + +GtkWidget *previewarea = NULL; + +static GtkWidget *appwin = NULL; +static GtkNotebook *options_note_book = NULL; + +static GtkWidget *pointlightwid; +static GtkWidget *dirlightwid; + +static GtkAdjustment *xadj, *yadj, *zadj; + +static GtkWidget *box_page = NULL; +static GtkWidget *cylinder_page = NULL; + +static guint left_button_pressed = FALSE; +static guint light_hit = FALSE; + + +static void create_main_notebook (GtkWidget *container); + +static gint preview_events (GtkWidget *area, + GdkEvent *event); + +static void update_light_pos_entries (void); + +static void double_adjustment_update (GtkAdjustment *adjustment, + gpointer data); + +static void toggle_update (GtkWidget *widget, + gpointer data); + +static void lightmenu_callback (GtkWidget *widget, + gpointer data); + +static void preview_callback (GtkWidget *widget, + gpointer data); + +static gint box_constrain (gint32 image_id, + gint32 drawable_id, + gpointer data); +static gint cylinder_constrain (gint32 image_id, + gint32 drawable_id, + gpointer data); + +static GtkWidget * create_options_page (void); +static GtkWidget * create_light_page (void); +static GtkWidget * create_material_page (void); +static GtkWidget * create_orientation_page (void); +static GtkWidget * create_box_page (void); +static GtkWidget * create_cylinder_page (void); + + +/******************************************************/ +/* Update angle & position (redraw grid if necessary) */ +/******************************************************/ + +static void +double_adjustment_update (GtkAdjustment *adjustment, + gpointer data) +{ + gimp_double_adjustment_update (adjustment, data); + + if (mapvals.livepreview) + compute_preview_image (); + + gtk_widget_queue_draw (previewarea); +} + +static void +update_light_pos_entries (void) +{ + g_signal_handlers_block_by_func (xadj, + double_adjustment_update, + &mapvals.lightsource.position.x); + gtk_adjustment_set_value (GTK_ADJUSTMENT (xadj), + mapvals.lightsource.position.x); + g_signal_handlers_unblock_by_func (xadj, + double_adjustment_update, + &mapvals.lightsource.position.x); + + g_signal_handlers_block_by_func (yadj, + double_adjustment_update, + &mapvals.lightsource.position.y); + gtk_adjustment_set_value (GTK_ADJUSTMENT (yadj), + mapvals.lightsource.position.y); + g_signal_handlers_unblock_by_func (yadj, + double_adjustment_update, + &mapvals.lightsource.position.y); + + g_signal_handlers_block_by_func (zadj, + double_adjustment_update, + &mapvals.lightsource.position.z); + gtk_adjustment_set_value (GTK_ADJUSTMENT (zadj), + mapvals.lightsource.position.z); + g_signal_handlers_unblock_by_func (zadj, + double_adjustment_update, + &mapvals.lightsource.position.z); +} + +/**********************/ +/* Std. toggle update */ +/**********************/ + +static void +toggle_update (GtkWidget *widget, + gpointer data) +{ + gimp_toggle_button_update (widget, data); + + compute_preview_image (); + gtk_widget_queue_draw (previewarea); +} + +/*****************************************/ +/* Main window light type menu callback. */ +/*****************************************/ + +static void +lightmenu_callback (GtkWidget *widget, + gpointer data) +{ + int active; + + gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), + &active); + + mapvals.lightsource.type = active; + + if (mapvals.lightsource.type == POINT_LIGHT) + { + gtk_widget_hide (dirlightwid); + gtk_widget_show (pointlightwid); + } + else if (mapvals.lightsource.type == DIRECTIONAL_LIGHT) + { + gtk_widget_hide (pointlightwid); + gtk_widget_show (dirlightwid); + } + else + { + gtk_widget_hide (pointlightwid); + gtk_widget_hide (dirlightwid); + } + + if (mapvals.livepreview) + { + compute_preview_image (); + gtk_widget_queue_draw (previewarea); + } +} + +/***************************************/ +/* Main window map type menu callback. */ +/***************************************/ + +static void +mapmenu_callback (GtkWidget *widget, + gpointer data) +{ + int active; + + gimp_int_combo_box_get_active (GIMP_INT_COMBO_BOX (widget), + &active); + + mapvals.maptype = active; + + if (mapvals.livepreview) + { + compute_preview_image (); + gtk_widget_queue_draw (previewarea); + } + + if (mapvals.maptype == MAP_BOX) + { + if (cylinder_page && gtk_widget_get_parent (GTK_WIDGET (cylinder_page)) == + GTK_WIDGET (options_note_book)) + { + gtk_container_remove (GTK_CONTAINER (options_note_book), cylinder_page); + } + + if (!box_page) + { + box_page = create_box_page (); + g_object_ref (box_page); + } + gtk_notebook_append_page (options_note_book, + box_page, + gtk_label_new_with_mnemonic (_("_Box"))); + } + else if (mapvals.maptype == MAP_CYLINDER) + { + if (box_page && gtk_widget_get_parent (GTK_WIDGET (box_page)) == + GTK_WIDGET (options_note_book)) + { + gtk_container_remove (GTK_CONTAINER (options_note_book), box_page); + } + + if (!cylinder_page) + { + cylinder_page = create_cylinder_page (); + g_object_ref (cylinder_page); + } + gtk_notebook_append_page (options_note_book, + cylinder_page, + gtk_label_new_with_mnemonic (_("C_ylinder"))); + } + else + { + if (box_page && gtk_widget_get_parent (GTK_WIDGET (box_page)) == + GTK_WIDGET (options_note_book)) + { + gtk_container_remove (GTK_CONTAINER (options_note_book), box_page); + } + + if (cylinder_page && gtk_widget_get_parent (GTK_WIDGET (cylinder_page)) == + GTK_WIDGET (options_note_book)) + { + gtk_container_remove (GTK_CONTAINER (options_note_book), cylinder_page); + } + } +} + +/******************************************/ +/* Main window "Preview!" button callback */ +/******************************************/ + +static void +preview_callback (GtkWidget *widget, + gpointer data) +{ + compute_preview_image (); + + gtk_widget_queue_draw (previewarea); +} + +static void +zoomed_callback (GimpZoomModel *model) +{ + mapvals.zoom = gimp_zoom_model_get_factor (model); + + compute_preview_image (); + + gtk_widget_queue_draw (previewarea); +} + +/**********************************************/ +/* Main window "Apply" button callback. */ +/* Render to GIMP image, close down and exit. */ +/**********************************************/ + +static gint +box_constrain (gint32 image_id, + gint32 drawable_id, + gpointer data) +{ + if (drawable_id == -1) + return TRUE; + + return (gimp_drawable_is_rgb (drawable_id) && + !gimp_drawable_is_indexed (drawable_id)); +} + +static gint +cylinder_constrain (gint32 image_id, + gint32 drawable_id, + gpointer data) +{ + if (drawable_id == -1) + return TRUE; + + return (gimp_drawable_is_rgb (drawable_id) && + !gimp_drawable_is_indexed (drawable_id)); +} + +/******************************/ +/* Preview area event handler */ +/******************************/ + +static gint +preview_events (GtkWidget *area, + GdkEvent *event) +{ + HVect __attribute__((unused))pos; +/* HMatrix RotMat; + gdouble a,b,c; */ + + switch (event->type) + { + case GDK_ENTER_NOTIFY: + break; + + case GDK_LEAVE_NOTIFY: + break; + + case GDK_BUTTON_PRESS: + light_hit = check_light_hit (event->button.x, event->button.y); + if (light_hit == FALSE) + { + pos.x = -(2.0 * (gdouble) event->button.x / + (gdouble) PREVIEW_WIDTH - 1.0); + pos.y = (2.0 * (gdouble) event->button.y / + (gdouble) PREVIEW_HEIGHT - 1.0); + /*ArcBall_Mouse(pos); + ArcBall_BeginDrag(); */ + } + left_button_pressed = TRUE; + break; + + case GDK_BUTTON_RELEASE: + if (light_hit == TRUE) + { + compute_preview_image (); + + gtk_widget_queue_draw (previewarea); + } + else + { + pos.x = -(2.0 * (gdouble) event->button.x / + (gdouble) PREVIEW_WIDTH - 1.0); + pos.y = (2.0 * (gdouble) event->button.y / + (gdouble) PREVIEW_HEIGHT - 1.0); + /*ArcBall_Mouse(pos); + ArcBall_EndDrag(); */ + } + left_button_pressed = FALSE; + break; + + case GDK_MOTION_NOTIFY: + if (left_button_pressed == TRUE) + { + if (light_hit == TRUE) + { + gint live = mapvals.livepreview; + + mapvals.livepreview = FALSE; + update_light (event->motion.x, event->motion.y); + update_light_pos_entries (); + mapvals.livepreview = live; + } + else + { + pos.x = -(2.0 * (gdouble) event->motion.x / + (gdouble) PREVIEW_WIDTH - 1.0); + pos.y = (2.0 * (gdouble) event->motion.y / + (gdouble) PREVIEW_HEIGHT - 1.0); +/* ArcBall_Mouse(pos); + ArcBall_Update(); + ArcBall_Values(&a,&b,&c); + Alpha+=RadToDeg(-a); + Beta+RadToDeg(-b); + Gamma+=RadToDeg(-c); + if (Alpha>180) Alpha-=360; + if (Alpha<-180) Alpha+=360; + if (Beta>180) Beta-=360; + if (Beta<-180) Beta+=360; + if (Gamma>180) Gamma-=360; + if (Gamma<-180) Gamma+=360; + UpdateAngleSliders(); */ + } + } + break; + + default: + break; + } + + return FALSE; +} + + +static GtkWidget * +spin_button_new (GtkAdjustment **adjustment, /* return value */ + gdouble value, + gdouble lower, + gdouble upper, + gdouble step_increment, + gdouble page_increment, + gdouble page_size, + gdouble climb_rate, + guint digits) +{ + GtkWidget *spinbutton; + + *adjustment = (GtkAdjustment *) + gtk_adjustment_new (value, lower, upper, + step_increment, page_increment, 0); + + spinbutton = gimp_spin_button_new (GTK_ADJUSTMENT (*adjustment), + climb_rate, digits); + + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbutton), TRUE); + + return spinbutton; +} + +/*******************************/ +/* Create general options page */ +/*******************************/ + +static GtkWidget * +create_options_page (void) +{ + GtkWidget *page; + GtkWidget *frame; + GtkWidget *vbox; + GtkWidget *hbox; + GtkWidget *label; + GtkWidget *combo; + GtkWidget *toggle; + GtkWidget *table; + GtkWidget *spinbutton; + GtkAdjustment *adj; + + page = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); + gtk_container_set_border_width (GTK_CONTAINER (page), 12); + + /* General options */ + + frame = gimp_frame_new (_("General Options")); + gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0); + gtk_widget_show (frame); + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); + gtk_container_add (GTK_CONTAINER (frame), vbox); + gtk_widget_show (vbox); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + gtk_widget_show (hbox); + + label = gtk_label_new (_("Map to:")); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); + + combo = gimp_int_combo_box_new (_("Plane"), MAP_PLANE, + _("Sphere"), MAP_SPHERE, + _("Box"), MAP_BOX, + _("Cylinder"), MAP_CYLINDER, + NULL); + gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo), mapvals.maptype); + gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0); + gtk_widget_show (combo); + + g_signal_connect (combo, "changed", + G_CALLBACK (mapmenu_callback), + &mapvals.maptype); + + gimp_help_set_help_data (combo, _("Type of object to map to"), NULL); + + toggle = gtk_check_button_new_with_label (_("Transparent background")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), + mapvals.transparent_background); + gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0); + gtk_widget_show (toggle); + + g_signal_connect (toggle, "toggled", + G_CALLBACK (toggle_update), + &mapvals.transparent_background); + + gimp_help_set_help_data (toggle, + _("Make image transparent outside object"), NULL); + + toggle = gtk_check_button_new_with_label (_("Tile source image")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), + mapvals.tiled); + gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0); + gtk_widget_show (toggle); + + g_signal_connect (toggle, "toggled", + G_CALLBACK (toggle_update), + &mapvals.tiled); + + gimp_help_set_help_data (toggle, + _("Tile source image: useful for infinite planes"), + NULL); + + toggle = gtk_check_button_new_with_label (_("Create new image")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), + mapvals.create_new_image); + gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0); + gtk_widget_show (toggle); + + g_signal_connect (toggle, "toggled", + G_CALLBACK (gimp_toggle_button_update), + &mapvals.create_new_image); + + gimp_help_set_help_data (toggle, + _("Create a new image when applying filter"), NULL); + + toggle = gtk_check_button_new_with_label (_("Create new layer")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), + mapvals.create_new_layer); + gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0); + gtk_widget_show (toggle); + + g_signal_connect (toggle, "toggled", + G_CALLBACK (gimp_toggle_button_update), + &mapvals.create_new_layer); + + gimp_help_set_help_data (toggle, + _("Create a new layer when applying filter"), NULL); + + /* Antialiasing options */ + + frame = gimp_frame_new (NULL); + gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0); + gtk_widget_show (frame); + + toggle = gtk_check_button_new_with_mnemonic (_("Enable _antialiasing")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), + mapvals.antialiasing); + gtk_frame_set_label_widget (GTK_FRAME (frame), toggle); + gtk_widget_show (toggle); + + g_signal_connect (toggle, "toggled", + G_CALLBACK (gimp_toggle_button_update), + &mapvals.antialiasing); + + gimp_help_set_help_data (toggle, + _("Enable/disable jagged edges removal " + "(antialiasing)"), NULL); + + table = gtk_table_new (2, 3, FALSE); + gtk_table_set_col_spacings (GTK_TABLE (table), 6); + gtk_table_set_row_spacings (GTK_TABLE (table), 6); + gtk_container_add (GTK_CONTAINER (frame), table); + gtk_widget_show (table); + + g_object_bind_property (toggle, "active", + table, "sensitive", + G_BINDING_SYNC_CREATE); + + adj = (GtkAdjustment *) + gimp_scale_entry_new (GTK_TABLE (table), 0, 0, + _("_Depth:"), 0, 0, + mapvals.maxdepth, 1.0, 5.0, 0.1, 1.0, + 1, TRUE, 0, 0, + _("Antialiasing quality. Higher is better, " + "but slower"), NULL); + g_signal_connect (adj, "value-changed", + G_CALLBACK (gimp_double_adjustment_update), + &mapvals.maxdepth); + + spinbutton = spin_button_new (&adj, mapvals.pixelthreshold, + 0.001, 1000, 0.1, 1, 0, 0, 3); + gimp_table_attach_aligned (GTK_TABLE (table), 0, 1, + _("_Threshold:"), 0.0, 0.5, + spinbutton, 1, TRUE); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (double_adjustment_update), + &mapvals.pixelthreshold); + + gimp_help_set_help_data (spinbutton, + _("Stop when pixel differences are smaller than " + "this value"), NULL); + + gtk_widget_show (page); + + return page; +} + +/******************************/ +/* Create light settings page */ +/******************************/ + +static GtkWidget * +create_light_page (void) +{ + GtkWidget *page; + GtkWidget *frame; + GtkWidget *table; + GtkWidget *combo; + GtkWidget *colorbutton; + GtkWidget *spinbutton; + GtkAdjustment *adj; + + page = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); + gtk_container_set_border_width (GTK_CONTAINER (page), 12); + + frame = gimp_frame_new (_("Light Settings")); + gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0); + gtk_widget_show (frame); + + table = gtk_table_new (2, 2, FALSE); + gtk_table_set_col_spacings (GTK_TABLE (table), 6); + gtk_table_set_row_spacings (GTK_TABLE (table), 6); + gtk_container_add (GTK_CONTAINER (frame), table); gtk_widget_show (table); + + combo = gimp_int_combo_box_new (_("Point light"), POINT_LIGHT, + _("Directional light"), DIRECTIONAL_LIGHT, + _("No light"), NO_LIGHT, + NULL); + gimp_int_combo_box_set_active (GIMP_INT_COMBO_BOX (combo), + mapvals.lightsource.type); + gimp_table_attach_aligned (GTK_TABLE (table), 0, 0, + _("Lightsource type:"), 0.0, 0.5, + combo, 1, FALSE); + + g_signal_connect (combo, "changed", + G_CALLBACK (lightmenu_callback), + &mapvals.lightsource.type); + + gimp_help_set_help_data (combo, _("Type of light source to apply"), NULL); + + colorbutton = gimp_color_button_new (_("Select lightsource color"), + 64, 16, + &mapvals.lightsource.color, + GIMP_COLOR_AREA_FLAT); + gimp_table_attach_aligned (GTK_TABLE (table), 0, 1, + _("Lightsource color:"), 0.0, 0.5, + colorbutton, 1, FALSE); + + g_signal_connect (colorbutton, "color-changed", + G_CALLBACK (gimp_color_button_get_color), + &mapvals.lightsource.color); + + gimp_help_set_help_data (colorbutton, + _("Set light source color"), NULL); + + pointlightwid = gimp_frame_new (_("Position")); + gtk_box_pack_start (GTK_BOX (page), pointlightwid, FALSE, FALSE, 0); + + if (mapvals.lightsource.type == POINT_LIGHT) + gtk_widget_show (pointlightwid); + + table = gtk_table_new (3, 2, FALSE); + gtk_table_set_col_spacings (GTK_TABLE (table), 6); + gtk_table_set_row_spacings (GTK_TABLE (table), 6); + gtk_container_add (GTK_CONTAINER (pointlightwid), table); + gtk_widget_show (table); + + spinbutton = spin_button_new (&xadj, mapvals.lightsource.position.x, + -G_MAXFLOAT, G_MAXFLOAT, + 0.1, 1.0, 0.0, 0.0, 2); + gimp_table_attach_aligned (GTK_TABLE (table), 0, 0, + _("X:"), 0.0, 0.5, + spinbutton, 1, TRUE); + + g_signal_connect (xadj, "value-changed", + G_CALLBACK (double_adjustment_update), + &mapvals.lightsource.position.x); + + gimp_help_set_help_data (spinbutton, + _("Light source X position in XYZ space"), NULL); + + spinbutton = spin_button_new (&yadj, mapvals.lightsource.position.y, + -G_MAXFLOAT, G_MAXFLOAT, + 0.1, 1.0, 0.0, 0.0, 2); + gimp_table_attach_aligned (GTK_TABLE (table), 0, 1, + _("Y:"), 0.0, 0.5, + spinbutton, 1, TRUE); + + g_signal_connect (yadj, "value-changed", + G_CALLBACK (double_adjustment_update), + &mapvals.lightsource.position.y); + + gimp_help_set_help_data (spinbutton, + _("Light source Y position in XYZ space"), NULL); + + spinbutton = spin_button_new (&zadj, mapvals.lightsource.position.z, + -G_MAXFLOAT, G_MAXFLOAT, + 0.1, 1.0, 0.0, 0.0, 2); + gimp_table_attach_aligned (GTK_TABLE (table), 0, 2, + _("Z:"), 0.0, 0.5, + spinbutton, 1, TRUE); + + g_signal_connect (zadj, "value-changed", + G_CALLBACK (double_adjustment_update), + &mapvals.lightsource.position.z); + + gimp_help_set_help_data (spinbutton, + _("Light source Z position in XYZ space"), NULL); + + + dirlightwid = gimp_frame_new (_("Direction Vector")); + gtk_box_pack_start (GTK_BOX (page), dirlightwid, FALSE, FALSE, 0); + + if (mapvals.lightsource.type == DIRECTIONAL_LIGHT) + gtk_widget_show (dirlightwid); + + table = gtk_table_new (3, 2, FALSE); + gtk_table_set_col_spacings (GTK_TABLE (table), 6); + gtk_table_set_row_spacings (GTK_TABLE (table), 6); + gtk_container_add (GTK_CONTAINER (dirlightwid), table); + gtk_widget_show (table); + + spinbutton = spin_button_new (&adj, mapvals.lightsource.direction.x, + -1.0, 1.0, 0.01, 0.1, 0.0, 0.0, 2); + gimp_table_attach_aligned (GTK_TABLE (table), 0, 0, + _("X:"), 0.0, 0.5, + spinbutton, 1, TRUE); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (double_adjustment_update), + &mapvals.lightsource.direction.x); + + gimp_help_set_help_data (spinbutton, + _("Light source X direction in XYZ space"), NULL); + + spinbutton = spin_button_new (&adj, mapvals.lightsource.direction.y, + -1.0, 1.0, 0.01, 0.1, 0.0, 0.0, 2); + gimp_table_attach_aligned (GTK_TABLE (table), 0, 1, + _("Y:"), 0.0, 0.5, + spinbutton, 1, TRUE); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (double_adjustment_update), + &mapvals.lightsource.direction.y); + + gimp_help_set_help_data (spinbutton, + _("Light source Y direction in XYZ space"), NULL); + + spinbutton = spin_button_new (&adj, mapvals.lightsource.direction.z, + -1.0, 1.0, 0.01, 0.1, 0.0, 0.0, 2); + gimp_table_attach_aligned (GTK_TABLE (table), 0, 2, + _("Z:"), 0.0, 0.5, + spinbutton, 1, TRUE); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (double_adjustment_update), + &mapvals.lightsource.direction.z); + + gimp_help_set_help_data (spinbutton, + _("Light source Z direction in XYZ space"), NULL); + + gtk_widget_show (page); + + return page; +} + +/*********************************/ +/* Create material settings page */ +/*********************************/ + +static GtkWidget * +create_material_page (void) +{ + GtkSizeGroup *group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + GtkWidget *page; + GtkWidget *frame; + GtkWidget *table; + GtkWidget *label; + GtkWidget *hbox; + GtkWidget *spinbutton; + GtkWidget *image; + GtkAdjustment *adj; + + page = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); + gtk_container_set_border_width (GTK_CONTAINER (page), 12); + + frame = gimp_frame_new (_("Intensity Levels")); + gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0); + gtk_widget_show (frame); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); + gtk_container_add (GTK_CONTAINER (frame), hbox); + gtk_widget_show (hbox); + + table = gtk_table_new (2, 4, FALSE); + gtk_table_set_row_spacings (GTK_TABLE (table), 6); + gtk_table_set_col_spacings (GTK_TABLE (table), 6); + gtk_box_pack_start (GTK_BOX (hbox), table, FALSE, FALSE, 0); + gtk_widget_show (table); + + /* Ambient intensity */ + + image = gtk_image_new_from_stock (STOCK_INTENSITY_AMBIENT_LOW, + GTK_ICON_SIZE_BUTTON); + label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 0, + _("Ambient:"), 0.0, 0.5, + image, 1, FALSE); + gtk_size_group_add_widget (group, label); + + spinbutton = spin_button_new (&adj, mapvals.material.ambient_int, + 0, G_MAXFLOAT, 0.1, 1.0, 0.0, 0.0, 2); + gtk_table_attach (GTK_TABLE (table), spinbutton, 2, 3, 0, 1, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (spinbutton); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (double_adjustment_update), + &mapvals.material.ambient_int); + + gimp_help_set_help_data (spinbutton, + _("Amount of original color to show where no " + "direct light falls"), NULL); + + image = gtk_image_new_from_stock (STOCK_INTENSITY_AMBIENT_HIGH, + GTK_ICON_SIZE_BUTTON); + gtk_table_attach (GTK_TABLE (table), image, 3, 4, 0, 1, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (image); + + /* Diffuse intensity */ + + image = gtk_image_new_from_stock (STOCK_INTENSITY_DIFFUSE_LOW, + GTK_ICON_SIZE_BUTTON); + label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 1, + _("Diffuse:"), 0.0, 0.5, + image, 1, FALSE); + gtk_size_group_add_widget (group, label); + + spinbutton = spin_button_new (&adj, mapvals.material.diffuse_int, + 0, G_MAXFLOAT, 0.1, 1.0, 0.0, 0.0, 2); + gtk_table_attach (GTK_TABLE (table), spinbutton, 2, 3, 1, 2, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (spinbutton); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (double_adjustment_update), + &mapvals.material.diffuse_int); + + gimp_help_set_help_data (spinbutton, + _("Intensity of original color when lit by a light " + "source"), NULL); + + image = gtk_image_new_from_stock (STOCK_INTENSITY_DIFFUSE_HIGH, + GTK_ICON_SIZE_BUTTON); + gtk_table_attach (GTK_TABLE (table), image, 3, 4, 1, 2, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (image); + + frame = gimp_frame_new (_("Reflectivity")); + gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0); + gtk_widget_show (frame); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); + gtk_container_add (GTK_CONTAINER (frame), hbox); + gtk_widget_show (hbox); + + table = gtk_table_new (3, 4, FALSE); + gtk_table_set_row_spacings (GTK_TABLE (table), 6); + gtk_table_set_col_spacings (GTK_TABLE (table), 6); + gtk_box_pack_start (GTK_BOX (hbox), table, FALSE, FALSE, 0); + gtk_widget_show (table); + + /* Diffuse reflection */ + + image = gtk_image_new_from_stock (STOCK_REFLECTIVITY_DIFFUSE_LOW, + GTK_ICON_SIZE_BUTTON); + label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 0, + _("Diffuse:"), 0.0, 0.5, + image, 1, FALSE); + gtk_size_group_add_widget (group, label); + + spinbutton = spin_button_new (&adj, mapvals.material.diffuse_ref, + 0, G_MAXFLOAT, 0.1, 1.0, 0.0, 0.0, 2); + gtk_table_attach (GTK_TABLE (table), spinbutton, 2, 3, 0, 1, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (spinbutton); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (double_adjustment_update), + &mapvals.material.diffuse_ref); + + gimp_help_set_help_data (spinbutton, + _("Higher values makes the object reflect more " + "light (appear lighter)"), NULL); + + image = gtk_image_new_from_stock (STOCK_REFLECTIVITY_DIFFUSE_HIGH, + GTK_ICON_SIZE_BUTTON); + gtk_table_attach (GTK_TABLE (table), image, 3, 4, 0, 1, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (image); + + /* Specular reflection */ + + image = gtk_image_new_from_stock (STOCK_REFLECTIVITY_SPECULAR_LOW, + GTK_ICON_SIZE_BUTTON); + label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 1, + _("Specular:"), 0.0, 0.5, + image, 1, FALSE); + gtk_size_group_add_widget (group, label); + + spinbutton = spin_button_new (&adj, mapvals.material.specular_ref, + 0, G_MAXFLOAT, 0.1, 1.0, 0.0, 0.0, 2); + gtk_table_attach (GTK_TABLE (table), spinbutton, 2, 3, 1, 2, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (spinbutton); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (double_adjustment_update), + &mapvals.material.specular_ref); + + gimp_help_set_help_data (spinbutton, + _("Controls how intense the highlights will be"), + NULL); + + image = gtk_image_new_from_stock (STOCK_REFLECTIVITY_SPECULAR_HIGH, + GTK_ICON_SIZE_BUTTON); + gtk_table_attach (GTK_TABLE (table), image, 3, 4, 1, 2, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (image); + + /* Highlight */ + + image = gtk_image_new_from_stock (STOCK_REFLECTIVITY_HIGHLIGHT_LOW, + GTK_ICON_SIZE_BUTTON); + label = gimp_table_attach_aligned (GTK_TABLE (table), 0, 2, + _("Highlight:"), 0.0, 0.5, + image, 1, FALSE); + gtk_size_group_add_widget (group, label); + + spinbutton = spin_button_new (&adj, mapvals.material.highlight, + 0, G_MAXFLOAT, 0.1, 1.0, 0.0, 0.0, 2); + gtk_table_attach (GTK_TABLE (table), spinbutton, 2, 3, 2, 3, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (spinbutton); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (double_adjustment_update), + &mapvals.material.highlight); + + gimp_help_set_help_data (spinbutton, + _("Higher values makes the highlights more focused"), + NULL); + + image = gtk_image_new_from_stock (STOCK_REFLECTIVITY_HIGHLIGHT_HIGH, + GTK_ICON_SIZE_BUTTON); + gtk_table_attach (GTK_TABLE (table), image, 3, 4, 2, 3, + GTK_SHRINK | GTK_FILL, GTK_SHRINK | GTK_FILL, 0, 0); + gtk_widget_show (image); + + gtk_widget_show (page); + + g_object_unref (group); + + return page; +} + +/****************************************/ +/* Create orientation and position page */ +/****************************************/ + +static GtkWidget * +create_orientation_page (void) +{ + GtkSizeGroup *group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + GtkWidget *page; + GtkWidget *frame; + GtkWidget *table; + GtkAdjustment *adj; + + page = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); + gtk_container_set_border_width (GTK_CONTAINER (page), 12); + + frame = gimp_frame_new (_("Position")); + gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0); + gtk_widget_show (frame); + + table = gtk_table_new (3, 3, FALSE); + gtk_table_set_col_spacings (GTK_TABLE (table), 6); + gtk_table_set_row_spacings (GTK_TABLE (table), 6); + gtk_container_add (GTK_CONTAINER (frame), table); + gtk_widget_show (table); + + adj = (GtkAdjustment *) + gimp_scale_entry_new (GTK_TABLE (table), 0, 0, + _("X:"), 0, 0, + mapvals.position.x, -1.0, 2.0, 0.01, 0.1, 5, + TRUE, 0, 0, + _("Object X position in XYZ space"), NULL); + gtk_size_group_add_widget (group, GIMP_SCALE_ENTRY_SPINBUTTON (adj)); + gtk_spin_button_configure (GIMP_SCALE_ENTRY_SPINBUTTON (adj), + GIMP_SCALE_ENTRY_SPINBUTTON_ADJ (adj), 0.01, 5); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (double_adjustment_update), + &mapvals.position.x); + + adj = (GtkAdjustment *) + gimp_scale_entry_new (GTK_TABLE (table), 0, 1, + _("Y:"), 0, 0, + mapvals.position.y, -1.0, 2.0, 0.01, 0.1, 5, + TRUE, 0, 0, + _("Object Y position in XYZ space"), NULL); + gtk_size_group_add_widget (group, GIMP_SCALE_ENTRY_SPINBUTTON (adj)); + gtk_spin_button_configure (GIMP_SCALE_ENTRY_SPINBUTTON (adj), + GIMP_SCALE_ENTRY_SPINBUTTON_ADJ (adj), 0.01, 5); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (double_adjustment_update), + &mapvals.position.y); + + adj = (GtkAdjustment *) + gimp_scale_entry_new (GTK_TABLE (table), 0, 2, + _("Z:"), 0, 0, + mapvals.position.z, -1.0, 2.0, 0.01, 0.1, 5, + TRUE, 0, 0, + _("Object Z position in XYZ space"), NULL); + gtk_size_group_add_widget (group, GIMP_SCALE_ENTRY_SPINBUTTON (adj)); + gtk_spin_button_configure (GIMP_SCALE_ENTRY_SPINBUTTON (adj), + GIMP_SCALE_ENTRY_SPINBUTTON_ADJ (adj), 0.01, 5); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (double_adjustment_update), + &mapvals.position.z); + + frame = gimp_frame_new (_("Rotation")); + gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0); + gtk_widget_show (frame); + + table = gtk_table_new (3, 3, FALSE); + gtk_table_set_col_spacings (GTK_TABLE (table), 6); + gtk_table_set_row_spacings (GTK_TABLE (table), 6); + gtk_container_add (GTK_CONTAINER (frame), table); + gtk_widget_show (table); + + adj = (GtkAdjustment *) + gimp_scale_entry_new (GTK_TABLE (table), 0, 0, + _("X:"), 0, 0, + mapvals.alpha, -180.0, 180.0, 1.0, 15.0, 1, + TRUE, 0, 0, + _("Rotation angle about X axis"), NULL); + gtk_size_group_add_widget (group, GIMP_SCALE_ENTRY_SPINBUTTON (adj)); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (double_adjustment_update), + &mapvals.alpha); + + adj = (GtkAdjustment *) + gimp_scale_entry_new (GTK_TABLE (table), 0, 1, + _("Y:"), 0, 0, + mapvals.beta, -180.0, 180.0, 1.0, 15.0, 1, + TRUE, 0, 0, + _("Rotation angle about Y axis"), NULL); + gtk_size_group_add_widget (group, GIMP_SCALE_ENTRY_SPINBUTTON (adj)); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (double_adjustment_update), + &mapvals.beta); + + adj = (GtkAdjustment *) + gimp_scale_entry_new (GTK_TABLE (table), 0, 2, + _("Z:"), 0, 0, + mapvals.gamma, -180.0, 180.0, 1.0, 15.0, 1, + TRUE, 0, 0, + _("Rotation angle about Z axis"), NULL); + gtk_size_group_add_widget (group, GIMP_SCALE_ENTRY_SPINBUTTON (adj)); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (double_adjustment_update), + &mapvals.gamma); + + gtk_widget_show (page); + + g_object_unref (group); + + return page; +} + +static GtkWidget * +create_box_page (void) +{ + GtkWidget *page; + GtkWidget *frame; + GtkWidget *vbox; + GtkWidget *table; + GtkAdjustment *adj; + gint i; + + static gchar *labels[] = + { + N_("Front:"), N_("Back:"), + N_("Top:"), N_("Bottom:"), + N_("Left:"), N_("Right:") + }; + + page = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); + gtk_container_set_border_width (GTK_CONTAINER (page), 12); + + frame = gimp_frame_new (_("Map Images to Box Faces")); + gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0); + gtk_widget_show (frame); + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); + gtk_container_add (GTK_CONTAINER (frame), vbox); + gtk_widget_show (vbox); + + table = gtk_table_new (6, 2, FALSE); + gtk_table_set_row_spacings (GTK_TABLE(table), 6); + gtk_table_set_col_spacings (GTK_TABLE(table), 6); + gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 5); + gtk_widget_show (table); + + for (i = 0; i < 6; i++) + { + GtkWidget *combo; + + combo = gimp_drawable_combo_box_new (box_constrain, NULL); + gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo), + mapvals.boxmap_id[i], + G_CALLBACK (gimp_int_combo_box_get_active), + &mapvals.boxmap_id[i]); + + gimp_table_attach_aligned (GTK_TABLE (table), 0, i, + gettext (labels[i]), 0.0, 0.5, + combo, 1, FALSE); + } + + /* Scale scales */ + + table = gtk_table_new (3, 3, FALSE); + gtk_table_set_row_spacings (GTK_TABLE(table), 6); + gtk_table_set_col_spacings (GTK_TABLE(table), 6); + gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0); + gtk_widget_show (table); + + adj = (GtkAdjustment *) + gimp_scale_entry_new (GTK_TABLE (table), 0, 0, + _("Scale X:"), 0, 0, + mapvals.scale.x, 0.0, 5.0, 0.01, 0.1, 2, + TRUE, 0, 0, + _("X scale (size)"), NULL); + gtk_spin_button_configure (GIMP_SCALE_ENTRY_SPINBUTTON (adj), + GIMP_SCALE_ENTRY_SPINBUTTON_ADJ (adj), 0.1, 2); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (double_adjustment_update), + &mapvals.scale.x); + + adj = (GtkAdjustment *) + gimp_scale_entry_new (GTK_TABLE (table), 0, 1, + _("Y:"), 0, 0, + mapvals.scale.y, 0.0, 5.0, 0.01, 0.1, 2, + TRUE, 0, 0, + _("Y scale (size)"), NULL); + gtk_spin_button_configure (GIMP_SCALE_ENTRY_SPINBUTTON (adj), + GIMP_SCALE_ENTRY_SPINBUTTON_ADJ (adj), 0.1, 2); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (double_adjustment_update), + &mapvals.scale.y); + + adj = (GtkAdjustment *) + gimp_scale_entry_new (GTK_TABLE (table), 0, 2, + _("Z:"), 0, 0, + mapvals.scale.z, 0.0, 5.0, 0.01, 0.1, 2, + TRUE, 0, 0, + _("Z scale (size)"), NULL); + gtk_spin_button_configure (GIMP_SCALE_ENTRY_SPINBUTTON (adj), + GIMP_SCALE_ENTRY_SPINBUTTON_ADJ (adj), 0.1, 2); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (double_adjustment_update), + &mapvals.scale.z); + + gtk_widget_show (page); + + return page; +} + +static GtkWidget * +create_cylinder_page (void) +{ + GtkSizeGroup *group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); + GtkWidget *page; + GtkWidget *frame; + GtkWidget *table; + GtkAdjustment *adj; + gint i; + + static const gchar *labels[] = { N_("_Top:"), N_("_Bottom:") }; + + page = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12); + gtk_container_set_border_width (GTK_CONTAINER (page), 12); + + frame = gimp_frame_new (_("Images for the Cap Faces")); + gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0); + gtk_widget_show (frame); + + table = gtk_table_new (2, 2, FALSE); + gtk_table_set_row_spacings (GTK_TABLE (table), 6); + gtk_table_set_col_spacings (GTK_TABLE (table), 6); + gtk_container_add (GTK_CONTAINER (frame), table); + gtk_widget_show (table); + + /* Option menus */ + + for (i = 0; i < 2; i++) + { + GtkWidget *combo; + GtkWidget *label; + + combo = gimp_drawable_combo_box_new (cylinder_constrain, NULL); + gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo), + mapvals.cylindermap_id[i], + G_CALLBACK (gimp_int_combo_box_get_active), + &mapvals.cylindermap_id[i]); + + label = gimp_table_attach_aligned (GTK_TABLE (table), 0, i, + gettext (labels[i]), 0.0, 0.5, + combo, 1, FALSE); + gtk_size_group_add_widget (group, label); + } + + frame = gimp_frame_new (_("Size")); + gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0); + gtk_widget_show (frame); + + table = gtk_table_new (2, 3, FALSE); + gtk_table_set_row_spacings (GTK_TABLE (table), 6); + gtk_table_set_col_spacings (GTK_TABLE (table), 6); + gtk_container_add (GTK_CONTAINER (frame), table); + gtk_widget_show (table); + + adj = (GtkAdjustment *) + gimp_scale_entry_new (GTK_TABLE (table), 0, 0, + _("R_adius:"), 0, 0, + mapvals.cylinder_radius, + 0.0, 2.0, 0.01, 0.1, 2, + TRUE, 0, 0, + _("Cylinder radius"), NULL); + gtk_size_group_add_widget (group, GIMP_SCALE_ENTRY_LABEL (adj)); + gtk_spin_button_configure (GIMP_SCALE_ENTRY_SPINBUTTON (adj), + GIMP_SCALE_ENTRY_SPINBUTTON_ADJ (adj), 0.1, 2); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (double_adjustment_update), + &mapvals.cylinder_radius); + + adj = (GtkAdjustment *) + gimp_scale_entry_new (GTK_TABLE (table), 0, 1, + _("L_ength:"), 0, 0, + mapvals.cylinder_length, + 0.0, 2.0, 0.01, 0.1, 2, + TRUE, 0, 0, + _("Cylinder length"), NULL); + gtk_size_group_add_widget (group, GIMP_SCALE_ENTRY_LABEL (adj)); + gtk_spin_button_configure (GIMP_SCALE_ENTRY_SPINBUTTON (adj), + GIMP_SCALE_ENTRY_SPINBUTTON_ADJ (adj), 0.1, 2); + + g_signal_connect (adj, "value-changed", + G_CALLBACK (double_adjustment_update), + &mapvals.cylinder_length); + + gtk_widget_show (page); + + g_object_unref (group); + + return page; +} + +/****************************/ +/* Create notbook and pages */ +/****************************/ + +static void +create_main_notebook (GtkWidget *container) +{ + GtkWidget *page; + + options_note_book = GTK_NOTEBOOK (gtk_notebook_new ()); + gtk_container_add (GTK_CONTAINER (container), + GTK_WIDGET (options_note_book)); + + page = create_options_page (); + gtk_notebook_append_page (options_note_book, page, + gtk_label_new_with_mnemonic (_("O_ptions"))); + + page = create_light_page (); + gtk_notebook_append_page (options_note_book, page, + gtk_label_new_with_mnemonic (_("_Light"))); + + page = create_material_page (); + gtk_notebook_append_page (options_note_book, page, + gtk_label_new_with_mnemonic (_("_Material"))); + + page = create_orientation_page (); + gtk_notebook_append_page (options_note_book, page, + gtk_label_new_with_mnemonic (_("O_rientation"))); + + if (mapvals.maptype == MAP_BOX) + { + box_page = create_box_page (); + g_object_ref (box_page); + gtk_notebook_append_page (options_note_book, box_page, + gtk_label_new_with_mnemonic (_("_Box"))); + } + else if (mapvals.maptype == MAP_CYLINDER) + { + cylinder_page = create_cylinder_page (); + g_object_ref (cylinder_page); + gtk_notebook_append_page (options_note_book, cylinder_page, + gtk_label_new_with_mnemonic (_("C_ylinder"))); + } + + gtk_widget_show (GTK_WIDGET (options_note_book)); +} + +/********************************/ +/* Create and show main dialog. */ +/********************************/ + +gboolean +main_dialog (gint32 drawable_id) +{ + GtkWidget *main_hbox; + GtkWidget *vbox; + GtkWidget *hbox; + GtkWidget *frame; + GtkWidget *button; + GtkWidget *toggle; + GimpZoomModel *model; + gboolean run = FALSE; + + gimp_ui_init (PLUG_IN_BINARY, FALSE); + + appwin = gimp_dialog_new (_("Map to Object"), PLUG_IN_ROLE, + NULL, 0, + gimp_standard_help_func, PLUG_IN_PROC, + + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_OK"), GTK_RESPONSE_OK, + + NULL); + + gtk_dialog_set_alternative_button_order (GTK_DIALOG (appwin), + GTK_RESPONSE_OK, + GTK_RESPONSE_CANCEL, + -1); + + gimp_window_set_transient (GTK_WINDOW (appwin)); + + main_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); + gtk_container_set_border_width (GTK_CONTAINER (main_hbox), 12); + gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (appwin))), + main_hbox, FALSE, FALSE, 0); + gtk_widget_show (main_hbox); + + /* Create the Preview */ + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); + gtk_box_pack_start (GTK_BOX (main_hbox), vbox, FALSE, FALSE, 0); + gtk_widget_show (vbox); + + /* Add preview widget and various buttons to the first part */ + + frame = gtk_frame_new (NULL); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); + gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); + gtk_widget_show (frame); + + gtk_widget_realize (appwin); + previewarea = gtk_drawing_area_new (); + gtk_widget_set_size_request (previewarea, PREVIEW_WIDTH, PREVIEW_HEIGHT); + gtk_widget_set_events (previewarea, (GDK_EXPOSURE_MASK | + GDK_BUTTON1_MOTION_MASK | + GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK)); + gtk_container_add (GTK_CONTAINER (frame), previewarea); + gtk_widget_show (previewarea); + + g_signal_connect (previewarea, "event", + G_CALLBACK (preview_events), + previewarea); + + g_signal_connect (previewarea, "expose-event", + G_CALLBACK (preview_expose), + previewarea); + + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + gtk_widget_show (hbox); + + button = gtk_button_new_with_mnemonic (_("_Preview!")); + gtk_misc_set_padding (GTK_MISC (gtk_bin_get_child (GTK_BIN (button))), 2, 0); + gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0); + gtk_widget_show (button); + + g_signal_connect (button, "clicked", + G_CALLBACK (preview_callback), + NULL); + + gimp_help_set_help_data (button, _("Recompute preview image"), NULL); + + model = gimp_zoom_model_new (); + gimp_zoom_model_set_range (model, 0.25, 1.0); + gimp_zoom_model_zoom (model, GIMP_ZOOM_TO, mapvals.zoom); + + button = gimp_zoom_button_new (model, GIMP_ZOOM_IN, GTK_ICON_SIZE_MENU); + gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0); + gtk_widget_show (button); + + button = gimp_zoom_button_new (model, GIMP_ZOOM_OUT, GTK_ICON_SIZE_MENU); + gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0); + gtk_widget_show (button); + + g_signal_connect (model, "zoomed", + G_CALLBACK (zoomed_callback), + NULL); + + toggle = gtk_check_button_new_with_mnemonic (_("Show _wireframe")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), mapvals.showgrid); + gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0); + gtk_widget_show (toggle); + + g_signal_connect (toggle, "toggled", + G_CALLBACK (toggle_update), + &mapvals.showgrid); + + toggle = gtk_check_button_new_with_mnemonic (_("Update preview _live")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle), mapvals.livepreview); + gtk_box_pack_start (GTK_BOX (vbox), toggle, FALSE, FALSE, 0); + gtk_widget_show (toggle); + + g_signal_connect (toggle, "toggled", + G_CALLBACK (toggle_update), + &mapvals.livepreview); + + create_main_notebook (main_hbox); + + gtk_widget_show (appwin); + + { + GdkCursor *cursor; + + cursor = gdk_cursor_new_for_display (gtk_widget_get_display (previewarea), + GDK_HAND2); + gdk_window_set_cursor (gtk_widget_get_window (previewarea), cursor); + gdk_cursor_unref (cursor); + } + + image_setup (drawable_id, TRUE); + + compute_preview_image (); + + if (gimp_dialog_run (GIMP_DIALOG (appwin)) == GTK_RESPONSE_OK) + run = TRUE; + + gtk_widget_destroy (appwin); + if (preview_rgb_data) + g_free (preview_rgb_data); + if (preview_surface) + cairo_surface_destroy (preview_surface); + if (box_page) + g_object_unref (box_page); + if (cylinder_page) + g_object_unref (cylinder_page); + + return run; +} diff --git a/plug-ins/map-object/map-object-ui.h b/plug-ins/map-object/map-object-ui.h new file mode 100644 index 0000000..69f6065 --- /dev/null +++ b/plug-ins/map-object/map-object-ui.h @@ -0,0 +1,14 @@ +#ifndef __MAPOBJECT_UI_H__ +#define __MAPOBJECT_UI_H__ + +/* Externally visible variables */ +/* ============================ */ + +extern GtkWidget *previewarea; + +/* Externally visible functions */ +/* ============================ */ + +gboolean main_dialog (gint32 drawable_id); + +#endif /* __MAPOBJECT_UI_H__ */ |