Merge branch 'next' into weather

Conflicts:
	apps/openmw/mwrender/renderingmanager.cpp
actorid
scrawl 13 years ago
commit 8b5da06fce

@ -1,11 +1,13 @@
project(OpenMW) project(OpenMW)
IF (APPLE) if (APPLE)
set(APP_BUNDLE_DIR "${OpenMW_BINARY_DIR}/OpenMW.app") set(APP_BUNDLE_NAME "${CMAKE_PROJECT_NAME}.app")
set(APP_BUNDLE_DIR "${OpenMW_BINARY_DIR}/${APP_BUNDLE_NAME}")
# using 10.6 sdk # using 10.6 sdk
set(CMAKE_OSX_SYSROOT "/Developer/SDKs/MacOSX10.6.sdk") set(CMAKE_OSX_SYSROOT "/Developer/SDKs/MacOSX10.6.sdk")
ENDIF (APPLE) endif (APPLE)
# Macros # Macros
@ -201,6 +203,13 @@ include_directories("."
link_directories(${Boost_LIBRARY_DIRS} ${OGRE_LIB_DIR}) link_directories(${Boost_LIBRARY_DIRS} ${OGRE_LIB_DIR})
if(APPLE)
# List used Ogre plugins
SET(USED_OGRE_PLUGINS "RenderSystem_GL"
"Plugin_OctreeSceneManager"
"Plugin_ParticleFX")
endif(APPLE)
add_subdirectory( extern/caelum ) add_subdirectory( extern/caelum )
add_subdirectory( extern/mygui_3.0.1 ) add_subdirectory( extern/mygui_3.0.1 )
@ -244,22 +253,17 @@ if (APPLE)
"${OpenMW_BINARY_DIR}/plugins.cfg") "${OpenMW_BINARY_DIR}/plugins.cfg")
configure_file(${OpenMW_SOURCE_DIR}/files/mac/Info.plist configure_file(${OpenMW_SOURCE_DIR}/files/mac/Info.plist
"${APP_BUNDLE_DIR}/Contents/Info.plist" COPYONLY) "${APP_BUNDLE_DIR}/Contents/Info.plist")
configure_file(${OpenMW_SOURCE_DIR}/files/mac/openmw.icns configure_file(${OpenMW_SOURCE_DIR}/files/mac/openmw.icns
"${APP_BUNDLE_DIR}/Contents/Resources/OpenMW.icns" COPYONLY) "${APP_BUNDLE_DIR}/Contents/Resources/OpenMW.icns" COPYONLY)
# prepare plugins # prepare plugins
configure_file(${OGRE_PLUGIN_DIR}/RenderSystem_GL.dylib foreach(plugin ${USED_OGRE_PLUGINS})
"${APP_BUNDLE_DIR}/Contents/Plugins/RenderSystem_GL.dylib" COPYONLY) configure_file("${OGRE_PLUGIN_DIR}/${plugin}.dylib"
"${APP_BUNDLE_DIR}/Contents/Plugins/${plugin}.dylib"
configure_file(${OGRE_PLUGIN_DIR}/Plugin_OctreeSceneManager.dylib COPYONLY)
"${APP_BUNDLE_DIR}/Contents/Plugins/Plugin_OctreeSceneManager.dylib" COPYONLY) endforeach()
configure_file(${OGRE_PLUGIN_DIR}/Plugin_ParticleFX.dylib
"${APP_BUNDLE_DIR}/Contents/Plugins/Plugin_ParticleFX.dylib" COPYONLY)
endif (APPLE) endif (APPLE)
@ -269,36 +273,6 @@ if (CMAKE_COMPILER_IS_GNUCC)
add_definitions (-Wall) add_definitions (-Wall)
endif (CMAKE_COMPILER_IS_GNUCC) endif (CMAKE_COMPILER_IS_GNUCC)
# Apple bundling
# TODO REWRITE!
if (APPLE)
set(MISC_FILES
${APP_BUNDLE_DIR}/Contents/MacOS/openmw.cfg
${APP_BUNDLE_DIR}/Contents/MacOS/plugins.cfg)
set(OGRE_PLUGINS
${APP_BUNDLE_DIR}/Contents/Plugins/*)
install(FILES ${MISC_FILES} DESTINATION ../MacOS)
install(DIRECTORY "${APP_BUNDLE_DIR}/Contents/Plugins" DESTINATION ..)
install(DIRECTORY "${APP_BUNDLE_DIR}/Contents/Resources/resources" DESTINATION ../Resources)
set(CPACK_GENERATOR "Bundle")
set(CPACK_BUNDLE_PLIST "${CMAKE_SOURCE_DIR}/files/mac/Info.plist")
set(CPACK_BUNDLE_ICON "${CMAKE_SOURCE_DIR}/files/mac/openmw.icns")
set(CPACK_BUNDLE_NAME "OpenMW")
set(CPACK_PACKAGE_VERSION ${OPENMW_VERSION})
set(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINO})
set(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE})
include(CPack)
set(CMAKE_EXE_LINKER_FLAGS "-arch i386")
set(CMAKE_CXX_FLAGS "-arch i386")
endif (APPLE)
if(DPKG_PROGRAM) if(DPKG_PROGRAM)
SET(CMAKE_INSTALL_PREFIX "/usr") SET(CMAKE_INSTALL_PREFIX "/usr")
@ -352,6 +326,45 @@ if(DPKG_PROGRAM)
include(CPack) include(CPack)
endif(DPKG_PROGRAM) endif(DPKG_PROGRAM)
if(WIN32)
FILE(GLOB files "${OpenMW_BINARY_DIR}/Release/*.*")
INSTALL(FILES ${files} DESTINATION ".")
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "." RENAME "openmw.cfg")
INSTALL(FILES "${OpenMW_BINARY_DIR}/launcher.cfg" "${OpenMW_BINARY_DIR}/launcher.qss" DESTINATION ".")
INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION ".")
SET(CPACK_GENERATOR "NSIS")
SET(CPACK_PACKAGE_NAME "OpenMW")
SET(CPACK_PACKAGE_VENDOR "OpenMW.org")
SET(CPACK_PACKAGE_VERSION ${OPENMW_VERSION})
SET(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR})
SET(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINO})
SET(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE})
SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW;esmtool;Esmtool;omwlauncher;OpenMW Launcher")
SET(CPACK_PACKAGE_DESCRIPTION_FILE "${OpenMW_SOURCE_DIR}/readme.txt")
SET(CPACK_RESOURCE_FILE_LICENSE "${OpenMW_SOURCE_DIR}/GPL3.txt")
SET(CPACK_NSIS_EXECUTABLES_DIRECTORY ".")
SET(CPACK_NSIS_DISPLAY_NAME "OpenMW")
SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\www.openmw.org")
SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\www.openmw.org")
SET(CPACK_NSIS_INSTALLED_ICON_NAME "omwlauncher.exe")
SET(VCREDIST "${OpenMW_BINARY_DIR}/vcredist_x86.exe")
if(EXISTS ${VCREDIST})
INSTALL(FILES ${VCREDIST} DESTINATION "redist")
SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "ExecWait '\\\"$INSTDIR\\\\redist\\\\vcredist_x86.exe\\\" /q'" )
endif(EXISTS ${VCREDIST})
SET(OALREDIST "${OpenMW_BINARY_DIR}/oalinst.exe")
if(EXISTS ${OALREDIST})
INSTALL(FILES ${OALREDIST} DESTINATION "redist")
SET(CPACK_NSIS_EXTRA_INSTALL_COMMANDS "${CPACK_NSIS_EXTRA_INSTALL_COMMANDS}
ExecWait '\\\"$INSTDIR\\\\redist\\\\oalinst.exe\\\" /s'" )
endif(EXISTS ${OALREDIST})
include(CPack)
endif(WIN32)
# Components # Components
add_subdirectory (components) add_subdirectory (components)
@ -406,3 +419,86 @@ if (WIN32)
#set_target_properties(openmw PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS") #set_target_properties(openmw PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS")
#set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS") #set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS")
endif() endif()
# Apple bundling
if (APPLE)
set(INSTALL_SUBDIR OpenMW)
#install(FILES ${MISC_FILES} DESTINATION ../MacOS)
#install(DIRECTORY "${APP_BUNDLE_DIR}/Contents/Plugins" DESTINATION ..)
#install(DIRECTORY "${APP_BUNDLE_DIR}/Contents/Resources/resources" DESTINATION ../Resources)
install(DIRECTORY "${APP_BUNDLE_DIR}" USE_SOURCE_PERMISSIONS DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" RENAME "openmw.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(FILES "${OpenMW_BINARY_DIR}/plugins.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(FILES "${OpenMW_BINARY_DIR}/launcher.qss" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
set(CPACK_GENERATOR "DragNDrop")
# set(CPACK_BUNDLE_PLIST "${CMAKE_SOURCE_DIR}/files/mac/Info.plist")
# set(CPACK_BUNDLE_ICON "${CMAKE_SOURCE_DIR}/files/mac/openmw.icns")
# set(CPACK_BUNDLE_NAME "OpenMW")
set(CPACK_PACKAGE_VERSION ${OPENMW_VERSION})
set(CPACK_PACKAGE_VERSION_MAJOR ${OPENMW_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${OPENMW_VERSION_MINO})
set(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE})
set(APPS "\${CMAKE_INSTALL_PREFIX}/${INSTALL_SUBDIR}/${APP_BUNDLE_NAME}")
set(PLUGINS "")
# Scan Plugins dir for *.dylibs
file(GLOB ALL_PLUGINS "${APP_BUNDLE_DIR}/Contents/Plugins/*.dylib")
foreach(PLUGIN ${ALL_PLUGINS})
get_filename_component(PLUGIN_FILENAME ${PLUGIN} NAME)
set(PLUGINS ${PLUGINS} "\${CMAKE_INSTALL_PREFIX}/${INSTALL_SUBDIR}/${APP_BUNDLE_NAME}/Contents/Plugins/${PLUGIN_FILENAME}")
endforeach()
#For now, search unresolved dependencies only in default system paths, so if you put unresolveable (i.e. with @executable_path in id name) lib or framework somewhere else, it would fail
set(DIRS "")
# Overriding item resolving during installation, it needed if
# some library already has be "fixed up", i.e. its id name contains @executable_path,
# but library is not embedded in bundle. For example, it's Ogre.framework from Ogre SDK.
# Current implementation of GetPrerequsities/BundleUtilities doesn't handle that case.
#
# Current limitations:
# 1. Handles only frameworks, not simple libs
INSTALL(CODE "
set(CMAKE_FIND_LIBRARY_PREFIXES ${CMAKE_FIND_LIBRARY_PREFIXES})
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
set(CMAKE_SYSTEM_FRAMEWORK_PATH ${CMAKE_SYSTEM_FRAMEWORK_PATH})
set(OPENMW_RESOLVED_ITEMS \"\")
function(gp_resolve_item_override context item exepath dirs resolved_item_var resolved_var)
if(item MATCHES \"@executable_path\" AND NOT \${\${resolved_var}})
if (item MATCHES \"Frameworks\") # if it is a framework
# get last segment of path
get_filename_component(fname \"\${item}\" NAME_WE)
find_library(ri NAMES \${fname} PATHS \${exepath} \${dirs} /Library/Frameworks)
if (ri)
message(STATUS \"found \${ri} for \${item}\")
string(REGEX REPLACE \"^.*/Frameworks/.*\\\\.framework\" \"\" item_part \${item})
set(ri \"\${ri}\${item_part}\")
set(\${resolved_item_var} \${ri} PARENT_SCOPE)
set(\${resolved_var} 1 PARENT_SCOPE)
set(OPENMW_RESOLVED_ITEMS \${_OPENMW_RESOLVED_ITEMS} \${ri})
endif()
else()
# code path for standard (non-framework) libs (ogre & qt pugins)
endif()
endif()
endfunction(gp_resolve_item_override)
cmake_policy(SET CMP0009 OLD)
set(BU_CHMOD_BUNDLE_ITEMS ON)
include(BundleUtilities)
fixup_bundle(\"${APPS}\" \"${PLUGINS}\" \"${DIRS}\")
" COMPONENT Runtime)
include(CPack)
set(CMAKE_EXE_LINKER_FLAGS "-arch i386")
set(CMAKE_CXX_FLAGS "-arch i386")
endif (APPLE)

@ -926,13 +926,13 @@ int update_arg(void *field, char **orig_field,
const char *long_opt, char short_opt, const char *long_opt, char short_opt,
const char *additional_error) const char *additional_error)
{ {
char *stop_char = 0; //char *stop_char = 0;
const char *val = value; //const char *val = value;
int found; //int found;
FIX_UNUSED (field); FIX_UNUSED (field);
stop_char = 0; //stop_char = 0;
found = 0; //found = 0;
if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given))) if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given)))
{ {
@ -955,8 +955,8 @@ int update_arg(void *field, char **orig_field,
(*prev_given)++; (*prev_given)++;
if (field_given) if (field_given)
(*field_given)++; (*field_given)++;
if (possible_values) //if (possible_values)
val = possible_values[found]; //val = possible_values[found];
switch(arg_type) { switch(arg_type) {
default: default:
@ -996,7 +996,7 @@ cmdline_parser_internal (
int override; int override;
int initialize; int initialize;
int check_required; //int check_required;
int check_ambiguity; int check_ambiguity;
char *optarg; char *optarg;
@ -1008,7 +1008,7 @@ cmdline_parser_internal (
override = params->override; override = params->override;
initialize = params->initialize; initialize = params->initialize;
check_required = params->check_required; //check_required = params->check_required;
check_ambiguity = params->check_ambiguity; check_ambiguity = params->check_ambiguity;
if (initialize) if (initialize)

@ -41,14 +41,25 @@ source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER} ${LAUNCHER_HEADER_MOC
find_package(Qt4 REQUIRED) find_package(Qt4 REQUIRED)
set(QT_USE_QTGUI 1) set(QT_USE_QTGUI 1)
find_package(PNG REQUIRED) #find_package(PNG REQUIRED)
include_directories(${PNG_INCLUDE_DIR}) #include_directories(${PNG_INCLUDE_DIR})
QT4_ADD_RESOURCES(RCC_SRCS resources.qrc) QT4_ADD_RESOURCES(RCC_SRCS resources.qrc)
QT4_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC}) QT4_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC})
include(${QT_USE_FILE}) include(${QT_USE_FILE})
# list here plugins that can't be detected statically, but loaded in runtime
# it needed for packaging automatisation
#set(USED_QT_PLUGINS imageformats/libqgif
# imageformats/libqico
# imageformats/libqjpeg
# imageformats/libqmng
# imageformats/libqsvg
# imageformats/libqtga
# imageformats/libqtiff)
# It seems that launcher works without this plugins, but it loads them into memory if they exists
# Main executable # Main executable
add_executable(omwlauncher add_executable(omwlauncher
${LAUNCHER} ${LAUNCHER}
@ -60,7 +71,7 @@ target_link_libraries(omwlauncher
${Boost_LIBRARIES} ${Boost_LIBRARIES}
${OGRE_LIBRARIES} ${OGRE_LIBRARIES}
${QT_LIBRARIES} ${QT_LIBRARIES}
${PNG_LIBRARY} # ${PNG_LIBRARY}
components components
) )
@ -73,6 +84,13 @@ if (APPLE)
"${APP_BUNDLE_DIR}/../launcher.qss") "${APP_BUNDLE_DIR}/../launcher.qss")
configure_file(${CMAKE_SOURCE_DIR}/files/launcher.qss configure_file(${CMAKE_SOURCE_DIR}/files/launcher.qss
"${APP_BUNDLE_DIR}/../launcher.cfg") "${APP_BUNDLE_DIR}/../launcher.cfg")
# copy used QT plugins into ${APP_BUNDLE_DIR}/Contents/Plugins
#foreach(PLUGIN ${USED_QT_PLUGINS})
# get_filename_component(PLUGIN_FILENAME ${PLUGIN} NAME)
# configure_file("${QT_PLUGINS_DIR}/${PLUGIN}.dylib" "${APP_BUNDLE_DIR}/Contents/Plugins/${PLUGIN_FILENAME}.dylib" COPYONLY)
#endforeach()
else() else()
configure_file(${CMAKE_SOURCE_DIR}/files/launcher.qss configure_file(${CMAKE_SOURCE_DIR}/files/launcher.qss
"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/launcher.qss") "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/launcher.qss")

@ -86,10 +86,6 @@ target_link_libraries(openmw
if(APPLE) if(APPLE)
find_library(CARBON_FRAMEWORK Carbon) find_library(CARBON_FRAMEWORK Carbon)
target_link_libraries(openmw ${CARBON_FRAMEWORK}) target_link_libraries(openmw ${CARBON_FRAMEWORK})
install(TARGETS openmw
BUNDLE DESTINATION .
RUNTIME DESTINATION ../MacOS
COMPONENT Runtime)
endif(APPLE) endif(APPLE)
if(DPKG_PROGRAM) if(DPKG_PROGRAM)

@ -445,6 +445,28 @@ void OMW::Engine::activate()
} }
} }
void OMW::Engine::screenshot()
{
// Count screenshots.
int shotCount = 0;
const std::string screenshotPath = mCfgMgr.getLocalConfigPath().string();
// Find the first unused filename with a do-while
std::ostringstream stream;
do
{
// Reset the stream
stream.str("");
stream.clear();
stream << screenshotPath << "screenshot" << std::setw(3) << std::setfill('0') << shotCount++ << ".png";
} while (boost::filesystem::exists(stream.str()));
mOgre->screenshot(stream.str());
}
void OMW::Engine::setCompileAll (bool all) void OMW::Engine::setCompileAll (bool all)
{ {
mCompileAll = all; mCompileAll = all;

@ -149,6 +149,9 @@ namespace OMW
/// Activate the focussed object. /// Activate the focussed object.
void activate(); void activate();
/// Write screenshot to file.
void screenshot();
/// Compile all scripts (excludign dialogue scripts) at startup? /// Compile all scripts (excludign dialogue scripts) at startup?
void setCompileAll (bool all); void setCompileAll (bool all);

@ -26,18 +26,18 @@ namespace MWClass
assert (ref->base != NULL); assert (ref->base != NULL);
const std::string &model = ref->base->model; const std::string &model = ref->base->model;
MWRender::Objects& objects = renderingInterface.getObjects();
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
if (!model.empty()) if (!model.empty())
{
MWRender::Objects& objects = renderingInterface.getObjects();
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false);
objects.insertMesh(ptr, "meshes\\" + model); objects.insertMesh(ptr, "meshes\\" + model);
const int color = ref->base->data.color;
const float r = ((color >> 0) & 0xFF) / 255.0f; const int color = ref->base->data.color;
const float g = ((color >> 8) & 0xFF) / 255.0f; const float r = ((color >> 0) & 0xFF) / 255.0f;
const float b = ((color >> 16) & 0xFF) / 255.0f; const float g = ((color >> 8) & 0xFF) / 255.0f;
const float radius = float (ref->base->data.radius); const float b = ((color >> 16) & 0xFF) / 255.0f;
objects.insertLight (ptr, r, g, b, radius); const float radius = float (ref->base->data.radius);
} objects.insertLight (ptr, r, g, b, radius);
} }
void Light::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const void Light::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics, MWWorld::Environment& environment) const
@ -45,13 +45,12 @@ namespace MWClass
ESMS::LiveCellRef<ESM::Light, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Light, MWWorld::RefData> *ref =
ptr.get<ESM::Light>(); ptr.get<ESM::Light>();
const std::string &model = ref->base->model;
assert (ref->base != NULL); assert (ref->base != NULL);
const std::string &model = ref->base->model;
if(!model.empty()){ if(!model.empty()){
physics.insertObjectPhysics(ptr, "meshes\\" + model); physics.insertObjectPhysics(ptr, "meshes\\" + model);
} }
} }
void Light::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const void Light::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const

