m3g/m3gcore11/src/m3g_world.c
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 14 Sep 2010 23:50:05 +0300
branchRCL_3
changeset 177 183e23d95fab
parent 0 5d03bc08d59c
permissions -rw-r--r--
Revision: 201029 Kit: 201035

/*
* Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: World implementation
*
*/


/*!
 * \internal
 * \file
 * \brief World implementation
 */

#ifndef M3G_CORE_INCLUDE
#   error included by m3g_core.c; do not compile separately.
#endif

#include "m3g_world.h"
#include "m3g_memory.h"

/*----------------------------------------------------------------------
 * Internal functions
 *--------------------------------------------------------------------*/

/*!
 * \internal
 * \brief Destroys this World object.
 *
 * \param obj World object
 */
static void m3gDestroyWorld(Object *obj)
{
    World *world = (World *) obj;
    M3G_VALIDATE_OBJECT(world);

    M3G_ASSIGN_REF(world->activeCamera, NULL);
    M3G_ASSIGN_REF(world->background, NULL);

    m3gDestroyGroup(obj);
}

/*!
 * \internal
 * \brief Overloaded Object3D method.
 *
 * \param self World object
 * \param time current world time
 * \return minimum validity
 */
static M3Gint m3gWorldApplyAnimation(Object *self, M3Gint time)
{
    M3Gint minValidity;
    World *world = (World *)self;
    M3G_VALIDATE_OBJECT(world);

    minValidity = m3gGroupApplyAnimation(self, time);
    
    if (world->background != NULL && minValidity > 0) {
        M3Gint validity = M3G_VFUNC(Object, world->background, applyAnimation)((Object *)world->background, time);
        minValidity = (minValidity < validity ? minValidity : validity);
    }
    return minValidity;
}

/*!
 * \internal
 * \brief Overloaded Object3D method.
 *
 * \param self World object
 * \param references array of reference objects
 * \return number of references
 */
static M3Gint m3gWorldDoGetReferences(Object *self, Object **references)
{
    World *world = (World *)self;
    M3Gint num = m3gGroupDoGetReferences(self, references);
    if (world->activeCamera != NULL) {
        if (references != NULL)
            references[num] = (Object *)world->activeCamera;
        num++;
    }
    if (world->background != NULL) {
        if (references != NULL)
            references[num] = (Object *)world->background;
        num++;
    }
    return num;
}

/*!
 * \internal
 * \brief Overloaded Object3D method.
 */
static Object *m3gWorldFindID(Object *self, M3Gint userID)
{
    World *world = (World *)self;
    Object *found = m3gGroupFindID(self, userID);
    
    if (!found && world->activeCamera != NULL) {
        found = m3gFindID((Object*) world->activeCamera, userID);
    }
    if (!found && world->background != NULL) {
        found = m3gFindID((Object*) world->background, userID);
    }
    return found;
}

/*!
 * \internal
 * \brief Overloaded Object3D method.
 *
 * \param originalObj original World object
 * \param cloneObj pointer to cloned World object
 * \param pairs array for all object-duplicate pairs
 * \param numPairs number of pairs
 */
static M3Gbool m3gWorldDuplicate(const Object *originalObj,
                                 Object **cloneObj,
                                 Object **pairs,
                                 M3Gint *numPairs)
{
    World *original = (World *)originalObj;
    World *clone;
    M3G_ASSERT(*cloneObj == NULL); /* no derived classes */

    /* Create the clone object */
    
    clone = (World *)m3gCreateWorld(originalObj->interface);
    if (!clone) {
        return M3G_FALSE;
    }
    *cloneObj = (Object *)clone;

    /* Duplicate base class data */
    
    if (!m3gGroupDuplicate(originalObj, cloneObj, pairs, numPairs)) {
        return M3G_FALSE;
    }

    /* Duplicate our own data */
    
    M3G_ASSIGN_REF(clone->background, original->background);
    M3G_ASSIGN_REF(clone->activeCamera, original->activeCamera);
    
    return M3G_TRUE;
}

/*!
 * \internal
 * \brief Overloaded Object3D method.
 *
 * \param self World object
 * \param pairs array for all object-duplicate pairs
 * \param numPairs number of pairs
 */