@ -20,7 +20,7 @@ namespace MWClass
if (!model.empty()) if (!model.empty())
{ {
MWRender::Objects& objects = renderingInterface.getObjects(); MWRender::Objects& objects = renderingInterface.getObjects();
objects.insertBegin(ptr, ptr.getRefData().isEnabled(), false); objects.insertBegin(ptr, ptr.getRefData().isEnabled(), true);
objects.insertMesh(ptr, "meshes\\" + model); objects.insertMesh(ptr, "meshes\\" + model);
} }
} }
@ -30,13 +30,12 @@ namespace MWClass
ESMS::LiveCellRef<ESM::Static, MWWorld::RefData> *ref = ESMS::LiveCellRef<ESM::Static, MWWorld::RefData> *ref =
ptr.get<ESM::Static>(); ptr.get<ESM::Static>();
const std::string &model = ref->base->model;
assert (ref->base != NULL); assert (ref->base != NULL);
const std::string &model = ref->base->model;
if(!model.empty()){ if(!model.empty()){
physics.insertObjectPhysics(ptr, "meshes\\" + model); physics.insertObjectPhysics(ptr, "meshes\\" + model);
} }
} }
std::string Static::getName (const MWWorld::Ptr& ptr) const std::string Static::getName (const MWWorld::Ptr& ptr) const

@ -32,8 +32,8 @@ book formatText(std::string text,book mBook,int maxLine, int lineSize)
mBook.pages.pop_back(); mBook.pages.pop_back();
} }
std::string::iterator wordBegin = text.begin(); //std::string::iterator wordBegin = text.begin();
std::string::iterator wordEnd; //std::string::iterator wordEnd;
std::string cText = text; std::string cText = text;

@ -83,27 +83,14 @@ namespace MWInput
MWGui::WindowManager &windows; MWGui::WindowManager &windows;
OMW::Engine& mEngine; OMW::Engine& mEngine;
// Count screenshots.
int shotCount;
/* InputImpl Methods */ /* InputImpl Methods */
// Write screenshot to file.
void screenshot() void screenshot()
{ {
mEngine.screenshot();
// Find the first unused filename with a do-while
char buf[50];
do
{
snprintf(buf, 50, "screenshot%03d.png", shotCount++);
} while (boost::filesystem::exists(buf));
ogre.screenshot(buf);
} }
/* toggleInventory() is called when the user presses the button to toggle the inventory screen. */ /* toggleInventory() is called when the user presses the button to toggle the inventory screen. */
void toggleInventory() void toggleInventory()
{ {
@ -183,8 +170,7 @@ namespace MWInput
poller(input), poller(input),
player(_player), player(_player),
windows(_windows), windows(_windows),
mEngine (engine), mEngine (engine)
shotCount(0)
{ {
using namespace OEngine::Input; using namespace OEngine::Input;
using namespace OEngine::Render; using namespace OEngine::Render;

@ -101,7 +101,6 @@ namespace MWRender{
} }
void Animation::handleShapes(std::vector<Nif::NiTriShapeCopy>* allshapes, Ogre::Entity* creaturemodel, Ogre::SkeletonInstance *skel){ void Animation::handleShapes(std::vector<Nif::NiTriShapeCopy>* allshapes, Ogre::Entity* creaturemodel, Ogre::SkeletonInstance *skel){
bool useHandles = skel == creaturemodel->getSkeleton();
shapeNumber = 0; shapeNumber = 0;
std::vector<Nif::NiTriShapeCopy>::iterator allshapesiter; std::vector<Nif::NiTriShapeCopy>::iterator allshapesiter;
@ -112,6 +111,9 @@ namespace MWRender{
Nif::NiTriShapeCopy& copy = *allshapesiter; Nif::NiTriShapeCopy& copy = *allshapesiter;
std::vector<Ogre::Vector3>* allvertices = &copy.vertices; std::vector<Ogre::Vector3>* allvertices = &copy.vertices;
std::vector<Ogre::Vector3>* allnormals = &copy.normals;
//std::set<unsigned int> vertices; //std::set<unsigned int> vertices;
//std::set<unsigned int> normals; //std::set<unsigned int> normals;
@ -121,8 +123,7 @@ namespace MWRender{
//std::cout << "Name " << copy.sname << "\n"; //std::cout << "Name " << copy.sname << "\n";
Ogre::HardwareVertexBufferSharedPtr vbuf = creaturemodel->getMesh()->getSubMesh(copy.sname)->vertexData->vertexBufferBinding->getBuffer(0); Ogre::HardwareVertexBufferSharedPtr vbuf = creaturemodel->getMesh()->getSubMesh(copy.sname)->vertexData->vertexBufferBinding->getBuffer(0);
Ogre::Real* pReal = static_cast<Ogre::Real*>(vbuf->lock(Ogre::HardwareBuffer::HBL_NORMAL)); Ogre::Real* pReal = static_cast<Ogre::Real*>(vbuf->lock(Ogre::HardwareBuffer::HBL_NORMAL));
//Ogre::HardwareVertexBufferSharedPtr vbufNormal = creaturemodel->getMesh()->getSubMesh(copy.sname)->vertexData->vertexBufferBinding->getBuffer(1);
// Ogre::Real* pRealNormal = static_cast<Ogre::Real*>(vbufNormal->lock(Ogre::HardwareBuffer::HBL_NORMAL));
std::vector<Ogre::Vector3> initialVertices = copy.morph.getInitialVertices(); std::vector<Ogre::Vector3> initialVertices = copy.morph.getInitialVertices();
//Each shape has multiple indices //Each shape has multiple indices
@ -181,146 +182,76 @@ namespace MWRender{
std::vector<Nif::NiSkinData::IndividualWeight> inds = iter->second; std::vector<Nif::NiSkinData::IndividualWeight> inds = iter->second;
int verIndex = iter->first; int verIndex = iter->first;
Ogre::Vector3 currentVertex = (*allvertices)[verIndex]; Ogre::Vector3 currentVertex = (*allvertices)[verIndex];
Ogre::Vector3 currentNormal = (*allnormals)[verIndex];
Nif::NiSkinData::BoneInfoCopy* boneinfocopy = &(allshapesiter->boneinfo[inds[0].boneinfocopyindex]); Nif::NiSkinData::BoneInfoCopy* boneinfocopy = &(allshapesiter->boneinfo[inds[0].boneinfocopyindex]);
Ogre::Bone *bonePtr = 0; Ogre::Bone *bonePtr = 0;
if(useHandles)
{
bonePtr = skel->getBone(boneinfocopy->bonehandle);
}
else
bonePtr = skel->getBone(boneinfocopy->bonename);
Ogre::Vector3 vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans;
Ogre::Quaternion vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation;
/*if(vecPosRot.find(boneinfocopy->bonehandle) == vecPosRot.end()){ Ogre::Vector3 vecPos;
Ogre::Quaternion vecRot;
std::map<Nif::NiSkinData::BoneInfoCopy*, PosAndRot>::iterator result = vecRotPos.find(boneinfocopy);
if(result == vecRotPos.end()){
bonePtr = skel->getBone(boneinfocopy->bonename);
vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans; vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans;
vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation; vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation;
if(useHandles){
PosAndRot both; PosAndRot both;
both.vecPos = vecPos; both.vecPos = vecPos;
both.vecRot = vecRot; both.vecRot = vecRot;
vecPosRot[boneinfocopy->bonehandle] = both; vecRotPos[boneinfocopy] = both;
}
} }
else{ else{
PosAndRot both = vecPosRot[boneinfocopy->bonehandle]; PosAndRot both = result->second;
vecPos = both.vecPos; vecPos = both.vecPos;
vecRot = both.vecRot; vecRot = both.vecRot;
}*/ }
Ogre::Vector3 absVertPos = (vecPos + vecRot * currentVertex) * inds[0].weight; Ogre::Vector3 absVertPos = (vecPos + vecRot * currentVertex) * inds[0].weight;
for(std::size_t i = 1; i < inds.size(); i++){ for(std::size_t i = 1; i < inds.size(); i++){
boneinfocopy = &(allshapesiter->boneinfo[inds[i].boneinfocopyindex]); boneinfocopy = &(allshapesiter->boneinfo[inds[i].boneinfocopyindex]);
if(useHandles) result = vecRotPos.find(boneinfocopy);
bonePtr = skel->getBone(boneinfocopy->bonehandle);
else
bonePtr = skel->getBone(boneinfocopy->bonename);
vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans;
vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation;
/*if(vecPosRot.find(boneinfocopy->bonehandle) == vecPosRot.end()){
if(result == vecRotPos.end()){
bonePtr = skel->getBone(boneinfocopy->bonename);
vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans; vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans;
vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation; vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation;
if(useHandles){
PosAndRot both; PosAndRot both;
both.vecPos = vecPos; both.vecPos = vecPos;
both.vecRot = vecRot; both.vecRot = vecRot;
vecPosRot[boneinfocopy->bonehandle] = both; vecRotPos[boneinfocopy] = both;
}
} }
else{ else{
PosAndRot both = vecPosRot[boneinfocopy->bonehandle]; PosAndRot both = result->second;
vecPos = both.vecPos; vecPos = both.vecPos;
vecRot = both.vecRot; vecRot = both.vecRot;
}*/ }
absVertPos += (vecPos + vecRot * currentVertex) * inds[i].weight; absVertPos += (vecPos + vecRot * currentVertex) * inds[i].weight;
} }
Ogre::Real* addr = (pReal + 3 * verIndex); Ogre::Real* addr = (pReal + 3 * verIndex);
*addr = absVertPos.x; *addr = absVertPos.x;
*(addr+1) = absVertPos.y; *(addr+1) = absVertPos.y;
*(addr+2) = absVertPos.z; *(addr+2) = absVertPos.z;
} }
#if 0
for (unsigned int i = 0; i < boneinfovector.size(); i++)
{
Nif::NiSkinData::BoneInfoCopy boneinfo = boneinfovector[i];
if(skel->hasBone(boneinfo.bonename)){
Ogre::Bone *bonePtr = skel->getBone(boneinfo.bonename);
Ogre::Vector3 vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfo.trafo.trans;
Ogre::Quaternion vecRot = bonePtr->_getDerivedOrientation() * boneinfo.trafo.rotation;
for (unsigned int j=0; j < boneinfo.weights.size(); j++)
{
unsigned int verIndex = boneinfo.weights[j].vertex;
if(vertices.find(verIndex) == vertices.end())
{
Ogre::Vector3 absVertPos = vecPos + vecRot * allvertices[verIndex];
absVertPos = absVertPos * boneinfo.weights[j].weight;
vertices.insert(verIndex);
Ogre::Real* addr = (pReal + 3 * verIndex);
*addr = absVertPos.x;
*(addr+1) = absVertPos.y;
*(addr+2) = absVertPos.z;
}
else
{
Ogre::Vector3 absVertPos = vecPos + vecRot * allvertices[verIndex];
absVertPos = absVertPos * boneinfo.weights[j].weight;
Ogre::Vector3 old = Ogre::Vector3(pReal + 3 * verIndex);
absVertPos = absVertPos + old;
Ogre::Real* addr = (pReal + 3 * verIndex);
*addr = absVertPos.x;
*(addr+1) = absVertPos.y;
*(addr+2) = absVertPos.z;
//std::cout << "Vertex" << verIndex << "Weight: " << boneinfo.weights[i].weight << "was seen twice\n";
}
if(normals.find(verIndex) == normals.end())
{
Ogre::Vector3 absNormalsPos = vecRot * allnormals[verIndex];
absNormalsPos = absNormalsPos * boneinfo.weights[j].weight;
normals.insert(verIndex);
Ogre::Real* addr = (pRealNormal + 3 * verIndex);
*addr = absNormalsPos.x;
*(addr+1) = absNormalsPos.y;
*(addr+2) = absNormalsPos.z;
}
else
{
Ogre::Vector3 absNormalsPos = vecRot * allnormals[verIndex];
absNormalsPos = absNormalsPos * boneinfo.weights[j].weight;
Ogre::Vector3 old = Ogre::Vector3(pRealNormal + 3 * verIndex);
absNormalsPos = absNormalsPos + old;
Ogre::Real* addr = (pRealNormal + 3 * verIndex);
*addr = absNormalsPos.x;
*(addr+1) = absNormalsPos.y;
*(addr+2) = absNormalsPos.z;
}
#endif
//}
//}
//} //Comment out
;
} }
else else
{ {
@ -329,11 +260,13 @@ namespace MWRender{
Ogre::Vector3 shapetrans = copy.trafo.trans; Ogre::Vector3 shapetrans = copy.trafo.trans;
float shapescale = copy.trafo.scale; float shapescale = copy.trafo.scale;
std::vector<std::string> boneSequence = copy.boneSequence; std::vector<std::string> boneSequence = copy.boneSequence;
std::vector<std::string>::iterator boneSequenceIter = boneSequence.begin();
Ogre::Vector3 transmult; Ogre::Vector3 transmult;
Ogre::Quaternion rotmult; Ogre::Quaternion rotmult;
float scale; float scale;
if(skel->hasBone(*boneSequenceIter)){ if(boneSequence.size() > 0){
std::vector<std::string>::iterator boneSequenceIter = boneSequence.begin();
if(skel->hasBone(*boneSequenceIter)){
Ogre::Bone *bonePtr = skel->getBone(*boneSequenceIter); Ogre::Bone *bonePtr = skel->getBone(*boneSequenceIter);
@ -360,6 +293,7 @@ namespace MWRender{
//std::cout << "Position: " << transmult << "Rotation: " << rotmult << "\n"; //std::cout << "Position: " << transmult << "Rotation: " << rotmult << "\n";
} }
}
else else
{ {
transmult = shapetrans; transmult = shapetrans;
@ -392,7 +326,7 @@ namespace MWRender{
} }
vbuf->unlock(); vbuf->unlock();
//vbufNormal->unlock();
} }
} }
@ -465,22 +399,18 @@ namespace MWRender{
base->getAllAnimationStates()->_notifyDirty(); base->getAllAnimationStates()->_notifyDirty();
//base->_updateAnimation(); //base->_updateAnimation();
base->_notifyMoved(); //base->_notifyMoved();
for(unsigned int i = 0; i < entityparts.size(); i++){ for(unsigned int i = 0; i < entityparts.size(); i++){
Ogre::SkeletonInstance* skel = entityparts[i]->getSkeleton(); //Ogre::SkeletonInstance* skel = entityparts[i]->getSkeleton();
Ogre::Bone* b = skel->getRootBone(); Ogre::Bone* b = skel->getRootBone();
b->setOrientation(Ogre::Real(.3),Ogre::Real(.3),Ogre::Real(.3), Ogre::Real(.3));//This is a trick b->setOrientation(Ogre::Real(.3),Ogre::Real(.3),Ogre::Real(.3), Ogre::Real(.3));//This is a trick
skel->_updateTransforms();
// skel->_notifyManualBonesDirty();
entityparts[i]->getAllAnimationStates()->_notifyDirty(); entityparts[i]->getAllAnimationStates()->_notifyDirty();
//entityparts[i]->_updateAnimation();
entityparts[i]->_notifyMoved();
} }
std::vector<Nif::NiKeyframeData>::iterator iter; std::vector<Nif::NiKeyframeData>::iterator iter;
int slot = 0; int slot = 0;
if(transformations){ if(transformations){
@ -488,9 +418,7 @@ namespace MWRender{
if(time < iter->getStartTime() || time < startTime || time > iter->getStopTime()) if(time < iter->getStartTime() || time < startTime || time > iter->getStopTime())
{ {
slot++; slot++;
//iter++;
continue; continue;
} }
float x; float x;
@ -511,7 +439,6 @@ namespace MWRender{
timeIndex(time, ttime, tindexI[slot], tindexJ, x); timeIndex(time, ttime, tindexI[slot], tindexJ, x);
//std::cout << "X: " << x << " X2: " << x2 << "\n";
Ogre::Vector3 t; Ogre::Vector3 t;
Ogre::Quaternion r; Ogre::Quaternion r;
@ -526,7 +453,6 @@ namespace MWRender{
bool bQuats = quats.size() > 0; bool bQuats = quats.size() > 0;
if(bQuats){ if(bQuats){
r = Ogre::Quaternion::Slerp(x2, quats[rindexI[slot]], quats[rindexJ], true); r = Ogre::Quaternion::Slerp(x2, quats[rindexI[slot]], quats[rindexJ], true);
//bone->setOrientation(r);
} }
skel = base->getSkeleton(); skel = base->getSkeleton();
if(skel->hasBone(iter->getBonename())){ if(skel->hasBone(iter->getBonename())){
@ -539,27 +465,10 @@ namespace MWRender{
skel->_updateTransforms(); skel->_updateTransforms();
//skel->_notifyManualBonesDirty();
base->getAllAnimationStates()->_notifyDirty(); base->getAllAnimationStates()->_notifyDirty();
//base->_updateAnimation();
base->_notifyMoved();
} }
for(std::size_t i = 0; i < entityparts.size(); i++){
skel = entityparts[i]->getSkeleton();
if(skel->hasBone(iter->getBonename())){
Ogre::Bone* bone = skel->getBone(iter->getBonename());
if(bTrans)
bone->setPosition(t);
if(bQuats)
bone->setOrientation(r);
skel->_updateTransforms();
//skel->_notifyManualBonesDirty();
entityparts[i]->getAllAnimationStates()->_notifyDirty();
// entityparts[i]->_updateAnimation();
entityparts[i]->_notifyMoved();
}
}
slot++; slot++;
} }
} }

@ -26,6 +26,7 @@ class Animation{
Ogre::SceneNode* insert; Ogre::SceneNode* insert;
OEngine::Render::OgreRenderer &mRend; OEngine::Render::OgreRenderer &mRend;
MWWorld::Environment& mEnvironment; MWWorld::Environment& mEnvironment;
std::map<Nif::NiSkinData::BoneInfoCopy*, PosAndRot> vecRotPos;
static std::map<std::string, int> mUniqueIDs; static std::map<std::string, int> mUniqueIDs;

@ -38,6 +38,7 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr& ptr, MWWorld::Environme
} }
void CreatureAnimation::runAnimation(float timepassed){ void CreatureAnimation::runAnimation(float timepassed){
vecRotPos.clear();
if(animate > 0){ if(animate > 0){
//Add the amount of time passed to time //Add the amount of time passed to time

@ -43,6 +43,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,O
char secondtolast = bodyRaceID.at(bodyRaceID.length() - 2); char secondtolast = bodyRaceID.at(bodyRaceID.length() - 2);
bool female = tolower(secondtolast) == 'f'; bool female = tolower(secondtolast) == 'f';
bool beast = bodyRaceID == "b_n_khajiit_m_" || bodyRaceID == "b_n_khajiit_f_" || bodyRaceID == "b_n_argonian_m_" || bodyRaceID == "b_n_argonian_f_"; bool beast = bodyRaceID == "b_n_khajiit_m_" || bodyRaceID == "b_n_khajiit_f_" || bodyRaceID == "b_n_argonian_m_" || bodyRaceID == "b_n_argonian_f_";
/*std::cout << "Race: " << ref->base->race ; /*std::cout << "Race: " << ref->base->race ;
if(female){ if(female){
std::cout << " Sex: Female" << " Height: " << race->data.height.female << "\n"; std::cout << " Sex: Female" << " Height: " << race->data.height.female << "\n";
@ -67,6 +68,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,O
//stay in the same place when we skipanim, or open a gui window //stay in the same place when we skipanim, or open a gui window
if((transformations = (NIFLoader::getSingletonPtr())->getAnim(smodel))){ if((transformations = (NIFLoader::getSingletonPtr())->getAnim(smodel))){
for(unsigned int init = 0; init < transformations->size(); init++){ for(unsigned int init = 0; init < transformations->size(); init++){
@ -177,7 +179,6 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,O
if(clavicler) if(clavicler)
insertBoundedPart("meshes\\" + clavicler->model , "Right Clavicle", base);*/ insertBoundedPart("meshes\\" + clavicler->model , "Right Clavicle", base);*/
if(neck) if(neck)
{ {
insertBoundedPart("meshes\\" + neck->model, "Neck"); insertBoundedPart("meshes\\" + neck->model, "Neck");
@ -213,6 +214,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, MWWorld::Environment& _env,O
} }
Ogre::Entity* NpcAnimation::insertBoundedPart(const std::string &mesh, std::string bonename){ Ogre::Entity* NpcAnimation::insertBoundedPart(const std::string &mesh, std::string bonename){
NIFLoader::load(mesh); NIFLoader::load(mesh);
Entity* ent = mRend.getScene()->createEntity(mesh); Entity* ent = mRend.getScene()->createEntity(mesh);
@ -225,15 +227,7 @@ void NpcAnimation::insertFreePart(const std::string &mesh, const std::string suf
Ogre::Entity* ent = mRend.getScene()->createEntity(meshNumbered); Ogre::Entity* ent = mRend.getScene()->createEntity(meshNumbered);
/*MaterialPtr material = ent->getSubEntity(0)->getMaterial();
material->removeAllTechniques();
Ogre::Technique* tech = material->createTechnique();
Pass* pass2 = tech->createPass();
pass2->setVertexProgram("Ogre/HardwareSkinningTwoWeights");
pass2->setColourWriteEnabled(false);
//tech->setSchemeName("blahblah");*/
insert->attachObject(ent); insert->attachObject(ent);
@ -249,6 +243,7 @@ void NpcAnimation::insertFreePart(const std::string &mesh, const std::string suf
void NpcAnimation::runAnimation(float timepassed){ void NpcAnimation::runAnimation(float timepassed){
//1. Add the amount of time passed to time //1. Add the amount of time passed to time
//2. Handle the animation transforms dependent on time //2. Handle the animation transforms dependent on time
@ -267,22 +262,17 @@ void NpcAnimation::runAnimation(float timepassed){
} }
handleAnimationTransforms(); handleAnimationTransforms();
Ogre::Vector3 current = insert->_getWorldAABB().getCenter();
std::vector<std::vector<Nif::NiTriShapeCopy>*>::iterator shapepartsiter = shapeparts.begin(); std::vector<std::vector<Nif::NiTriShapeCopy>*>::iterator shapepartsiter = shapeparts.begin();
std::vector<Ogre::Entity*>::iterator entitypartsiter = entityparts.begin(); std::vector<Ogre::Entity*>::iterator entitypartsiter = entityparts.begin();
while(shapepartsiter != shapeparts.end()) while(shapepartsiter != shapeparts.end())
{ {
vecRotPos.clear();
std::vector<Nif::NiTriShapeCopy>* shapes = *shapepartsiter; std::vector<Nif::NiTriShapeCopy>* shapes = *shapepartsiter;
Ogre::Entity* theentity = *entitypartsiter; Ogre::Entity* theentity = *entitypartsiter;
/*
Pass* pass = theentity->getSubEntity(0)->getMaterial()->getBestTechnique()->getPass(0);
if (pass->hasVertexProgram() && pass->getVertexProgram()->isSkeletalAnimationIncluded()) handleShapes(shapes, theentity, base->getSkeleton());
std::cout << "It's hardware\n";
else
std::cout << "It's software\n";*/
handleShapes(shapes, theentity, theentity->getSkeleton());
shapepartsiter++; shapepartsiter++;
entitypartsiter++; entitypartsiter++;
} }

@ -1,11 +1,11 @@
#include "objects.hpp" #include "objects.hpp"
#include <OgreSceneNode.h> #include <OgreSceneNode.h>
#include <components/nifogre/ogre_nif_loader.hpp> #include <components/nifogre/ogre_nif_loader.hpp>
using namespace Ogre;
using namespace MWRender; using namespace MWRender;
bool Objects::lightConst = false; bool Objects::lightConst = false;
float Objects::lightConstValue = 0.0f; float Objects::lightConstValue = 0.0f;
@ -23,10 +23,24 @@ bool Objects::lightOutQuadInLin = false;
int Objects::uniqueID = 0; int Objects::uniqueID = 0;
void Objects::setMwRoot(Ogre::SceneNode* root){ void Objects::clearSceneNode (Ogre::SceneNode *node)
{
/// \todo This should probably be moved into OpenEngine at some point.
for (int i=node->numAttachedObjects()-1; i>=0; --i)
{
Ogre::MovableObject *object = node->getAttachedObject (i);
node->detachObject (object);
mRenderer.getScene()->destroyMovableObject (object);
}
}
void Objects::setMwRoot(Ogre::SceneNode* root)
{
mMwRoot = root; mMwRoot = root;
} }
void Objects::insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_){
void Objects::insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_)
{
Ogre::SceneNode* root = mMwRoot; Ogre::SceneNode* root = mMwRoot;
Ogre::SceneNode* cellnode; Ogre::SceneNode* cellnode;
if(mCellSceneNodes.find(ptr.getCell()) == mCellSceneNodes.end()) if(mCellSceneNodes.find(ptr.getCell()) == mCellSceneNodes.end())
@ -49,90 +63,91 @@ void Objects::insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_){
f = ptr.getCellRef().pos.rot; f = ptr.getCellRef().pos.rot;
// Rotate around X axis // Rotate around X axis
Quaternion xr(Radian(-f[0]), Vector3::UNIT_X); Ogre::Quaternion xr(Ogre::Radian(-f[0]), Ogre::Vector3::UNIT_X);
// Rotate around Y axis // Rotate around Y axis
Quaternion yr(Radian(-f[1]), Vector3::UNIT_Y); Ogre::Quaternion yr(Ogre::Radian(-f[1]), Ogre::Vector3::UNIT_Y);
// Rotate around Z axis // Rotate around Z axis
Quaternion zr(Radian(-f[2]), Vector3::UNIT_Z); Ogre::Quaternion zr(Ogre::Radian(-f[2]), Ogre::Vector3::UNIT_Z);
// Rotates first around z, then y, then x // Rotates first around z, then y, then x
insert->setOrientation(xr*yr*zr); insert->setOrientation(xr*yr*zr);
if (!enabled) if (!enabled)
insert->setVisible (false); insert->setVisible (false);
ptr.getRefData().setBaseNode(insert); ptr.getRefData().setBaseNode(insert);
isStatic = static_; mIsStatic = static_;
} }
void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh){
void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh)
{
Ogre::SceneNode* insert = ptr.getRefData().getBaseNode(); Ogre::SceneNode* insert = ptr.getRefData().getBaseNode();
assert(insert); assert(insert);
NifOgre::NIFLoader::load(mesh); NifOgre::NIFLoader::load(mesh);
Entity *ent = mRend.getScene()->createEntity(mesh); Ogre::Entity *ent = mRenderer.getScene()->createEntity(mesh);
if(!isStatic) if(!mIsStatic)
{ {
insert->attachObject(ent); insert->attachObject(ent);
} }
else else
{ {
Ogre::StaticGeometry* sg = 0; Ogre::StaticGeometry* sg = 0;
if(mSG.find(ptr.getCell()) == mSG.end()) if(mStaticGeometry.find(ptr.getCell()) == mStaticGeometry.end())
{ {
uniqueID = uniqueID +1; uniqueID = uniqueID +1;
sg = mRend.getScene()->createStaticGeometry( "sg" + Ogre::StringConverter::toString(uniqueID)); sg = mRenderer.getScene()->createStaticGeometry( "sg" + Ogre::StringConverter::toString(uniqueID));
//Create the scenenode and put it in the map //Create the scenenode and put it in the map
mSG[ptr.getCell()] = sg; mStaticGeometry[ptr.getCell()] = sg;
} }
else else
{ {
sg = mSG[ptr.getCell()]; sg = mStaticGeometry[ptr.getCell()];
} }
sg->addEntity(ent,insert->_getDerivedPosition(),insert->_getDerivedOrientation(),insert->_getDerivedScale()); sg->addEntity(ent,insert->_getDerivedPosition(),insert->_getDerivedOrientation(),insert->_getDerivedScale());
sg->setRegionDimensions(Ogre::Vector3(100000,10000,100000)); sg->setRegionDimensions(Ogre::Vector3(100000,10000,100000));
mRenderer.getScene()->destroyEntity(ent);
mRend.getScene()->destroyEntity(ent);
} }
} }
void Objects::insertLight (const MWWorld::Ptr& ptr, float r, float g, float b, float radius){
Ogre::SceneNode* insert = mRend.getScene()->getSceneNode(ptr.getRefData().getHandle()); void Objects::insertLight (const MWWorld::Ptr& ptr, float r, float g, float b, float radius)
{
Ogre::SceneNode* insert = mRenderer.getScene()->getSceneNode(ptr.getRefData().getHandle());
assert(insert); assert(insert);
Ogre::Light *light = mRend.getScene()->createLight(); Ogre::Light *light = mRenderer.getScene()->createLight();
light->setDiffuseColour (r, g, b); light->setDiffuseColour (r, g, b);
float cval=0.0f, lval=0.0f, qval=0.0f; float cval=0.0f, lval=0.0f, qval=0.0f;
if(lightConst) if(lightConst)
cval = lightConstValue; cval = lightConstValue;
if(!lightOutQuadInLin)
{ if(!lightOutQuadInLin)
if(lightLinear) {
radius *= lightLinearRadiusMult; if(lightLinear)
if(lightQuadratic) radius *= lightLinearRadiusMult;
radius *= lightQuadraticRadiusMult; if(lightQuadratic)
radius *= lightQuadraticRadiusMult;
if(lightLinear)
lval = lightLinearValue / pow(radius, lightLinearMethod); if(lightLinear)
if(lightQuadratic) lval = lightLinearValue / pow(radius, lightLinearMethod);
qval = lightQuadraticValue / pow(radius, lightQuadraticMethod); if(lightQuadratic)
} qval = lightQuadraticValue / pow(radius, lightQuadraticMethod);
else }
{ else
// FIXME: {
// Do quadratic or linear, depending if we're in an exterior or interior // FIXME:
// cell, respectively. Ignore lightLinear and lightQuadratic. // Do quadratic or linear, depending if we're in an exterior or interior
} // cell, respectively. Ignore lightLinear and lightQuadratic.
}
light->setAttenuation(10*radius, cval, lval, qval);
light->setAttenuation(10*radius, cval, lval, qval);
insert->attachObject(light);
insert->attachObject(light);
} }
bool Objects::deleteObject (const MWWorld::Ptr& ptr) bool Objects::deleteObject (const MWWorld::Ptr& ptr)
@ -145,8 +160,9 @@ bool Objects::deleteObject (const MWWorld::Ptr& ptr)
mCellSceneNodes.begin()); iter!=mCellSceneNodes.end(); ++iter) mCellSceneNodes.begin()); iter!=mCellSceneNodes.end(); ++iter)
if (iter->second==parent) if (iter->second==parent)
{ {
clearSceneNode (base);
base->removeAndDestroyAllChildren(); base->removeAndDestroyAllChildren();
mRend.getScene()->destroySceneNode (base); mRenderer.getScene()->destroySceneNode (base);
ptr.getRefData().setBaseNode (0); ptr.getRefData().setBaseNode (0);
return true; return true;
} }
@ -157,29 +173,35 @@ bool Objects::deleteObject (const MWWorld::Ptr& ptr)
return true; return true;
} }
void Objects::removeCell(MWWorld::Ptr::CellStore* store){ void Objects::removeCell(MWWorld::Ptr::CellStore* store)
{
if(mCellSceneNodes.find(store) != mCellSceneNodes.end()) if(mCellSceneNodes.find(store) != mCellSceneNodes.end())
{ {
Ogre::SceneNode* base = mCellSceneNodes[store]; Ogre::SceneNode* base = mCellSceneNodes[store];
for (int i=0; i<base->numChildren(); ++i)
clearSceneNode (static_cast<Ogre::SceneNode *> (base->getChild (i)));
base->removeAndDestroyAllChildren(); base->removeAndDestroyAllChildren();
mCellSceneNodes.erase(store); mCellSceneNodes.erase(store);
mRend.getScene()->destroySceneNode(base); mRenderer.getScene()->destroySceneNode(base);
base = 0; base = 0;
} }
if(mStaticGeometry.find(store) != mStaticGeometry.end())
if(mSG.find(store) != mSG.end())
{ {
Ogre::StaticGeometry* sg = mSG[store]; Ogre::StaticGeometry* sg = mStaticGeometry[store];
mSG.erase(store); mStaticGeometry.erase(store);
mRend.getScene()->destroyStaticGeometry (sg); mRenderer.getScene()->destroyStaticGeometry (sg);
sg = 0; sg = 0;
} }
} }
void Objects::buildStaticGeometry(ESMS::CellStore<MWWorld::RefData>& cell){
if(mSG.find(&cell) != mSG.end()) void Objects::buildStaticGeometry(ESMS::CellStore<MWWorld::RefData>& cell)
{
if(mStaticGeometry.find(&cell) != mStaticGeometry.end())
{ {
Ogre::StaticGeometry* sg = mSG[&cell]; Ogre::StaticGeometry* sg = mStaticGeometry[&cell];
sg->build(); sg->build();
} }
} }

@ -1,20 +1,21 @@
#ifndef _GAME_RENDER_OBJECTS_H #ifndef _GAME_RENDER_OBJECTS_H
#define _GAME_RENDER_OBJECTS_H #define _GAME_RENDER_OBJECTS_H
#include "components/esm_store/cell_store.hpp" #include <openengine/ogre/renderer.hpp>
#include <components/esm_store/cell_store.hpp>
#include "../mwworld/refdata.hpp" #include "../mwworld/refdata.hpp"
#include "../mwworld/ptr.hpp" #include "../mwworld/ptr.hpp"
#include <openengine/ogre/renderer.hpp>
namespace MWRender{ namespace MWRender{
class Objects{ class Objects{
OEngine::Render::OgreRenderer &mRend; OEngine::Render::OgreRenderer &mRenderer;
std::map<MWWorld::Ptr::CellStore *, Ogre::SceneNode *> mCellSceneNodes; std::map<MWWorld::Ptr::CellStore *, Ogre::SceneNode *> mCellSceneNodes;
std::map<MWWorld::Ptr::CellStore *, Ogre::StaticGeometry*> mSG; std::map<MWWorld::Ptr::CellStore *, Ogre::StaticGeometry*> mStaticGeometry;
Ogre::SceneNode* mMwRoot; Ogre::SceneNode* mMwRoot;
bool isStatic; bool mIsStatic;
static int uniqueID; static int uniqueID;
static bool lightConst; static bool lightConst;
static float lightConstValue; static float lightConstValue;
@ -30,8 +31,12 @@ class Objects{
static float lightQuadraticRadiusMult; static float lightQuadraticRadiusMult;
static bool lightOutQuadInLin; static bool lightOutQuadInLin;
void clearSceneNode (Ogre::SceneNode *node);
///< Remove all movable objects from \a node.
public: public:
Objects(OEngine::Render::OgreRenderer& _rend): mRend(_rend){} Objects(OEngine::Render::OgreRenderer& renderer): mRenderer (renderer){}
~Objects(){} ~Objects(){}
void insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_); void insertBegin (const MWWorld::Ptr& ptr, bool enabled, bool static_);
void insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh); void insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh);

@ -41,6 +41,7 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
mObjects.setMwRoot(mMwRoot); mObjects.setMwRoot(mMwRoot);
mActors.setMwRoot(mMwRoot); mActors.setMwRoot(mMwRoot);
//mSkyManager = 0;
mSkyManager = MWRender::SkyManager::create(mRendering.getWindow(), mRendering.getCamera(), mMwRoot, resDir); mSkyManager = MWRender::SkyManager::create(mRendering.getWindow(), mRendering.getCamera(), mMwRoot, resDir);
//used to obtain ingame information of ogre objects (which are faced or selected) //used to obtain ingame information of ogre objects (which are faced or selected)
@ -53,10 +54,12 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
cameraPitchNode->attachObject(mRendering.getCamera()); cameraPitchNode->attachObject(mRendering.getCamera());
mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode); mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode);
mSun = 0;
} }
RenderingManager::~RenderingManager () RenderingManager::~RenderingManager ()
{ {
//TODO: destroy mSun?
delete mPlayer; delete mPlayer;
delete mSkyManager; delete mSkyManager;
} }
@ -134,27 +137,32 @@ void RenderingManager::update (float duration){
void RenderingManager::skyEnable () void RenderingManager::skyEnable ()
{ {
if(mSkyManager)
mSkyManager->enable(); mSkyManager->enable();
} }
void RenderingManager::skyDisable () void RenderingManager::skyDisable ()
{ {
mSkyManager->disable(); if(mSkyManager)
mSkyManager->disable();
} }
void RenderingManager::skySetHour (double hour) void RenderingManager::skySetHour (double hour)
{ {
mSkyManager->setHour(hour); if(mSkyManager)
mSkyManager->setHour(hour);
} }
void RenderingManager::skySetDate (int day, int month) void RenderingManager::skySetDate (int day, int month)
{ {
mSkyManager->setDate(day, month); if(mSkyManager)
mSkyManager->setDate(day, month);
} }
int RenderingManager::skyGetMasserPhase() const int RenderingManager::skyGetMasserPhase() const
{ {
return mSkyManager->getMasserPhase(); return mSkyManager->getMasserPhase();
} }
@ -163,9 +171,9 @@ int RenderingManager::skyGetSecundaPhase() const
return mSkyManager->getSecundaPhase(); return mSkyManager->getSecundaPhase();
} }
void RenderingManager::skySetMoonColour (bool red) void RenderingManager::skySetMoonColour (bool red){
{ if(mSkyManager)
mSkyManager->setMoonColour(red); mSkyManager->setMoonColour(red);
} }
bool RenderingManager::toggleRenderMode(int mode) bool RenderingManager::toggleRenderMode(int mode)
@ -228,12 +236,15 @@ void RenderingManager::configureAmbient(ESMS::CellStore<MWWorld::RefData> &mCell
// Create a "sun" that shines light downwards. It doesn't look // Create a "sun" that shines light downwards. It doesn't look
// completely right, but leave it for now. // completely right, but leave it for now.
Ogre::Light *light = mRendering.getScene()->createLight(); if(!mSun)
{
mSun = mRendering.getScene()->createLight();
}
Ogre::ColourValue colour; Ogre::ColourValue colour;
colour.setAsABGR (mCell.cell->ambi.sunlight); colour.setAsABGR (mCell.cell->ambi.sunlight);
light->setDiffuseColour (colour); mSun->setDiffuseColour (colour);
light->setType(Ogre::Light::LT_DIRECTIONAL); mSun->setType(Ogre::Light::LT_DIRECTIONAL);
light->setDirection(0,-1,0); mSun->setDirection(0,-1,0);
} }
// Switch through lighting modes. // Switch through lighting modes.

@ -121,6 +121,7 @@ class RenderingManager: private RenderingInterface {
int mAmbientMode; int mAmbientMode;
Ogre::ColourValue mAmbientColor; Ogre::ColourValue mAmbientColor;
Ogre::Light* mSun;
/// Root node for all objects added to the scene. This is rotated so /// Root node for all objects added to the scene. This is rotated so
/// that the OGRE coordinate system matches that used internally in /// that the OGRE coordinate system matches that used internally in

@ -5,6 +5,8 @@
#include <OgreSceneNode.h> #include <OgreSceneNode.h>
#include <OgreSceneManager.h> #include <OgreSceneManager.h>
#include <OgreCamera.h> #include <OgreCamera.h>
#include <OgreHardwareVertexBuffer.h>
#include <OgreHighLevelGpuProgramManager.h>
#include <components/nifogre/ogre_nif_loader.hpp> #include <components/nifogre/ogre_nif_loader.hpp>
@ -42,25 +44,123 @@ namespace MWRender
private: private:
Camera* mCamera; Camera* mCamera;
Viewport* mViewport;
SceneNode* mRootNode; SceneNode* mRootNode;
SceneManager* mSceneMgr; SceneManager* mSceneMgr;
MaterialPtr mCloudMaterial; MaterialPtr mCloudMaterial;
MaterialPtr mAtmosphereMaterial; MaterialPtr mAtmosphereMaterial;
HighLevelGpuProgramPtr mCloudFragmentShader;
void ModVertexAlpha(Entity* ent, unsigned int meshType);
}; };
void MWSkyManager::ModVertexAlpha(Entity* ent, unsigned int meshType)
{
// Get the vertex colour buffer of this mesh
VertexDeclaration* dec = ent->getMesh()->getSubMesh(0)->vertexData->vertexDeclaration;
const Ogre::VertexElement* ves_diffuse = ent->getMesh()->getSubMesh(0)->vertexData->vertexDeclaration->findElementBySemantic( Ogre::VES_DIFFUSE );
HardwareVertexBufferSharedPtr colourBuffer = ent->getMesh()->getSubMesh(0)->vertexData->vertexBufferBinding->getBuffer(ves_diffuse->getSource());
// Lock
void* pData = colourBuffer->lock(HardwareBuffer::HBL_NORMAL);
// Iterate over all vertices
int vertex_size = colourBuffer->getVertexSize();
float * currentVertex = NULL;
for (int i=0; i<colourBuffer->getNumVertices(); ++i)
{
// Get a pointer to the vertex colour
ves_diffuse->baseVertexPointerToElement( pData, &currentVertex );
unsigned char alpha;
if (meshType == 0) alpha = i%2 ? 0 : 255; // this is a cylinder, so every second vertex belongs to the bottom-most row
else if (meshType == 1)
{
if (i>= 49 && i <= 64) alpha = 0; // bottom-most row
else if (i>= 33 && i <= 48) alpha = 64; // second bottom-most row
else alpha = 255;
}
uint8 tmpR = static_cast<uint8>(255);
uint8 tmpG = static_cast<uint8>(255);
uint8 tmpB = static_cast<uint8>(255);
uint8 tmpA = static_cast<uint8>(alpha);
// This does not matter since R and B are always 1.
/*VertexElementType format = Root::getSingleton().getRenderSystem()->getColourVertexElementType();
switch (format)
{
case VET_COLOUR_ARGB:
std::swap(tmpR, tmpB);
break;
case VET_COLOUR_ABGR:
break;
default:
break;
}*/
// Modify
*((uint32*)currentVertex) = tmpR | (tmpG << 8) | (tmpB << 16) | (tmpA << 24);
// Move to the next vertex
pData+=vertex_size;
}
// Unlock
ent->getMesh()->getSubMesh(0)->vertexData->vertexBufferBinding->getBuffer(ves_diffuse->getSource())->unlock();
}
MWSkyManager::MWSkyManager (SceneNode* pMwRoot, Camera* pCamera) MWSkyManager::MWSkyManager (SceneNode* pMwRoot, Camera* pCamera)
{ {
mViewport = pCamera->getViewport();
mSceneMgr = pMwRoot->getCreator(); mSceneMgr = pMwRoot->getCreator();
mRootNode = pMwRoot->createChildSceneNode(); mRootNode = pMwRoot->createChildSceneNode();
mRootNode->setScale(100.f, 100.f, 100.f);
mViewport->setBackgroundColour(ColourValue(0.87, 0.87, 0.87));
HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
// Atmosphere // Atmosphere
NifOgre::NIFLoader::load("meshes\\sky_atmosphere.nif"); MeshPtr mesh = NifOgre::NIFLoader::load("meshes\\sky_atmosphere.nif");
Entity* atmosphere_ent = mSceneMgr->createEntity("meshes\\sky_atmosphere.nif"); Entity* atmosphere_ent = mSceneMgr->createEntity("meshes\\sky_atmosphere.nif");
ModVertexAlpha(atmosphere_ent, 0);
atmosphere_ent->setRenderQueueGroup(RENDER_QUEUE_SKIES_EARLY); atmosphere_ent->setRenderQueueGroup(RENDER_QUEUE_SKIES_EARLY);
Ogre::SceneNode* atmosphere_node = mRootNode->createChildSceneNode(); Ogre::SceneNode* atmosphere_node = mRootNode->createChildSceneNode();
atmosphere_node->attachObject(atmosphere_ent); atmosphere_node->attachObject(atmosphere_ent);
mAtmosphereMaterial = atmosphere_ent->getSubEntity(0)->getMaterial(); mAtmosphereMaterial = atmosphere_ent->getSubEntity(0)->getMaterial();
// Atmosphere shader
HighLevelGpuProgramPtr vshader = mgr.createProgram("Atmosphere_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
"cg", GPT_VERTEX_PROGRAM);
vshader->setParameter("profiles", "vs_2_x arbvp1");
vshader->setParameter("entry_point", "main_vp");
StringUtil::StrStreamType outStream;
outStream <<
"void main_vp( \n"
" float4 position : POSITION, \n"
" in float4 color : COLOR, \n"
" out float4 oPosition : POSITION, \n"
" out float4 oColor : COLOR, \n"
" uniform float4 emissive, \n"
" uniform float4x4 worldViewProj \n"
") \n"
"{ \n"
" oPosition = mul( worldViewProj, position ); \n"
" oColor = color * emissive; \n"
"}";
vshader->setSource(outStream.str());
vshader->load();
vshader->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
vshader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader->getName());
// Clouds // Clouds
NifOgre::NIFLoader::load("meshes\\sky_clouds_01.nif"); NifOgre::NIFLoader::load("meshes\\sky_clouds_01.nif");
@ -70,6 +170,60 @@ namespace MWRender
clouds_node->attachObject(clouds_ent); clouds_node->attachObject(clouds_ent);
mCloudMaterial = clouds_ent->getSubEntity(0)->getMaterial(); mCloudMaterial = clouds_ent->getSubEntity(0)->getMaterial();
// Clouds vertex shader
HighLevelGpuProgramPtr vshader2 = mgr.createProgram("Clouds_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
"cg", GPT_VERTEX_PROGRAM);
vshader2->setParameter("profiles", "vs_2_x arbvp1");
vshader2->setParameter("entry_point", "main_vp");
StringUtil::StrStreamType outStream3;
outStream3 <<
"void main_vp( \n"
" float4 position : POSITION, \n"
" in float4 color : COLOR, \n"
" out float4 oColor : TEXCOORD1, \n"
" in float2 uv : TEXCOORD0, \n"
" out float2 oUV : TEXCOORD0, \n"
" out float4 oPosition : POSITION, \n"
" uniform float4x4 worldViewProj \n"
") \n"
"{ \n"
" oUV = uv; \n"
" oColor = color; \n"
" oPosition = mul( worldViewProj, position ); \n"
"}";
vshader2->setSource(outStream3.str());
vshader2->load();
vshader2->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
mCloudMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader2->getName());
// Clouds fragment shader
mCloudFragmentShader = mgr.createProgram("Clouds_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
"cg", GPT_FRAGMENT_PROGRAM);
mCloudFragmentShader->setParameter("profiles", "ps_2_x arbfp1");
mCloudFragmentShader->setParameter("entry_point", "main_fp");
StringUtil::StrStreamType outStream2;
outStream2 <<
"void main_fp( \n"
" in float2 uv : TEXCOORD0, \n"
" out float4 oColor : COLOR, \n"
" in float4 color : TEXCOORD1, \n"
" uniform sampler2D texture : TEXUNIT0, \n"
" uniform float time, \n"
" uniform float4 emissive \n"
") \n"
"{ \n"
" uv += float2(1,1) * time * 0.01; \n" // Scroll in x,y direction
" float4 tex = tex2D(texture, uv); \n"
" clip(tex.a<0.5); \n"
" oColor = color * float4(emissive.xyz,1) * tex2D(texture, uv); \n"
"}";
mCloudFragmentShader->setSource(outStream2.str());
mCloudFragmentShader->load();
mCloudFragmentShader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
mCloudMaterial->getTechnique(0)->getPass(0)->setFragmentProgram(mCloudFragmentShader->getName());
ModVertexAlpha(clouds_ent, 1);
// Sun // Sun
/// \todo calculate the sun position based on time of day /// \todo calculate the sun position based on time of day
Vector3 sunPosition(0, 0, 1.f); Vector3 sunPosition(0, 0, 1.f);
@ -107,18 +261,20 @@ namespace MWRender
atmosphere_ent->getSubEntity(0)->setMaterial(mAtmosphereMaterial); atmosphere_ent->getSubEntity(0)->setMaterial(mAtmosphereMaterial);
// Default atmosphere color: light blue // Default atmosphere color: light blue
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setAmbient(0.235, 0.5, 0.73); mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(0.235, 0.5, 0.73);
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, 1.0); mAtmosphereMaterial->getTechnique(0)->getPass(0)->setDiffuse(0.0, 0.0, 0.0, 0.0);
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setAmbient(0.0, 0.0, 0.0);
// Set up an UV scroll animation to move the clouds // Set up an UV scroll animation to move the clouds
mCloudMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setScrollAnimation(0.01f, 0.01f); mCloudMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setScrollAnimation(0.01f, 0.01f);
mCloudMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0);
// Disable depth writing so that the sky does not cover any objects // Disable depth writing so that the sky does not cover any objects
mCloudMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); mCloudMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); //mAtmosphereMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
// Alpha-blend the clouds with the atmosphere mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
mCloudMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA); mCloudMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
mCamera = pCamera; mCamera = pCamera;
mCamera->setFarClipDistance(50000.f); mCamera->setFarClipDistance(500000.f);
} }
MWSkyManager::~MWSkyManager() MWSkyManager::~MWSkyManager()
{ {
@ -129,6 +285,9 @@ namespace MWRender
// Sync the position of the skydomes with the camera // Sync the position of the skydomes with the camera
/// \todo for some reason this is 1 frame delayed, which causes the skydome move funnily when the camera moves /// \todo for some reason this is 1 frame delayed, which causes the skydome move funnily when the camera moves
mRootNode->_setDerivedPosition(mCamera->getParentSceneNode()->_getDerivedPosition()); mRootNode->_setDerivedPosition(mCamera->getParentSceneNode()->_getDerivedPosition());
// UV Scroll the clouds
mCloudMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstantFromTime("time", 1);
} }
void MWSkyManager::enable() void MWSkyManager::enable()
@ -237,12 +396,12 @@ namespace MWRender
{ {
SkyManager* pSkyManager = NULL; SkyManager* pSkyManager = NULL;
try //try
{ //{
//pSkyManager = new CaelumManager(pRenderWindow, pCamera, resDir); //pSkyManager = new CaelumManager(pRenderWindow, pCamera, resDir);
pSkyManager = new MWSkyManager(pMwRoot, pCamera); pSkyManager = new MWSkyManager(pMwRoot, pCamera);
} //}
catch (Ogre::Exception& e) /*catch (Ogre::Exception& e)
{ {
std::cout << "\nOGRE Exception when attempting to add sky: " std::cout << "\nOGRE Exception when attempting to add sky: "
<< e.getFullDescription().c_str() << std::endl; << e.getFullDescription().c_str() << std::endl;
@ -251,7 +410,7 @@ namespace MWRender
{ {
std::cout << "\nException when attempting to add sky: " std::cout << "\nException when attempting to add sky: "
<< e.what() << std::endl; << e.what() << std::endl;
} }*/
return pSkyManager; return pSkyManager;
} }