static void m3gWorldUpdateDuplicateReferences(Node *self, Object **pairs, M3Gint numPairs)
{
    World *world = (World *)self;
    m3gGroupUpdateDuplicateReferences(self, pairs, numPairs);
    if (world->activeCamera != NULL) {
        Node *duplicatedInstance = m3gGetDuplicatedInstance(self, pairs, numPairs);
        Node *activeCamDuplicate = m3gGetDuplicatedInstance((Node *)world->activeCamera, pairs, numPairs);
        if (activeCamDuplicate != NULL &&
            m3gIsChildOf(duplicatedInstance, activeCamDuplicate)) {
            M3G_ASSIGN_REF(((World *)duplicatedInstance)->activeCamera, activeCamDuplicate);
        }
    }
}

/*!
 * \internal
 * \brief Initializes a World object. See specification
 * for default values.
 *
 * \param m3g           M3G interface
 * \param world         World object
 */
static void m3gInitWorld(Interface *m3g, World *world)
{
	/* World is derived from group */
	m3gInitGroup(m3g, &world->group, M3G_CLASS_WORLD);
}


/*----------------------------------------------------------------------
 * Virtual function table
 *--------------------------------------------------------------------*/

static const NodeVFTable m3gvf_World = {
    {
        {
            m3gWorldApplyAnimation,
            m3gNodeIsCompatible,
            m3gNodeUpdateProperty,
            m3gWorldDoGetReferences,
            m3gWorldFindID,
            m3gWorldDuplicate,
            m3gDestroyWorld
        }
    },
    m3gGroupAlign,
    NULL, /* pure virtual DoRender */
    m3gGroupGetBBox,
    m3gGroupRayIntersect,
    m3gGroupSetupRender,
    m3gWorldUpdateDuplicateReferences,
    m3gGroupValidate
};


/*----------------------------------------------------------------------
 * Public API functions
 *--------------------------------------------------------------------*/

/*!
 * \brief Creates a World object.
 *
 * \param interface M3G interface
 * \retval World new World object
 * \retval NULL World creating failed
 */

/*@access M3Ginterface@*/
/*@access M3Gobject@*/
M3G_API M3GWorld m3gCreateWorld(M3GInterface interface)
{
    Interface *m3g = (Interface *) interface;
    M3G_VALIDATE_INTERFACE(m3g);

	{
		World *world = m3gAllocZ(m3g, sizeof(World));
	
        if (world != NULL) {
    		m3gInitWorld(m3g, world);
        }

		return (M3GWorld) world;
	}
}

/*!
 * \brief Set active camera.
 *
 * \param handle        World object
 * \param hCamera       Camera object
 */

/*@access M3Gobject@*/
M3G_API void m3gSetActiveCamera(M3GWorld handle, M3GCamera hCamera)
{
    World *world = (World *) handle;
    M3G_VALIDATE_OBJECT(world);

    if(hCamera == NULL) {
        m3gRaiseError(M3G_INTERFACE(world), M3G_NULL_POINTER);
        return;
    }

    M3G_ASSIGN_REF(world->activeCamera, hCamera);
}

/*!
 * \brief Set background.
 *
 * \param handle        World object
 * \param hBackground   Background object
 */

/*@access M3Gobject@*/
M3G_API void m3gSetBackground(M3GWorld handle, M3GBackground hBackground)
{
    World *world = (World *) handle;
    M3G_VALIDATE_OBJECT(world);

    M3G_ASSIGN_REF(world->background, hBackground);
}

/*!
 * \brief Get background.
 *
 * \param handle        World object
 * \return              Background object
 */

/*@access M3Gobject@*/
M3G_API M3GBackground m3gGetBackground(M3GWorld handle)
{
    World *world = (World *) handle;
    M3G_VALIDATE_OBJECT(world);

    return world->background;
}

/*!
 * \brief Get active camera.
 *
 * \param handle        World object
 * \return              Camera object
 */

/*@access M3Gobject@*/
M3G_API M3GCamera m3gGetActiveCamera(M3GWorld handle)
{
    World *world = (World *) handle;
    M3G_VALIDATE_OBJECT(world);

    return world->activeCamera;
}