@ -63,9 +63,10 @@ MWWorld::Ptr::CellStore *MWWorld::Cells::getExterior (int x, int y)
result = mExteriors.insert (std::make_pair ( result = mExteriors.insert (std::make_pair (
std::make_pair (x, y), Ptr::CellStore (cell))).first; std::make_pair (x, y), Ptr::CellStore (cell))).first;
}
if (result->second.mState!=Ptr::CellStore::State_Loaded)
result->second.load (mStore, mReader); result->second.load (mStore, mReader);
}
return &result->second; return &result->second;
} }
@ -79,9 +80,10 @@ MWWorld::Ptr::CellStore *MWWorld::Cells::getInterior (const std::string& name)
const ESM::Cell *cell = mStore.cells.findInt (name); const ESM::Cell *cell = mStore.cells.findInt (name);
result = mInteriors.insert (std::make_pair (name, Ptr::CellStore (cell))).first; result = mInteriors.insert (std::make_pair (name, Ptr::CellStore (cell))).first;
}
if (result->second.mState!=Ptr::CellStore::State_Loaded)
result->second.load (mStore, mReader); result->second.load (mStore, mReader);
}
return &result->second; return &result->second;
} }

@ -60,12 +60,12 @@ namespace MWWorld
std::cout << "Unloading cell\n"; std::cout << "Unloading cell\n";
ListHandles functor; ListHandles functor;
MWWorld::Ptr::CellStore* active = *iter;
active->forEach<ListHandles>(functor);
(*iter)->forEach<ListHandles>(functor);
{ {
@ -77,13 +77,15 @@ namespace MWWorld
mPhysics->removeObject (node->getName()); mPhysics->removeObject (node->getName());
} }
} }
mRendering.removeCell(active); mRendering.removeCell(*iter);
//mPhysics->removeObject("Unnamed_43"); //mPhysics->removeObject("Unnamed_43");
mWorld->getLocalScripts().clearCell (active);
mEnvironment.mMechanicsManager->dropActors (active);
mEnvironment.mSoundManager->stopSound (active);
mActiveCells.erase(active);
mWorld->getLocalScripts().clearCell (*iter);
mEnvironment.mMechanicsManager->dropActors (*iter);
mEnvironment.mSoundManager->stopSound (*iter);
mActiveCells.erase(*iter);
} }
void Scene::loadCell (Ptr::CellStore *cell) void Scene::loadCell (Ptr::CellStore *cell)

@ -181,6 +181,7 @@ namespace MWWorld
} }
World::~World() World::~World()
{ {
delete mWorldScene; delete mWorldScene;
@ -610,7 +611,7 @@ namespace MWWorld
bool World::toggleCollisionMode() bool World::toggleCollisionMode()
{ {
return mPhysics->toggleCollisionMode(); return mPhysics->toggleCollisionMode();;
} }
bool World::toggleRenderMode (RenderMode mode) bool World::toggleRenderMode (RenderMode mode)

@ -228,6 +228,7 @@ namespace MWWorld
/// references that are currently not in the rendered scene should be ignored. /// references that are currently not in the rendered scene should be ignored.
void update (float duration); void update (float duration);
}; };
} }

@ -473,7 +473,7 @@ void read(NIFFile *nif)
int vertCount = nif->getInt(); int vertCount = nif->getInt();
nif->getByte(); nif->getByte();
int magic = nif->getInt(); int magic = nif->getInt();
int type = nif->getInt(); /*int type =*/ nif->getInt();
for(int i = 0; i < vertCount; i++){ for(int i = 0; i < vertCount; i++){
float x = nif->getFloat(); float x = nif->getFloat();
@ -485,7 +485,7 @@ void read(NIFFile *nif)
for(int i=1; i<morphCount; i++) for(int i=1; i<morphCount; i++)
{ {
magic = nif->getInt(); magic = nif->getInt();
type = nif->getInt(); /*type =*/ nif->getInt();
std::vector<Ogre::Vector3> current; std::vector<Ogre::Vector3> current;
std::vector<float> currentTime; std::vector<float> currentTime;
for(int i = 0; i < magic; i++){ for(int i = 0; i < magic; i++){

@ -220,14 +220,15 @@ void NIFLoader::createMaterial(const String &name,
//Hardware Skinning code, textures may be the wrong color if enabled //Hardware Skinning code, textures may be the wrong color if enabled
/*if(!mSkel.isNull()){
/* if(!mSkel.isNull()){
material->removeAllTechniques(); material->removeAllTechniques();
Ogre::Technique* tech = material->createTechnique(); Ogre::Technique* tech = material->createTechnique();
//tech->setSchemeName("blahblah"); //tech->setSchemeName("blahblah");
Pass* pass = tech->createPass(); Pass* pass = tech->createPass();
pass->setVertexProgram("Ogre/HardwareSkinningFourWeights"); pass->setVertexProgram("Ogre/BasicVertexPrograms/AmbientOneTexture");*/
}*/
// This assigns the texture to this material. If the texture name is // This assigns the texture to this material. If the texture name is
// a file name, and this file exists (in a resource directory), it // a file name, and this file exists (in a resource directory), it
@ -358,7 +359,7 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std
HardwareVertexBufferSharedPtr vbuf = HardwareVertexBufferSharedPtr vbuf =
HardwareBufferManager::getSingleton().createVertexBuffer( HardwareBufferManager::getSingleton().createVertexBuffer(
VertexElement::getTypeSize(VET_FLOAT3), VertexElement::getTypeSize(VET_FLOAT3),
numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); numVerts, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY, false);
if(flip) if(flip)
{ {
@ -424,6 +425,7 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std
bind->setBinding(nextBuf++, vbuf); bind->setBinding(nextBuf++, vbuf);
} }
// Vertex colors // Vertex colors
if (data->colors.length) if (data->colors.length)
{ {
@ -530,6 +532,8 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std
{ {
sub->addBoneAssignment(*it); sub->addBoneAssignment(*it);
} }
if(mSkel.isNull())
needBoneAssignments.push_back(sub);
} }
// Helper math functions. Reinventing linear algebra for the win! // Helper math functions. Reinventing linear algebra for the win!
@ -580,6 +584,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
{ {
assert(shape != NULL); assert(shape != NULL);
bool saveTheShape = inTheSkeletonTree;
// Interpret flags // Interpret flags
bool hidden = (flags & 0x01) != 0; // Not displayed bool hidden = (flags & 0x01) != 0; // Not displayed
bool collide = (flags & 0x02) != 0; // Use mesh for collision bool collide = (flags & 0x02) != 0; // Use mesh for collision
@ -738,6 +743,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
std::list<VertexBoneAssignment> vertexBoneAssignments; std::list<VertexBoneAssignment> vertexBoneAssignments;
Nif::NiTriShapeCopy copy = shape->clone(); Nif::NiTriShapeCopy copy = shape->clone();
if(!shape->controller.empty()) if(!shape->controller.empty())
{ {
Nif::Controller* cont = shape->controller.getPtr(); Nif::Controller* cont = shape->controller.getPtr();
@ -747,6 +753,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
copy.morph = morph->data.get(); copy.morph = morph->data.get();
copy.morph.setStartTime(morph->timeStart); copy.morph.setStartTime(morph->timeStart);
copy.morph.setStopTime(morph->timeStop); copy.morph.setStopTime(morph->timeStop);
saveTheShape = true;
} }
} }
@ -888,6 +895,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
boneIndex++; boneIndex++;
} }
} }
else else
{ {
@ -924,10 +932,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
} }
if(!mSkel.isNull() ){ if(!mSkel.isNull() ){
int boneIndex; int boneIndex;
Ogre::Bone *parentBone = mSkel->getBone(boneSequence[boneSequence.size() - 1]);
if(parentBone)
boneIndex = parentBone->getHandle();
else
boneIndex = mSkel->getNumBones() - 1; boneIndex = mSkel->getNumBones() - 1;
for(int i = 0; i < numVerts; i++){ for(int i = 0; i < numVerts; i++){
VertexBoneAssignment vba; VertexBoneAssignment vba;
@ -943,7 +948,8 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
{ {
// Add this vertex set to the bounding box // Add this vertex set to the bounding box
bounds.add(optr, numVerts); bounds.add(optr, numVerts);
shapes.push_back(copy); if(saveTheShape)
shapes.push_back(copy);
// Create the submesh // Create the submesh
createOgreSubMesh(shape, material, vertexBoneAssignments); createOgreSubMesh(shape, material, vertexBoneAssignments);
@ -1063,19 +1069,22 @@ void NIFLoader::handleNode(Nif::Node *node, int flags,
//FIXME: "Bip01" isn't every time the root bone //FIXME: "Bip01" isn't every time the root bone
if (node->name == "Bip01" || node->name == "Root Bone") //root node, create a skeleton if (node->name == "Bip01" || node->name == "Root Bone") //root node, create a skeleton
{ {
inTheSkeletonTree = true;
mSkel = SkeletonManager::getSingleton().create(getSkeletonName(), resourceGroup, true); mSkel = SkeletonManager::getSingleton().create(getSkeletonName(), resourceGroup, true);
} }
else if (!mSkel.isNull() && !parentBone)
inTheSkeletonTree = false;
if (!mSkel.isNull()) //if there is a skeleton if (!mSkel.isNull()) //if there is a skeleton
{ {
std::string name = node->name.toString(); std::string name = node->name.toString();
boneSequence.push_back(name);
// Quick-n-dirty workaround for the fact that several // Quick-n-dirty workaround for the fact that several
// bones may have the same name. // bones may have the same name.
if(!mSkel->hasBone(name)) if(!mSkel->hasBone(name))
{ {
boneSequence.push_back(name);
bone = mSkel->createBone(name); bone = mSkel->createBone(name);
if (parentBone) if (parentBone)
@ -1140,8 +1149,11 @@ void NIFLoader::handleNode(Nif::Node *node, int flags,
void NIFLoader::loadResource(Resource *resource) void NIFLoader::loadResource(Resource *resource)
{ {
inTheSkeletonTree = false;
allanim.clear(); allanim.clear();
shapes.clear(); shapes.clear();
needBoneAssignments.clear();
// needBoneAssignments.clear();
mBoundingBox.setNull(); mBoundingBox.setNull();
mesh = 0; mesh = 0;
mSkel.setNull(); mSkel.setNull();
@ -1150,8 +1162,12 @@ void NIFLoader::loadResource(Resource *resource)
char suffix = name.at(name.length() - 2); char suffix = name.at(name.length() - 2);
bool addAnim = true; bool addAnim = true;
bool hasAnim = false; bool hasAnim = false;
bool baddin = false; //bool baddin = false;
bNiTri = true; bNiTri = true;
if(name == "meshes\\base_anim.nif" || name == "meshes\\base_animkna.nif")
{
bNiTri = false;
}
if(suffix == '*') if(suffix == '*')
{ {
@ -1168,7 +1184,7 @@ void NIFLoader::loadResource(Resource *resource)
} }
else if(suffix == '>') else if(suffix == '>')
{ {
baddin = true; //baddin = true;
bNiTri = true; bNiTri = true;
std::string sub = name.substr(name.length() - 6, 4); std::string sub = name.substr(name.length() - 6, 4);
@ -1268,7 +1284,7 @@ void NIFLoader::loadResource(Resource *resource)
Nif::Node *o = dynamic_cast<Nif::Node*>(f->target.getPtr()); Nif::Node *o = dynamic_cast<Nif::Node*>(f->target.getPtr());
Nif::NiKeyframeDataPtr data = f->data; Nif::NiKeyframeDataPtr data = f->data;
if (f->timeStart == 10000000000000000) if (f->timeStart >= 10000000000000000.0f)
continue; continue;
data->setBonename(o->name.toString()); data->setBonename(o->name.toString());
data->setStartTime(f->timeStart); data->setStartTime(f->timeStart);
@ -1299,15 +1315,24 @@ void NIFLoader::loadResource(Resource *resource)
mesh->_setBounds(mBoundingBox, false); mesh->_setBounds(mBoundingBox, false);
} }
if (!mSkel.isNull()) if (!mSkel.isNull() )
{ {
for(std::vector<Ogre::SubMesh*>::iterator iter = needBoneAssignments.begin(); iter != needBoneAssignments.end(); iter++)
{
int boneIndex = mSkel->getNumBones() - 1;
VertexBoneAssignment vba;
vba.boneIndex = boneIndex;
vba.vertexIndex = 0;
vba.weight = 1;
(*iter)->addBoneAssignment(vba);
}
mesh->_notifySkeleton(mSkel); mesh->_notifySkeleton(mSkel);
} }
} }
void NIFLoader::addInMesh(Ogre::Mesh* input){
addin.push_back(input);
}

@ -111,7 +111,6 @@ class NIFLoader : Ogre::ManualResourceLoader
std::vector<Nif::NiKeyframeData>* getAnim(std::string name); std::vector<Nif::NiKeyframeData>* getAnim(std::string name);
std::vector<Nif::NiTriShapeCopy>* getShapes(std::string name); std::vector<Nif::NiTriShapeCopy>* getShapes(std::string name);
std::map<std::string, float>* getTextIndices(std::string name); std::map<std::string, float>* getTextIndices(std::string name);
void addInMesh(Ogre::Mesh* input);
Ogre::Vector3 convertVector3(const Nif::Vector& vec); Ogre::Vector3 convertVector3(const Nif::Vector& vec);
@ -121,8 +120,9 @@ class NIFLoader : Ogre::ManualResourceLoader
void setVerbosePath(std::string path); void setVerbosePath(std::string path);
private: private:
NIFLoader() : resourceName(""), resourceGroup("General"), flip(false), mNormaliseNormals(false), NIFLoader() : resourceName(""), resourceGroup("General"), flip(false), mNormaliseNormals(false),
mFlipVertexWinding(false), mOutputAnimFiles(false) {} mFlipVertexWinding(false), mOutputAnimFiles(false), inTheSkeletonTree(false) {}
NIFLoader(NIFLoader& n) {} NIFLoader(NIFLoader& n) {}
void calculateTransform(); void calculateTransform();
@ -184,13 +184,16 @@ class NIFLoader : Ogre::ManualResourceLoader
std::string name; std::string name;
std::string triname; std::string triname;
std::vector<Nif::NiKeyframeData> allanim; std::vector<Nif::NiKeyframeData> allanim;
std::map<std::string,float> textmappings;
std::map<std::string,std::map<std::string,float>,ciLessBoost> alltextmappings; std::map<std::string,float> textmappings;
std::map<std::string,std::vector<Nif::NiKeyframeData>,ciLessBoost> allanimmap; std::map<std::string,std::map<std::string,float>,ciLessBoost> alltextmappings;
std::map<std::string,std::vector<Nif::NiTriShapeCopy>,ciLessBoost> allshapesmap; std::map<std::string,std::vector<Nif::NiKeyframeData>,ciLessBoost> allanimmap;
std::vector<Ogre::Mesh*> addin; std::map<std::string,std::vector<Nif::NiTriShapeCopy>,ciLessBoost> allshapesmap;
std::vector<Nif::NiKeyframeData> mAnim; std::vector<Nif::NiKeyframeData> mAnim;
std::vector<Nif::NiTriShapeCopy> mS; std::vector<Nif::NiTriShapeCopy> mS;
std::vector<Ogre::SubMesh*> needBoneAssignments;
bool inTheSkeletonTree;
}; };

@ -19,7 +19,7 @@
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>0.10</string> <string>${OPENMW_VERSION}</string>
<key>CSResourcesFileMapped</key> <key>CSResourcesFileMapped</key>
<true/> <true/>
<key>LSRequiresCarbon</key> <key>LSRequiresCarbon</key>

@ -7,6 +7,6 @@ PluginFolder=${OGRE_PLUGIN_DIR_REL}
Plugin=RenderSystem_GL Plugin=RenderSystem_GL
Plugin=Plugin_ParticleFX Plugin=Plugin_ParticleFX
Plugin=Plugin_OctreeSceneManager Plugin=Plugin_OctreeSceneManager
# Plugin=Plugin_CgProgramManager Plugin=Plugin_CgProgramManager

@ -7,6 +7,6 @@ PluginFolder=
Plugin=RenderSystem_GL.dylib Plugin=RenderSystem_GL.dylib
Plugin=Plugin_ParticleFX.dylib Plugin=Plugin_ParticleFX.dylib
Plugin=Plugin_OctreeSceneManager.dylib Plugin=Plugin_OctreeSceneManager.dylib
# Plugin=Plugin_CgProgramManager Plugin=Plugin_CgProgramManager

Loading…
Cancel
Save